稀疏矩阵是否通常存储在列主要顺序或行主要顺序中?

时间:2016-05-18 20:43:21

标签: matlab matrix sparse-matrix hpc blas

一点背景:我有兴趣对稀疏矩阵*向量乘法进行一些研究。

我一直在浏览这个稀疏矩阵数据库:

The University of Florida Sparse Matrix Collection

我注意到矩阵有3种格式:

  1. MATLAB(.mat)
  2. Matrix Market(.mtx)
  3. Harwell-Boeing(.rb)
  4. 似乎矩阵以列主要顺序存储(即,列一个接一个地存储,而不是彼此紧接着存储)。然而,在文献中看来,压缩的稀疏行(CSR)格式显然是最常见的格式(参见“Cell Processor Samuel上的科学计算内核”)。我知道只是索引(i,j)和那些坐标处的值被存储,但我想我必须首先重新格式化数据才能有效地执行矩阵*向量乘法。

    对于我的实现,将数据存储在行主要顺序中更有意义,以便可以按顺序访问行中的元素,因为它们将存储在连续的内存地址中。

    CSR格式似乎假设数据按行主顺序存储。所以我想知道的是: 如何将数据存储在稀疏矩阵的内存中?部分稀疏矩阵*向量计算是否涉及将数据从列主要重组为行主要顺序? 我问,因为我想知道这种转换是否通常在稀疏矩阵基准测试结果中考虑。

2 个答案:

答案 0 :(得分:3)

恐怕没有简短的回答。最佳存储方案取决于您尝试解决的问题。需要考虑的事项不仅是存储大小,还包括从计算和硬件角度来看,这种存储格式的访问和操作的效率。

对于稀疏矩阵向量乘法CSR是一种很好的格式,因为它允许线性访问矩阵行的元素,这有利于内存和缓存性能。然而,CSR会在被乘数中引入更不规则的访问模式:取不同于从行检索的索引,在不同位置获取元素;这对缓存性能不利。 CSC矩阵向量乘法可以去除被乘数上的不规则访问,代价是在解向量中更不规则的访问。根据您的矩阵结构,您可以选择一个或另一个。例如,具有几个长行的具有类似非零分布的矩阵在CSC格式中处理可能更有效。

众所周知的软件包/工具中的一些例子:

  1. 据我所知,Matlab默认使用列存储。
  2. 基于Fortran的科学代码(和BLAS)默认使用列存储。这主要是由于历史原因,因为Fortran数组是以AFAIK列为导向的,并且大量的Dense / Sparse BLAS代码最初是用Fortran编写的。

  3. Eigen默认情况下也会使用列存储,但这可以自定义。

  4. Intel MKL要求您选择IIRC。

  5. Boost ublas默认使用基于行的存储格式。

  6. PetSC,是大规模科学计算中广泛使用的工具,使用a row based format(SequentialAIJ代表CSR),但也允许您从多种类型中进行选择存储格式(参见documentation上的MatCreate *函数)

  7. 列表可以继续。正如您所看到的,各种工具之间存在一些差异,我怀疑标准是SpMV操作的性能:)可能是诸如目标问题域中的常见存储格式,目标问题域中程序员的典型期望等方面,与其他库方面的集成和已有的代码一直是使用CSR / CSC的主要原因。显然,这些因工具而异。

    无论如何,可以找到关于稀疏存储格式的简短概述here,但在稀疏矩阵研究中提出了更多的存储格式:

    • 还有块存储格式,它试图利用矩阵的局部密集子结构。例如,参见Richard W. Vuduc,Hyun-Jin Moon的“快速稀疏矩阵 - 通过利用可变块结构的向量乘法”。
    • 关于稀疏格式scipy的Python http://docs.scipy.org/doc/scipy/reference/sparse.html文档中可以找到一些非常简短但有用的常见存储格式概述。
    • 有关各种格式优势的更多信息,请参阅以下文本(以及许多其他文本):
      • 稀疏线性系统的迭代方法,Yousef Saad
      • SPARSKIT:用于稀疏矩阵计算的基本工具包,Tech。 Rep.CSRD TR 1029,CSRD,伊利诺伊大学,厄巴纳,伊利诺伊州,1990年。
      • LAPACK工作说明50:用于线性代数运算的分布式稀疏数据结构,Tech。田纳西大学计算机科学系,1992年,诺克斯维尔,1992年,代表CS 92-169。

    我一直在稀疏矩阵领域进行研究,为稀疏矩阵算法(如SpMV)创建自定义硬件架构。根据经验,一些稀疏矩阵基准测试往往忽略了各种格式之间转换的开销。这是因为原则上可以假设您可以调整整个算法的存储格式。 SpMV本身很难单独使用,并且通常是一些较大迭代算法的一部分(例如,线性或非线性求解器)。在这种情况下,格式之间转换的成本可以在整个算法的许多迭代和总运行时间内分摊。当然,你必须证明你的假设在这种情况下是正确的。

    作为免责声明,在我所在的区域,我们特别倾向于尽可能多地做出假设,因为为线性求解器实现硬件架构的成本和时间来对新的SpMV存储格式进行基准测试通常是实质性的(大约几个月)。在软件中工作时,通过运行尽可能多的基准来测试,鉴定和量化您的假设要容易得多,这可能需要不到一周的时间来设置:D

答案 1 :(得分:0)

这不是答案,但不能写在评论中。最佳表示格式取决于底层实现。例如,

M = [m_11 m_12 m_13; == [r1; == [c1 c2 c3]
     m_21 m_22 m_23]     r2]

其中r1,2是行,c1,2,3是列 和

v = [v1;
     v2;
     v3]

您可以将M * v实现为

M*v = [r1.v;
       r2.v]

作为矢量的点积,或

M*v = v1*c1 + v2*c2 + v3*c3

其中*是标量向量乘法。

您可以根据矩阵的稀疏度选择格式,从而最大限度地减少操作次数。通常,行/列越少越好。