我目前有一段代码,它产生多个进程,如下所示:
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实际上只是:
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)],也可能使用更多的进程,但不确定它是否会使用。决定是否使用多个进程?
发布于 2018-02-15 13:01:26
您已经指出了Python2.7文档,因此我将以Python2.7多处理实现为基础。它在Python3.X上可能有所不同,但不应该有太大的不同。
apply与apply_async的区别
这两者之间的区别实际上是自我描述的,当您查看它们是如何在下面实现的。在这里,我将从multiprocessing/pool.py复制/粘贴用于机器人功能的代码。
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块,直到返回结果为止。
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 resultapply_async在任务队列中对任务进行排队,并返回已提交任务的handle。使用该handle,您可以分别调用get或wait来获取结果或等待任务完成。任务完成后,它返回的内容将作为参数传递给callback函数。
示例:
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()结果:
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时可能运行多个进程的原因。
为了更好地理解作者试图传达的想法,我多次浏览了这部分。让我们在这里检查一下:
# 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中使用了多少进程。这就是为什么人们说五月份。
https://stackoverflow.com/questions/48807196
复制相似问题