我正在尝试并行化脚本,但由于未知原因,内核只是冻结而没有抛出任何错误。
最小工作示例:
from multiprocessing import Pool
def f(x):
return x*x
p = Pool(6)
print(p.map(f, range(10)))
有趣的是,如果我在另一个文件中定义函数然后导入它,一切都会正常工作。我怎样才能让它工作而不需要另一个文件?
我使用spyder(anaconda),如果我从Windows命令行运行我的代码,我会得到相同的结果。
发生这种情况是因为当您的子进程导入时,您没有保护代码的“过程”部分不被重新执行f
.
他们需要进口f
, 因为Windows不支持分叉作为新进程的启动方法(仅spawn)。一个新的Python进程必须从头开始,f
导入并且此导入还将触发在所有子进程中创建另一个池...及其子进程和子进程...
为了防止这种递归,你必须插入一个if __name__ == '__main__':
- 上部部分(应在导入时运行)和下部部分(应仅在脚本作为主脚本执行时运行)之间的行(仅适用于父脚本)。
from multiprocessing import Pool
def f(x):
return x*x
if __name__ == '__main__': # protect your program's entry point
p = Pool(6)
print(p.map(f, range(10)))
当与“spawn”或“forkserver”启动方法而不是默认的“fork”一起使用时,在 Windows 和 Unix-y 系统上进行多处理时,必须如此分离代码。一般来说,启动方法可以修改为multiprocessing.set_start_method(method) https://docs.python.org/3/library/multiprocessing.html#multiprocessing.set_start_method.
Since Python 3.8 https://docs.python.org/3/whatsnew/3.8.html#multiprocessing, macOS还使用“spawn”而不是“fork”作为默认值。
分开通常是一个好习惯any脚本位于上方的“定义”和下方的“作为主执行”,以使代码可导入,而无需执行仅在作为顶级脚本运行时相关的部分。最后但并非最不重要的一点是,当您不混合定义和执行时,它有助于理解程序的控制流。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)