我有一个640x480图像的numpy.array,每张图像长630张。 因此总阵列为630x480x640。 我想生成一个平均图像,以及计算标准偏差 所有630张图片中的每个像素。
这很容易通过
完成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中放置print语句,我能够确定一次只启动一个或两个进程,而不是 16(正如我所料)。
然后我通过iPython中的cProfile运行我的代码:
%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 :(得分:7)
我认为问题在于,处理每个块所需的CPU时间相对于复制输入和输出与工作进程之间所需的时间相比较小。我修改了您的示例代码,将输出拆分为16个偶数块,并打印出time.clock()
运行开始和结束之间的CPU时间差异(chunk_avg_map()
)。在我的系统上,每个单独运行的CPU时间略短于一秒,但进程组的总CPU时间使用(系统+用户时间)超过38秒。每个块的明显0.75秒复制开销使得程序执行计算的速度仅比multiprocessing
提供数据的速度略快,导致一次只能使用两个工作进程。
如果我修改代码使得“输入数据”只是xrange(16)
并在chunk_avg_map()
内构建随机数组,那么我看到sysem +用户时间下降到大约19秒并且所有16个工作者进程同时执行。