稀疏矩阵存储格式总结+存储效率对比:COO,CSR,DIA,ELL,HYB

稀疏矩阵是指矩阵中的元素大部分是0的矩阵,事实上,实际问题中大规模矩阵基本上都是稀疏矩阵,不少稀疏度在90%甚至99%以上。所以咱们须要有高效的稀疏矩阵存储格式。本文总结几种典型的格式:COO,CSR,DIA,ELL,HYB。html

 

(1)Coordinate(COO)git

image

这是最简单的一种格式,每个元素须要用一个三元组来表示,分别是(行号,列号,数值),对应上图右边的一列。这种方式简单,可是记录单信息多(行列),每一个三元组本身能够定位,所以空间不是最优。github

 

(2)Compressed Sparse Row (CSR)数组

image

CSR是比较标准的一种,也须要三类数据来表达:数值,列号,以及行偏移。CSR不是三元组,而是总体的编码方式。数值和列号与COO一致,表示一个元素以及其列号,行偏移表示某一行的第一个元素在values里面的起始偏移位置。如上图中,第一行元素1是0偏移,第二行元素2是2偏移,第三行元素5是4偏移,第4行元素6是7偏移。在行偏移的最后补上矩阵总的元素个数,本例中是9。dom

 

CSC是和CSR相对应的一种方式,即按列压缩的意思。ui

以上图中矩阵为例:this

Values:        [1 5 7 2 6 8 3 9 4]编码

Row Indices:[0 2 0 1 3 1 2 2 3]spa

Column Offsets:[0 2 5 7 9].net

 

再来看一个CSR的例子[4]:

96202_2458312_1

 

(3)ELLPACK (ELL)

image

用两个和原始矩阵相同行数的矩阵来存:第一个矩阵存的是列号,第二个矩阵存的是数值,行号就不存了,用自身所在的行来表示;这两个矩阵每一行都是从头开始放,若是没有元素了就用个标志好比*结束。上图中间矩阵有误,第三行应该是  0 2 3。

 

注:这样若是某一行不少元素,那么后面两个矩阵就会很胖,其余行结尾*不少,浪费。能够存成数组,好比上面两个矩阵就是:

0 1 * 1 2 * 0 2 3 * 1 3 *

1 7 * 2 8 * 5 3 9 * 6 4 *

可是这样要取一行就比较不方便了

(4)Diagonal (DIA)

image

对角线存储法,按对角线方式存,列表明对角线,行表明行。省略全零的对角线。(从左下往右上开始:第一个对角线是零忽略,第二个对角线是5,6,第三个对角线是零忽略,第四个对角线是1,2,3,4,第五个对角线是7,8,9,第六第七个对角线忽略)。[3]

这里行对应行,因此5和6是分别在第三行第四行的,前面补上无效元素*。若是对角线中间有0,存的时候也须要补0,因此若是原始矩阵就是一个对角性很好的矩阵那压缩率会很是高,好比下图,可是若是是随机的那效率会很是糟糕。

imageimage

 

(5)Hybrid (HYB) ELL + COO

image

为了解决(3)ELL中提到的,若是某一行特别多,形成其余行的浪费,那么把这些多出来的元素(好比第三行的9,其余每一行最大都是2个元素)用COO单独存储。

 

选择稀疏矩阵存储格式的一些经验[2]:

  1. DIA和ELL格式在进行稀疏矩阵-矢量乘积(sparse matrix-vector products)时效率最高,因此它们是应用迭代法(如共轭梯度法)解稀疏线性系统最快的格式;
  2. COO和CSR格式比起DIA和ELL来,更加灵活,易于操做;
  3. ELL的优势是快速,而COO优势是灵活,两者结合后的HYB格式是一种不错的稀疏矩阵表示格式;
  4. 根据Nathan Bell的工做,CSR格式在存储稀疏矩阵时非零元素平均使用的字节数(Bytes per Nonzero Entry)最为稳定(float类型约为8.5,double类型约为12.5),而DIA格式存储数据的非零元素平均使用的字节数与矩阵类型有较大关系,适合于StructuredMesh结构的稀疏矩阵(float类型约为4.05,double类型约为8.10),对于Unstructured Mesh以及Random Matrix,DIA格式使用的字节数是CSR格式的十几倍;
  5. 从我使用过的一些线性代数计算库来讲,COO格式经常使用于从文件中进行稀疏矩阵的读写,如matrix market即采用COO格式,而CSR格式经常使用于读入数据后进行稀疏矩阵计算。

 

一些特殊类型矩阵的存储效率(数值越小说明压缩率越高,即存储效率越高):

Structured Mesh

image

Unstructured Mesh

image

Random matrix

image

Power-Law Graph

image

 

格式适用性总结:

image

 

 

下面摘自[2]

6. Skyline Storage Format

The skyline storage format is important for the direct sparse solvers, and it is well suited for Cholesky or LU decomposition when no pivoting is required.

The skyline storage format accepted in Intel MKL can store only triangular matrix or triangular part of a matrix. This format is specified by two arrays:values andpointers. The following table describes these arrays:

values

A scalar array. For a lower triangular matrix it contains the set of elements from each row of the matrix starting from the first non-zero element to and including the diagonal element. For an upper triangular matrix it contains the set of elements from each column of the matrix starting with the first non-zero element down to and including the diagonal element. Encountered zero elements are included in the sets.

pointers

An integer array with dimension(m+1), where m is the number of rows for lower triangle (columns for the upper triangle).pointers(i) -pointers(1)+1gives the index of element invalues that is first non-zero element in row (column)i. The value ofpointers(m+1)is set tonnz+pointers(1), wherennz is the number of elements in the arrayvalues.

7. Block Compressed Sparse Row Format (BSR)

The Intel MKL block compressed sparse row (BSR) format for sparse matrices is specified by four arrays:values,columns,pointerB, andpointerE. The following table describes these arrays.

values

A real array that contains the elements of the non-zero blocks of a sparse matrix. The elements are stored block-by-block in row-major order. A non-zero block is the block that contains at least one non-zero element. All elements of non-zero blocks are stored, even if some of them is equal to zero. Within each non-zero block elements are stored in column-major order in the case of one-based indexing, and in row-major order in the case of the zero-based indexing.

columns

Element i of the integer array columns is the number of the column in the block matrix that contains thei-th non-zero block.

pointerB

Element j of this integer array gives the index of the element in thecolumns array that is first non-zero block in a rowj of the block matrix.

pointerE

Element j of this integer array gives the index of the element in thecolumns array that contains the last non-zero block in a rowj of the block matrix plus 1.

 

 

 

 

[1] Sparse Matrix Representations & Iterative Solvers, Lesson 1 by Nathan Bell. http://www.bu.edu/pasi/files/2011/01/NathanBell1-10-1000.pdf

[2] http://blog.csdn.net/anshan1984/article/details/8580952

[3] http://zhangjunhd.github.io/2014/09/29/sparse-matrix.html

[4] http://www.360doc.com/content/09/0204/17/96202_2458312.shtml

[5] Implementing Sparse Matrix-Vector Multiplication on Throughput-Oriented Processors, Nathan Bell and Michael Garland, Proceedings of Supercomputing '09

[6] Efficient Sparse Matrix-Vector Multiplication on CUDA, Nathan Bell and Michael Garland, NVIDIA Technical Report NVR-2008-004, December 2008

相关文章
相关标签/搜索