Anu*_*ush 5 python python-multiprocessing
我第一次尝试使用多处理。所以我想我会做一个非常简单的测试示例,它可以分解 100 个不同的数字。
from multiprocessing import Pool
from primefac import factorint
N = 10**30
L = range(N,N + 100)
pool = Pool()
pool.map(factorint, L)
Run Code Online (Sandbox Code Playgroud)
这给了我错误:
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
Run Code Online (Sandbox Code Playgroud)
我看到Python 进程池非守护进程?讨论了这个问题,但我不明白为什么它与我的简单玩具示例相关。我究竟做错了什么?
问题似乎是primefac使用它自己的multiprocessing.Pool. 不幸的是,当 PyPI 宕机时,我找不到模块的源代码——但我确实在 GitHub 上找到了各种分支,比如这个,它们都有multiprocessing代码。
因此,您看似简单的示例并不是那么简单——因为它正在导入和运行非简单代码。
默认情况下,所有Pool进程都是守护进程,因此您无法从另一个Pool. 通常,尝试这样做是错误的。
如果您确实想要多处理这些因素,即使其中一些因素要多处理他们自己的工作(很可能会在不添加任何并行性的情况下增加更多的争用开销),那么您只需要子类化Pool并覆盖它——如相关问题中所述你链接的。
但最简单的事情就是不要multiprocessing在这里使用,如果primefac已经在有效地使用您的内核。(如果您需要准并发,在它们进来时获得答案而不是按顺序获得它们,我想您可以使用线程池来做到这一点,但我认为这里没有任何优势 - 您没有使用imap_unordered或AsyncResult在任何地方明确。)
或者,如果它大部分时间没有使用您的所有内核,仅在分解一些数字结束时为“棘手的余数”这样做,而您有 7 个内核闲置了 60% 的时间……那么您可能想完全阻止primefac使用multiprocessing。我不知道该模块是否具有用于执行此操作的公共 API。如果是这样,当然,只需使用它。如果不是……好吧,您可能必须对它的某些代码进行子类化或猴子修补,或者,最坏的情况是,猴子修补其导入的multiprocessing,这可能不值得这样做。
在理想的解决方案可能会进行重构primefac,推动了“棘手剩女”的工作在你已经使用同一个池。但这可能是迄今为止最多的工作,而不是更多的好处。
附带说明一下,这不是您的问题,但是您应该对__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)
Run Code Online (Sandbox Code Playgroud)
否则,当使用spawn或forkserverstart 方法运行时——请注意,这spawn是 Windows 上唯一可用的方法——每个池进程将尝试创建另一个子池。所以,如果你在 Windows 上运行你的代码,你会得到同样的断言——作为一种multiprocessing保护你免受意外 forkbombing 你的系统的方法。
这在文档的“编程指南”部分中的主模块的安全导入下进行了解释multiprocessing。
| 归档时间: |
|
| 查看次数: |
7245 次 |
| 最近记录: |