假设CSR存储格式,我有以下C中稀疏矩阵向量(SpMV)乘积的代码:
void dcsrmv(SparseMatrixCSR *A, double *x, double *y) {
for (int i=0; i<A->m; i++) {
double sum = 0.;
for (int jj=A->row_start[i]; jj<A->row_start[i+1]; jj++) {
sum += A->val[jj] * x[A->col_idx[jj]];
}
y[i] = sum;
}
}
当我使用数组运行此函数100次时
ecology1
从SuiteParse矩阵集合中,平均运行时间为5.9毫秒,而如果我运行MKL
mkl_sparse_d_mv
函数的平均运行时间为8.4ms。
现在,我想为相同的存储格式提供一个稀疏矩阵多矢量(SpMM)乘积函数,我用以下3种方法对其进行了编码:
void dcsrmm0(SparseMatrixCSR *A, double *X, double *Y, int nvec) {
for (int vec=0; vec<nvec; vec++) {
double *x = X + vec * A->n;
double *y = Y + vec * A->m;
for (int i=0; i<A->m; i++) {
double sum = 0.;
for (int jj=A->row_start[i]; jj<A->row_start[i+1]; jj++) {
sum += A->val[jj] * x[A->col_idx[jj]];
}
y[i] = sum;
}
}
}
void dcsrmm1(SparseMatrixCSR *A, double *X, double *Y, int nvec) {
for (int i=0; i<A->m; i++) {
for (int vec=0; vec<nvec; vec++) {
double sum = 0.;
double *x = X + vec * A->n;
double *y = Y + vec * A->m;
for (int jj=A->row_start[i]; jj<A->row_start[i+1]; jj++) {
sum += A->val[jj] * x[A->col_idx[jj]];
}
y[i] = sum;
}
}
}
和
void dcsrmm2(SparseMatrixCSR *A, double *X, double *Y, int nvec) {
double *x[nvec], *y[nvec];
for (int vec=0; vec<nvec; vec++) x[vec] = X + vec * A->n;
for (int vec=0; vec<nvec; vec++) y[vec] = Y + vec * A->m;
double sum[nvec];
for (int i=0; i<A->m; i++) {
for (int vec=0; vec<nvec; vec++) sum[vec] = 0.;
for (int jj=A->row_start[i]; jj<A->row_start[i+1]; jj++) {
for (int vec=0; vec<nvec; vec++) {
sum[vec] += A->val[jj] * x[vec][A->col_idx[jj]];
}
}
for (int vec=0; vec<nvec; vec++) y[vec][i] = sum[vec];
}
}
哪里
X
和
Y
按列存储。
然后我用
nvec=10
.在这种情况下
dcsrmm0
平均耗时49.8ms,
dcsrmm1
平均耗时38.3ms,并且
dcsrmm2
平均耗时34.8毫秒,而
mkl_sparse_d_mm
只需26.7ms。
所以我的问题是,为什么我的实施
dcsrmv
做得比
mkl_sparse_d_mv
,但是我的
dcsrmm0-2
功能落后太多
mkl_sparse_d_mm
? 我可以做些什么来改进这些功能?