Используйте глобальную переменную, чтобы отслеживать прогресс многопроцессорной программы - PullRequest
0 голосов
/ 08 мая 2018

Я получил программу, запущенную в многопроцессорной среде. Я хотел бы иметь систему прогрессии с принтом.

Вот что я придумал:

import multiprocessing as mp
import os

global counter
global size

def f(x):
    global counter
    global size
    print ("{} / {}".format(counter, size))
    counter += 1
    return x**2

size = 4
counter = 1

result = list()
for x in [1,2,3,4]:
    result.append(f(x))

Этот работает. Однако, если вы замените нижнюю часть на:

with mp.Pool(processes = 2) as p:
    p.starmap(f, [1,2,3,4])

Это не так. Я не понимаю почему, кто-нибудь может помочь запустить это? Спасибо:)

N.B: Это, конечно, фиктивный пример.

EDIT:

Хорошо, новая проблема появляется с вашим решением. Я приведу пример:

fix1 = 1
fix2 = 2
dynamic = [1,2,3,4,5]

def f(x, y, z):
    return x**2 + y + z

size = len(dynamic)
counter = 1

with mp.Pool(processes = 2) as p:
    for output in p.starmap(f, [(x, fix1, fix2) for x in dynamic]):
        print ("{} / {}".format(counter, size))
        counter += 1

Этот работает, но печатает все в конце.

with mp.Pool(processes = 2) as p:
    for output in p.imap_unordered(f, [(x, fix1, fix2) for x in dynamic]):
        print ("{} / {}".format(counter, size))
        counter += 1

Этот не работает и говорит, что в f () отсутствуют 2 обязательных позиционных аргумента fix1 и fix2.

Есть идеи, почему у меня такое поведение?

N.B: я работаю на Windows.

1 Ответ

0 голосов
/ 08 мая 2018

В разветвленной системе, такой как linux, подпроцессы совместно используют представление копирования при записи родительского пространства памяти. Если одна сторона обновляет память, она получает свою собственную копию измененных страниц. В других системах создается новый процесс и запускается новый питон. В любом случае, ни одна из сторон не видит изменений, которые делают другие. А это значит, что каждый обновляет свою личную копию count и не видит дополнений, сделанных другими.

Чтобы не усложнять ситуацию, stdout не синхронизируется. Если работники печатают, вы, скорее всего, получите искаженные сообщения.

Альтернативой является подсчет результатов по мере их возвращения в родительский пул. Родитель отслеживает счет, а родитель - единственная распечатка. Если вам не важен порядок возвращаемых данных, то imap_unordered будет хорошо работать для вас.

import multiprocessing as mp

def f(x):
    return x**2

data = [1,2,3,4]
result = []

with mp.Pool(processes = 2) as p:
    for val in p.imap_unordered(f, data):
        result.append(val)
        print("progress",  len(result)/len(data))
...