我是Python中multiprocessing
模块的新手,并使用Jupyter Notebooks。我尝试了以下来自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()
当我按原样运行时,没有输出。
我还尝试过创建一个称为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()
在这种情况下仍然没有输出。在控制台中,我看到以下错误(重复多次(:
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "C:Program FilesAnaconda3libmultiprocessingspawn.py", line 106, in spawn_main
exitcode = _main(fd)
File "C:Program FilesAnaconda3libmultiprocessingspawn.py", line 116, in _main
self = pickle.load(from_parent)
AttributeError: Can't get attribute 'worker' on <module '__main__' (built-in)>
但是,当代码保存为Python脚本并将其显示时,我将获得预期的输出。
我该怎么做才能直接从笔记本上运行此代码而不创建单独的脚本?
我对并行计算我相对较新,因此我可能有一些技术性是错误的。我的理解是:
jupyter笔记本电脑不使用multiprocessing
,因为模块泡菜(序列化(数据要发送到进程。 multiprocess
是multiprocessing
的叉子,它使用DILL代替泡菜来序列数据,该数据允许其在Jupyter笔记本中使用。API是相同的,因此您唯一需要做的就是更改
import multiprocessing
to ...
import multiprocess
您可以很容易地使用简单的
安装multiprocess
pip install multiprocess
但是,您会发现您的流程仍然不会打印到输出中(尽管在Jupyter Labs中,他们将打印到服务器正在运行的终端(。我偶然发现了这篇文章,试图解决此问题,并在找出该方法时编辑这篇文章。
我在multiprocessing
或ipykernel
中都不是导出(Jupyter Notebook使用(,但是由于似乎没有人给出答案,所以我会告诉您我猜到了什么。我希望有人在稍后对此进行补充。
我猜您的Jupyter笔记本服务器正在Windows主机上运行。在多处理中,有三种不同的开始方法。让我们重点关注 spawn ,这是Windows上的默认值, fork ,UNIX上的默认值。
这是一个快速概述。
-
Spawn
- (cpython(互动shell - 始终提出错误
-
以脚本运行 - 仅在
if __name__ == '__main'__
中嵌套多处理代码
时才能运行
-
fork
- 总是好的
例如,
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 Interactive Shell中输入时会引起错误。这是Ipython内核的实现,我的猜测是它使用了某种交互式外壳,因此与 Spawn> Spawn (但请不要相信我(。
对于旁注,我将为您提供有关 Spawn 和 fork 的一般想法。每个子过程都在多处理中运行不同的python解释器。特别是,使用 Spawn ,子过程启动了一个新的解释器,并从头开始导入必要的模块。很难在交互式外壳中导入代码,因此可能会引起错误。
fork 是不同的。使用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)
很像您,我遇到了属性错误。问题似乎与Jupyter处理多线程有关。我得到的最快的结果是遵循多处理示例。
,The Treadpool照顾了我的问题。
from multiprocessing.pool import ThreadPool as Pool
def worker():
"""worker function"""
print('Workern')
return
pool = Pool(4)
for result in pool.map(worker, range(5)):
pass # or print diagnostics
这对我在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文件,然后将功能重新导入。