使用 Rcpp 在 R 中使用矩阵有限制吗?

1 c++ r matrix rcpp

我试图用 R 开发一个程序来估计与 Rcpp 的 Spearman 相关性。我做到了,但它只适用于范围小于 45 00 - 50 000 个向量的矩阵。我不知道为什么,但它只适用于那个维度。我想这种类型的信息是有限制的,也许如果我像 data.frame 一样工作?如果有人给我见解,我将不胜感激。

在这里我发布我的代码。我一直试图限制我称之为“分母”的最大整数,它超过了它。也许你可以帮助我。

cppFunction('double spearman(NumericMatrix x){
 int nrow = x.nrow(), ncol = x.ncol();
 int nrow1 = nrow - 1;
 double out = 0;
 double cont = 0;
 double cont1 = 0;
 double r = 0;
 int denominador = ncol*(pow(ncol,2.0)-1)

 for(int i = 0; i < nrow1; i++){
 #Here i use every combination of vectors starting with the first one, and so on
  for(int j = i +1; j < nrow; j++){
   cont1 = 0;
   for(int t = 0; t < ncol; t++){
    cont = pow(x(i,t)-x(j,t), 2.0);
    cont1 += cont;
   }
   #Here i begin to store the mean correlation, in order to a final mean of all the possible correlations
   r = 2*(1-6*(cont1/denominador))/(nrow*nrow1);
   out += r;
  }
 }
 return out;
}')
Run Code Online (Sandbox Code Playgroud)

coa*_*ess 6

几个注意事项

在我们开始之前,我假设:

构建大 NumericMatrix

我认为您可能会遇到内存分配问题...

由于以下适用于我的 32GB 机器:

Rcpp::cppFunction("NumericMatrix make_matrix(){
                   NumericMatrix m(50000, 50000);
                   return m;
                  }")

m = make_matrix()

object.size(m)

## 20000000200 bytes # about 20.0000002 gb
Run Code Online (Sandbox Code Playgroud)

跑步:

# Creates an 18.6gb matrix!!!
m = matrix(0, ncol = 50000, nrow = 50000)

Rcpp::cppFunction("void get_length(NumericMatrix m){
                   Rcout << m.nrow() << ' ' << m.ncol(); 
            }")

get_length(m)
## 50000 50000

object.size(m)
## 20000000200 bytes # about 20.0000002 gb
Run Code Online (Sandbox Code Playgroud)

矩阵边界

理论上,您受到矩阵中元素总数小于 (2^31 - 1)^2 = 4,611,686,014,132,420,609 的限制:

数组(包括矩阵)可以基于长向量,前提是它们的每个维度最多为 2^31 - 1:因此没有一维长数组。

龙矢量

现在,拟合成一个矩阵:

m = matrix(nrow=2^31, ncol=1)
Run Code Online (Sandbox Code Playgroud)

矩阵错误(nrow = 2^31,ncol = 1):无效的“nrow”值(太大或不适用)

另外:警告消息:在矩阵(nrow = 2^31, ncol = 1) 中:

强制引入整数范围的 NA

极限都[RRCPP遵守关于列/行是:

.Machine$integer.max
## 2147483647
Run Code Online (Sandbox Code Playgroud)

请注意,通过 1 个数字,我们有:

2^31 = 2,147,483,648 > 2,147,483,647 = .Machine$integer.max

向量中元素的最大数量

但是,与 原子向量相关的限制为 2^52(即使它应该在 2 ^ 64 - 1 的范围内)。因此,我们有以下示例,它说明了通过连接两个 2^31 + 2^31 向量来访问 2^32 的能力:

v = numeric(2^31)
length(v)
## [1] 2147483648

object.size(v)
## 17179869224 bytes # about 17.179869224 gb

v2 = c(v,v)
length(v2)
## 4294967296

object.size(v2)
## 34359738408 bytes # about 34.359738408 gb
Run Code Online (Sandbox Code Playgroud)

建议

  1. 使用bigmemory通过Rcpp
  2. 维护自己的向量堆栈。


Dir*_*tel 6

更简洁地重复:

  1. 向量中可以有超过 2^31-1 个元素。

  2. 矩阵是具有dim属性的向量。

  3. 矩阵中可以有超过 2^31-1 个元素(即ntimes k

  4. 您的行和列索引仍限制为 2^31。

大向量的例子:

R> n <- .Machine$integer.max + 100
R> tmpVec <- 1:n
R> length(tmpVec)
[1] 2147483747
R> newVec <- sqrt(tmpVec)
R> 
Run Code Online (Sandbox Code Playgroud)