我目前正在尝试优化我用Pure Python编写的代码。此代码使用 numpy 当我使用numpy阵列时,非常沉重。下面您可以看到我转换为我的最简单的课程 凯森. 。它仅乘以两个Numpy阵列。这里:

bendingForces = self.matrixPrefactor * membraneHeight

我的问题是,当我查看“ cython -a”生成的C代码时,我是否以及如何对此进行优化,这看起来不太有效。

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调用操作的最佳方法是什么?

有帮助吗?

解决方案

对于简单的矩阵乘法,Numpy代码已经仅在本地进行循环和乘法,因此很难在Cython中击败它。 Cython非常适合您与Cython中的Python替换python的循环。您的代码比Numpy慢的原因之一是因为每次在数组中进行索引查找时,

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

它进行更多的计算,例如界限检查(索引是有效的)。如果您将索引置于未签名的ints,则可以使用装饰器 @cython.boundscheck(False) 在功能之前。

看到这个 教程 有关加速Cython代码的更多详细信息。

其他提示

您可能可以使用

for index1 from 0 <= index1 < max1:

我不确定不确定键入的范围。

你检查过吗? 这个这个 ?

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top