使用 Rcpp 提高 R 程序的性能

Improve performance of the R program using Rcpp

我正在尝试加速我的 R 代码 - 我想知道这是否可以在 Rcpp 中完成。这是我开始写的代码。

library(Rcpp)

cppFunction('int cont.run_C(int reps=10000,int n=10000,int d=0.005,int l=10 ,int s=0.1) {
  r = rep(0, reps)
  theta = rep(0, n)
  for(int t = 0; t < reps; t++) {
    epsilon = rnorm(1, 0, d)
    Zt = sum(epsilon > theta ? 1 : epsilon < -theta ? -1: 0)
    r[t] = Zt / (l * n)
    theta = runif(n) < s ? abs(r[t]) : theta
  }
  return mean(r)
}')

system.time(cont.run_C())

在尝试将您的代码转换为 C++ 之前,首先查看 R 代码是有意义的,尤其是在您不了解 C++ 的情况下。如果你在你的代码上使用分析器,你会发现大部分时间花在了 ifelse 的两行中。但是,两条线都可以改进。第一行相当于:

Zt <- sum(epsilon > theta) - sum(epsilon < -theta)

第二行可以写成

theta[runif(n) < s] <- abs(r[t])

这两项更改将我系统上的运行时间从 10 秒以上减少到 5 秒以下。再次查看分析器结果,我们发现现在大部分时间都花在 runif 上。在这里,我们可以使用我的 dqrng 包中更快的 RNG,将运行时间减少到 2 秒以下。最终代码:

library(dqrng)

cont.run <- function(reps=10000, n=10000, d=0.005, l=10 ,s=0.1) {
  r <- rep(0, reps)
  theta <- rep(0, n)
  for (t in 1:reps) {
    epsilon <- dqrnorm(1, 0, d)
    #Zt = sum(ifelse(epsilon > theta, 1, ifelse(epsilon < -theta, -1, 0)))
    Zt <- sum(epsilon > theta) - sum(epsilon < -theta)
    r[t] <- Zt / (l * n)
    theta[dqrunif(n) < s] <- abs(r[t])
  }
  return(mean(r))
}

system.time(cont.run())
#>        User      System verstrichen 
#>       1.804       0.244       2.049

reprex package (v0.2.1)

创建于 2019-05-21