我观察到在python中使用多处理之前设置一个随机种子会导致奇怪的行为。
在python 3.5.2中,只使用了2或3个核心,CPU使用率很低。 在python 2.7.13中,所有请求的内核都以100%使用,但代码似乎永远不会完成。当我删除随机种子的初始化时,并行化工作正常。
即使在并行化函数中没有明确使用random,也会发生这种情况。我现在假设种子在进程之间共享,这阻止了多处理的顺利运行,但有人可以提供正确的答案吗?
我在Linux上运行代码,这是一个最小的代码示例:
from multiprocessing import Pool
import numpy as np
import random
random.seed = 2018
NB_CPUS = 4
def test(x):
return x**2
pool = Pool(NB_CPUS)
args = [np.random.rand() for _ in range(100000)]
results = pool.map(test, args)
pool.terminate()
results[-5:]
答案 0 :(得分:0)
回答得有点晚,但是您通过将random.seed
function设置为int
来破坏事情。相反,您应该这样做:
random.seed(2018)
追溯的最后几行提供了应该使这一点显而易见的上下文:
File "/usr/lib64/python2.7/multiprocessing/process.py", line 130, in start
self._popen = Popen(self)
File "/usr/lib64/python2.7/multiprocessing/forking.py", line 125, in __init__
random.seed()
TypeError: 'int' object is not callable
这会导致Pool
继续尝试创建新的工作进程,但是因为这种情况每发生一次都无法取得进展。
其背后的原因是multiprocessing
知道在派生时应重新种子随机模块,以使子进程不会共享相同的RNG状态。为此,它尝试调用random.seed
函数,但已将其设置为不可调用的int
---因此出错!
与此相关的另一个问题是multiprocessing
不知道重新播种NumPy RNG,因此以下代码:
from multiprocessing import Pool
import numpy as np
def test(i):
print(i, np.random.rand())
with Pool(4) as pool:
pool.map(test, range(4))
将导致每个工作人员打印相同的值。 This issue已有一段时间了,但是仍然开放。您可以使用工作程序initializer
解决此问题,例如:
def initfn():
np.random.seed()
with Pool(4, initializer=initfn) as pool:
pool.map(test, range(4))
现在将使上面的test
函数打印不同的值。请注意,如果您没有进行任何其他工作级别初始化,甚至可以使用Pool(4, initializer=np.random.seed)
。