我正在尝试第一次使用多重处理。所以我想我会做一个非常简单的测试示例,将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?讨论了这个问题,但我不明白为什么它与我的简单玩具示例有关。我在做什么错了?
答案 0 :(得分:2)
问题似乎是primefac
使用了自己的multiprocessing.Pool
。不幸的是,当PyPI崩溃时,我找不到该模块的源代码,但是我确实在GitHub上找到了各种分支,例如this one,它们都具有multiprocessing
代码。
因此,您看似简单的示例并不是那么简单,因为它正在导入并运行非简单代码。
默认情况下,所有Pool
进程都是守护进程,因此您不能从另一个Pool
内部创建更多子进程。通常,尝试这样做是错误的。
如果您确实想对这些因素进行多处理,即使其中一些因素要对自己的工作进行多处理(可能会增加更多争用开销而又不增加任何并行性),那么您只需将Pool
子类化并覆盖如the related question that you linked所述。
但是最简单的事情是,如果multiprocessing
已经在有效地使用您的内核,那就不要在这里使用primefac
。 (如果您需要准并发性,而不是按顺序获取答案,我想您可以使用 thread 池来做到,但我认为这样做没有任何好处此处-您不在任何地方使用imap_unordered
或显式AsyncResult
。)
或者,如果大多数情况下不都使用所有内核,那么在考虑到一些数字后,仅对“微不足道的剩余”这样做,而您有7个内核空闲60%的时间...那么您可能想完全禁止primefac
使用multiprocessing
。我不知道该模块是否具有用于执行此操作的公共API。如果是这样,当然可以使用它。如果没有,那么,您可能必须对其某些代码进行子类化或monkeypatch,或者更糟糕的是,对multiprocessing
的导入进行monkeypatching,这可能是不值得的。
理想的解决方案可能是重构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)
否则,当使用spawn
或forkserver
启动方法运行时,请注意spawn
是Windows上唯一可用的方法,每个池进程将尝试创建另一个池。孩子们。因此,如果您在Windows上运行代码,您将得到相同的断言—作为multiprocessing
的一种保护您免于意外破坏系统的方法。
multiprocessing
文档的“编程准则”部分的safe importing of main module下对此进行了解释。
答案 1 :(得分:0)
我来这里是因为我的单元测试提高了
#Set number value
number = 2
#Check closest object
def total_num(number):
total = 0 #declare total variable here instead.
while number % 2 == 0 and number <=20:
total = total + number
number = number + 2
print('The total is {}'.format(total)) #Modify to display the total
return total #Do not remove this line
#Do not remove the next line
total_num(number)
这是因为我使用过AssertionError: daemonic processes are not allowed to have children
而没有使用multiprocessing
和close
join
正确,在pool
和close
之后,现在一切都很好了。