首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >模块中apply()和apply_async()的区别

模块中apply()和apply_async()的区别
EN

Stack Overflow用户
提问于 2018-02-15 12:22:03
回答 1查看 11.9K关注 0票数 7

我目前有一段代码,它产生多个进程,如下所示:

代码语言:javascript
运行
复制
pool = Pool(processes=None)
results = [pool.apply(f, args=(arg1, arg2, arg3)) for arg3 in arg_list]

我的想法是,使用自processes=None以来可用的所有核心,这将把工作分散到不同的核心上。但是,Pool.apply()方法在多处理模块文档中的文档如下:

等效于apply()内置函数。它阻塞直到结果就绪,因此apply_async()更适合并行执行工作。此外,func只在池中的一个工作人员中执行。

第一个问题:,我不清楚这一点。apply是如何在工人之间分配工作的,在什么方面与apply_async的工作有什么不同?如果任务分布在工人之间,那么func怎么可能只在其中一个工作人员中执行?

我的猜测:我的猜测是,在我当前的实现中,apply给一个具有特定参数集的工作人员一个任务,然后等待完成该工作人员,然后将下一组参数提供给另一个工作人员。通过这种方式,我将工作发送到不同的进程,但是没有并行性发生。情况似乎是这样的,因为apply实际上只是:

代码语言:javascript
运行
复制
def apply(self, func, args=(), kwds={}):
    '''
    Equivalent of `func(*args, **kwds)`.
    Pool must be running.
    '''
    return self.apply_async(func, args, kwds).get()

第二个问题:我也想更好地理解为什么,在文档的介绍中,第16.6.1.5节。(“使用员工池”),他们说,即使是使用apply_async的构造,如[pool.apply_async(os.getpid, ()) for i in range(4)],也可能使用更多的进程,但不确定它是否会使用。决定是否使用多个进程?

EN

回答 1

Stack Overflow用户

发布于 2018-02-15 13:01:26

您已经指出了Python2.7文档,因此我将以Python2.7多处理实现为基础。它在Python3.X上可能有所不同,但不应该有太大的不同。

applyapply_async的区别

这两者之间的区别实际上是自我描述的,当您查看它们是如何在下面实现的。在这里,我将从multiprocessing/pool.py复制/粘贴用于机器人功能的代码。

代码语言:javascript
运行
复制
def apply(self, func, args=(), kwds={}):
    '''
    Equivalent of `apply()` builtin
    '''
    assert self._state == RUN
    return self.apply_async(func, args, kwds).get()

如您所见,apply实际上正在调用apply_async,但在返回结果之前,调用了get。这基本上会导致apply_async块,直到返回结果为止。

代码语言:javascript
运行
复制
def apply_async(self, func, args=(), kwds={}, callback=None):
    '''
    Asynchronous equivalent of `apply()` builtin
    '''
    assert self._state == RUN
    result = ApplyResult(self._cache, callback)
    self._taskqueue.put(([(result._job, None, func, args, kwds)], None))
    return result

apply_async在任务队列中对任务进行排队,并返回已提交任务的handle。使用该handle,您可以分别调用getwait来获取结果或等待任务完成。任务完成后,它返回的内容将作为参数传递给callback函数。

示例:

代码语言:javascript
运行
复制
from multiprocessing import Pool
from time import sleep


def callback(a):
    print a


def worker(i, n):
    print 'Entering worker ', i
    sleep(n)
    print 'Exiting worker'
    return 'worker_response'


if __name__ == '__main__':
    pool = Pool(4)
    a = [pool.apply_async(worker, (i, 4), callback=callback) for i in range(8)]
    for i in a:
        i.wait()

结果:

代码语言:javascript
运行
复制
Entering worker  0
Entering worker  1
Entering worker  2
Entering worker  3
Exiting worker
Exiting worker
Exiting worker
Exiting worker
Entering worker  4
Entering worker  5
worker_response
Entering worker  6
worker_response
Entering worker  7
worker_response
worker_response
Exiting worker
Exiting worker
Exiting worker
Exiting worker
worker_response
worker_response
worker_response
worker_response

注意,在使用apply_async时,您必须等待结果或等待任务完成。如果您没有注释我的示例的最后2行,您的脚本将在运行它之后立即完成。

为什么apply_async可能使用更多的进程

我理解apply是如何描述和工作的。由于apply按任务运行,将其发送到Pool中的可用进程,因此apply_async将任务添加到队列中,然后任务队列线程将其发送到Pool中的可用进程。这就是为什么在使用apply_async时可能运行多个进程的原因。

为了更好地理解作者试图传达的想法,我多次浏览了部分。让我们在这里检查一下:

代码语言:javascript
运行
复制
# evaluate "os.getpid()" asynchronously
res = pool.apply_async(os.getpid, ()) # runs in *only* one process
print res.get(timeout=1)              # prints the PID of that process

# launching multiple evaluations asynchronously *may* use more processes
multiple_results = [pool.apply_async(os.getpid, ()) for i in range(4)]
print [res.get(timeout=1) for res in multiple_results]

如果我们试图通过查看前一个示例来理解最后一个示例,那么当您连续多次调用apply_async时,可能会同时运行更多的。这可能取决于当时在Pool中使用了多少进程。这就是为什么人们说五月份

票数 10
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/48807196

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档