让我们使用,例如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 )
还是有更好的方法吗?
答案 0 :(得分:56)
是更好的方式:numexpr
从主页略微改写:
这是一个用C语言编写的多线程VM,它可以分析表达式,更有效地重写它们,并将它们编译成代码,使内存和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
文档,包括支持的函数here。您需要检查或提供更多信息,以确定是否可以通过numexpr评估更复杂的函数。
答案 1 :(得分:19)
如果您运行以下命令,这是一个有趣的注释:
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.
yep 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函数的几个问题,即使它只是一个包装器与纯c函数,还有复制值的开销,多处理默认不共享数据,因此每个值都需要来回复制。
请注意,如果正确分割我们的数据:
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
是最好,最安全的多线程代码方法......
我希望这会有所帮助。
答案 2 :(得分:6)
SciPy在这个问题上有一个非常好的写作:http://wiki.scipy.org/ParallelProgramming