我想在多个子流程中并行执行一些任务,如果任务没有在一定的延迟内完成,则超时。
第一种方法是分别分叉和合并子过程 ,并根据this answer中的建议,根据全局超时计算剩余的超时。对我来说很好。
我想在这里使用的第二种方法是创建一个子进程池并等待全局超时,如this answer中所建议的那样。
但是我对第二种方法有问题:在为子流程池中的任务包含multiprocessing.Event()
个对象之后,等待其完成会引发此异常:
RuntimeError:条件对象仅应通过继承在进程之间共享
这是Python代码段:
import multiprocessing.pool
import time
class Worker:
def __init__(self):
self.event = multiprocessing.Event() # commenting this removes the RuntimeError
def work(self, x):
time.sleep(1)
return x * 10
if __name__ == "__main__":
pool_size = 2
timeout = 5
with multiprocessing.pool.Pool(pool_size) as pool:
result = pool.map_async(Worker().work, [4, 5, 2, 7])
print(result.get(timeout)) # raises the RuntimeError
答案 0 :(得分:0)
multiprocessing
的{{3}}部分-基于进程的并行性文档中,有以下段落:
比泡菜/腌制更好地继承
使用 spawn 或 forkserver 启动方法时,
multiprocessing
中的许多类型都必须是可腌制的,以便子进程可以使用它们。但是,通常应该避免使用管道或队列将共享对象发送到其他进程。相反,您应该安排程序,以便需要访问在其他位置创建的共享资源的进程可以从祖先进程继承该程序。
因此multiprocessing.Event()
导致了RuntimeError
,因为它是不可选取的,如以下Python代码片段所示:
import multiprocessing
import pickle
pickle.dumps(multiprocessing.Event())
会引发相同的异常:
RuntimeError:条件对象仅应通过继承在进程之间共享
一种解决方案是使用"Programming guidlines":
代理是一个对象,它指的是一个共享对象,该共享对象(大概)生活在不同的进程中。
因为:
代理对象的重要特征是它们是可腌制的,因此可以在进程之间传递。
proxy object创建一个共享的threading.Event()
对象并为其返回代理,因此替换此行:
self.event = multiprocessing.Event()
通过该问题的Python代码段中的以下行解决了该问题:
self.event = multiprocessing.Manager().Event()