multiprocessing.Pool() 的意外表现

Unexpected performance of multiprocessing.Pool()

我发现 multiprocessing.Pool() 在下面的案例中没有按预期运行。任何人都可以解释为什么它的行为方式以及如何在可能的情况下提高性能。以下是简单的代码:

import numpy as np
import multiprocessing  
from itertools import repeat

def group_data_by_runID(args):
    data, runID = args
    return data[data[:,0].astype(int)==runID,:]

%%time
DATA = np.array([[0,1],[0,2],[0,3],[0,4],[1,5],[1,6],[1,7],[1,8],[2,9],[2,10],[2,11],[2,12]])
runIDs = [0,1,2]*10000000
pool = multiprocessing.Pool(40)
list(pool.map(group_data_by_runID, zip(repeat(DATA), runIDs)))

正如您在上面的代码中看到的那样,我打算使用 40 个内核(56 个内核,并且在这个系统上可用的内存远远超过足够多)到 运行 代码,它花了 1 分钟 31 秒。然后我用了:

list(map(group_data_by_runID, zip(repeat(DATA), runIDs)))

用了2分33秒。所以使用 40 个内核的性能又只不到两倍的性能,这对我来说很奇怪。我还注意到,即使我有 40 个内核,它有时也不会像在 htop 中看到的那样实际以 40 个内核启动它。

我哪里做错了?我怎样才能提高速度。请注意,实际数据要大得多。

可能还有很多人和我一样对python中的multiprocessing性能一头雾水。有时您可能会获得性能提升,有时您甚至可能会获得更差的性能。因此,我决定根据我自己的多处理经验自己回答这个问题。

如果您的输入数据很大,使用多处理可能会产生开销,因为这些数据将被复制并通过网络发送到不同的进程,如 juanpa 上面评论的那样。这种开销可能非常大。然而,我们仍然可以通过将输入数据分成小块并让每个进程处理每个块来获得巨大的性能提升。

另一个可以显着提高性能的场景是没有输入数据。比如从几十上百个文件中读取数据。

虽然multiprocessing可以提升速度,但大部分精力还是花在了算法本身,这可能从根本上决定了代码的效率。