直接上结论:
apply()
和apply_async().get()
可以说是一样的,但在处理task
上有点不一样。apply_async().get
相对节省时间。首先扯点历史(链接):
在python的幼儿时期,执行带参数的
function
是这样的:apply(function, args, kwargs) # `apply`在`python2.7`里还有,当然`python3.x`没有了
现在直接是:
function(*args, **kwargs)
Multiprocessing.Pool模块就是借鉴了相同的操作定义的函数。
然后再说apply
和apply_async
def apply(self, func, args=(), kwds={}):
"""
Equivalent of `func(*args, **kwds)`. # 相当于内置的apply()
"""
assert self._state == RUN
return self.apply_async(func, args, kwds).get()
def apply_async(self, func, args=(), kwds={}, callback=None, error_callback=None):
"""
Asynchronous equivalent of `apply()` method.
"""
assert self._state == RUN
result = ApplyResult(self._cache, callback)
self._taskqueue.put(([(result._job, 0, func, args, kwds)], None))
return result
综上:从文档可以很直观的看到,pool.apply(func, args, kwds)
等价于pool.apply_async(func, args, kwds).get()
。
task
上有什么不一样?这牵扯到apply
是 什么 & 怎么运行的。因为在跑多个task的时候,apply
是一个接一个地分配到可用的Pool
,而apply_async
是一股脑放到队列里、然后由负责该队列的一个thread把它们分配到可用的Pool
。所以使用apply_async
可能存在不止1个process在运行。
举个栗子:
import os
from multiprocessing.pool import Pool
if __name__ == '__main__': # 不限定的话,程序会重复导入__main__,
pool = Pool(processes=8) # 8核CPU
# 异步启动 `os.getpid()`
res = pool.apply_async(os.getpid, ()) # 仅在1个process汇总运行
print(res.get(timeout=1)) # 显示该process的ID
# 异步启动多个`os.getpid()`“可能”有多个有多个process参与运行
mul_results = [pool.apply_async(os.getpid, (()) for i in range(4)]
print([res.get(timeout=1) for res in mul_results])
print([pool.apply(os.getpid, ()) for i in range(4)])
# 结果如下
10508
[10924, 10884, 10384, 5048]
[10904, 10508, 10924, 10884]
apply_async().get()
比apply()
稍快些呢?实际就是这样。原因暂时没找到。
手头一个的任务,使用
from multiprocessing.pool import Pool, ThreadPool
# 似乎下边2种功能一模一样,实际使用起来没区别:
# from multiprocessing import Pool 和 from multiprocessing.pool import Pool
if __name__ == '__main__':
""" 耗时32 s"""
pool =Pool(processes = 8)
a = pool.apply(func, ())
""" 耗时28s"""
pool =Pool(processes = 8)
a = pool.apply_async(func, ()).get()
""" 耗时25s"""
pool =ThreadPool(processes = 8)
a = pool.apply(func, ())
""" 耗时23s"""
pool =ThreadPool(processes = 8)
a = pool.apply_async(func, ()).get()