并行化numpy的矢量运算(Parallelizing a Numpy vector operati

2019-06-14 20:53发布

让我们使用,例如, numpy.sin()

下面的代码将返回正弦为阵列的每个值的值a

import numpy
a = numpy.arange( 1000000 )
result = numpy.sin( a )

但是我的机器有32个内核,所以我想利用它们。 (开销可能不值得像numpy.sin()但其实我是想使用的功能更复杂了不少,我会用大量的数据来工作。)

这是最好的(阅读:最聪明的或最快)的方法:

from multiprocessing import Pool
if __name__ == '__main__':
    pool = Pool()
    result = pool.map( numpy.sin, a )

还是有更好的方式来做到这一点?

Answer 1:

一个更好的办法: numexpr

从他们的主页稍微改写:

这是一个多线程的虚拟机用C写的,分析的表达,更有效地重写它们,并编译它们在飞行中为代码,获得接近最优的并行性能两个内存和CPU界操作。

举例来说,在我的4芯机,评估正弦比numpy的速度只是略少于4次。

In [1]: import numpy as np
In [2]: import numexpr as ne
In [3]: a = np.arange(1000000)
In [4]: timeit ne.evaluate('sin(a)')
100 loops, best of 3: 15.6 ms per loop    
In [5]: timeit np.sin(a)
10 loops, best of 3: 54 ms per loop

文档,包括支持的功能在这里 。 你必须检查或给我们更多的信息,看看你更复杂的功能可以通过numexpr进行评估。



Answer 2:

嗯,这是一种,如果你运行下面的命令有趣的注意事项:

import numpy
from multiprocessing import Pool
a = numpy.arange(1000000)    
pool = Pool(processes = 5)
result = pool.map(numpy.sin, a)

UnpicklingError: NEWOBJ class argument has NULL tp_new

没想到的是,这样怎么回事,还有:

>>> help(numpy.sin)
   Help on ufunc object:

sin = class ufunc(__builtin__.object)
 |  Functions that operate element by element on whole arrays.
 |  
 |  To see the documentation for a specific ufunc, use np.info().  For
 |  example, np.info(np.sin).  Because ufuncs are written in C
 |  (for speed) and linked into Python with NumPy's ufunc facility,
 |  Python's help() function finds this page whenever help() is called
 |  on a ufunc.

是的numpy.sin在C这样你不能真正直接与多用它来实现。

所以,我们有另一个函数把它包

PERF:

import time
import numpy
from multiprocessing import Pool

def numpy_sin(value):
    return numpy.sin(value)

a = numpy.arange(1000000)
pool = Pool(processes = 5)

start = time.time()
result = numpy.sin(a)
end = time.time()
print 'Singled threaded %f' % (end - start)
start = time.time()
result = pool.map(numpy_sin, a)
pool.close()
pool.join()
end = time.time()
print 'Multithreaded %f' % (end - start)


$ python perf.py 
Singled threaded 0.032201
Multithreaded 10.550432

哇,没想到,要么,以及那里有对于初学者,我们使用的是Python函数,即使它只是一个包装VS纯C函数,并且也Theres复制值的开销,多在默认情况下没有按”几个问题吨共享数据,因为这样的每个值需要被复制回/类推。

千万注意,如果正确段我们的数据:

import time
import numpy
from multiprocessing import Pool

def numpy_sin(value):
    return numpy.sin(value)

a = [numpy.arange(100000) for _ in xrange(10)]
pool = Pool(processes = 5)

start = time.time()
result = numpy.sin(a)
end = time.time()
print 'Singled threaded %f' % (end - start)
start = time.time()
result = pool.map(numpy_sin, a)
pool.close()
pool.join()
end = time.time()
print 'Multithreaded %f' % (end - start)

$ python perf.py 
Singled threaded 0.150192
Multithreaded 0.055083

那么,我们可以从这个取,多是伟大的,但我们应该始终测试其速度更快,有时它更慢,取决于如何使用它有时比较一下...

就算你不使用numpy.sin但其他功能,我建议您先验证确实多会加速计算,复制值的可能开销前/后可能会影响到你。

无论哪种方式,我还 ,使用pool.map是多线程代码的最好的,最安全的方法...

我希望这有帮助。



Answer 3:

SciPy的实际上有关于这个问题的一个很好的书面记录在这里: http://wiki.scipy.org/ParallelProgramming



文章来源: Parallelizing a Numpy vector operation