OpenMP和Python

53 python parallel-processing openmp

我有为共享内存机器(在C和FORTRAN中)编码OpenMP的经验,可以执行矩阵添加,乘法等简单任务(只是为了看看它与LAPACK的竞争).我知道OpenMP足以执行简单的任务而无需查看文档.

最近,我为我的项目转移到Python,除了绝对的基础知识,我没有任何Python经验.

我的问题是:

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

我使用OpenMP的原因是因为串行代码可以转换为一个工作的并行代码,其中有几个!$OMP散布在周围.实现粗略并行化所需的时间非常小.有没有办法在Python中复制这个功能?

通过浏览SO,我可以找到:

  • C扩展
  • StackLess Python

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

jfs*_*jfs 28

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

你可以很容易地写在用Cython,使用多线程的C扩展例子.

  • 如果基本上所有的工作都是在C函数中完成的,那么@Inquest ctypes对于并行化真的很有用,而你的python只是调用它们的包装器.这不是"Python中的并行编程",但它有时候很方便. (4认同)
  • 对 Python 中的“ctypes”(常规)有何评论? (2认同)

boa*_*der 21

用Cython

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

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

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

使用Cython,prange,我们可以选择不同的调度方法.使用静态,工作负载均匀分布在可用的CPU上.然而,随着你的一些计算区域在时间上昂贵的,而有些则是便宜-如果我们要求用Cython平等地制定工作计划块使用静态跨越的CPU,那么对于一些地区的结果将完成比别人更快,这些线程也就那么闲着.无论是动态引导计划选项试图通过这样,当工作负载的计算时间是可变的CPU被更均匀地分布在运行时动态分配较小的块工作,以减轻这个问题.因此,对于您的代码,正确的选择将根据您的工作负载的性质而有所不同.

Numba

Numba的高级版本NumbaPro prange为使用OpenMP 的并行化运算符提供了实验支持.

Pythran

Pythran(用于Python子集的Python-to-C++编译器)可以利用矢量化可能性和基于OpenMP的并行化可能性,尽管它仅使用Python 2.7运行.您可以使用pragma omp指令指定并行部分(与上面描述的Cython的OpenMP支持非常相似),例如:

pragma omp

PyPy

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

旁注:多处理

OpenMP是多核的低级接口.你可能想看看multiprocessing.multiprocessing模块工作在较高的水平,共享Python数据结构,而OpenMP的作品使用C原始的对象(例如,整数和浮点数)一旦你编译为C.它才有意义,使用OpenMP的,如果你正在编译你的代码; 如果你没有编译(例如,如果你使用的是高效的numpy代码而你想在许多内核上运行),那么坚持使用multiprocessing可能是正确的方法.


Nat*_*han 13

据我所知,没有适用于Python的OpenMP软件包(我不知道如果有的话会怎么做).如果您希望线程直接在您的控制之下,则必须使用其中一个线程库.但是,正如其他人所指出的那样,GIL(全局解释器锁)在Python中使用多线程来提高性能......好吧,毫无意义*.GIL意味着一次只有一个线程可以访问解释器.

我建议改为查看NumPy/SciPy.NumPy允许您编写Matlab式代码,您可以在单个操作的阵列和矩阵上操作.它也有一些并行处理功能,请参阅SciPy Wiki.

其他地方开始寻找:

*好吧,这不是没有意义的,但除非在Python代码之外消耗时间(例如通过popen或通过某种方式调用的外部进程),线程除了方便之外不会给你买任何东西.

  • @MySchizoBuddy - 是的,您可以编写 OpenMP C 代码,编译它并从 Python 中调用它。这在 GIL 的范围之外执行,因为它不是由 Python 引擎执行的。但是,在 Python 中没有使用 OpenMP 的 *直接* 方式。 (2认同)

bte*_*tel 10

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


小智 8

也许您的回复是在Cython中:

"Cython通过cython.parallel模块支持本机并行性.要使用这种并行性,必须释放GIL(请参阅释放GIL).它目前支持OpenMP,但稍后可能会支持更多的后端." Cython文档

  • 使用openmp的cython在多核cpu上非常棒,与单线程相比,我在8核机器上获得700%的加速 (2认同)

小智 7

有一个名为pymp的包,作者将其描述为将类似 OpenMP 的功能引入 Python 的包。我试过使用它,但有不同的用例:文件处理。有效。我认为使用起来非常简单。以下是取自 GitHub 页面的示例:

import pymp
ex_array = pymp.shared.array((100,), dtype='uint8')
with pymp.Parallel(4) as p:
    for index in p.range(0, 100):
        ex_array[index] = 1
        # The parallel print function takes care of asynchronous output.
        p.print('Yay! {} done!'.format(index))
Run Code Online (Sandbox Code Playgroud)