我正在尝试将原生python函数的一部分转换为cython以改善计算时间。我想为占用时间的循环组件编写一个cython函数(正如ipython lprun告诉我的那样)。然而,这个函数采用了可变大小的矩阵..我无法看到如何将其轻松地转换为静态类型的cython。
for index1 in range(0,num_products):
for index2 in range(0,num_products):
cond_prob = (data[index1] * data[index2]).sum() / max(col_sums[index1], col_sums[index2])
prox[index1][index2] = cond_prob
这个问题是num_products逐年变化,因此矩阵(数据)大小是可变的。
这里最好的策略是什么?
答案 0 :(得分:3)
Cython代码(策略性地)是静态类型的,但这并不意味着数组必须具有固定大小。在直接C中,将多维数组传递给函数可能会有点尴尬,但在Cython中,您应该能够执行以下操作:
中获取了函数和变量名称import numpy as np
cimport numpy as np
cimport cython
@cython.boundscheck(False)
@cython.cdivision(True)
def cooccurance_probability_cy(double[:,:] X):
cdef int P, i, j, k
P = X.shape[0]
cdef double item
cdef double [:] CS = np.sum(X, axis=1)
cdef double [:,:] D = np.empty((P, P), dtype=np.float)
for i in range(P):
for j in range(P):
item = 0
for k in range(P):
item += X[i,k] * X[j,k]
D[i,j] = item / max(CS[i], CS[j])
return D
另一方面,如果你使用正确的功能和一些广播,使用Numpy也应该很快解决这个问题。事实上,由于计算复杂性由矩阵乘法控制,我发现以下内容比上面的Cython代码快得多(np.inner
使用高度优化的BLAS例程):
def new(X):
CS = np.sum(X, axis=1, keepdims=True)
D = np.inner(X,X) / np.maximum(CS, CS.T)
return D
答案 1 :(得分:2)
你是否试过摆脱numpy中的for循环?
对于等式的第一部分,您可以尝试:
(data[ np.newaxis,:] * data[:,np.newaxis]).sum(2)
如果内存有问题,您也可以使用np.einsum()函数。 对于第二部分,如果你还没有尝试过,那么你可能也会做出一个笨拙的表达(有点困难)。