Совместное использование примитива синхронизации многопроцессорности через процессы

(Python 3.4, Linux).

У меня есть основной процесс «P», который развивает 8 процессов («C1» – «C8»). Я хочу создать multiprocessing.Barrier которая обеспечит синхронизацию всех 8 дочерних процессов в определенной точке.

Все работает нормально, если я определяю примитив синхронизации в родительском процессе, так что, когда я форк дочерних процессов, он правильно унаследован:

 import multiprocessing as mp barrier = mp.Barrier(8) def f(): # do something barrier.wait() # do more stuff def main(): for i in range(8): p = mp.Process(target = f) p.start() if __name__ == '__main__': main() 

Но в моем случае я не знаю деталей, необходимых для создания объекта Barrier до тех пор, пока не начнут запускать дочерние процессы (я не знаю аргумент, который я хочу передать в качестве его параметра action ). Поэтому я хочу создать Barrier в одном из дочерних процессов, но я не знаю, как сделать его доступным для других дочерних процессов. Следующие не будут работать, конечно, потому что 8 объектов Barrier в дочернем процессе полностью независимы друг от друга:

 import multiprocessing as mp def f(): global barrier # do something barrier = mp.Barrier(8) barrier.wait() # do more stuff def main(): for i in range(8): p = mp.Process(target = f) p.start() if __name__ == '__main__': main() 

Я думал создать barrier в одном из дочерних процессов и передать его другим, используя multiprocessing.Queue (или если Queue не принимает объекты Barrier , используя multiprocessing.Manager().Barrier ). Однако, даже если это работает, я не знаю, как обеспечить, чтобы только один процесс фактически put (7 копий) примитивов синхронизации в очередь, в то время как другие получат их только. (Конечно, я могу создать еще один примитив синхронизации в родительском процессе только для этого, но тогда я мог бы также реорганизовать мой код, чтобы создать оригинальный Barrier в родительском процессе.)

2 Solutions collect form web for “Совместное использование примитива синхронизации многопроцессорности через процессы”

Вот пример того, как вы могли бы это сделать, создав multiprocessing.managers.BaseManager у одного ребенка, а затем подключившись к этому менеджеру из всех других детей. Обратите внимание, что для этого требуется передача multiprocessing.Lock элемент от родителя ко всем дочерним элементам в целях синхронизации, о которых вы упомянули, вы предпочитаете избегать. Я не уверен, что есть другой вариант.

 import multiprocessing as mp from multiprocessing.managers import BaseManager class MyManager(BaseManager): pass def f(lock): # do something with lock: try: MyManager.register('get_barrier') m = MyManager(address=('localhost', 5555), authkey=b'akey') m.connect() b = m.get_barrier() print("Got the barrier from the manager") except OSError as e: # We are the first. Create the manager, register # a mp.Barrier instance with it, and start it up. print("Creating the manager...") b = mp.Barrier(8) MyManager.register('get_barrier', callable=lambda:b) m = MyManager(address=('localhost', 5555), authkey=b'akey') m.start() b.wait() print("Done!") # do more stuff def main(): lock = mp.Lock() for i in range(8): p = mp.Process(target=f, args=(lock,)) p.start() if __name__ == '__main__': main() 

Вывод:

 Creating the manager... Got the barrier from the manager Got the barrier from the manager Got the barrier from the manager Got the barrier from the manager Got the barrier from the manager Got the barrier from the manager Got the barrier from the manager Done! Done! Done! Done! Done! Done! Done! Done! 

Можно ли просто захватить id процессов и manaully вызвать ваше действие только в одном из них? Что-то вроде этого?

 import multiprocessing as mp barrier = mp.Barrier(8) def f(): # create action def action(): print("action was run on process {}.".format(id)) # do something print("Hello from process {}.".format(id)) id = barrier.wait() if id == 0: action() barrier.wait() # Do more stuff def main(): for i in range(8): p = mp.Process(target = f) p.start() if __name__ == '__main__': main() 
  • Вывод Python в Консоль внутри подпроцесса из дочернего скребка
  • Команда «collectstatic» не работает, когда WhiteNoise включен
  • Пространство имен по умолчанию Python ElementTree?
  • Python проверяет, существует ли столбец в списке
  • python - загрузка сюжета из памяти в s3 с использованием matplotlib и boto
  • Написание типа Python с исключениями
  • Python NameError: имя не определено
  • Почему некоторый код детерминирован в Python2 и не является детерминированным в Python 3?
  • Python - лучший язык программирования в мире.