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

Setting random seed in python disturbs 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:]

回答有点晚了,但是你通过将 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 知道它应该 re-seed 分叉时的随机模块,这样子进程就不会共享相同的 RNG 状态。为此,它会尝试调用 random.seed 函数,但您已将其设置为不可调用的 int --- 因此出现错误!

与此相关的另一个问题是 multiprocessing 不知道 re-seed 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 已经有一段时间了,但仍然开放。您可以使用 worker 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)