繁体   English   中英

Python 3.8 多处理,用于在 MacOS 上复制随机数

[英]Python 3.8 multiprocessing for copying the random on MacOS

from multiprocessing import Pool, cpu_count
import numpy as np
from numpy.random import multivariate_normal

F = multivariate_normal(np.zeros(3), np.eye(3), (3, 5))

def test(k):
    print(k)
    res = np.zeros((5, 3))
    for i in range(3):
        res[:, i] = F[k, :, i]
        #print(res[:, i])
    return res


if __name__ == '__main__':
    with Pool(cpu_count()) as pool:
        result = pool.map(test, range(3))
    pool.close()
    pool.join()
    result = np.array(results)

在python3.6中,结果等于随机矩阵F。但是在python 3.8中它们的两个矩阵是不同的。 这只是一个例子。 在实际代码中,我想在每个时间步中取出 F 的每一列并对其进行一些操作。

心理调试:您在 Windows(任何 Python 版本)或 macOS(Python 3.8 或更高版本)上运行,两者都默认使用'spawn'制作工作进程的方法,而不是'fork' 发生这种情况时,会在子进程中导入__main__模块(使用不同的名称,因此它不会再次尝试运行主代码)以模拟fork

这主要是可行的,但在自播 PRNG 的情况下会失败,因为它们在子进程中重新播种,并且全局是从新的 PRNG 重新生成的,而不是让子进程继承它们生成的值。

简而言之,完成这项工作的方法是:

  1. 使用'fork'作为multiprocessing启动方法运行它(在 Windows 上不可能,在 macOS 上技术上允许,但可能会中断,这就是他们将默认设置更改为'spawn'的原因)。 我在 Linux 上测试了你的代码(默认情况下它是fork s),除了修复一个错字(你在一个应该是result的地方输入了results )之外, resultF在那里是一样的。 当我在创建Pool之前添加multiprocessing.set_start_method('spawn')时,它们不匹配。
  2. 将初始化程序 function 和 arguments 显式传递给Pool以便每个工作人员将F重置为在父项中看到的值
  3. 在生成F之前使用显式种子,因此无论过程如何它都是一致的(缺点:每次运行都会相同,或者至少非常可预测,具体取决于您尝试获得的聪明程度)

请注意,#2 和#3 可以组合以最小化数据流。 在父级中生成一个“真正的”随机种子(例如使用os.urandom )并编写一个简单的 function 接受种子并使用它来播种 PRNG 并生成F (使用global F让它改变全局值)。 在父级中调用 function 并将其作为带有种子参数的初始化程序传递给每个子级。 现在,不需要传递F的生成值(可能是巨大的),您只需要传递种子,子进程就可以在本地重现F而无需序列化整个事物。 缺点:所有进程共享相同的随机种子; 它不像硬编码的种子那样可预测,但父母和孩子将从一组相同的随机数中提取。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM