[英]Multiprocessing pool 'apply_async' only seems to call function once
我一直在关注文档以尝试理解多处理池。 我想出了这个:
import time
from multiprocessing import Pool
def f(a):
print 'f(' + str(a) + ')'
return True
t = time.time()
pool = Pool(processes=10)
result = pool.apply_async(f, (1,))
print result.get()
pool.close()
print ' [i] Time elapsed ' + str(time.time() - t)
我正在尝试使用10个进程来评估函数f(a)
。 我在f
了一个打印声明。
这是我得到的输出:
$ python pooltest.py
f(1)
True
[i] Time elapsed 0.0270888805389
在我看来,函数f
只被评估一次。
我可能没有使用正确的方法,但我正在寻找的最终结果是同时运行f
10个进程,并获得每个进程返回的结果。 所以我最后会列出10个结果(可能相同也可能不相同)。
关于多处理的文档非常令人困惑,要弄清楚我应该采用哪种方法并不容易,而且在我看来f
应该在我上面提供的示例中运行10次。
apply_async并不意味着启动多个进程; 它只是用于在池的一个进程中使用参数调用该函数。 如果要将函数调用10次,则需要进行10次调用。
首先,请注意apply()
上的文档(强调添加):
apply(func[, args[, kwds]])
使用参数args和关键字参数kwds调用func。 它会阻塞,直到结果准备就绪。 给定此块,apply_async()更适合并行执行工作。 此外,func仅在池中的一个工作程序中执行。
现在,在apply_async()
的文档中:
apply_async(func[, args[, kwds[, callback[, error_callback]]]])
apply()方法的一种变体,它返回一个结果对象。
两者之间的区别仅在于apply_async立即返回。 您可以使用map()
多次调用函数,但是如果您使用相同的输入进行调用,那么创建相同参数的列表只是为了获得正确长度的序列,这是一个小的减少。
但是,如果您使用相同的输入调用不同的函数,那么您实际上只是调用更高阶函数,并且可以使用map
或map_async()
此操作:
multiprocessing.map(lambda f: f(1), functions)
除了lambda函数不是pickleable之外,所以你需要使用一个已定义的函数(参见如何让Pool.map获取lambda函数 )。 你实际上可以使用内置的apply()
(而不是多处理的)(尽管它已被弃用):
multiprocessing.map(apply,[(f,1) for f in functions])
编写自己的也很容易:
def apply_(f,*args,**kwargs):
return f(*args,**kwargs)
multiprocessing.map(apply_,[(f,1) for f in functions])
每次编写pool.apply_async(...)
它都会将该函数调用委托给池中启动的其中一个进程。 如果要在多个进程中调用该函数,则需要发出多个pool.apply_async
调用。
注意,还有一个pool.map
(和pool.map_async
)函数,它将接受一个函数和一个可迭代的输入:
inputs = range(30)
results = pool.map(f, inputs)
这些函数将函数应用于inputs
iterable中的每个输入。 它尝试将“批处理”放入池中,以便负载在池中的所有进程之间相当均衡。
如果要在十个进程中运行单个代码,然后每个进程退出,则十个进程Pool
可能不是正确的使用方法。
相反,创建十个Process
es来运行代码:
processes = []
for _ in range(10):
p = multiprocessing.Process(target=f, args=(1,))
p.start()
processes.append(p)
for p in processes:
p.join()
multiprocessing.Pool
类旨在处理进程数和作业数不相关的情况。 通常,进程数量选择为您拥有的CPU核心数,而作业数量则要大得多。 谢谢!
如果你因为任何特殊原因没有致力于Pool,我已经编写了一个围绕multiprocessing.Process的函数,它可能会为你提供帮助。 它发布在这里 ,但如果你需要,我很乐意将最新版本上传到github。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.