直接上結論:
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
- 先上2段來自multiprocessing/pool.py文檔的代碼(借鑑思路的來源鏈接):
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()