我刚刚发现了一件事情。在Armadillo中,将密集矩阵乘以稀疏矩阵的速度比将稀疏矩阵乘以密集矩阵慢得多(即颠倒顺序)。
// [[Rcpp::depends(RcppArmadillo)]]
#include <RcppArmadillo.h>
// [[Rcpp::export]]
arma::sp_mat mult_sp_den_to_sp(arma::sp_mat& a, arma::mat& b)
{
// sparse x dense -> sparse
arma::sp_mat result(a * b);
return result;
}
// [[Rcpp::export]]
arma::sp_mat mult_den_sp_to_sp(arma::mat& a, arma::sp_mat& b)
{
// dense x sparse -> sparse
arma::sp_mat result(a * b);
return result;
}
我正在使用RcppArmadillo包将Arma与R进行接口交互;RcppArmadillo.h
包含armadillo
。以下是在R中对一些相当大的矩阵进行计时的结果:
set.seed(98765)
# 10000 x 10000 sparse matrices, 99% sparse
a <- rsparsematrix(1e4, 1e4, 0.01, rand.x=function(n) rpois(n, 1) + 1)
b <- rsparsematrix(1e4, 1e4, 0.01, rand.x=function(n) rpois(n, 1) + 1)
# dense copies
a_den <- as.matrix(a)
b_den <- as.matrix(b)
system.time(mult_sp_den_to_sp(a, b_den))
# user system elapsed
# 508.66 0.79 509.95
system.time(mult_den_sp_to_sp(a_den, b))
# user system elapsed
# 13.52 0.74 14.29
因此,第一个乘法比第二个乘法慢了约35倍(所有时间以秒为单位)。
有趣的是,如果我只是暂时地制作一个稀疏矩阵的副本,性能会大大提高:
// [[Rcpp::export]]
arma::sp_mat mult_sp_den_to_sp2(arma::sp_mat& a, arma::mat& b)
{
// sparse x dense -> sparse
// copy dense to sparse, then multiply
arma::sp_mat temp(b);
arma::sp_mat result(a * temp);
return result;
}
system.time(mult_sp_den_to_sp2(a, b_den))
# user system elapsed
# 5.45 0.41 5.86
这是预期的行为吗?我知道在稀疏矩阵中,你做事情的确切方式对代码的效率有很大的影响,比密集矩阵更加明显。但是速度相差35倍似乎有些太大了。