我想知道是否有一种快速有效的方法来预先确定稀疏矩阵乘法运算的非零数,假设两个矩阵都为CSC或CSR格式。
我知道smmp包中有一个,但是我需要已经用C或C ++实现的东西。
任何帮助将不胜感激。提前致谢。
我想知道是否有一种快速有效的方法来预先确定稀疏矩阵乘法运算的非零数,假设两个矩阵都为CSC或CSR格式。
我知道smmp包中有一个,但是我需要已经用C或C ++实现的东西。
任何帮助将不胜感激。提前致谢。
Answers:
您可以通过形成两个稀疏模式的乘积来模拟矩阵矩阵乘积,即,您将稀疏模式(以CSR格式存储在单独的数组中)视为包含零或一的矩阵。每个条目。执行此模拟产品仅需要您形成和对这些零和一进行运算,因此比实际的矩阵矩阵乘积要快得多-实际上,您要做的就是遍历两个矩阵的行和列,并验证在一个矩阵中至少有一个条目行和列乘以两个矩阵都不为零的位置。这是一种便宜的操作-在任何情况下都比在实际产品中实际进行浮点乘法要便宜得多,这不仅需要您进行浮点算术(昂贵),而且还需要从内存中读取实际的浮点数(甚至更昂贵,但是在乘以稀疏模式时您不需要这样做,因为矩阵的非零值分别存储在CSR中)。
我实际上是在Matlab中为A * B(A和B稀疏)编写了原始代码。预分配结果空间确实是有趣的部分。我们观察到Godric指出的内容-知道AB中的非零数与计算AB一样昂贵。
我们在1990年左右进行了稀疏Matlab的最初实现,随后Edith Cohen的论文提出了第一种实用,快速的方法来准确估算AB的大小。我们将大小估算器放在一起,如果我们在计算中用尽了空间,则将分配加倍,并复制部分计算的结果。
我不知道Matlab现在有什么。
另一种可能性是一次计算AB一列。每列都可以临时存储在稀疏累加器中(有关这些解释,请参见稀疏Matlab论文),并分配空间以容纳结果列的确切已知大小。结果将是分散的压缩稀疏列形式-CSC中的每个列但没有列间连续性-使用2个长度为numcols的向量(col start,col length)而不是一个向量作为元数据。它的存储形式可能值得一看;它具有另一种优势-您可以在不重新分配整个矩阵的情况下增加一列。
此论文描述一种算法,以从两个稀疏矩阵的矩阵乘积近似所得的大小。
在稀疏矩阵乘法中找到确切数量的非零条目的问题是结果中的每个元素都取决于两个向量的相互作用,这两个向量都可能包含至少几个非零元素。因此,要计算数量,您需要为结果中的每个元素评估一对向量的逻辑运算。这样做的问题是,它需要许多运算,这些运算与计算矩阵乘积本身所需的运算数量相似。在我的评论中,我提到了利用原始矩阵的非零元素中某些结构的可能性,但是这些相同的利用也可以用来减少矩阵乘法中的工作。
您可能会更好地使用上述论文来高估内存需求,进行乘法运算,然后截断分配的内存,或者将结果矩阵移到大小更合适的数组中。同样,稀疏矩阵乘积也不是罕见的情况,我几乎可以保证这个问题之前已经得到解决。稍微研究一些开放源代码的稀疏矩阵库应该使您了解它们用于预分配内存的算法。
对于CSR或CSC,是否可以保证矩阵元素数组不存在零?在这种情况下,使用类似于以下内容的方法很容易找出有多少个非零元素:
int nnz = sizeof(My_Array)/sizeof(long int);
但是,如果不是这种情况(似乎有点容易),则可以尝试减少。如果矩阵元素数组很大,这可能是计算非零元素数量的最有效方法。许多并行的C / C ++库(例如Thrust(CUDA库)或OpenCL(您不需要GPU即可使用))都支持条件约简-为每个元素添加结果Condition(Element)
。如果将条件设置为,Element != 0
则将添加非零元素的数量。您可能还希望从元素数组,行/列索引数组中删除零值元素,并调整列/行指针。
实施CSR的最简单方法是尝试
std::vector< std::map<int, complex<float>> >
代表你的矩阵。在这种情况下,您不必担心非零元素的数量,所有元素都可以通过访问
std::map< int, complex<float> >::iterator
在每一行上。最好 ..