简体   繁体   English

Scipy.sparse CSC矩阵性能

[英]Scipy.sparse CSC-matrix performance

I'm currently trying to solve some equations using implicit euler. 我目前正在尝试使用隐式欧拉求解某些方程。 Since I was bored of Fortran, I thought it might be a good idea to try it with Python and see how close I can come (from performance point of view) to the existing Fortran program. 由于我对Fortran感到无聊,所以我认为最好是使用Python尝试一下,看看从现有的性能来看,与现有的Fortran程序之间的距离有多近。 For my problem, i want to take advantage of sparse matrices. 对于我的问题,我想利用稀疏矩阵。 I encountered that the current bottleneck of my program is initializing the sparse matrix and subtract something from the diagonal. 我遇到了程序的当前瓶颈是初始化稀疏矩阵并从对角线中减去一些东西。

The following minimal example demonstrates this: 以下最小示例说明了这一点:

import numpy                as np
from scipy.sparse           import csc_matrix
from scipy.sparse.linalg    import spsolve
from timeit                 import default_timer

# Example data for Sparse Matrix in CSC format
data = np.array([ -6.07315337e+07,  -1.08191534e+06,  -5.85677031e+07, \
               5.96496184e+07,   1.99723260e+07,  -3.99136095e+07, \
              -3.10384281e+04,   1.99412852e+07,   3.10384281e+04, \
               4.14012789e+04,  -4.13845644e+04,  -4.14179805e+04, \
               4.13845708e+04,   1.67016486e+01,   6.40664368e+03, \
              -1.21556953e+02,   6.28508672e+03,  -6.40664368e+03, \
               1.21556953e+02,   1.87698938e-03,   1.87698938e-03, \
              -1.87698938e-03,   6.17782975e-05,   6.17782975e-05, \
              -6.17782975e-05,   3.23024684e+00,   3.23024684e+00, \
              -3.23024684e+00,   1.59838512e+00,   1.59838512e+00, \
              -1.59838512e+00,   1.96353333e-02,   1.96353333e-02, \
              -1.96353333e-02,   4.25269958e+01,   4.25269958e+01, \
              -4.25269958e+01,   4.84489810e-06,   4.84489810e-06, \
              -4.84489810e-06,   2.54951658e-07,   2.54951658e-07, \
              -2.54951658e-07,   6.42250438e-08,   6.42250438e-08, \
              -6.42250438e-08])

indices = np.array([ 0,  1,  2,  3,  0,  1,  2,  3,  4,  0,\
                     1,  2,  4,  5,  0,  1,  2,  3,  5,  0,\
                     3,  4,  0,  4,  5,  0,  5,  6,  0,  6,\
                     7,  0,  7,  8,  0,  8,  9,  0,  9, 10,\
                     0, 10, 11,  0, 11, 12], dtype=np.int32)

indptr = np.array([ 0,  4,  9, 14, 19, 22, 25, 28, 31, 34,\
                   37, 40, 43, 46], dtype=np.int32)

# Stop the time to initialize the Sparse matrix in CSC-format
start = default_timer()
for i in range(10000):
    J = csc_matrix((data, indices, indptr), shape=(13, 13))
stop = default_timer()
print 'Initialize:'.ljust(15),stop - start

# Set the diagonal of the matrix. The diagonal is in principle known.
start = default_timer()
for i in range(10000):
    J.setdiag(1./1e-10 + J.diagonal())
stop = default_timer()
print 'Set diagonal:'.ljust(15), stop - start

# Set an array to solve something
b = np.array([ -4.16737068e+05, 8.32180182e+05, 1.29378997e+03,\
               -4.15443441e+05,-1.29326784e+03,-2.60963259e-01,\
                0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\
                0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\
                0.00000000e+00])

# Stop the time to solve the system
start = default_timer()
for i in range(10000):
    x = spsolve(J,b)
stop = default_timer()
print 'Solve:'.ljust(15), stop - start

I know that changing the sparsity of a matrix is usually expensive. 我知道更改矩阵的稀疏度通常很昂贵。 In principle I know the indices of the diagonal, but I don't know how to change the data, once it is stored in a scipy csc_matrix. 原则上,我知道对角线的索引,但是一旦将数据存储在scipy csc_matrix中,我就不知道如何更改数据。 But also the initialization of the Matrix is almost as expensive as solving the system? 但是,矩阵的初始化几乎和解决系统一样昂贵吗? For me the output of the example program is: 对我而言,示例程序的输出为:

Initialize: 0.516402959824 初始化:0.516402959824

Set diagonal: 1.67107796669 设置对角线:1.67107796669

Solve: 0.845117807388 解决:0.845117807388

Is there a way to get around the scipy sparse matrices or speeding this up? 有没有办法绕过稀疏的稀疏矩阵或加快速度呢? I thought about directly calling Pardiso, but this looked rather complicated for me. 我曾考虑过直接打电话给Pardiso,但对我来说,这似乎很复杂。

The computation time can be drastically reduced when initializing an instance of scipy.sparse.csc_matrix only once. 仅初始化一次scipy.sparse.csc_matrix实例一次,可以大大减少计算时间。 Instead of writing 而不是写作

J = csc_matrix((data, indices, indptr), shape=(13, 13))

in every iteration, it is better to write: 在每次迭代中,最好编写以下内容:

J.data = data
J.indices = indices
J.indptr = indptr

If the sparsity does not change and the indices of the diagonal are known, one can manipulate the data of the diagonal also directly instead of using the setdiag and diagonal property from scipy. 如果稀疏性没有变化并且对角线的索引已知,则可以直接使用对角线的数据,而不必使用scipy的setdiag和对角线属性。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM