[英]Python Multiprocessing within Jupyter Notebook
我是 Python 中的multiprocessing
模塊的新手,並且可以使用 Jupyter 筆記本。 我嘗試了PMOTW的以下代碼片段:
import multiprocessing
def worker():
"""worker function"""
print('Worker')
return
if __name__ == '__main__':
jobs = []
for i in range(5):
p = multiprocessing.Process(target=worker)
jobs.append(p)
p.start()
當我按原樣運行時,沒有 output。
我還嘗試創建一個名為worker.py
的模塊,然后將其導入以運行代碼:
import multiprocessing
from worker import worker
if __name__ == '__main__':
jobs = []
for i in range(5):
p = multiprocessing.Process(target=worker)
jobs.append(p)
p.start()
在這種情況下仍然沒有 output。 在控制台中,我看到以下錯誤(重復多次):
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "C:\Program Files\Anaconda3\lib\multiprocessing\spawn.py", line 106, in spawn_main
exitcode = _main(fd)
File "C:\Program Files\Anaconda3\lib\multiprocessing\spawn.py", line 116, in _main
self = pickle.load(from_parent)
AttributeError: Can't get attribute 'worker' on <module '__main__' (built-in)>
但是,當代碼保存為 Python 腳本並執行時,我得到了預期的 output。
我可以做些什么來直接從筆記本運行此代碼而不創建單獨的腳本?
我對並行計算比較陌生,所以我可能對一些技術有誤。 我的理解是這樣的:
Jupyter 筆記本不適用於multiprocessing
,因為模塊會腌制(序列化)數據以發送到進程。 multiprocess
是multiprocessing
的一個分支,它使用 dill 而不是 pickle 來序列化數據,這允許它在 Jupyter notebook 中工作。 API 是相同的,因此您唯一需要做的就是更改
import multiprocessing
至...
import multiprocess
你可以很容易地安裝multiprocess
pip install multiprocess
但是,您會發現您的進程仍然不會打印到輸出(盡管在 Jupyter 實驗室中,它們會打印到服務器輸出正在運行的終端)。 我偶然發現這篇文章試圖解決這個問題,當我知道如何做時會編輯這篇文章。
我不是multiprocessing
或ipykernel
(由 jupyter notebook 使用)中的導出,但因為似乎沒有人給出答案,所以我會告訴你我的猜測。 我希望以后有人對此進行補充。
我猜你的 jupyter notebook 服務器正在 Windows 主機上運行。 在多處理中,有三種不同的啟動方法。 讓我們關注spawn ,這是 windows 上的默認設置,以及fork ,這是 Unix 上的默認設置。
這是一個快速概述。
產卵
if __name__ == '__main'__
中嵌套多處理代碼時才可以叉子
例如,
import multiprocessing
def worker():
"""worker function"""
print('Worker')
return
if __name__ == '__main__':
multiprocessing.set_start_method('spawn')
jobs = []
for i in range(5):
p = multiprocessing.Process(target=worker)
jobs.append(p)
p.start()
此代碼在保存並作為腳本運行時有效,但在 python 交互式 shell 中輸入時會引發錯誤。 這是 ipython 內核的實現,我的猜測是它使用了某種交互式 shell,因此不適合spawn (但請不要相信我)。
作為旁注,我將大致了解spawn和fork的不同之處。 每個子進程在多處理中運行不同的 python 解釋器。 特別是,使用spawn ,子進程會啟動一個新的解釋器並從頭開始導入必要的模塊。 在交互式 shell 中很難導入代碼,因此可能會引發錯誤。
叉子是不同的。 使用fork,子進程復制主進程,包括python解釋器的大部分運行狀態,然后繼續執行。 此代碼將幫助您理解這個概念。
import os
main_pid = os.getpid()
os.fork()
print("Hello world(%d)" % os.getpid()) # print twice. Hello world(id1) Hello world(id2)
if os.getpid() == main_pid:
print("Hello world(main process)") # print once. Hello world(main process)
這在 MAC 上對我有用(不能在 Windows 上工作):
import multiprocessing as mp
mp_start_count = 0
if __name__ == '__main__':
if mp_start_count == 0:
mp.set_start_method('fork')
mp_start_count += 1
將函數保存到單獨的 Python 文件中,然后重新導入函數。這樣應該可以正常工作。
我發現遵循Multi-processing example是最簡單的。
所以 ThreadPool 解決了我的問題。
from multiprocessing.pool import ThreadPool as Pool
def worker():
"""worker function"""
print('Worker\n')
return
pool = Pool(4)
for result in pool.map(worker, range(5)):
pass # or print diagnostics
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.