gpt4 book ai didi

python - 进一步优化简单的cython代码

转载 作者:太空宇宙 更新时间:2023-11-04 04:27:11 26 4
gpt4 key购买 nike

我有一个用 cython 编写的函数,它通过双 for 循环计算特定的相关度量(距离相关):

%%cython -a
import numpy as np

def distances_Matrix(X):
return np.array([[np.linalg.norm(xi-xj) for xi in X] for xj in X])

def c_dCov(double[:, :] a, double[:, :] b, int n):
cdef int i
cdef int j
cdef double U = 0
cdef double W1 = n/(n-1)
cdef double W2 = 2/(n-2)
cdef double[:] a_M = np.mean(a,axis=1)
cdef double a_ = np.mean(a)
cdef double[:] b_M = np.mean(b,axis=1)
cdef double b_ = np.mean(b)

for i in range(n):
for j in range(n):
if i != j:
U = U + (a[i][j] + W1*(-a_M[i]-a_M[j]+a_)) * (b[i][j] + W1*(-b_M[i]-b_M[j]+b_))
else:
U = U - W2*(W1**2)*(a_M[i] - a_) * (b_M[i] - b_)
return U/(n*(n-3))

def c_dCor(X,Y):
n = len(X)
a = distances_Matrix(X)
b = distances_Matrix(Y)
V_XX = c_dCov(a,a,n)
V_YY = c_dCov(b,b,n)
V_XY = c_dCov(a,b,n)
return V_XY/np.sqrt(V_XX*V_YY)

当我编译这段代码时,我得到编译器的以下优化报告:

enter image description here

第 23 行仍然很黄,这表明 python 交互很重要,我该如何进一步优化该行?

在那条线上完成的操作非常简单,只是乘积和求和,因为我确实指定了该函数中使用的每个数组和变量的类型,为什么我在那条线上的表现如此糟糕?

提前致谢。

最佳答案

简答:disable bounds checkingc_dCov 函数中,在它之前的行中添加以下装饰器:

cimport cython
@cython.boundscheck(False) # Deactivate bounds checking
def c_dCov(double[:, :] a, double[:, :] b, int n):

或者,您可以在代码顶部添加编译器指令。在你的 Cython 魔术线之后,你会放:

%%cython -a
#cython: language_level=3, boundscheck=False

如果您有一个 setup.py 文件,您还可以在那里全局关闭边界检查:

from distutils.core import setup
from Cython.Build import cythonize

setup(
name="foo",
ext_modules=cythonize('foo.pyx', compiler_directives={'boundscheck': False}),
)

不管它是如何完成的,禁用边界检查本身就足以获得以下优化报告:

enter image description here

其他optimizations suggested by the Cython docs正在关闭负数索引,并声明您的数组保证在内存中具有连续布局。通过所有这些优化,c_dCov 的签名将变为:

cimport cython
@cython.boundscheck(False) # Deactivate bounds checking
@cython.wraparound(False) # Deactivate negative indexing.
def c_dCov(double[:, ::1] a, double[:, ::1] b, int n):

但只需要 @cython.boundscheck(False) 即可获得更好的优化报告。

现在我仔细观察,即使您的代码片段中没有这些优化,您也有 boundscheck(False)wraparound(False) 优化报告代码中的装饰器。您是否已经尝试过这些但它们没有用?你运行的是什么版本的 Cython?也许您需要升级。

说明

每次按索引访问数组时,都会进行边界检查。这样当您有一个形状为 (5,5) 的数组 arr 并且您尝试访问 arr[19,27] 时,您的程序将吐出一个错误,而不是让您访问越界数据。然而,为了速度,有些语言不对数组访问进行边界检查(例如 C/C++)。 Cython 允许您有选择地关闭边界检查以优化性能。使用 Cython,您可以使用 boundscheck compiler directive 全局禁用整个程序的边界检查。 , 或者对于带有 the @cython.boundscheck(False) decorator 的单个函数.

关于python - 进一步优化简单的cython代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53272344/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com