OpenMP和Python

我有OpenMP共享内存机器(C和FORTRAN)的编码经验,以执行像matrix加法,乘法等简单的任务(只是看看它是如何与LAPACK竞争)。 我知道OpenMP足以执行简单的任务,而无需查看文档。

最近,我转移到Python为我的项目,我没有任何超过绝对的基本知识Python的经验。

我的问题是:

在Python中使用OpenMP 最简单的方法是什么? 最简单的,我的意思是在程序员方面花费最less的时间(即使它是以增加系统时间为代价的)。

我使用OpenMP的原因是因为串行代码可以转换为一个有效的并行代码,并且散布着几个!$OMP 。 实现粗略平行所需的时间非常less。 有没有什么办法在Python中复制这个function?

从浏览SO,我可以find:

  • C扩展
  • StackLess Python

还有更多吗? 哪个最符合我的问题?

由于GIL,在CPython中使用线程进行CPU密集型任务是没有意义的。 您需要多处理( 例如 )或使用在计算过程中释放GIL的C扩展,例如一些numpy函数, 例如 。

你可以很容易地编写在Cython中使用多个线程的C扩展, 例如 。

据我所知,没有Python的OpenMP包(我不知道如果有的话会怎么做)。 如果你想直接控制线程,你将不得不使用其中一个线程库。 然而,正如其他人指出的那样,GIL(全局解释器锁)在Python中进行了multithreading处理,性能有点…没有意义*。 GIL意味着一次只有一个线程可以访问解释器。

我会build议看看NumPy / SciPy。 NumPy允许您在单个操作的arrays和matrix上编写Matlab-esque代码。 它也有一些并行处理能力,请参见SciPy Wiki 。

其他地方开始寻找:

  • 经验使CPU绑定任务更快
  • 加速Python(NumPy,Cython和Weave)

*好的,这不是没有意义的,除非时间在Python代码之外被使用(比如通过popen或者类似的方式调用外部进程),除了方便之外,线程不会为你购买任何东西。

如果你想释放GIL并使用OpenMP的话你可以看看Cython。 它为一些常见的任务提供了简单的并行性。 您可以在Cython 文档中阅读更多内容 。

也许你的回答是在Cython:

“Cython通过cython.parallel模块支持本地并行性,要使用这种并行性,GIL必须被释放(参见释放GIL),它目前支持OpenMP,但后来可能会支持更多的后端。 Cython文档

用Cython

Cython具有OpenMP支持:使用Cython,可以使用prange (并行范围)运算符并将-fopenmp编译器指令添加到setup.py来添加OpenMP。

当在prange节中工作时,执行是并行执行的,因为我们通过使用with nogil:来禁用全局解释器锁(GIL) with nogil:指定GIL被禁用的块。

要编译_cython_np.pyx_,我们必须修改setup.py脚本,如下所示。 我们告诉它通知C编译器在编译过程中使用-fopenmp作为参数来启用OpenMP并与OpenMP库链接。 setup.py

用Cython的prange,我们可以select不同的调度方法。 使用静态,工作负载均匀分布在可用的CPU上。 然而,由于你的一些计算区域价格昂贵,而另外一些则很便宜,如果我们要求Cython在CPU上使用静态方法来平均地调度工作块,那么某些区域的结果将比其他地方的结果更快,然后这些线程将会闲置。 dynamic引导计划选项都尝试通过在运行时dynamic分配较小块的工作来缓解此问题,以便在工作负载的计算时间可变时更均匀地分配CPU。 因此,对于您的代码,正确的select取决于您的工作负载的性质。

Numba

Numba的高级版本NumbaPro拥有与OpenMP一起使用的prange并行操作符的实验性支持。

Pythran

Pythran(用于Python子集的Python到C ++编译器)可以利用向量化可能性和基于OpenMP的并行化可能性,尽pipe它只使用Python 2.7运行。 您可以使用pragma omp指令来指定并行部分(非常类似于上述的Cython的OpenMP支持),例如:

杂注omp

PyPy

JIT Python编译器PyPy支持多处理模块(参见下文),并且有一个名为“PyPy-STM”的项目,这是一个特殊的PyPy开发版本,可以在同一进程中并行运行多个独立的CPU线程 。

附注:多处理

OpenMP是多核心的低级别接口。 你可能想看看multiprocessing. multiprocessing模块工作在更高层次,共享Python数据结构,而OpenMP与C原语对象(例如,整数和浮点数)一起编译到C之后。只有编译代码时才使用OpenMP ; 如果你不编译(例如,如果你正在使用高效的numpy代码,并且你想运行在许多内核上),那么坚持multiprocessing可能是正确的方法。

http://archive.euroscipy.org/talk/6857 “介绍了Cython的OpenMP能力,专注于NumPy数组上的并行循环,源代码示例演示了如何使用Python中的OpenMP,OpenMP并行algorithm的结果显示了什么是加速与其他并行化策略相比,实现了不同的数据大小。“

 import numpy import cython from cython cimport parallel @cython.boundscheck(False) @cython.wraparound(False) def func(object[double, ndim=2] buf1 not None, object[double, ndim=2] buf2 not None, object[double, ndim=2] output=None, int num_threads=2): cdef unsigned int x, y, inner, outer if buf1.shape != buf2.shape: raise TypeError('Arrays have different shapes: %s, %s' % (buf1.shape, buf2.shape)) if output is None: output = numpy.empty_like(buf1) outer = buf1.shape[0] inner = buf1.shape[1] with nogil, cython.boundscheck(False), cython.wraparound(False): for x in parallel.prange(outer, schedule='static', num_threads=num_threads): for y in xrange(inner): output[x, y] = ((buf1[x, y] + buf2[x, y]) * 2 + buf1[x, y] * buf2[x, y]) return output