我基本上使用多处理模块,我还在学习多处理的功能。我正在使用Dusty Phillips的书,这段代码属于它。
import multiprocessing
import random
from multiprocessing.pool import Pool
def prime_factor(value):
factors = []
for divisor in range(2, value-1):
quotient, remainder = divmod(value, divisor)
if not remainder:
factors.extend(prime_factor(divisor))
factors.extend(prime_factor(quotient))
break
else:
factors = [value]
return factors
if __name__ == '__main__':
pool = Pool()
to_factor = [ random.randint(100000, 50000000) for i in range(20)]
results = pool.map(prime_factor, to_factor)
for value, factors in zip(to_factor, results):
print("The factors of {} are {}".format(value, factors))
在Windows PowerShell上(不在jupyter笔记本上),我看到以下内容
Process SpawnPoolWorker-5:
Process SpawnPoolWorker-1:
AttributeError: Can't get attribute 'prime_factor' on <module '__main__' (built-in)>
我不知道为什么细胞永远不会结束?
答案 0 :(得分:16)
似乎Jupyter笔记本中的问题与不同的ide一样是设计特征。因此,我们必须将函数(prime_factor)写入不同的文件并导入模块。此外,我们必须处理调整。例如,在我的例子中,我已将函数编码为名为defs.py
的文件def prime_factor(value):
factors = []
for divisor in range(2, value-1):
quotient, remainder = divmod(value, divisor)
if not remainder:
factors.extend(prime_factor(divisor))
factors.extend(prime_factor(quotient))
break
else:
factors = [value]
return factors
然后在jupyter笔记本中我写了以下几行
import multiprocessing
import random
from multiprocessing import Pool
import defs
if __name__ == '__main__':
pool = Pool()
to_factor = [ random.randint(100000, 50000000) for i in range(20)]
results = pool.map(defs.prime_factor, to_factor)
for value, factors in zip(to_factor, results):
print("The factors of {} are {}".format(value, factors))
这解决了我的问题
答案 1 :(得分:1)
要执行功能而无需手动将其写入单独的文件中:
我们可以动态地将要处理的任务写入临时文件,然后将其导入并执行功能。
from multiprocessing import Pool
from functools import partial
import inspect
def parallal_task(func, iterable, *params):
with open(f'./tmp_func.py', 'w') as file:
file.write(inspect.getsource(func).replace(func.__name__, "task"))
from tmp_func import task
if __name__ == '__main__':
func = partial(task, params)
pool = Pool(processes=8)
res = pool.map(func, iterable)
pool.close()
return res
else:
raise "Not in Jupyter Notebook"
然后我们可以像这样在笔记本电脑中简单地调用它:
def long_running_task(params, id):
# Heavy job here
return params, id
data_list = range(8)
for res in parallal_task(long_running_task, data_list, "a", 1, "b"):
print(res)
输出:
('a', 1, 'b') 0
('a', 1, 'b') 1
('a', 1, 'b') 2
('a', 1, 'b') 3
('a', 1, 'b') 4
('a', 1, 'b') 5
('a', 1, 'b') 6
('a', 1, 'b') 7
注意:如果您正在使用Anaconda,并且想要查看繁重的任务进度,则可以在print()
内使用long_running_task()
。打印的内容将显示在Anaconda Prompt控制台中。
答案 2 :(得分:1)
为处理让多进程在Jupyter会话中正常运行的许多怪癖,我创建了一个库mpify
,该库允许一次性执行多进程功能,并使用一个将内容从笔记本传递给子进程的函数。简单的API。
Jupyter Shell进程本身可以作为工作进程参与。用户可以选择从所有工作者或其中之一收集结果。
这里是:
https://github.com/philtrade/mpify
在后台,它使用multiprocess
(来自标准python multiprocessing
库的受积极支持的派生)允许子集中可访问笔记本中本地定义的变量/函数。它还使用spawn
启动方法,如果子进程要使用多个GPU,这是越来越普遍的用例,这是必需的。它使用Process()
API中的Pool()
而不是multiprocess
。
用户可以提供一个自定义上下文管理器来获取资源,设置/拆卸函数执行周围的执行环境。我提供了一个示例上下文管理器来支持PyTorch的分布式数据并行(DDP)设置,并提供了更多示例,介绍了如何使用DDP在Jupyter中的多个GPU上训练fastai v2
。
欢迎查看错误报告,PR,用例共享。
绝不是一个花哨的/功能强大的库,mpify
仅打算支持单主机/多进程类型的分布式设置,而只是生成-执行-终止。它也不支持持久的进程池和精美的任务调度-ipyparallel
或dask
已经做到了。
我希望它对于那些在Jupyter +多处理以及在使用多GPU方面可能遇到困难的人们很有用。谢谢。
答案 3 :(得分:0)
严格来说,即使添加了 if __name__="__main__"
,Windows Jupyter Notebook 也不支持 Python 多处理。
Windows 10 中的一种解决方法是将 Windows 浏览器与 WSL 中的 Jupyter 服务器连接。
您可以获得与 Linux 相同的体验。
您可以手动设置或参考https://github.com/mszhanyi/gemini
中的脚本