[英]Python: parallel execution of a function which has a sequential loop inside
我正在从 Sutton 和 Barto 的书Reinforcement Learning: An Introduction 中复制一些简单的 10 臂老虎机实验。 其中一些需要大量的计算时间,因此我试图利用多核 CPU 的优势。
这是我需要运行 2000 次的函数。 它有 1000 个连续步骤,可逐步提高奖励:
import numpy as np
def foo(eps): # need an (unused) argument to use pool.map()
# initialising
# the true values of the actions
q = np.random.normal(0, 1, size=10)
# the estimated values
q_est = np.zeros(10)
# the counter of how many times each of the 10 actions was chosen
n = np.zeros(10)
rewards = []
for i in range(1000):
# choose an action based on its estimated value
a = np.argmax(q_est)
# get the normally distributed reward
rewards.append(np.random.normal(q[a], 1))
# increment the chosen action counter
n[a] += 1
# update the estimated value of the action
q_est[a] += (rewards[-1] - q_est[a]) / n[a]
return rewards
我执行这个函数 2000 次来得到 (2000, 1000) 数组:
reward = np.array([foo(0) for _ in range(2000)])
然后我绘制了 2000 次实验的平均奖励:
import matplotlib.pyplot as plt
plt.plot(np.arange(1000), reward.mean(axis=0))
这完全符合预期的结果(看起来和书中的一样)。 但是当我尝试并行执行它时,我得到的平均奖励的标准偏差要大得多:
import multiprocessing as mp
with mp.Pool(mp.cpu_count()) as pool:
reward_p = np.array(pool.map(foo, [0]*2000))
plt.plot(np.arange(1000), reward_p.mean(axis=0))
我想这是由于 foo 内部循环的并行化。 当我减少分配给任务的内核数量时,奖励图接近预期的形状。
有没有办法在获得正确结果的同时获得多处理的优势?
UPD:我尝试在 Windows 10 和顺序与并行上运行相同的代码,结果是一样的! 可能是什么原因?
Ubuntu 20.04、Python 3.8.5、jupyter
Windows 10、Python 3.7.3、jupyter
我们发现它在 windows 和 ubuntu 上是不同的。 大概是因为这个:
spawn 父进程启动一个新的python解释器进程。 子进程将只继承运行进程对象 run() 方法所需的资源。 特别是,父进程中不必要的文件描述符和句柄将不会被继承。 与使用 fork 或 forkserver 相比,使用此方法启动进程相当慢。
在 Unix 和 Windows 上可用。 Windows 和 macOS 上的默认设置。
fork 父进程使用 os.fork() 来 fork Python 解释器。 子进程在开始时实际上与父进程相同。 父进程的所有资源都由子进程继承。 请注意,安全地分叉多线程进程是有问题的。
仅在 Unix 上可用。 Unix 上的默认设置。
尝试将此行添加到您的代码中:
mp.set_start_method('spawn')
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.