5

我正在尝试使用 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

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

我的问题是这段代码的运行时间略高于20几秒钟,所以我什至没有将性能提高一倍2!更糟糕的是,即使池中包含进程,性能也没有提高!8知道为什么没有发生加速吗?


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


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

4

1 回答 1

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

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

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

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

编辑:

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

于 2015-01-05T22:38:59.863 回答