python筆記:multiprocessing 函數apply和apply_async有什麼區別?


直接上結論:

  • apply()apply_async().get()可以說是一樣的,但在處理task上有點不一樣。
  • 使用apply_async().get相對節省時間。

一、爲什麼兩者可以說是一樣的?

首先扯點歷史(鏈接):

在python的幼兒時期,執行帶參數的function是這樣的:

apply(function, args, kwargs)  #   `apply`在`python2.7`裏還有,當然`python3.x`沒有了

現在直接是:

function(*args, **kwargs)

Multiprocessing.Pool模塊就是借鑑了相同的操作定義的函數。

然後再說applyapply_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()
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章