使用 Cython 并行支持:
# asd.pyx
from cython.parallel cimport prange
import numpy as np
def foo():
cdef int i, j, n
x = np.zeros((200, 2000), float)
n = x.shape[0]
for i in prange(n, nogil=True):
with gil:
for j in range(100):
x[i,:] = np.cos(x[i,:])
return x
在 2 核机器上:
$ cython asd.pyx
$ gcc -fPIC -fopenmp -shared -o asd.so asd.c -I/usr/include/python2.7
$ export OMP_NUM_THREADS=1
$ time python -c 'import asd; asd.foo()'
real 0m1.548s
user 0m1.442s
sys 0m0.061s
$ export OMP_NUM_THREADS=2
$ time python -c 'import asd; asd.foo()'
real 0m0.602s
user 0m0.826s
sys 0m0.075s
这可以并行运行,因为np.cos
(与其他 ufunc 一样)释放了 GIL。
如果您想以交互方式使用它:
# asd.pyxbdl
def make_ext(modname, pyxfilename):
from distutils.extension import Extension
return Extension(name=modname,
sources=[pyxfilename],
extra_link_args=['-fopenmp'],
extra_compile_args=['-fopenmp'])
和(删除asd.so
和asd.c
第一):
>>> import pyximport
>>> pyximport.install(reload_support=True)
>>> import asd
>>> q1 = asd.foo()
# Go to an editor and change asd.pyx
>>> reload(asd)
>>> q2 = asd.foo()
所以是的,在某些情况下,您可以仅使用线程进行并行化。OpenMP 只是一个花哨的线程包装器,因此这里只需要 Cython 以实现更简单的语法。如果没有 Cython,您可以使用该threading
模块 --- 与多处理类似(并且可能更健壮),但您不需要做任何特殊的事情来将数组声明为共享内存。
然而,并不是所有的操作都会释放 GIL,所以 YMMV 用于性能。
***
从其他 Stackoverflow 答案中提取的另一个可能有用的链接 --- 多处理的另一个接口:http ://packages.python.org/joblib/parallel.html