如果你运行以下命令,那么这就是一个有趣的注释:
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实现的,因此你无法直接在多进程中使用它。因此,我们需要使用另一个函数对其进行包装。
性能:
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
哇,我也没想到那样,首先有几个问题,即使我们只是在使用包装器而不是纯C函数,我们仍然在使用Python函数,还有复制值的开销,多进程默认不共享数据,因此每个值都需要来回复制。
请注意,如果正确地分段我们的数据:
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
是最好、最安全的多线程代码方法...
希望这可以帮到您。
pool.map()
,你应该使用math.sin
,因为它比numpy.sin
更快。参考:https://dev59.com/lXA65IYBdhLWcg3wvxeE。 - Eric O. Lebigotnumpy.sin
函数可以并行计算,但需要在编译numpy时开启openmp选项。参考链接为:https://software.intel.com/en-us/articles/numpyscipy-with-intel-mkl。 - Ziyuanimport bohrium as numpy
即可。 - j08lue