Python 使用“事件”的多处理暂停重启功能`
我正在使用下面发布的代码来启用Python 使用“事件”的多处理暂停重启功能`,python,multiprocessing,Python,Multiprocessing,我正在使用下面发布的代码来启用多处理池的暂停重启功能 如果您能解释一下为什么必须将事件变量作为参数发送给设置()函数,我将不胜感激。为什么在setup()函数的作用域内声明了一个全局变量unpaused,然后将其设置为与事件变量相同: def setup(event): global unpaused unpaused = event 我还想知道以下声明背后的逻辑: pool=mp.Pool(2, setup, (event,)) 提交的第一个参数是池要使用的CPU内核数。
多处理
池的暂停重启功能
如果您能解释一下为什么必须将事件
变量作为参数发送给设置()
函数,我将不胜感激。为什么在setup()
函数的作用域内声明了一个全局变量unpaused
,然后将其设置为与事件
变量相同:
def setup(event):
global unpaused
unpaused = event
我还想知道以下声明背后的逻辑:
pool=mp.Pool(2, setup, (event,))
提交的第一个参数是池要使用的CPU内核数。
提交的第二个参数是上面提到的函数setup()
为什么不能像这样完成这一切:
global event
event=mp.Event()
pool = mp.Pool(processes=2)
每次需要暂停或重新启动作业时,我们只需使用:
暂停:
event.clear()
要重新启动:
event.set()
为什么我们需要一个全局变量非伪
?我不明白!请告知
您误解了
事件的工作原理。但首先,我将介绍setup
正在做什么
setup
函数在池中的每个子进程启动后立即执行。因此,您正在将每个进程中名为event
的全局变量设置为与主进程中创建的multiprocessing.event
对象相同的对象。最后,每个子进程都有一个名为event
的全局变量,该变量引用同一multiprocessing.event
对象。这将允许您从主进程向子进程发送信号,就像您希望的那样。请参见此示例:
import multiprocessing
event = None
def my_setup(event_):
global event
event = event_
print "event is %s in child" % event
if __name__ == "__main__":
event = multiprocessing.Event()
p = multiprocessing.Pool(2, my_setup, (event,))
print "event is %s in parent" % event
p.close()
p.join()
输出:
dan@dantop2:~$ ./mult.py
event is <multiprocessing.synchronize.Event object at 0x7f93cd7a48d0> in child
event is <multiprocessing.synchronize.Event object at 0x7f93cd7a48d0> in child
event is <multiprocessing.synchronize.Event object at 0x7f93cd7a48d0> in parent
dan@dantop2:~$ ./mult.py
event is <multiprocessing.synchronize.Event object at 0x7fea3b1dc8d0> in child
event is <multiprocessing.synchronize.Event object at 0x7fea3b1dc8d0> in child
event is <multiprocessing.synchronize.Event object at 0x7fea3b1dc8d0> in parent
main is sleeping
<Process(PoolWorker-1, started daemon)> is waiting
<Process(PoolWorker-2, started daemon)> is waiting
<Process(PoolWorker-4, started daemon)> is waiting
<Process(PoolWorker-3, started daemon)> is waiting
main is setting event
<Process(PoolWorker-2, started daemon)> has woken up
<Process(PoolWorker-1, started daemon)> has woken up
<Process(PoolWorker-4, started daemon)> has woken up
<Process(PoolWorker-3, started daemon)> has woken up
输出:
dan@dantop2:~$ ./mult.py
event is <multiprocessing.synchronize.Event object at 0x7f93cd7a48d0> in child
event is <multiprocessing.synchronize.Event object at 0x7f93cd7a48d0> in child
event is <multiprocessing.synchronize.Event object at 0x7f93cd7a48d0> in parent
dan@dantop2:~$ ./mult.py
event is <multiprocessing.synchronize.Event object at 0x7fea3b1dc8d0> in child
event is <multiprocessing.synchronize.Event object at 0x7fea3b1dc8d0> in child
event is <multiprocessing.synchronize.Event object at 0x7fea3b1dc8d0> in parent
main is sleeping
<Process(PoolWorker-1, started daemon)> is waiting
<Process(PoolWorker-2, started daemon)> is waiting
<Process(PoolWorker-4, started daemon)> is waiting
<Process(PoolWorker-3, started daemon)> is waiting
main is setting event
<Process(PoolWorker-2, started daemon)> has woken up
<Process(PoolWorker-1, started daemon)> has woken up
<Process(PoolWorker-4, started daemon)> has woken up
<Process(PoolWorker-3, started daemon)> has woken up
现在,回到您对事件
工作方式的误解<代码>事件
的用法如下:
import time
import multiprocessing
def event_func(num):
print '\t%r is waiting' % multiprocessing.current_process()
event.wait()
print '\t%r has woken up' % multiprocessing.current_process()
if __name__ == "__main__":
event = multiprocessing.Event()
pool = multiprocessing.Pool()
a = pool.map_async(event_func, [i for i in range(pool._processes)])
print 'main is sleeping'
time.sleep(2)
print 'main is setting event'
event.set()
pool.close()
pool.join()
输出:
dan@dantop2:~$ ./mult.py
event is <multiprocessing.synchronize.Event object at 0x7f93cd7a48d0> in child
event is <multiprocessing.synchronize.Event object at 0x7f93cd7a48d0> in child
event is <multiprocessing.synchronize.Event object at 0x7f93cd7a48d0> in parent
dan@dantop2:~$ ./mult.py
event is <multiprocessing.synchronize.Event object at 0x7fea3b1dc8d0> in child
event is <multiprocessing.synchronize.Event object at 0x7fea3b1dc8d0> in child
event is <multiprocessing.synchronize.Event object at 0x7fea3b1dc8d0> in parent
main is sleeping
<Process(PoolWorker-1, started daemon)> is waiting
<Process(PoolWorker-2, started daemon)> is waiting
<Process(PoolWorker-4, started daemon)> is waiting
<Process(PoolWorker-3, started daemon)> is waiting
main is setting event
<Process(PoolWorker-2, started daemon)> has woken up
<Process(PoolWorker-1, started daemon)> has woken up
<Process(PoolWorker-4, started daemon)> has woken up
<Process(PoolWorker-3, started daemon)> has woken up
main正在睡觉
正在等待
正在等待
正在等待
正在等待
主要是设置事件
他醒了
他醒了
他醒了
他醒了
如您所见,子进程需要显式调用
event.wait()
,才能暂停它们。当在主进程中调用event.set
时,它们将取消暂停。现在,没有工作人员正在调用事件。请稍候
,因此他们中的任何人都无法暂停。我建议您查看文档,其中multiprocessing.Event
replicates.您在哪里找到此代码的?这是Stackoverflow上建议的。我已询问如何暂停/重新启动池。这就是建议。我知道这不是政策,但谢谢!很好的信息性回答,加上额外的背景知识。非常有帮助!注意:在我的系统(macOSX-10.13.6、python-3.7.6、eclipse-4.11.0)上,如果您的启动进程是“spawn”,即多处理。set_start_方法(“spawn”,force=True),此解决方案将不起作用。(由此产生的“failure”很有趣,因为没有生成错误,但是,代码只在event_func()中的event.wait()行停止。)这很重要,因为“spawn”是MacOSX上python 3.8的默认start_方法。另外请注意:如果使用“pool.map()”,则上述代码中存在显著差异(如果start_方法是“spawn”,则会抛出一条错误消息),而不是“pool.map_async()”(其中不会生成错误,但代码会失败)。最终,我放弃了“pool”,并使用多个单独的进程来实现更干净的执行(如:“multiprocessing.Process(target=runGUIthread_v2,args=(myEvent,yearParams,)))。