我有一个用cython编写的函数,它通过一个double 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)
当我编译这段代码时,我得到了编译器的以下优化报告:
第23行仍然是黄色的,这表示python的交互作用非常显著,我如何使这一行进一步优化?。在
在那一行所做的操作非常简单,只有乘积和和和,因为我确实指定了函数中使用的每个数组和变量的类型,为什么我在那一行得到如此糟糕的性能?在
提前谢谢。在
简而言之:disable bounds checking在
c_dCov
函数中,在其前面的行上添加以下装饰符:或者,可以在代码的顶部添加编译器指令。在你的Cython魔术台词后面你会说:
^{pr2}$如果有一个
setup.py
文件,还可以在那里全局关闭边界检查:不管是如何完成的,禁用边界检查本身就足以获得以下优化报告:
其他一些optimizations suggested by the Cython docs正在关闭负数索引,并声明保证数组在内存中具有连续布局。通过所有这些优化,
c_dCov
的签名将变成:但是只有{}就可以得到更好的优化报告。在
现在我仔细看一下,即使代码片段中没有这些优化,但是在优化报告的代码中确实有}装饰符。你是不是已经试过了,但没用?你在运行什么版本的Cython?也许你需要升级。在
boundscheck(False)
和{说明
每次按索引访问数组时,都会进行边界检查。这样,当您有一个形状为} compiler directive 全局禁用整个程序的边界检查,也可以使用the ^{} decorator 禁用单个函数的边界检查。在
(5,5)
的数组arr
,并且您试图访问arr[19,27]
时,程序将发出错误而不是允许您访问越界数据。然而,为了速度,一些语言不做数组访问(如C/C++)的边界检查。Cython允许您选择关闭边界检查以优化性能。使用Cython,可以使用^{相关问题 更多 >
编程相关推荐