所以我以为我终于发帖了;管理Process
工人的正确方法是什么?我曾尝试使用Pool
,但我发现无法获得每个已完成流程的返回值。我尝试使用回调,但这也没有按预期工作。我应该自己使用active_children ()
管理它们吗?
我的泳池代码:
from multiprocessing import *
import time
import random
SOME_LIST = []
def myfunc():
a = random.randint(0,3)
time.sleep(a)
return a
def cb(retval):
SOME_LIST.append(retval)
print("Starting...")
p = Pool(processes=8)
p.apply_async(myfunc, callback=cb)
p.close()
p.join()
print("Stopping...")
print(SOME_LIST)
我期待一个价值清单;但我得到的只是完成工作者工作的最后一项:
$ python multi.py
Starting...
Stopping...
[3]
注意:答案不应该使用threading
模块;这就是为什么:
在CPython中,由于Global Interpreter Lock,只有一个线程可以 一次执行Python代码(即使某些性能导向 图书馆可能会克服这个限制)。如果你想要你的 应用程序,以更好地利用计算资源 多核机器,建议您使用多处理。
答案 0 :(得分:4)
你误解了apply_async
的工作方式。它不会调用您在Pool
中的每个进程中传递给它的函数。它只是在一个工作进程中调用该函数一次。因此,您所看到的结果是可以预期的。您有几种方法可以获得所需的行为:
from multiprocessing import Pool
import time
import random
SOME_LIST = []
def myfunc():
a = random.randint(0,3)
time.sleep(a)
return a
def cb(retval):
SOME_LIST.append(retval)
print("Starting...")
p = Pool(processes=8)
for _ in range(p._processes):
p.apply_async(myfunc, callback=cb)
p.close()
p.join()
print("Stopping...")
print(SOME_LIST)
或者
from multiprocessing import Pool
import time
import random
def myfunc():
a = random.randint(0,3)
time.sleep(a)
return a
print("Starting...")
p = Pool(processes=8)
SOME_LIST = p.map(myfunc, range(p._processes))
p.close()
p.join()
print("Stopping...")
print(SOME_LIST)
请注意,您还可以为更多调用apply_async
或map
,而不是池中的进程数。 Pool
的想法是,无论您提交多少任务,它都会保证num_processes
的整个生命周期内都会运行Pool
个进程。因此,如果您创建一个Pool(8)
并呼叫apply_async
一次,您的八名工作人员中的一名将获得一项任务,而其他七名工作人员将处于闲置状态。如果你创建一个Pool(8)
并调用apply_async
80次,那么80个任务将分发给你的8个工作人员,一次实际处理的任务不超过8个。