为什么我的并行代码比顺序代码慢

时间:2018-03-08 12:59:26

标签: python python-3.x parallel-processing multiprocessing

我正在尝试实现一种高度可并行化的在线递归并行算法。我的问题是我的python实现不能正常工作。我有两个2D矩阵,我希望每次在时间步t观察到新观察时,每列都递归更新。 我的并行代码就像这样

def apply_async(t):
    worker =  mp.Pool(processes = 4)
    for i in range(4):
        X[:,i,np.newaxis], b[:,i,np.newaxis] =  worker.apply_async(OULtraining, args=(train[t,i], X[:,i,np.newaxis], b[:,i,np.newaxis])).get()


    worker.close()
    worker.join()      




for t in range(p,T):
    count = 0 
    for l in range(p):
        for k in range(4):
            gn[count]=train[t-l-1,k]
            count+=1
    G = G*v +  gn @ gn.T
    Gt = (1/(t-p+1))*G

    if __name__ == '__main__':
        apply_async(t)

两个矩阵是X和b。我想直接替换master的内存,因为每个进程只递归更新矩阵的一个特定列。

为什么这个实现比顺序慢?

有没有办法在每个时间步骤恢复这个过程而不是杀死它们并再次创建它们?这可能是它变慢的原因吗?

1 个答案:

答案 0 :(得分:1)

原因是,您的程序在实践中是顺序的。这是一个示例代码片段,它与您的并行性立场相同:

from multiprocessing import Pool
from time import sleep

def gwork( qq):
    print (qq)
    sleep(1)
    return 42

p = Pool(processes=4)

for q in range(1, 10):
    p.apply_async(gwork, args=(q,)).get()
p.close()
p.join()

运行此选项,您会注意到数字1-9恰好出现在一秒钟内。为什么是这样?原因是你.get()。这意味着每次调用apply_async都会在get()中实际阻止,直到结果可用。它将提交一个任务,等待一秒仿真处理延迟,然后返回结果,之后将另一个任务提交给您的池。这意味着根本没有并行执行。

尝试用以下方法替换池管理部分:

results = []
for q in range(1, 10):
    res = p.apply_async(gwork, args=(q,))
    results.append(res)
p.close()
p.join()
for r in results:
    print (r.get())

您现在可以看到并行性,因为现在可以同时处理四个任务。你的循环不会阻塞get,因为get被移出循环,结果仅在它们准备好时才被接收。

注意:如果你的工作者的参数或它们的返回值是大数据结构,你将失去一些性能。实际上,Python将这些实现为队列,并且相对于在子进程分叉时获取数据结构的内存中副本而相对而言,通过队列传输大量数据的速度很慢。