使用Pool进行Python多处理 - 主要过程需要永远

时间:2017-05-03 23:23:06

标签: python multiprocessing

我试图理解多处理如何与Python一起工作。这是我的测试代码:

import numpy as np
import multiprocessing
import time

def worker(a):
    for i in range(len(a)):
        for j in arr2:
            a[i] = a[i]*j
    return len(a)

arr2 = np.random.rand(10000).tolist()

if __name__ == '__main__':
    multiprocessing.freeze_support()
    cores = multiprocessing.cpu_count()
    arr1 = np.random.rand(1000000).tolist()
    tmp = time.time()
    pool = multiprocessing.Pool(processes=cores)
    result = pool.map(worker, [arr1], chunksize=1000000/(cores-1))
    print "mp time", time.time()-tmp

我有8个核心。它通常最终只有大约一秒使用〜3%的CPU的7个进程,最后一个进程永远使用~1 / 8的CPU ...(它已经运行了大约15分钟)

据我所知,进程间通信通常会限制并行编程的复杂性,但它通常需要这么长时间吗?还有什么可能导致最后一个过程永远消失?

这个帖子:Python multiprocessing never joins似乎解决了类似的问题,但它没有解决Pool的问题。

2 个答案:

答案 0 :(得分:1)

看起来你想把工作分成几块。您可以使用范围功能对数据进行分区。在Linux上,分叉进程获得父内存的写时复制视图,因此您可以传递您想要处理的索引。在Windows上,没有这样的运气。您需要传入每个子列表。这个程序应该这样做

import numpy as np
import multiprocessing
import time
import platform

def worker(a):
    if platform.system() == "Linux":
        # on linux we passed in start:len
        start, length = a
        a = arr1[start:length]
    for i in range(len(a)):
        for j in arr2:
            a[i] = a[i]*j
    return len(a)

arr2 = np.random.rand(10000).tolist()

if __name__ == '__main__':
    multiprocessing.freeze_support()
    cores = multiprocessing.cpu_count()
    arr1 = np.random.rand(1000000).tolist()
    tmp = time.time()
    pool = multiprocessing.Pool(processes=cores)
    chunk = (len(arr1)+cores-1)//cores
    # on Windows, pass the sublist, on linux just the indexes and let the
    # worker split from the view of parent memory space
    if platform.system() == "Linux":
        seq = [(i, i+chunk) for i in range(0, len(arr1), chunk)]
    else:
        seq = [arr1[i:i+chunk] for i in range(0, len(arr1), chunk)]
    result = pool.map(worker, seq, chunksize=1)
    print "mp time", time.time()-tmp

答案 1 :(得分:0)

你指的是:

pool.map将自动迭代程序中[arr1]的对象。请注意,对象为[arr1]但不是arr1,这意味着您传递给pool.map的对象的长度仅为一个

我认为最简单的解决方案是将[arr1]替换为arr1