简体   繁体   English

快速稀疏矩阵乘法

[英]Fast sparse matrix multiplication

for class I have to write my own linear equation solver for sparse matrices. 对于类,我必须为稀疏矩阵编写自己的线性方程求解器。 I am free to use any type of data structure for sparse matrices and I have to implement several solves, including conjuguate gradient. 我可以自由地为稀疏矩阵使用任何类型的数据结构,我必须实现几个解,包括共轭渐变。

I was wondering if there is a famous way to store sparse matrices such that multiplication with a vector is relatively fast. 我想知道是否有一种着名的方法来存储稀疏矩阵,使得与向量的乘法相对较快。

Right now my sparse matrices are basically implemented a wrapped std::map< std::pair<int, int>, double> which stores the data, if any. 现在我的稀疏矩阵基本上实现了一个包装的std::map< std::pair<int, int>, double> ,它存储数据(如果有的话)。 This transforms the multiplication of a matrix with from vector to a O(n²) complexity to a O(n²log(n)) as I have to perform look-up for each matrix elements. 这将矩阵与向量的乘法转换为O(n²)复杂度到O(n²log(n)),因为我必须对每个矩阵元素进行查找。 I've looked into the Yale Sparse matrix format and it seems that retrieval of an element is also in O(log(n)) so I'm not sure if it would be much faster. 我查看了耶鲁稀疏矩阵格式,似乎元素的检索也在O(log(n))中,所以我不确定它是否会更快。

For reference I have a 800x800 matrix that is populated with 5000 entries. 作为参考,我有一个800x800矩阵,填充了5000个条目。 It takes roughly to 450 seconds solve such a system with the conjugate gradient method. 使用共轭梯度法大约需要450秒来解决这样的系统。

Do you think it's possible to do it much quicker with another data structure? 您认为使用其他数据结构可以更快地完成吗?

thanks! 谢谢!

The most common choices are CSC or CSR storage . 最常见的选择是CSC或CSR存储 These are both efficient for matrix-vector multiplication. 这些对于矩阵向量乘法都是有效的。 It's also very easy to code those multiplication routines, if you have to do it yourself. 如果你必须自己编写,那么编写这些乘法例程也很容易。

That said, Yale storage also yields very efficient matrix-vector multiply. 也就是说,耶鲁存储也产生非常有效的矩阵向量乘法。 If you are performing matrix element lookup, then you have misunderstood how to use the format. 如果您正在执行矩阵元素查找,那么您误解了如何使用该格式。 I suggest you study some of the standard sparse libraries to learn how matrix-vector multiplication is implemented. 我建议你研究一些标准的稀疏库来学习如何实现矩阵向量乘法。

Even with your current storage you can perform matrix multiplication in O(n) complexity. 即使使用当前存储,您也可以执行O(n)复杂度的矩阵乘法。 All sparse matrix-vector multiplication algorithms that I have ever seen boil down to the same steps. 我见过的所有稀疏矩阵向量乘法算法归结为相同的步骤。 For example consider y = Ax. 例如,考虑y = Ax。

  1. Zeroise the result vector, y. 将结果向量归零,y。
  2. Initialise an iterator for the non-zero elements of the matrix, A. 初始化矩阵的非零元素的迭代器,A。
  3. Get the next non-zero element of the matrix, A[i,j] say. 得到矩阵的下一个非零元素,A [i,j]说。 Note that the pattern of i,j doesn't follow a regular pattern. 请注意,i,j的模式不遵循常规模式。 It simply reflects the order in which the non-zero elements of A are stored. 它只是反映了存储A的非零元素的顺序。
  4. y[i] += A[i,j]*x[j] y [i] + = A [i,j] * x [j]
  5. If there are more elements of A, goto 3. 如果有更多A元素,请转到3。

I suspect you are writing the classic double for loop dense multiplication code: 我怀疑你正在编写经典的双循环密集乘法代码:

for (i=0; i<N; i++)
    for (j=0; j<N; j++)
        y[i] += A[i,j]*x[j]

and that's what is leading you to perform lookups. 这就是导致你执行查找的原因。

But I'm not suggesting that you stick with your std::map storage. 但我并不是说你坚持使用std::map存储。 That's not going to be super efficient. 这不会超级高效。 I'd recommend CSC mainly because it is the most widely used. 我推荐CSC主要是因为它是使用最广泛的。

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

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