Подтвердить что ты не робот

Пул многопроцессорности Python, join; не ожидая продолжения?

(1) Я пытаюсь использовать pool.map, а затем pool.join(), но python, похоже, не ждет завершения pool.map, прежде чем продолжить pool.join(). Вот простой пример того, что я пробовал:

from multiprocessing import Pool

foo = {1: []}

def f(x):
    foo[1].append(x)
    print foo

def main():
    pool = Pool()
    pool.map(f, range(100))
    pool.close()
    pool.join()
    print foo

if __name__ == '__main__':
    main()

Печатный результат равен {1: []}, как если бы python просто проигнорировал команду join и запустил print foo, прежде чем у нее появилась возможность запускать f. Предполагаемый результат состоит в том, что foo - {1:[0,1,...,99]}, и использование обычного встроенного python map дает этот результат. Почему печать с пул-версией {1: []}, и как я могу изменить свой код, чтобы заставить его распечатать предполагаемый результат?

(2) В идеале я также хотел бы определить foo как локальную переменную в main() и передать ее в f, но делая это, сделав foo первым аргументом f и используя

pool.map(functools.partial(f, foo), range(100))

производит тот же вывод. (и, возможно, также имеет проблему, что каждый процесс теперь имеет свою собственную копию foo?) Хотя опять же, он работает вместо обычного map.

4b9b3361

Ответ 1

Это не правильный способ использования map.

  • Использование глобальной переменной таким образом абсолютно неверно. Процессы не используют одну и ту же память (обычно), поэтому каждая f будет иметь свою собственную копию foo. Чтобы разделить переменную между различными процессами, вы должны использовать Manager
  • Функция, переданная в map, обычно возвращает значение.

Я предлагаю вам прочитать документацию.

Однако вот фиктивный пример того, как вы могли его реализовать:

from multiprocessing import Pool

foo = {1: []}

def f(x):
    return x

def main():
    pool = Pool()
    foo[1] = pool.map(f, range(100))
    pool.close()
    pool.join()
    print foo

if __name__ == '__main__':
    main()

Вы также можете сделать что-то вроде pool.map(functools.partial(f, foo), range(100)), где foo - это Manager.