需要帮助在python中并行化循环

时间:2012-06-26 15:25:25

标签: python numpy parallel-processing multiprocessing

我有一个庞大的数据集,我必须为它的每个点计算一系列属性。我的代码非常慢,我想以某种方式更快地并行化do循环。我希望每个处理器为我的数据的有限子样本计算“一系列属性”,然后将所有属性连接在一个数组中。 我会尝试用一个例子来解释我的所作所为。

假设我的数据集是数组x

x = linspace(0,20,10000)

我想要的“属性”是,例如x的平方根:

prop=[]
for i in arange(0,len(x)):
    prop.append(sqrt(x[i]))

问题是如何并行化上述循环?假设我有4个处理器,我希望每个处理器计算10000/4 = 2500点的sqrt。

我尝试查看一些python模块,例如multiprocessingmpi4py但是从指南中我找不到这么简单问题的答案。

EDITS

我将感谢大家提供的宝贵意见和链接。但是,我想澄清一下我的问题。我对sqrt函数不感兴趣。 我在循环中进行一系列操作。我完全知道循环是坏的,矢量操作总是比它们更好,但在这种情况下我真的需要做一个循环。我不会详细讨论我的问题,因为这会给这个问题增加不必要的复杂性。 我想分割我的循环,以便每个处理器完成它的一部分,这意味着我可以运行我的代码40次,每次循环的1/40并且合并结果但这将是愚蠢的。 这是一个简短的例子

     for i in arange(0,len(x)):
         # do some complicated stuff

我想要的是使用40 cpus来做到这一点:

    for npcu in arange(0,40):
       for i in arange(len(x)/40*ncpu,len(x)/40*(ncpu+1)):
          # do some complicated stuff

是否可以使用python?

3 个答案:

答案 0 :(得分:3)

并行化并非易事,但您可能会发现numexpr很有用。

对于数字作品,你真的应该研究numpy给你的实用程序(vectorize和类似的),这些通常会给你一个很好的加速作为工作的基础。

对于更复杂的非数字案例,您可以使用multiprocessing(请参阅评论)。


在旁注中,多线程使用python比使用其他语言更加重要,是CPython有Global Interpreter Lock (GIL)不允许两部分python代码同时在同一个解释器中运行(即没有真正的多线程纯python代码)。对于I / O和繁重的计算,第三方库往往会释放该锁,因此可以进行有限的多线程处理。

这增加了通常的多线程麻烦,即必须使用互斥共享数据访问等。

答案 1 :(得分:2)

我不确定这是你应该做的事情,因为我希望numpy有一个更有效的方法来解决它,但你只是意味着这样的事情吗?

import numpy
import multiprocessing

x = numpy.linspace(0,20,10000)
p = multiprocessing.Pool(processes=4)

print p.map(numpy.sqrt, x)

以下是timeit两种解决方案的结果。正如@SvenMarcach指出的那样,使用更昂贵的功能,多处理将开始变得更加有效。

% python -m timeit -s 'import numpy; x=numpy.linspace(0,20,10000)' 'prop=[]                                                                          
for i in numpy.arange(0,len(x)):
         prop.append(numpy.sqrt(x[i]))'
10 loops, best of 3: 31.3 msec per loop

% python -m timeit -s 'import numpy, multiprocessing; x=numpy.linspace(0,20,10000)
p = multiprocessing.Pool(processes=4)' 'l = p.map(numpy.sqrt, x)' 
10 loops, best of 3: 102 msec per loop

根据Sven的要求,l = numpy.sqrt(x)的结果是显着比其中任何一种方法更快。

% python -m timeit -s 'import numpy; x=numpy.linspace(0,20,10000)' 'l = numpy.sqrt(x)'
10000 loops, best of 3: 70.3 usec per loop

答案 2 :(得分:0)

我建议你看看cython: http://www.cython.org/

它使您能够非常快速地为python创建c扩展,并且与numpy集成得非常好。这是一个很好的教程,可以帮助您入门:http://docs.cython.org/src/tutorial/numpy.html