【发布时间】:2018-11-13 01:12:04
【问题描述】:
我有一个用 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)
当我编译这段代码时,我得到编译器的以下优化报告:
第 23 行还是很黄的,这表明 python 交互很重要,如何使该行进一步优化?
在那条线上的操作很简单,只是乘积和求和,因为我确实指定了该函数中使用的每个数组和变量的类型,为什么我在那条线上的表现如此糟糕?
提前致谢。
【问题讨论】:
-
我可以通过将
@cython.boundscheck(False)装饰器添加到c_dCov来优化第 23 行。仅此一项就足以将黄色变为白色。虽然@cython.boundscheck(False)不在您的代码 sn-p 中,但它看起来确实在优化报告中。您是否已经尝试使用boundscheck,但它不起作用?如果是这样,您可能只需要升级 Cython 包。您目前使用的是什么版本? -
a[i][j]到a[i,j]也可能有用 -
最明显的优化是distances_Matrix函数。例如。 stackoverflow.com/q/50675705/4045774(别忘了给 euclidean_distance_square_einsum 添加一个 sqrt)。
-
@max9111 我现在将尝试优化 distances_Matrix。您是否认为使用纯 python 循环来完成这一切以对函数进行 cythonize 是一种好方法?提前感谢您的洞察力。
-
至少对于稍微大一点的问题,除了快速的 BLAS 后端(例如 Intel MKL)之外,没有太多的优化潜力。您可以简单地使用 euclidean_distance_square_einsum 函数并添加一个 np.sqrt 。
标签: python numpy optimization cython