基本上我有一个非常令人尴尬的并行问题,我认为我已经达到了使用普通 python 和多处理实现它的速度的极限,所以我现在正试图通过 Cython 将它降低到一个较低的水平,并希望 openMP .
所以简而言之,我想知道如何将 openMP 与 Cython 一起使用,或者我是否必须包装一些原始 C 代码并通过 Cython 加载/绑定到它?
或者我可以让 Cython 编译成 C 代码,然后修改 C 代码以添加到 openMP 编译指示中,然后编译到库并将其加载到 Python 中?
基本上我有一个非常令人尴尬的并行问题,我认为我已经达到了使用普通 python 和多处理实现它的速度的极限,所以我现在正试图通过 Cython 将它降低到一个较低的水平,并希望 openMP .
所以简而言之,我想知道如何将 openMP 与 Cython 一起使用,或者我是否必须包装一些原始 C 代码并通过 Cython 加载/绑定到它?
或者我可以让 Cython 编译成 C 代码,然后修改 C 代码以添加到 openMP 编译指示中,然后编译到库并将其加载到 Python 中?
这个问题来自 3 年前,现在 Cython 具有支持 OpenMP 后端的可用功能。例如,请参阅此处的文档。一个非常方便的功能是prange
. 这是如何dot
使用prange
.
不要忘记编译将"/opemmp"
参数传递给 C 编译器。
import numpy as np
cimport numpy as np
import cython
from cython.parallel import prange
ctypedef np.double_t cDOUBLE
DOUBLE = np.float64
def mydot(np.ndarray[cDOUBLE, ndim=2] a, np.ndarray[cDOUBLE, ndim=2] b):
cdef np.ndarray[cDOUBLE, ndim=2] c
cdef int i, M, N, K
c = np.zeros((a.shape[0], b.shape[1]), dtype=DOUBLE)
M = a.shape[0]
N = a.shape[1]
K = b.shape[1]
for i in prange(M, nogil=True):
multiply(&a[i,0], &b[0,0], &c[i,0], N, K)
return c
@cython.wraparound(False)
@cython.boundscheck(False)
@cython.nonecheck(False)
cdef void multiply(double *a, double *b, double *c, int N, int K) nogil:
cdef int j, k
for j in range(N):
for k in range(K):
c[k] += a[j]*b[k+j*K]
如果有人偶然发现这个问题:
现在,通过 cython.parallel 模块直接支持 cython 中的 OpenMP,请参阅 http://docs.cython.org/src/userguide/parallelism.html
Cython 的核心开发人员之一 Stefan Behnel 的这个 youtube 演讲将为您提供精彩的介绍。循环的多线程在最后 30 分钟(prange
部分)。该代码是一组压缩的ipython 笔记本,可在此处下载。
range
简而言之,通过替换和释放 GIL ,编写优化的非线程代码、使用 Cython 类型和多线程进行优化。
根据cython wiki,开发人员已经考虑了多种选择,但我认为他们还没有实现任何东西。
如果您的问题是令人尴尬的并行,并且您已经有了多处理解决方案,为什么不让每个工作进程调用一些 cython 代码而不是 python 代码呢?
我没有使用 OpenMP 的经验,但尝试zeromq(包括 python 绑定)可能会很幸运:
easy_install pyzmq