为什么在使用joblib.Parallel时保护主循环很重要?

2024-05-15 11:35:51 发布

您现在位置:Python中文网/ 问答频道 /正文

joblib文档包含以下警告:

Under Windows, it is important to protect the main loop of code to avoid recursive spawning of subprocesses when using joblib.Parallel. In other words, you should be writing code like this:

import ....

def function1(...):
    ...

def function2(...):
    ...

... if __name__ == '__main__':
    # do stuff with imports and functions defined about
    ...

No code should run outside of the “if __name__ == ‘__main__’” blocks, only imports and definitions.

最初,我假设这只是为了防止偶尔出现的奇怪情况,即传递给joblib.Parallel的函数递归地调用模块,这意味着这通常是一种好的做法,但通常是不必要的。然而,我不明白为什么这只会对Windows造成风险。另外,this answer似乎表明,保护主循环的失败导致代码的运行速度比一个非常简单的非递归问题的运行速度慢几倍。

出于好奇,我从joblib文档运行了一个超级简单的并行循环示例,但没有保护windows框上的主循环。在我关闭终端之前,我的终端收到垃圾邮件,并出现以下错误:

ImportError: [joblib] Attempting to do parallel computing without protecting your import on a system that does not suppo
rt forking. To use parallel-computing in a script, you must protect you main loop using "if __name__ == '__main__'". Ple
ase see the joblib documentation on Parallel for more information

我的问题是,对于joblib的windows实现,在任何情况下都需要保护主循环呢?

如果这是一个非常基本的问题,请道歉。我对并行化还不太熟悉,所以我可能遗漏了一些基本概念,但是我在任何地方都找不到这个问题的明确讨论。

最后,我想指出,这纯粹是学术性的;我理解为什么用这种方式编写代码是generally good practice,并且将继续这样做,而不考虑joblib。


Tags: ofthetoname文档loopyouif
1条回答
网友
1楼 · 发布于 2024-05-15 11:35:51

这是必要的,因为Windows没有fork()。由于这个限制,Windows需要在它生成的所有子进程中重新导入__main__模块,以便在子进程中重新创建父进程的状态。这意味着,如果您有在模块级生成新进程的代码,那么它将在所有子进程中递归执行。if __name__ == "__main__"保护用于防止在子进程中重新执行模块作用域中的代码。

这在Linux上是不必要的,因为它有fork(),这允许它派生一个保持父进程相同状态的子进程,而无需重新导入__main__模块。

相关问题 更多 >