Использование Python multiprocessing.pool.map для манипулирования одним и тем же целым числом
проблема
Я использую многопроцессорный модуль Python для асинхронного выполнения функций. То, что я хочу сделать, это иметь возможность отслеживать общий прогресс моего сценария, когда каждый процесс вызывает и выполняет def add_print
, Например, я хотел бы, чтобы код ниже добавил 1 к total
и распечатать значение (1 2 3 ... 18 19 20
) каждый раз, когда процесс запускает эту функцию. Моей первой попыткой было использование глобальной переменной, но это не сработало. Поскольку функция вызывается асинхронно, каждый процесс читает total
как 0, чтобы начать, и добавляет 1 независимо от других процессов. Таким образом, выход составляет 20 1
вместо увеличения значений.
Как я могу получить ссылку на один и тот же блок памяти из моей сопоставленной функции синхронно, даже если функция выполняется асинхронно? У меня была идея как-то кешировать total
в памяти, а затем ссылаться на этот точный блок памяти, когда я добавляю к total
, Это возможный и принципиально правильный подход в питоне?
Пожалуйста, дайте мне знать, если вам нужна дополнительная информация или я что-то не объяснил достаточно хорошо.
Спасибо!
Код
#!/usr/bin/python
## Import builtins
from multiprocessing import Pool
total = 0
def add_print(num):
global total
total += 1
print total
if __name__ == "__main__":
nums = range(20)
pool = Pool(processes=20)
pool.map(add_print, nums)
1 ответ
Вы можете использовать общийValue
:
import multiprocessing as mp
def add_print(num):
total.value += 1
print(total.value)
def setup(t):
global total
total = t
if __name__ == "__main__":
total = mp.Value('i', 0)
nums = range(20)
pool = mp.Pool(initializer=setup, initargs=[total])
pool.map(add_print, nums)
Вызов инициализатора пула setup
один раз для каждого рабочего подпроцесса. setup
марки total
глобальная переменная в рабочем процессе, так total
можно получить доступ внутри add_print
когда рабочий звонит add_print
,
Обратите внимание, что количество процессов не должно превышать количество процессоров на вашей машине. Если вы это сделаете, избыточные подпроцессы будут ждать, пока процессоры станут доступными. Так что не используйте processes=20
если у вас нет 20 или более процессоров. Если вы не поставите processes
аргумент, multiprocessing
определит количество доступных процессоров и создаст пул с таким количеством рабочих для вас. Количество заданий (например, длина nums
) обычно значительно превышает количество процессоров. Все в порядке; задачи ставятся в очередь и обрабатываются одним из рабочих, когда рабочий становится доступным.