稀疏矩阵-向量乘法的压缩稀疏行(CSR)存储格式优化算法
题目描述
在科学计算和工程应用中,大型稀疏线性方程组的求解常依赖于Krylov子空间迭代法(如共轭梯度法、GMRES等),其核心计算开销之一是稀疏矩阵-向量乘法(SpMV)。压缩稀疏行(CSR)格式是一种广泛使用的稀疏矩阵存储格式。本题目要求:详细阐述CSR格式的存储原理,并设计一种优化算法,通过重排序矩阵行(或列)来提升SpMV操作的缓存局部性,从而加速计算。请逐步讲解该优化算法的设计思路、步骤及效果分析。
解题过程
1. CSR存储格式基础
CSR格式用三个数组表示一个\(m \times n\)的稀疏矩阵:
val:存储所有非零元素的值,按行优先顺序排列。col_ind:存储每个非零元素对应的列索引。row_ptr:长度为\(m+1\)的数组,其中row_ptr[i]表示第\(i\)行(0-based)在val和col_ind中的起始位置,row_ptr[i+1] - row_ptr[i]即为第\(i\)行的非零元个数。
例如矩阵
\[A = \begin{pmatrix} 10 & 0 & 0 & 0 \\ 0 & 20 & 30 & 0 \\ 0 & 0 & 0 & 40 \\ 50 & 0 & 60 & 0 \end{pmatrix} \]
的CSR表示为:
val = [10, 20, 30, 40, 50, 60]
col_ind = [0, 1, 2, 3, 0, 2]
row_ptr = [0, 1, 3, 4, 6]
2. SpMV操作与性能瓶颈
SpMV计算\(y = A x\)的伪代码如下:
for i = 0 to m-1:
y[i] = 0
for k = row_ptr[i] to row_ptr[i+1]-1:
y[i] += val[k] * x[col_ind[k]]
性能瓶颈:
- 内存访问不规则:
x[col_ind[k]]的访问是随机且不连续的,导致缓存命中率低。 - 并行化时负载不均衡:若某些行非零元远多于其他行(如稀疏矩阵中的“稠密行”),在并行计算中会引起线程负载不均。
3. 优化思路:行重排序
目标:通过对矩阵行进行重排,使得相邻行访问的x向量的元素尽可能相近,从而提升缓存局部性。
基本思想:将非零元列索引相近的行分组存储,这样在连续处理多行时,对向量x的访问会集中在较窄的地址范围内,提高缓存重用率。
算法步骤:
步骤1:计算行的“特征向量”
为每一行\(i\)定义一个特征向量\(f_i\),表示该行非零元的列索引集合。常用简化特征:
- 使用该行非零元列索引的最小值(或平均值)作为代表值。
- 或直接使用列索引集合(如位图表示)。
步骤2:聚类分组
根据特征向量对行进行聚类。例如:
- 按列索引范围分组:设定一个列索引区间大小\(B\),将列索引落在同一区间内的行归为一组。
- 贪心重排:从第一行开始,依次将当前行与其后所有行比较,选择列索引重叠度最高(即共同访问
x中相同位置)的行作为下一行。重叠度可通过列索引集合的交集大小衡量。
步骤3:重排矩阵
按照聚类结果对行顺序重新排列,生成新的CSR格式。注意:
- 仅重排行顺序,不改变每行内部的列索引顺序。
- 对应的右端向量(若存在)的行也需要同步重排。
步骤4:SpMV计算调整
使用重排后的CSR矩阵进行SpMV,算法不变,但缓存性能提升。
4. 算法示例
考虑矩阵:
\[A = \begin{pmatrix} 0 & a_{12} & 0 & 0 \\ a_{21} & 0 & a_{23} & 0 \\ 0 & 0 & 0 & a_{34} \\ 0 & a_{42} & 0 & a_{44} \end{pmatrix} \]
原始行顺序为[0,1,2,3]。
- 行0访问列1,行1访问列0和2,行2访问列3,行3访问列1和3。
- 若按列索引重叠度贪心重排:
- 从行0开始(访问列1)。
- 行3也访问列1,重叠度最高,故置为下一行。
- 剩余行1和行2,行1访问列0、2,与当前最后一行(行3)无重叠;行2访问列3,与行3重叠(列3),故选择行2。
- 最后放行1。
新顺序为[0,3,2,1]。此时连续处理行0和行3时,均需访问x[1],该值可能已缓存。
5. 效果分析
- 缓存命中率:重排后,对
x的访问局部性增强,L1/L2缓存未命中率下降。 - 负载均衡:若结合行分块,可将非零元数量相近的行分到同一线程块,提升并行效率。
- 局限性:重排序本身需要额外计算,适用于需要多次SpMV的迭代求解器(如迭代法求解线性方程组),以分摊重排序开销。
- 扩展:可结合列重排序或使用图划分工具(如METIS)对矩阵对应的图进行划分,进一步优化。
总结
该优化算法通过重排行顺序改善SpMV的内存访问模式,是一种典型的“数据布局优化”技术。实际应用中,常与分块、循环展开等技术结合,在现代处理器上可获得显著的加速比。