Python 具有可变大小矩阵输入的Cython函数

Python 具有可变大小矩阵输入的Cython函数,python,numpy,cython,Python,Numpy,Cython,我试图将本机python函数的一部分转换为cython,以提高计算时间。我想为占用时间的循环组件编写一个cython函数(正如ipythonlprun善意地告诉我的那样)。但是,此函数接受大小可变的矩阵。。我看不出如何让静态类型的cython轻松理解这一点 for index1 in range(0,num_products): for index2 in range(0,num_products): cond_prob = (data[index1] * data[in

我试图将本机python函数的一部分转换为cython,以提高计算时间。我想为占用时间的循环组件编写一个cython函数(正如ipythonlprun善意地告诉我的那样)。但是,此函数接受大小可变的矩阵。。我看不出如何让静态类型的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_产品每年都在变化,因此矩阵(数据)大小是可变的

这里最好的策略是什么

  • 我应该写两个C函数吗。一个是使用memalloc创建一个特定维度的矩阵,然后一个是在创建的矩阵上进行循环
  • 在这个场景中,有没有一些奇特的cython/numpy魔法可以帮助你?我是否可以编写一个C函数,在内存中接收大小可变的Numpy数组并传递大小

  • 你试过在numpy中去掉for循环吗

    例如,对于等式的第一部分,您可以尝试:

    (data[ np.newaxis,:] * data[:,np.newaxis]).sum(2) 
    
    如果内存有问题,还可以使用np.einsum()函数。
    对于第二部分,如果您还没有尝试过的话,您可能还可以编写一个numpy表达式(有点困难)。

    您尝试过去掉numpy中的For循环吗

    例如,对于等式的第一部分,您可以尝试:

    (data[ np.newaxis,:] * data[:,np.newaxis]).sum(2) 
    
    如果内存有问题,还可以使用np.einsum()函数。 对于第二部分,如果您还没有尝试过,您可能还可以编写一个numpy表达式(稍微困难一些)。

    Cython代码(策略上)是静态类型的,但这并不意味着数组必须具有固定的大小。在C语言中,将多维数组传递给函数可能有点尴尬,但在Cython中,您应该能够执行以下操作:

    注意,我从您的

    另一方面,如果您使用正确的函数和一些广播,那么使用justnumpy解决这个问题也应该相当快。事实上,由于计算复杂度主要取决于矩阵乘法,我发现下面的代码比上面的Cython代码快得多(
    np.inner
    使用高度优化的BLAS例程):

    Cython代码(策略上)是静态类型的,但这并不意味着数组必须具有固定的大小。在C语言中,将多维数组传递给函数可能有点尴尬,但在Cython中,您应该能够执行以下操作:

    注意,我从您的

    另一方面,如果您使用正确的函数和一些广播,那么使用justnumpy解决这个问题也应该相当快。事实上,由于计算复杂度主要取决于矩阵乘法,我发现下面的代码比上面的Cython代码快得多(
    np.inner
    使用高度优化的BLAS例程):


    嗨,在cython中,你也可以做一些事情,比如num_products=data.shape[0]或类似的事情,这样你的循环长度就会适合你。但是,我不太确定您将要改进循环的方式是否会有很大帮助,因为您正在cython循环中使用numpy函数。在numpy,你想做的似乎也很直截了当。。。上面的表达式是您的原始python代码吗?因为如果是,您可以通过省去for循环来优化它,从而使它更快。几个问题:数组
    数据
    prox的
    形状是什么?它们都是numpy阵列吗?
    num_products
    通常有多大?谢谢您的评论。很好的观点是:矢量化而不是在numpy数组上循环!data=(170 x 800),因此prox是800 x 800Hi,同样在cython中,您可以执行num_products=data.shape[0]或类似操作,这样循环的长度将适合您。但是,我不太确定您将要改进循环的方式是否会有很大帮助,因为您正在cython循环中使用numpy函数。在numpy,你想做的似乎也很直截了当。。。上面的表达式是您的原始python代码吗?因为如果是,您可以通过省去for循环来优化它,从而使它更快。几个问题:数组
    数据
    prox的
    形状是什么?它们都是numpy阵列吗?
    num_products
    通常有多大?谢谢您的评论。很好的观点是:矢量化而不是在numpy数组上循环!数据=(170 x 800),因此prox是800 x 800的好主意。。。我明天会试试这个,并更新这个伟大的想法。。。我明天会试试这个,并更新这篇博文。。。我已经用你的Cython更新了后续问题()Function@sanguineturtle,同时我编辑了我的答案:事实证明,禁用Cython函数的边界检查可以显著提高性能。我还发现普通的Numpy更快,你一定要看看
    :)
    很好的解释re:Cython。。。我已经用你的Cython更新了后续问题()Function@sanguineturtle,同时我编辑了我的答案:事实证明,禁用Cython函数的边界检查可以显著提高性能。我还发现普通Numpy的速度更快,你一定要看看
    :)
    def new(X):
        CS = np.sum(X, axis=1, keepdims=True)
        D = np.inner(X,X) / np.maximum(CS, CS.T)
        return D