[英]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.