我有一个庞大的数据集,我必须为它的每个点计算一系列属性。我的代码非常慢,我想以某种方式更快地并行化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模块,例如multiprocessing
和mpi4py
但是从指南中我找不到这么简单问题的答案。
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?
答案 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