使用Cython优化NumPy

时间:2011-03-16 20:21:13

标签: python numpy cython matrix-multiplication optimization

我目前正在尝试优化我用纯Python编写的代码。当我使用NumPy数组时,此代码使用NumPy。您可以在下面看到我转换为Cython的最简单的类。这只是两个Numpy数组的乘法。这里:

bendingForces = self.matrixPrefactor * membraneHeight

我的问题是,我是否以及如何优化它,当我看到“cython -a”生成的C代码有很多NumPy调用时,这看起来效率不高。

import numpy as np
cimport numpy as np
ctypedef np.float64_t dtype_t
ctypedef np.complex128_t cplxtype_t
ctypedef Py_ssize_t index_t

    cdef class bendingForcesClass( object ):
        cdef dtype_t bendingRigidity
        cdef np.ndarray matrixPrefactor
        cdef np.ndarray bendingForces

        def __init__( self, dtype_t bendingRigidity, np.ndarray[dtype_t, ndim=2] waveNumbersNorm ):
            self.bendingRigidity = bendingRigidity
            self.matrixPrefactor = -self.bendingRigidity * waveNumbersNorm**2

        cpdef np.ndarray calculate( self, np.ndarray membraneHeight ) :
            cdef np.ndarray bendingForces
            bendingForces = self.matrixPrefactor * membraneHeight
            return bendingForces

我的想法是使用两个for循环并迭代数组的条目。也许我可以使用编译器来优化SIMD操作?!我试过,我可以编译,但它给出了奇怪的结果,并且永远。这是替代函数的代码:

cpdef np.ndarray calculate( self, np.ndarray membraneHeight ) :

    cdef index_t index1, index2 # corresponds to: cdef Py_ssize_t index1, index2
    for index1 in range( self.matrixSize ):
        for index2 in range( self.matrixSize ):
            self.bendingForces[ index1, index2 ] = self.matrixPrefactor.data[ index1, index2 ] * membraneHeight.data[ index1, index2 ]
    return self.bendingForces

然而,正如我所说,这段代码非常慢,并且没有按预期运行。那么我做错了什么?优化此操作并删除NumPy调用操作的最佳方法是什么?

2 个答案:

答案 0 :(得分:9)

对于简单的矩阵乘法,NumPy代码本身只进行循环和乘法运算,因此在Cython中很难超越它。 Cython非常适合用Python替换Python中的循环的情况。您的代码比NumPy慢的原因之一是因为每次在数组中进行索引查找时,

self.bendingForces[ index1, index2 ] = self.matrixPrefactor.data[ index1, index2 ] * membraneHeight.data[ index1, index2 ]

它执行更多计算,如边界检查(索引有效)。如果将索引转换为无符号整数,则可以在函数前使用装饰器@cython.boundscheck(False)

有关加速Cython代码的更多详细信息,请参阅此tutorial

答案 1 :(得分:0)

你可以使用

加快速度
for index1 from 0 <= index1 < max1:

而不是使用范围,我不确定是否输入。

您是否选中了this outthis one