在 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>
我正在尝试将对角矩阵 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
并执行矩阵运算吗?
有人问了一个类似的问题 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>