多处理池' apply_async'似乎只调用一次函数

时间:2015-02-09 22:21:59

标签: python multithreading multiprocessing threadpool

我一直在关注文档以尝试理解多处理池。我想出了这个:

import time
from multiprocessing import Pool

def f(a):
    print 'f(' + str(a) + ')'
    return True

t = time.time()
pool = Pool(processes=10)
result = pool.apply_async(f, (1,))
print result.get()
pool.close()
print ' [i] Time elapsed ' + str(time.time() - t)

我尝试使用10个进程来评估函数f(a)。我在f中添加了一份打印声明。

这是我得到的输出:

$ python pooltest.py 
f(1)
True
 [i] Time elapsed 0.0270888805389

在我看来,函数f只被评估一次。

我可能没有使用正确的方法,但我正在寻找的最终结果是同时运行f 10个进程,并获得每个进程返回的结果。所以我最后会得到10个结果的列表(可能相同也可能不相同)。

关于多处理的文档非常混乱,要弄清楚我应该采用哪种方法并不容易,而且在我看来f应该在我上面提供的示例中运行10次。

4 个答案:

答案 0 :(得分:8)

apply_async并不意味着启动多个进程;它只是用于在池的一个进程中使用参数调用该函数。如果你想要调用10次函数,你需要进行10次调用。

首先,请注意apply()上的文档(强调添加):

apply(func[, args[, kwds]])
     

使用参数args和关键字参数kwds调用func。它阻止   直到结果准备好。给定这个块,apply_async()更好   适合并行工作。 另外,func只是   在游泳池的一名工人中执行。

现在,在apply_async()的文档中:

apply_async(func[, args[, kwds[, callback[, error_callback]]]])
     

apply()方法的一种变体,它返回一个结果对象。

两者之间的区别仅在于apply_async立即返回。您可以使用map()多次调用函数,但是如果您使用相同的输入进行调用,那么创建相同参数的列表只需要一个减少量就可以了正确长度的序列。

但是,如果您使用相同的输入调用不同的函数,那么您实际上只是调用更高阶函数,而您可以使用map或{{{ 3}}像这样:

multiprocessing.map(lambda f: f(1), functions)

除了lambda函数不是pickleable之外,所以你需要使用一个已定义的函数(参见map_async())。你实际上可以使用内置的apply()(不是多处理的)(虽然它已被弃用):

multiprocessing.map(apply,[(f,1) for f in functions])

编写自己的内容也很容易:

def apply_(f,*args,**kwargs):
  return f(*args,**kwargs)

multiprocessing.map(apply_,[(f,1) for f in functions])

答案 1 :(得分:3)

每次编写pool.apply_async(...)时,它都会将该函数调用委托给池中启动的其中一个进程。如果要在多个进程中调用该函数,则需要发出多个pool.apply_async调用。

注意,还有一个pool.map(和pool.map_async)函数,它将接受一个函数和一个可迭代的输入:

inputs = range(30)
results = pool.map(f, inputs)

这些函数将函数应用于inputs iterable中的每个输入。它试图将#34;批次"进入池中,以便在池中的所有进程之间相当均匀地均衡负载。

答案 2 :(得分:0)

如果你想在十个进程中运行一段代码,然后每个进程退出,那么十个进程的Pool可能不是正确的使用方法。

相反,创建十个Process es来运行代码:

processes = []

for _ in range(10):
    p = multiprocessing.Process(target=f, args=(1,))
    p.start()
    processes.append(p)

for p in processes:
    p.join()

multiprocessing.Pool类旨在处理进程数和作业数不相关的情况。通常,进程数量选择为您拥有的CPU核心数,而作业数量则要大得多。谢谢!

答案 3 :(得分:-1)

如果您因任何特殊原因没有致力于Pool,我已经编写了一个围绕multiprocessing.Process的函数,它可能会为您提供帮助。它已发布here,但如果您愿意,我很乐意将最新版本上传到github。