在python中设置随机种子会干扰多处理

时间:2018-06-04 07:36:22

标签: python python-3.x random python-2.x python-multiprocessing

我观察到在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:]

1 个答案:

答案 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)