Python多处理Pool.map正在调用aquire?

问题描述:

我有一张640x480图片的numpy.array,每张图片长630张。 总阵列因此是630x480x640。 我想要生成一幅平均图像,并且计算所有630张图像上每个像素的标准偏差 。Python多处理Pool.map正在调用aquire?

这是很容易

avg_image = numpy.mean(img_array, axis=0) 
std_image = numpy.std(img_array, axis=0) 

完成然而,因为我跑这50个左右这样的阵列,并有 8核/ 16线程工作站,我想我会得到贪婪使用 multiprocessing.Pool并行化。

所以我做了以下内容:

def chunk_avg_map(chunk): 
    #do the processing 
    sig_avg = numpy.mean(chunk, axis=0) 
    sig_std = numpy.std(chunk, axis=0) 
    return([sig_avg, sig_std]) 

def chunk_avg(img_data): 

    #take each row of the image 
    chunks = [img_data[:,i,:] for i in range(len(img_data[0]))] 

    pool = multiprocessing.Pool() 
    result = pool.map(chunk_avg_map, chunks) 
    pool.close() 
    pool.join() 
    return result 

但是,我看到的只是一个小的加速。通过将打印语句放在chunk_avg_map中,我可以确定一次只能启动一个或两个进程,而不是我所期望的那样。

然后,我跑到通过CPROFILE我的代码在IPython中:

%prun current_image_anal.main() 

结果表明,目前大部分时间在电话都花在收购:

ncalls tottime percall cumtime percall filename:lineno(function) 
    1527 309.755 0.203 309.755 0.203 {built-in method acquire} 

我的理解是什么与锁定有关,但我不明白为什么我的代码会这样做。有没有人有任何想法?

[编辑]根据要求,这是一个可运行的脚本,它演示了这个问题。 你可以通过任何你喜欢的方式来分析它,但是当我发现狮子 份额的时间已被调用获取,而不是像我想 预期的那样。

#!/usr/bin/python 
import numpy 
import multiprocessing 

def main(): 
    fake_images = numpy.random.randint(0,2**14,(630,480,640)) 
    chunk_avg(fake_images) 

def chunk_avg_map(chunk): 
    #do the processing 
    sig_avg = numpy.mean(chunk, axis=0) 
    sig_std = numpy.std(chunk, axis=0) 
    return([sig_avg, sig_std]) 

def chunk_avg(img_data): 

    #take each row of the image 
    chunks = [img_data[:,i,:] for i in range(len(img_data[0]))] 

    pool = multiprocessing.Pool() 
    result = pool.map(chunk_avg_map, chunks) 
    pool.close() 
    pool.join() 
    return result 

if __name__ == "__main__": 
    main() 
+0

什么给你multiprocessing.cpu_count()?如预期的那样, – 2010-09-22 17:26:05

+0

multiprocessing.cpu_count()产生16。 – 2010-09-22 17:48:04

+0

这可能没关系,但是'chunk_avg(im_data)'是'chunk_avg(img_data)'? – unutbu 2010-09-22 17:58:06

我相信问题是,CPU花费的时间来处理每块中的量相对于所花费的时间与输入和输出复制到和来自工作进程的量小。我修改了示例代码,将输出分为16个块,并打印出在运行chunk_avg_map()开始和结束时的CPU时间差异(time.clock())。在我的系统上,每个单独的运行在CPU时间的一秒钟内略微下降,但进程组(系统+用户时间)的整体CPU时间使用超过38秒。每块大约0.75秒的复制开销使得您的程序执行计算的速度仅略快于multiprocessing可以传递数据,从而导致只有两个工作进程被同时使用。

如果我修改代码,使“输入数据”只是xrange(16)并在chunk_avg_map()内构建随机数组,然后我看到sysem +用户时间下降到大约19秒,并且所有16个工作进程同时执行。