scipy稀疏矩阵和cython

SKV*_*SKV 5 python numpy cython scipy sparse-matrix

我需要在Cython方法中的scipy稀疏矩阵上执行一组操作.

为了有效地应用这些,我需要访问lil_matrix表示.python中的lil(链表稀疏矩阵)数据表示使用list of lists不同的长度.

如何有效地将不同长度的列表列表传递给cython(不复制)?有没有其他方法可以访问cython中的lil-matrices?

Sau*_*tro 5

下面的示例迭代a lil_matrix并计算每行的总和.

注意我没有声明,即使它非常快,因为Cython已经针对内置类型(如列表)进行了优化.时间也如下所示......

import time

import numpy as np
cimport numpy as np

from scipy.sparse import lil_matrix

cdef iter_over_lil_matrix(m):
    cdef list sums, data_row
    sums = []
    for data_row in m.data:
        s = 0
        for value in data_row:
            s += value
        sums.append(s)
    return sums

def main():
    a = np.random.random((1e4*1e4))
    a[a>0.1] = 0
    a = a.reshape(1e4,1e4)
    m = lil_matrix(a)

    t0 = time.clock()
    sums = iter_over_lil_matrix(m)
    t1 = time.clock()
    print 'Cython lil_matrix Time', t1-t0

    t0 = time.clock()
    array_sums = a.sum(axis=1)
    t1 = time.clock()
    print 'Numpy ndarray Time', t1-t0

    t0 = time.clock()
    lil_sums = m.sum(axis=1)
    t1 = time.clock()
    print 'lil_matrix Time', t1-t0

    mcsr = m.tocsr()
    t0 = time.clock()
    csr_sums = mcsr.sum(axis=1)
    t1 = time.clock()
    print 'csr_matrix Time', t1-t0

    assert np.allclose(array_sums, sums)
    assert np.allclose(array_sums, np.asarray(lil_sums).flatten())
    assert np.allclose(array_sums, np.asarray(csr_sums).flatten())
Run Code Online (Sandbox Code Playgroud)

以秒为单位的时间 - 仅比超优化的NumPy:D慢约2倍,比lil_matrix.sum()方法快得多,因为它转换为csr_matrix()之前,正如@hpaulj所阐明并由下面的结果所证实.请注意,csr_matrix.sum()列上的密度几乎比密集总和快一个数量级.

Cython lil_matrix Time 0.183935034665
Numpy ndarray Time 0.106583238273
lil_matrix Time 2.47158218631
csr_matrix Time 0.0140050888745
Run Code Online (Sandbox Code Playgroud)

会减慢代码速度的事情:

  • 使用for i in range(len(m.data)):data_row = m.data[i]
  • 声明诸如缓冲区np.ndarray[object, ndim=1] datadata=m.data

不影响的事情:

  • boundscheck 要么 wraparound

  • `稀疏``sum`是一个带有适当向量的点积.为了做这个数学,`lil`被转换为`csr`.使用样本矩阵,`csr`总和比密集总和快5倍.由于将它转换为`csr`所需的时间,`lil`总和很慢. (3认同)