在 RcppArmadillo 中处理非常大和稀疏的矩阵

Handling extremely large and sparse matrices in RcppArmadillo

我正在尝试将对角矩阵 W 传递给 Rcpp 函数。问题是 W 的大小为 1,000,000 x 1,000,000,这(我认为)远远超出了 Armadillo 允许的限制(即使使用启用了 ARMA_64BIT_WORD 的 C++11 编译器)。

由于W是一个对角矩阵,它非常稀疏。出于这个原因,我首先生成了 W 的密集表示(使用 Matrix 包函数 Diagonal)。然后我将 W 的这些压缩表示传递给我的函数。我认为这可以解决任何内存问题。这是一个小例子:

C++代码:

#define ARMA_64BIT_WORD 1
#include <RcppArmadillo.h>
// [[Rcpp::depends(RcppArmadillo)]]
// [[Rcpp::plugins(cpp11)]]

using namespace Rcpp;
using namespace arma;


// [[Rcpp::export]]
int test(sp_mat W){
  
  return 0;
  
}

R代码:

# define the diagonal matrix
nrows <- 1e6
W <- Matrix::Diagonal(nrows)

# call Rcpp function
test(W)

然而,尽管使用了压缩表示,我仍然会收到此错误。

error: SpMat::init(): requested size is too large; suggest to compile in C++11 mode and/or enable ARMA_64BIT_WORD

有什么方法可以处理 W 以便我可以将它传递给 test 并执行矩阵运算吗?

有人问了一个类似的问题 。但是,我认为@Dirk 提供的解决方案在这种情况下有效,因为与我的 W.

相比,输入矩阵仍然很小

最初发布的代码实际上是正确的,但不知何故 运行 所在的机器却不正确——有关详细信息,请参阅上面的讨论。

作为 add-on,这里是代码的略微编辑版本,没有全局命名空间,实际访问矩阵(传递就足够了,这更明确)并返回 void。我们还添加了通常的 'call it from R for me' 技巧,人们可以使用 Rcpp 属性来做到这一点。

代码

// lightly edited version of question, working fine for me
#define ARMA_64BIT_WORD 1
#include <RcppArmadillo.h>
// [[Rcpp::depends(RcppArmadillo)]]

// [[Rcpp::export]]
void spmatTest(arma::sp_mat M) {
  // show a simple access of matrix,
  // here we just sum elements on diagonal
  Rcpp::Rcout << "Sum of diag is "
              << arma::as_scalar(arma::sum(M.diag()))
              << std::endl;
}

/*** R
spmatTest( Matrix::Diagonal( 1e6 ))
spmatTest( Matrix::Diagonal( 1e7 ))
spmatTest( Matrix::Diagonal( 1e8 ))
*/

输出

R> Rcpp::sourceCpp("~/git/Whosebug/64428776/answer.cpp")

R> spmatTest( Matrix::Diagonal( 1e6 ))
Sum of diag is 1e+06

R> spmatTest( Matrix::Diagonal( 1e7 ))
Sum of diag is 1e+07

R> spmatTest( Matrix::Diagonal( 1e8 ))
Sum of diag is 1e+08
R>