我有以下设置:
results = [f(args) for _ in range(10**3)]
但是,f(args)
需要很长时间才能计算出来。所以我想把多处理器扔到它身上。我想这样做:
pool = mp.pool(mp.cpu_count() -1) # mp.cpu_count() -> 8
results = [pool.apply_async(f, args) for _ in range(10**3)]
显然,我的计算机上没有1000个处理器,所以我担心:
以上调用是否导致1000个进程同时竞争CPU时间或7个进程同时运行,在前一个调用结束时迭代计算下一个f(args)
?
我想我可以做pool.async_map(f, (args for _ in range(10**3)))
之类的事情来获得相同的结果,但这篇文章的目的是了解pool.apply_async
的行为
答案 0 :(得分:11)
您的进程中的进程数永远不会超过池中的工作程序(在您的情况下为mp.cpu_count() - 1
。如果您调用apply_async
并且所有工作人员都忙,则任务将排队一旦工人释放,就立即执行。你可以通过一个简单的测试程序看到这个:
#!/usr/bin/python
import time
import multiprocessing as mp
def worker(chunk):
print('working')
time.sleep(10)
return
def main():
pool = mp.Pool(2) # Only two workers
for n in range(0, 8):
pool.apply_async(worker, (n,))
print("called it")
pool.close()
pool.join()
if __name__ == '__main__':
main()
输出如下:
called it
called it
called it
called it
called it
called it
called it
called it
working
working
<delay>
working
working
<delay>
working
working
<delay>
working
working
答案 1 :(得分:6)
工作进程的数量完全由mp.pool()
的参数控制。因此,如果mp.cpu_count()
在您的方框中返回8,则将创建7个工作进程。
所有pool
方法(其中apply_async()
)然后只使用那么多工作进程。在封面下,参数在主程序中被pickle并通过进程间管道发送到工作进程。这个隐藏的机器有效地创建了一个工作队列,固定数量的工作进程从中拉出工作描述(函数名+参数)。
除此之外,它只是魔术; - )