我很好奇为什么将稀疏矩阵乘以稠密矩阵所花的时间与相反的时间不同。算法明显不同吗?
以下是matlab 2018a中的示例:
a=sprand(M,M,0.01);
b=rand(M);
tic;ref1=a*b;t_axb=toc
tic;ref2=b*a;t_bxa=toc
下面是使用1个线程的Eigen 3和C ++的示例:
//prepare acol=MxM ColMajor Eigen sparse matrix with 0.01 density
...
Map<Matrix<double,M,M,ColMajor> > bcol (PR, M, M );
double tic,toc;
tic=getHighResolutionTime();
result=acol*bcol;
toc=getHighResolutionTime();
printf("\nacol*bcol time: %f seconds", (toc - tic));
tic=getHighResolutionTime();
result=bcol*acol;
toc=getHighResolutionTime();
printf("\nbcol*acol time: %f seconds\n", (toc - tic));
当M = 4000时,结果为:
t_axb =
0.6877
t_bxa =
0.4803
acol*bcol time: 0.937590 seconds
bcol*acol time: 0.532622 seconds
当M = 10000时,结果为
t_axb =
11.5649
t_bxa =
9.7872
acol*bcol time: 20.140380 seconds
bcol*acol time: 8.061626 seconds
在两种情况下,对于Matlab和Eigen而言,稀疏产品的速度都比稠密产品的速度慢。我对
很好奇为什么会这样?稀疏算法与稀疏算法是否有显着差异? FLOP的数量是一样的,对吧?
为什么对于稀疏产品而言,本征值等于或超过Matlab的性能,而对于稀疏产品而言,本征值为什么不匹配或超过Matlab?性能上的细微差异是正常的,但考虑到两者都是高度优化的库,相差约1.4-1.8似乎很奇怪。我正在根据文档进行所有优化的本征编译。即-fPIC -fomit-frame-pointer -O3 -DNDEBUG -fopenmp -march=native
答案 0 :(得分:4)
通过比较稀疏矩阵乘以矢量乘积y = A * x
的列主存储和行主存储,您可以观察到相同的差异。如果A
是主要行(等效于y
的每个系数),则可以并行处理A
的每一行,而不会产生任何开销(无需通信,无需额外的临时操作,无需额外的操作) )。相比之下,如果A
是主要列多线程,则不能免费获得,在大多数情况下,开销要大于收益。
即使没有多线程,您也会看到内存访问模式非常不同:
x
的多个随机只读访问,y
的每个系数只能写一次。x
的每个系数都读取一次,但是我们对目标y
进行了多次随机读写访问。因此,即使没有多线程,这种情况自然也适合行优先。