Python多处理pool.map没有响应,工作进程太多

时间:2017-07-11 15:33:20

标签: python numpy multiprocessing

关于堆栈溢出的第一个问题所以请耐心等待。我希望计算组评级(长numpy数组)的方差。在没有并行处理的情况下运行程序工作正常,但是鉴于每个进程可以独立运行,我希望有32个组可以利用多处理来加快速度。这适用于少数组< 10,但在此之后,程序通常看起来似乎停止运行,没有错误消息在未指定数量的组(通常在20到30之间),尽管不太频繁将一直运行。阵列非常大(21451 x 11462用户项目评级),所以我想知道问题是否是由内存不足引起的,虽然没有打印错误信息。

import numpy as np
from functools import partial
import multiprocessing

def variance_parallel(extra_matrices, group_num):
    # do some variation calculation
    # print confirmation that we have entered function, and group number
    return single_group_var

def variance(extra_matrices, num_groups):
    variance_partial = partial(variance_parallel, extra_matrices)
    for g in list(range(num_groups)):
        group_var = pool.map(variance_partial,range(g))
    return(group_var)     

num_cores = multiprocessing.cpu_count() - 1
pool = multiprocessing.Pool(processes=num_cores)
variance(extra_matrices, num_groups)

运行上面的代码显示程序在最终打印之前逐步建立检查方差([0],[0,1],[0,1,2],...)的组数。< / p>

如果我的格式/问题有点偏离,请提前感谢任何帮助和道歉!

1 个答案:

答案 0 :(得分:0)

  • 多个进程不共享数据
  • 需要复制发送到流程的数据

由于数组很大,因此将大型数组复制到进程很可能会出现问题。在Python的多处理中,将数据发送到进程是通过序列化来完成的,这是(a)CPU密集型和(b)自带的额外内存。

简而言之,多处理不适合您的用例。由于numpy是本机代码扩展(GIL不适用)并且是线程安全的,因此最好使用线程而不是多处理。通过线程,工作线程可以通过父进程的地址空间共享数据,从而无需复制。

这应该可以阻止程序耗尽内存。

但是,对于共享地址空间的线程,它们共享的数据需要绑定到一个对象,就像在python类中一样。

如下所示 - 未经测试,因为代码示例不完整。

import numpy as np
from functools import partial
from threading import Thread
from multiprocessing import cpu_count

class Variance(Thread):

    def __init__(self, extra_matrices, group_num):
        Thread.__init__(self)
        self.extra_matrices = extra_matrices
        self.group_num = group_num
        self.output = None

    def run(self):
        # do some variation calculation
        # print confirmation that we have entered function, and group number
        self.output = single_group_var

num_cores = cpu_count() - 1
results = []
for g in list(range(num_groups)):
    workers = [Variance(extra_matrices, range(g)) 
               for _ in range(num_cores)]
    # Start threads
    for worker in workers:
        worker.start()
    # Wait for completion
    for worker in workers:
        worker.join()
    results.extend([w.output for w in workers])
print results