如何计算稀疏矩阵 - 矩阵乘积?我知道这样做的“经典”/数学方法,但看起来效率很低。可以改进吗?
我想过以CSR形式存储第一个矩阵而第二个以CSC格式存储,所以由于行和列向量已经排序,我不需要搜索我需要的特定行/列,但我猜没什么用。
答案 0 :(得分:8)
免责声明(i)你真的不想实现你自己的稀疏矩阵包,(ii)如果你还需要,你应该阅读蒂姆戴维斯关于稀疏线性代数的书,这里是如何进行稀疏矩阵乘法的。
通常天真的密集乘法看起来像这样。
C = 0
for i {
for j {
for k {
C(i, j) = C(i, j) + (A(i, k) * B(k, j))
}
}
}
由于添加通勤,我们可以按照我们喜欢的方式置换循环索引。我们将j
置于最外层,i
置于最里面。
C = 0
for j {
for k {
for i {
C(i, j) = C(i, j) + (A(i, k) * B(k, j))
}
}
}
以CSC格式存储所有矩阵。由于j
位于最外层,因此我们会在B
和C
(但不是A
)上一次一列地工作。中间循环超过k
,这是B
行,而且很方便,我们不需要访问零B
的条目。这使得外部两个循环以自然顺序遍历B
的非零项。内部循环将j
的{{1}}列增加C
k
次A
列。为了简化这一过程,我们将当前列B(k, j)
密集存储,并将此列非零的索引集合存储为列表/密集布尔数组。我们通过通常的隐式初始化技巧避免编写所有C
或布尔数组。