高效编程以克服R中的内存限制

时间:2014-09-18 22:32:35

标签: r

我有一个函数,用于计算二进制数据矩阵的R中的索引。此函数的目标是计算称为HT的二进制响应数据的人适合索引。它通过两个响应模式之间的最大可能协方差来划分两个响应者的响应向量之间的协方差(例如人 i & j ),这两个响应模式可以使用平均值来计算响应向量(例如Bi)。功能是:

fit<-function(Data){
        N<-dim(Data)[1]
        L<-dim(Data)[2]
        r <- rowSums(Data)          
        p.cor.n <- (r/L)    #proportion correct for each response pattern           
        sig.ij <- var(t(Data),t(Data)) #covariance of response patterns
        diag(sig.ij) <-0
        H.num <- apply(sig.ij,1,sum)
        H.denom1 <- matrix(p.cor.n,N,1) %*% matrix(1-p.cor.n,1,N)  #Bi(1-Bj)
        H.denom2 <- matrix(1-p.cor.n,N,1) %*% matrix(p.cor.n,1,N)  #(1-Bi)Bj
        H.denomm <- ifelse(H.denom1>H.denom2,H.denom2,H.denom1)
        diag(H.denomm) <-0
        H.denom <- apply(H.denomm,1,sum)
        HT <- H.num / H.denom
        return(HT)
        }

这个函数适用于小矩阵(例如1000乘20),但当我增加行数(例如10000)时,我遇到了内存限制问题。问题的根源是函数中的这一行:

H.denomm <- ifelse(H.denom1>H.denom2,H.denom2,H.denom1)

为每个响应模式选择分母。是否还有其他方法可以重写此行,这需要更低的内存?

P.S。:您可以尝试data<-matrix(rbinom(200000,1,.7),10000,20)

感谢。

2 个答案:

答案 0 :(得分:3)

这里有一种方法可以节省一点时间。总的来说,我仍然认为在你采取的方法方面可能有更好的理论答案......但是这里有。我编写了一个Rcpp函数,它专门实现了ifelse,就像你在上面使用它一样。它仅适用于您的示例中的方形矩阵。顺便说一下,我并没有真正尝试优化R ifelse,因为我很确定它已经调用了内部C函数。我只是很好奇,如果一个C ++函数被设计为完全按照你想要做的那样而且没有更多会更快。我刮了11秒钟。 (选择较大的值)。

C ++功能:

library(Rcpp)
library(inline)

    code <-"
        Rcpp::NumericMatrix x(xs);
        Rcpp::NumericMatrix y(ys);
        Rcpp::NumericMatrix ans (x.nrow(), y.ncol());
          int ii, jj;

          for (ii=0; ii < x.nrow(); ii++){
            for (jj=0; jj < x.ncol(); jj++){
          if(x(ii,jj) < y(ii,jj)){
           ans(ii,jj) = y(ii,jj);
          } else {
           ans(ii,jj) = x(ii,jj);
          }
         }
        }
        return(ans);"

    matIfelse <- cxxfunction(signature(xs="numeric",ys="numeric"),
                    plugin="Rcpp",
                    body=code) 

现在,如果您使用matIfelse替换上述函数中的ifelse,您可以尝试一下。例如:

     H.denomm <- matIfelse(H.denom1,H.denom2)

    # Time for old version to run with the matrix you suggested above matrix(rbinom(200000,1,.7),10000,20)
    #  user   system  elapsed 
    #  37.78  3.36    41.30 

    # Time to run with dedicated Rcpp function
    #  user   system  elapsed 
    #  28.25  0.96    30.22 

差不多大约快了36%,但我并没有声称这在一个非常具体的例子中通常比ifelse更快。干杯

P.s.我忘了提到要使用Rcpp,你需要安装Rtools,在安装过程中确保为Rtools和gcc添加了环境路径变量。在我的机器上,它们看起来像:c:\ Rtools \ bin; c:\ Rtools \ gcc-4.6.3 \ bin

编辑:

我刚注意到你遇到了内存问题...所以我不确定你是在运行32位还是64位机器,但你可能只需要允许R增加内存量就可以了可以使用。我假设您运行32位是安全的。所以你应该能够让R占用至少2g的RAM。尝试一下: memory.limit(size=1900) 大小以兆字节为单位,所以我只是为了安全而去了1.9场演出。我想象这是你需要的充足记忆。

答案 1 :(得分:0)

你真的打算做NxL独立ifelse((H.denom1>H.denom2,...操作吗?

H.denomm <- ifelse(H.denom1>H.denom2,H.denom2,H.denom1)

如果你真的这样做,寻找一个库,或者更好的分解。 如果你一般性地告诉我们这段代码试图做什么,那将有助于我们回答它。