multiprocessing gives AssertionError: daemonic processes are not allowed to have children
multiprocessing gives AssertionError: daemonic processes are not allowed to have children
我是第一次尝试使用多处理。所以我想我会做一个非常简单的测试示例,其中包含 100 个不同的数字。
from multiprocessing import Pool
from primefac import factorint
N = 10**30
L = range(N,N + 100)
pool = Pool()
pool.map(factorint, L)
这给了我错误:
Traceback (most recent call last):
File "test.py", line 8, in <module>
pool.map(factorint, L)
File "/usr/lib/python2.7/multiprocessing/pool.py", line 251, in map
return self.map_async(func, iterable, chunksize).get()
File "/usr/lib/python2.7/multiprocessing/pool.py", line 567, in get
raise self._value
AssertionError: daemonic processes are not allowed to have children
我看到 Python Process Pool non-daemonic? 讨论了这个问题,但我不明白为什么它与我的简单玩具示例相关。我做错了什么?
问题似乎是 primefac
使用了它自己的 multiprocessing.Pool
。不幸的是,当 PyPI 关闭时,我找不到模块的源代码——但我确实在 GitHub 上找到了各种分支,比如 this one,它们都有 multiprocessing
代码。
因此,您看似简单的示例并不是那么简单 — 因为它正在导入和 运行 非简单代码。
默认情况下,所有 Pool
进程都是守护进程,因此您无法从另一个 Pool
中创建更多子进程。通常,尝试这样做是错误的。
如果你真的想要多处理这些因素,即使其中一些要多处理他们自己的工作(很可能在不增加任何并行性的情况下增加更多的争用开销),那么你只需要子类化 Pool
并覆盖它——如 the related question that you linked.
中所述
但最简单的事情就是不要在这里使用 multiprocessing
,如果 primefac
已经在有效地使用您的核心。 (如果你需要准并发,在答案进来时得到答案而不是按顺序得到它们,我想你可以用 thread 池来做到这一点,但我认为没有这里的优势——你没有在任何地方使用 imap_unordered
或明确的 AsyncResult
。)
或者,如果它 不是 大部分时间都在使用你的所有内核,那么只在对一些数字进行因式分解后 "tricky remainders" 这样做,而你有 7 个内核在 60% 的时间内处于空闲状态……那么您可能想要完全阻止 primefac
使用 multiprocessing
。我不知道该模块是否有 public API 来执行此操作。如果是这样,当然就使用它。如果不是……好吧,您可能必须对其某些代码进行子类化或猴子修补,或者最坏的情况是,猴子修补其导入的multiprocessing
,这可能不值得这样做。
理想的 解决方案可能是重构 primefac
以将 "tricky remainder" 作业推送到您已经在使用的同一个池中。但这可能是迄今为止最多的工作,并没有更多的好处。
附带说明一下,这不是你的问题,但你应该 __main__
保护你的顶级代码,如下所示:
from multiprocessing import Pool
from primefac import factorint
if __name__ == '__main__':
N = 10**30
L = range(N,N + 100)
pool = Pool()
pool.map(factorint, L)
否则,当 运行 使用 spawn
或 forkserver
启动方法时——请注意 spawn
是 Windows 上唯一可用的启动方法——每个池进程将尝试创建另一个子池。因此,如果您 运行 您在 Windows 上的代码,您将得到相同的断言 — 作为 multiprocessing
保护您免受意外 forkbombing 系统的一种方式。
这在 multiprocessing
文档的 "programming guidelines" 部分的 safe importing of main module 下进行了解释。
我来这里是因为我的单元测试提高了
AssertionError: daemonic processes are not allowed to have children
这是因为我用过multiprocessing
而没有close
和join
pool
正常,在 close
和 join
之后一切正常。
我是第一次尝试使用多处理。所以我想我会做一个非常简单的测试示例,其中包含 100 个不同的数字。
from multiprocessing import Pool
from primefac import factorint
N = 10**30
L = range(N,N + 100)
pool = Pool()
pool.map(factorint, L)
这给了我错误:
Traceback (most recent call last):
File "test.py", line 8, in <module>
pool.map(factorint, L)
File "/usr/lib/python2.7/multiprocessing/pool.py", line 251, in map
return self.map_async(func, iterable, chunksize).get()
File "/usr/lib/python2.7/multiprocessing/pool.py", line 567, in get
raise self._value
AssertionError: daemonic processes are not allowed to have children
我看到 Python Process Pool non-daemonic? 讨论了这个问题,但我不明白为什么它与我的简单玩具示例相关。我做错了什么?
问题似乎是 primefac
使用了它自己的 multiprocessing.Pool
。不幸的是,当 PyPI 关闭时,我找不到模块的源代码——但我确实在 GitHub 上找到了各种分支,比如 this one,它们都有 multiprocessing
代码。
因此,您看似简单的示例并不是那么简单 — 因为它正在导入和 运行 非简单代码。
默认情况下,所有 Pool
进程都是守护进程,因此您无法从另一个 Pool
中创建更多子进程。通常,尝试这样做是错误的。
如果你真的想要多处理这些因素,即使其中一些要多处理他们自己的工作(很可能在不增加任何并行性的情况下增加更多的争用开销),那么你只需要子类化 Pool
并覆盖它——如 the related question that you linked.
但最简单的事情就是不要在这里使用 multiprocessing
,如果 primefac
已经在有效地使用您的核心。 (如果你需要准并发,在答案进来时得到答案而不是按顺序得到它们,我想你可以用 thread 池来做到这一点,但我认为没有这里的优势——你没有在任何地方使用 imap_unordered
或明确的 AsyncResult
。)
或者,如果它 不是 大部分时间都在使用你的所有内核,那么只在对一些数字进行因式分解后 "tricky remainders" 这样做,而你有 7 个内核在 60% 的时间内处于空闲状态……那么您可能想要完全阻止 primefac
使用 multiprocessing
。我不知道该模块是否有 public API 来执行此操作。如果是这样,当然就使用它。如果不是……好吧,您可能必须对其某些代码进行子类化或猴子修补,或者最坏的情况是,猴子修补其导入的multiprocessing
,这可能不值得这样做。
理想的 解决方案可能是重构 primefac
以将 "tricky remainder" 作业推送到您已经在使用的同一个池中。但这可能是迄今为止最多的工作,并没有更多的好处。
附带说明一下,这不是你的问题,但你应该 __main__
保护你的顶级代码,如下所示:
from multiprocessing import Pool
from primefac import factorint
if __name__ == '__main__':
N = 10**30
L = range(N,N + 100)
pool = Pool()
pool.map(factorint, L)
否则,当 运行 使用 spawn
或 forkserver
启动方法时——请注意 spawn
是 Windows 上唯一可用的启动方法——每个池进程将尝试创建另一个子池。因此,如果您 运行 您在 Windows 上的代码,您将得到相同的断言 — 作为 multiprocessing
保护您免受意外 forkbombing 系统的一种方式。
这在 multiprocessing
文档的 "programming guidelines" 部分的 safe importing of main module 下进行了解释。
我来这里是因为我的单元测试提高了
AssertionError: daemonic processes are not allowed to have children
这是因为我用过multiprocessing
而没有close
和join
pool
正常,在 close
和 join
之后一切正常。