带池的Python多处理—主进程需要花费很长时间

带池的Python多处理—主进程需要花费很长时间,python,multiprocessing,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_

我试图理解多处理是如何与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个核。它通常以7个进程结束,仅占用约3%的CPU约1秒钟,最后一个进程永远占用约1/8的CPU…它已运行约15分钟

我知道进程间通信通常限制了并行编程的复杂性,但它通常需要这么长的时间吗?还有什么会导致最后一个过程永远持续下去


此线程:似乎解决了一个类似的问题,但它无法解决池的问题。

看起来您希望将工作划分为块。您可以使用range函数对数据进行分区。在Linux上,分叉进程会获得父内存的“写时拷贝”视图,这样您就可以只传递要处理的索引。在窗户上,没有这样的运气。您需要传入每个子列表。这个程序应该做到这一点

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
你的观点是:

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


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

[arr1]-您对整个数据集只做了一项工作。@tdelaney不应该pool.map将arr1切成块?与arr1大小为10000的单核代码相比,并行代码的工作速度更快。您必须自己进行拆分。您使用的是Windows还是类unix系统?unixy系统有一种更快的方法。@tdelaney哦,我刚刚意识到arr1在每次工作调用中都会被池自动迭代。你说的分裂技术是什么?谢谢