我正在尝试并行化脚本,但由于未知原因,内核只是冻结而没有抛出任何错误。
最小的工作范例:
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不支持forking作为新进程的启动方法(仅生成)。必须从头开始新的Python进程,导入f
,此导入还将触发在所有子进程中创建另一个池......以及它们的子进程及其子进程。
要防止这种递归,您必须在上部(应该在导入上运行)和下部之间插入一个if __name__ == '__main__':
-line,它应该只在脚本作为主脚本执行时运行(仅适用于父脚本)。
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)))
当使用'forkserver'start-method而不是默认的'fork'时,在Windows和Unix-y系统上进行多处理是必需的。
一般来说,将上层“定义”中的任何脚本分开并将“执行作为主”分开是一种很好的做法,以使代码可导入而无需执行部分仅在作为顶级脚本运行时相关的部分。最后但同样重要的是,当您不混合定义和执行时,它有助于理解程序的控制流程。