我想使用multiprocessing.Pool并行应用函数。 问题是如果一个函数调用触发了分段错误,则Pool会永久挂起。 有没有人知道如何让一个Pool能够检测出这样的事情发生时会引发错误?
以下示例显示了如何重现它(需要scikit-learn> 0.14)
import numpy as np
from sklearn.ensemble import gradient_boosting
import time
from multiprocessing import Pool
class Bad(object):
tree_ = None
def fit_one(i):
if i == 3:
# this will segfault
bad = np.array([[Bad()] * 2], dtype=np.object)
gradient_boosting.predict_stages(bad,
np.random.rand(20, 2).astype(np.float32),
1.0, np.random.rand(20, 2))
else:
time.sleep(1)
return i
pool = Pool(2)
out = pool.imap_unordered(fit_one, range(10))
# we will never see 3
for o in out:
print o
答案 0 :(得分:2)
这是known bug, issue #22393, in Python。只要您使用multiprocessing.pool
直到修复它,就没有有意义的解决方法。该链接提供了一个补丁,但尚未将其集成到主版本中,因此没有稳定版本的Python可以解决问题。
答案 1 :(得分:1)
您可能希望自己使用Pool().imap()
手动创建子流程,而不是使用Process()
。我敢打赌,返回的对象可以让你获得任何孩子的活跃状态。你会知道他们是否挂断了。
答案 2 :(得分:1)
如评论中所述,如果您使用concurrent.Futures.ProcessPoolExecutor
而不是multiprocessing.Pool
,这只适用于Python 3。
如果您遇到Python 2,我发现的最佳选择是在timeout
和Pool.apply_async
返回的结果对象上使用Pool.map_async
参数。例如:
pool = Pool(2)
out = pool.map_async(fit_one, range(10))
for o in out:
print o.get(timeout=1000) # allow 1000 seconds max
只要你有一个上限来确定子进程完成一项任务应该花多长时间,这就行了。
答案 3 :(得分:0)
我没有运行你的例子,看看它是否可以处理错误,但尝试并发期货。只需用fit_one(i)替换my_function(i)即可。保持__name__=='__main__':
结构。并行期货似乎需要这个。下面的代码在我的机器上测试,所以希望能直接在你的机器上进行测试。
import concurrent.futures
def my_function(i):
print('function running')
return i
def run():
number_processes=4
executor = concurrent.futures.ProcessPoolExecutor(number_processes)
futures = [executor.submit(my_function,i) for i in range(10)]
concurrent.futures.wait(futures)
for f in futures:
print(f.result())
if __name__ == '__main__':
run()