替代在多处理中使用Queue作为返回值

时间:2014-04-13 01:24:20

标签: python multithreading numpy

在python多处理中,是否有类似Process.return_value()的东西? 为什么不,有什么选择? (除了使用队列)

背景: 目前,我的代码包含许多像这样的函数,这些函数对大量数据进行操作,这些数据是numpy数组(a,b)

b= f(a)

def f(a):
    # do some work here
    return b

我可以像这样并行化每个函数:

plist=[]
for i in range(ncores):
    p= Process(target=f, args=(a[i::ncores]))
    p.start()
    plist.append(p)

这会使代码的这一部分加速因子ncores。问题是获得返回值:

for i, p in enumerate(plist):
    p.join()
    b[i::ncores]= p.return_value()

我找不到通过p检索返回值的方法。我不明白为什么不可能这样,因为p可以与核心上的进程通信。

现在,我正在使用Queue来获取返回值,但我发现它们有点麻烦:我必须将Queue和一个标识符传递给每个函数并将结果和ID放入队列:

def f(a, Queue=Queue, ID=-1):
    # do some work here
    if ID==-1:
        # normal interface
        return b
    else:
        # parallel interface
        Queue.put([ID, b])

然后当我读出队列时,我必须将ID与原始数组匹配:

for i in range(ncores):
    ID, result= Queue.get()
    b[ID::ncores]= result
    plist[ID].join()

有没有更短的方法来实现这一目标?

我尝试将字典或列表作为关键字传递给结果,这适用于线程,但不适用于多处理。

1 个答案:

答案 0 :(得分:0)

什么是回报值?

如果它是简单的类似数组或数字,您可以将共享内存容器传递给它可以存储其结果的Process实例。如果我们想象你只想在多个进程中求和一个数组:

from multiprocessing import Process,Value
import ctypes as C
import numpy as np

def func(input,output):
    # do something with input                                                         
    # put the result in output                                                        
    output.value = input.sum()

def launch_processes(n):
    outputs = []
    jobs = []
    for ii in range(n):
        input = np.arange(ii)

        # here use a synchronised wrapper to store the result of the func run
        # This can be replaced with an Array instance if an array is returned
        output = Value(C.c_size_t) 

        job = Process(target=func,args=(input,output))
        outputs.append(output)
        jobs.append(job)
        job.start()

    for job in jobs:
        job.join()

    for output in outputs:
        print output.value

launch_processes(10)

执行上述操作的更简洁方法是通过子类化Process将作业封装在单个对象中:

from multiprocessing import Process,Value
import ctypes as C
import numpy as np

class Job(Process):
    def __init__(self,input):
        super(Job,self).__init__()
        self.retval = Value(C.c_size_t)
        self.input = input

    def run(self):
        self.retval.value = self.input.sum()

def launch_processes(n):
    jobs = []
    for ii in range(n):
        job = Job(np.arange(ii))
        job.start()
        jobs.append(job)

    for job in jobs:
        job.join()
        print job.retval.value

launch_processes(10)