如何在Cython中使用openMP?

6 投票
5 回答
5633 浏览
提问于 2025-04-16 10:40

基本上,我遇到了一个问题,这个问题让我感到有点尴尬。我的程序需要处理并行计算,但我觉得用普通的Python和多进程的方式已经达到了速度的极限。所以我现在想尝试用Cython来提高性能,并希望能用上openMP。

简单来说,我想知道如何在Cython中使用openMP,或者我是否需要先写一些原生的C代码,然后通过Cython来加载和绑定这些代码?

或者,我能否让Cython把代码编译成C代码,然后再修改这段C代码,添加openMP的指令,最后编译成库文件并加载到Python中?

5 个回答

3

如果有人碰巧看到这个问题:

现在,Cython通过cython.parallel模块直接支持OpenMP,具体可以查看这个链接:http://docs.cython.org/src/userguide/parallelism.html

12

这个问题是三年前的事了,现在Cython已经有了支持OpenMP的函数。你可以看看这里的文档。其中一个非常方便的函数是prange。下面是一个例子,展示了如何用prange来实现一个(比较简单的)dot函数。

别忘了在编译时给C编译器传递"/opemmp"这个参数。

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]
1

根据cython的维基页面,开发者们考虑了很多不同的方案,但我觉得他们还没有真正实现什么。

如果你的问题是那种特别适合并行处理的类型,而且你已经有了多进程的解决方案,那为什么不让每个工作进程去调用一些cython代码,而不是用python代码呢?

撰写回答