Python多处理无法产生预期的速度提升

Python多处理无法产生预期的速度提升,python,performance,python-multiprocessing,Python,Performance,Python Multiprocessing,我试图使用Python的多处理.Pool模块优化我的代码,但我没有得到逻辑上预期的加速效果 我正在做的主要方法是计算大量向量和固定的大型稀疏矩阵的矩阵向量积。下面是一个玩具示例,它执行我需要的操作,但使用随机矩阵 import time import numpy as np import scipy.sparse as sp def calculate(vector, matrix = None): for i in range(50): v = matrix.dot(

我试图使用Python的
多处理.Pool
模块优化我的代码,但我没有得到逻辑上预期的加速效果

我正在做的主要方法是计算大量向量和固定的大型稀疏矩阵的矩阵向量积。下面是一个玩具示例,它执行我需要的操作,但使用随机矩阵

import time
import numpy as np
import scipy.sparse as sp

def calculate(vector, matrix = None):
    for i in range(50):
        v = matrix.dot(vector)
    return v

if __name__ == '__main__':
    N = 1e6
    matrix = sp.rand(N, N, density = 1e-5, format = 'csr')
    t = time.time()
    res = []
    for i in range(10):
        res.append(calculate(np.random.rand(N), matrix = matrix))    
    print time.time() - t
该方法在大约
30
秒后终止

现在,由于
结果的每个元素的计算不依赖于任何其他计算的结果,因此很自然地认为并行计算将加速该过程。我们的想法是创建4个进程,如果每个进程都进行一些计算,那么所有进程完成所需的时间应该减少大约
4
。为此,我编写了以下代码:

import time
import numpy as np
import scipy.sparse as sp
from multiprocessing import Pool
from functools import partial

def calculate(vector, matrix = None):
    for i in range(50):
        v = matrix.dot(vector)
    return v

if __name__ == '__main__':
    N = 1e6
    matrix = sp.rand(N, N, density = 1e-5, format = 'csr')

    t = time.time()
    input = []
    for i in range(10):
        input.append(np.random.rand(N))
    mp = partial(calculate, matrix = matrix)
    p = Pool(4)
    res = p.map(mp, input)
    print time.time() - t
我的问题是,这段代码的运行时间略高于
20
秒,因此我甚至没有将性能提高
2
!更糟糕的是,即使池中包含
8个
进程,性能也没有提高!你知道为什么没有加速吗


注意:我的实际方法需要更长的时间,输入向量存储在一个文件中。如果我将文件拆分为
4个
部分,然后手动在单独的进程中为每个文件运行脚本,则每个进程终止的速度是整个文件的四倍(如预期)。我不明白为什么在
multiprocessing.Pool


Edi:我刚刚发现了这个可能相关的问题。不过我必须检查一下。

试试:

p = Pool(4)
for i in range(10):
    input = np.random.rand(N)
    p.apply_async(calculate, args=(input, matrix)) # perform function calculate as new process with arguments input and matrix

p.close()  
p.join() # wait for all processes to complete
我怀疑“部分”对象和贴图会导致阻塞行为。(虽然我从未使用过partial,但我对它并不熟悉。)

“apply_async”(或“map_async”)是专门不阻塞的多处理方法—(请参阅:)

一般来说,对于像这样的“令人尴尬的并行问题”,apply_async对我来说是可行的

编辑:


我倾向于在完成后将结果写入MySQL数据库——如果这不是您的方法,那么我提供的实现就不起作用。如果您想使用列表中的顺序来跟踪哪个条目是哪个条目,那么“映射”可能是正确的答案,但我仍然怀疑“部分”对象。

问题:您运行此操作的系统有多少物理(非超线程)CPU核?@klauds。实际上,我有
4个
内核。这就是为什么我手动将文件拆分为
4
,而不是
8
部分。如果在
calculate
方法中放置一些
time.time()
基准测试,您将看到50个
dot
调用所花费的时间比在非并行情况下长近4倍。我不清楚为什么,因为像
top
这样的工具使得非并行情况下只完全使用了一个CPU,而并行情况下看起来好像有4个CPU被完全使用了。@AmitKumarGupta确实,当我使用多个进程时,
numpy
似乎发生了一些奇怪的事情。我们可以从等式和基准中提取
numpy
。这里有一个pastebin,它具有并行和串行实现,只需执行一系列算术:。为了使它们更相似,series版本使用内置的
map
与并行情况下的
p.map
进行对比。在我的机器上(有4个CPU),系列机箱每次计算大约需要
1.8s
,总共大约
22.8s
。1-4名工人的平行案例每次计算的平均时间分别为
1.75s
2.6s
2.6s
3.3s
,总计分别约为
21s
16s
11.0s