Rcpp中的元素明确矩阵乘法

时间:2013-02-14 08:23:07

标签: c++ r rcpp

我正在尝试使用R来加速Rcpp代码,该代码采用长度为L(psi)的向量和一个维度矩阵(L,L),并执行一些元素操作。有没有更有效的方法来使用Rcpp进行这些元素操作?

r:

 UpdateLambda <- function(psi,phi){
                                      # updated full-day infection probabilites
    psi.times.phi <- apply(phi,1,function(x) x*psi)
    ## return Lambda_{i,j} = 1 - \prod_{j} (1 - \psi_{i,j,t} \phi_{i,j})
    apply(psi.times.phi,2,function(x) 1-prod(1-x))
  }

CPP:

#include <Rcpp.h>
#include <algorithm>
using namespace Rcpp;


// [[Rcpp::export]]
NumericVector UpdateLambdaC(NumericVector psi,
                NumericMatrix phi
                ){

  int n = psi.size();
  NumericMatrix psi_times_phi(n,n);
  NumericVector tmp(n,1.0);
  NumericVector lambda(n);

  for(int i=0; i<n;i++){
    psi_times_phi(i,_) = psi*phi(i,_);
   }

  for(int i=0; i<n;i++){
     // \pi_{j} (1- \lambda_{i,j,t})
    for(int j=0; j<n;j++){
      tmp[i] *= 1-psi_times_phi(i,j);
    }
     lambda[i] = 1-tmp[i];
  }

  return lambda;
}

1 个答案:

答案 0 :(得分:1)

您可以使用矢量化替代方案替换apply循环。

第一个相当于:

t(phi)*psi

第二个:

1-exp(colSums(log(1-psi.times.phi)))

#test data
phi <- matrix(runif(1e6),1e3)
psi <- runif(1e3)

#new function
UpdateLambda2 <- function(psi,phi) 1-exp(colSums(log(1-t(phi)*psi)))

#sanity check
identical(UpdateLambda(psi,phi),UpdateLambda2(psi,phi))
[1] TRUE

#timings
library(rbenchmark)
benchmark(UpdateLambda(psi,phi),UpdateLambda2(psi,phi))
                     test replications elapsed relative user.self sys.self
1  UpdateLambda(psi, phi)          100   16.05    1.041     15.06     0.93
2 UpdateLambda2(psi, phi)          100   15.42    1.000     14.19     1.19

好吧,它似乎没有太大的区别,这是非常令人惊讶的,因为colSums通常比apply快得多。我不确定我使用的测试数据是否相关,因为输出是全部1的第二部分中由于数量小于1的乘法数。如果你想记下这些小数字的细节,你最好还是以对数比例工作。