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

  • 先上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()

你可能感兴趣的:(python并行处理)