Python多处理不会产生预期的加速

5xu*_*xum 5 python performance python-multiprocessing

我正在尝试使用Python的multiprocessing.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
Run Code Online (Sandbox Code Playgroud)

该方法在大约30几秒钟内终止.

现在,由于每个元素的计算results不依赖于任何其他计算的结果,因此很自然地认为并行计算将加速该过程.我们的想法是创建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
Run Code Online (Sandbox Code Playgroud)

我的问题是这段代码需要稍微超过20秒才能运行,所以我甚至没有提高性能2!更糟糕的是,即使池包含进程,性能也不会提高8!知道加速没有发生的原因吗?


注意:我的实际方法需要更长的时间,输入向量存储在一个文件中.如果我将文件分成4几部分,然后在一个单独的进程中为每个文件手动运行我的脚本,则每个进程的终止速度是整个文件的四倍(如预期的那样).我很困惑为什么这种加速(显然是可能的)没有发生multiprocessing.Pool


Edi:我刚刚发现了Multiprocessing.Pool使Numpy矩阵乘法慢了这个问题可能是相关的.不过我必须检查一下.

cod*_*key 0

尝试:

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
Run Code Online (Sandbox Code Playgroud)

我怀疑“部分”对象和地图导致了阻塞行为。(虽然我从来没有使用过partial,所以我不熟悉它。)

“apply_async”(或“map_async”)是专门不会阻塞的多处理方法 - (请参阅:Python multiprocessing.Pool:何时使用 apply、apply_async 或 map?

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

编辑:

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