R 加速循环中指数随机变量的重复生成
我正在实现一个算法,作为其中的一部分,我需要生成指数随机变量。不幸的是,我不能真正避免循环,因为每个生成的随机变量都依赖于前一个,所以我认为矢量化是不可能的。我对这一代人做了一些计算,但瓶颈(目前)是这一代人。此时,我假设N将很大(N>=1000000) 下面是一些示例代码:R 加速循环中指数随机变量的重复生成,r,performance,random,rcpp,R,Performance,Random,Rcpp,我正在实现一个算法,作为其中的一部分,我需要生成指数随机变量。不幸的是,我不能真正避免循环,因为每个生成的随机变量都依赖于前一个,所以我认为矢量化是不可能的。我对这一代人做了一些计算,但瓶颈(目前)是这一代人。此时,我假设N将很大(N>=1000000) 下面是一些示例代码: N <- 1e7 #Preallocate x <- rep(0, times=N) #Set a starting seed x[1] <- runif(1) for(i in 2:N) {
N <- 1e7
#Preallocate
x <- rep(0, times=N)
#Set a starting seed
x[1] <- runif(1)
for(i in 2:N) {
#Do some calculations
x[i] <- x[i-1] + rexp(1, x[i-1]) #Bottleneck
#Do some more calculations
}
N我们可以利用如果X~Exp(λ)那么kX~Exp(λ/k)的事实来加速代码。通过这种方式,我们可以预先使用rate=1
进行所有随机绘制,然后在循环中进行划分,以适当地缩放它们
draws = rexp(N, rate = 1)
x <- rep(0, times = N)
x[1] <- runif(1)
for(i in 2:N) {
#Do some calculations
x[i] <- x[i-1] + draws[i] / x[i-1]
#Do some more calculations
}
强力Rcpp解决方案:
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
NumericVector genExp(int N) {
NumericVector res(N);
double prev;
res[0] = unif_rand();
for (int i = 1; i < N; i++) {
prev = res[i-1];
res[i] = prev + exp_rand() / prev;
}
return res;
}
使用N=1e7
:
Unit: milliseconds
expr min lq mean median uq max neval
draw_up_front 1698.730 1708.739 1737.8633 1716.1345 1752.3276 1923.3940 20
rcpp 297.142 319.794 338.6755 327.6626 364.6308 398.1554 20
陛下有趣。我将尝试一下,看看它是如何进行的。谢谢你的回复。如果你没有把所有的函数都放在基准测试中,那就是作弊。谢谢。我用这个答案来帮助加速我的代码,但是真正的进步是由于上面格雷戈的答案,所以我接受了这个答案。
Unit: milliseconds
expr min lq mean median uq max neval
draw_up_front 167.17031 168.57345 170.62292 170.18072 171.73782 175.46868 20
draw_one_at_time 1415.01898 1465.57139 1510.81220 1502.15753 1550.07829 1623.70831 20
rcpp 28.25466 29.33682 33.52528 29.89636 30.74908 94.38009 20
Unit: milliseconds
expr min lq mean median uq max neval
draw_up_front 1698.730 1708.739 1737.8633 1716.1345 1752.3276 1923.3940 20
rcpp 297.142 319.794 338.6755 327.6626 364.6308 398.1554 20