在 R 中快速生成约 10^9 步骤的随机过程

标签 r performance loops rcpp random-walk

我有以下任务要执行:

Generate 10^9 steps of the process described by the formula:

X(0)=0
X(t+1)=X(t)+Y(t)

where Y(t) are independent random variables with the distribution N(0,1). Calculate in what percentage of indices t the value of X(t) was negative.

我尝试了以下代码:

  x<-c(0,0)
  z<-0
  loop<-10^9
  for(i in 2:loop) {
    x[1]<-x[2]
    x[2]<-x[1]+rnorm(1, 0, 1)
    if (x[2]<0) {z<-z+1}
  }

但是,速度非常慢。我怎样才能加快速度?

最佳答案

一般来说,对于这样的问题,您可以使用 Rcpp 包将您的函数一对一地转换为 C++。这应该会带来相当大的加速。

首先是R版本:

random_sum <- function(loop = 1000) {
  x<-c(0,0)
  z<-0
  for(i in 2:loop) {
    x[1]<-x[2]
    x[2]<-x[1]+rnorm(1, 0, 1)
    if (x[2]<0) {z<-z+1}
  }
  z / loop
}
set.seed(123)
random_sum()
# [1] 0.134

现在是 C++ 版本:

library("Rcpp")
cppFunction("
  double random_sum_cpp(unsigned long loop = 1000) {
    double x1 = 0;
    double x2 = 0;
    double z = 0;
    for (unsigned long i = 2; i < loop; i++) {
      x1 = x2;
      x2 = x1 + Rcpp::rnorm(1)[0];
      if (x2 < 0) z = z+1;
    }
    return z/loop;
  }")

set.seed(123)
random_sum_cpp()
# [1] 0.134

为了完整起见,我们还考虑提出的矢量化版本:

random_sum_vector <- function(loop = 1000) {
  Y = rnorm(loop)
  sum(cumsum(Y)<0)/loop
}
set.seed(123)
random_sum_vector()
# [1] 0.134

我们看到它对于相同的随机种子给出相同的结果,因此它似乎是一个可行的竞争者。

在基准测试中,C++ 版本和矢量化版本的表现类似,矢量化版本比 C++ 版本略有优势:

> microbenchmark(random_sum(100000),
                 random_sum_vector(100000),
                 random_sum_cpp(100000))
Unit: milliseconds
                     expr        min         lq       mean     median         uq       max neval
        random_sum(1e+05) 184.205588 199.859266 209.220232 205.137043 211.026740 274.47615   100
 random_sum_vector(1e+05)   6.320690   6.631704   7.273645   6.799093   7.334733  18.48649   100
    random_sum_cpp(1e+05)   8.950091   9.362303  10.663295   9.956996  11.079513  21.30898   100

但是,矢量化版本会牺牲内存和 will blow up your memory for long loops. 的速度。 C++ 版本几乎不使用内存。

对于 10^9 个步骤,C++ 版本在我的计算机上运行大约需要 2 分钟(110 秒)。我没有尝试R版本。根据较短的基准,可能需要大约 7 小时。

> microbenchmark(random_sum_cpp(10^9), times = 1)
Unit: seconds
                 expr      min       lq     mean   median       uq      max neval
 random_sum_cpp(10^9) 110.2182 110.2182 110.2182 110.2182 110.2182 110.2182     1

关于在 R 中快速生成约 10^9 步骤的随机过程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47953580/

相关文章:

r - 在 R 中,检查属性是否在数据框整列的列表中

r - 使用 RecordLinkage 在连续存储的数据上删除唯一对

java - Android日常工作凌晨12点

java - 代码似乎陷入了潜在的循环

r - Data.table - 在 group by 期间有效评估 "j"中的表达式

reshape::recast 不会使用 fill=NA 求和

mysql - 对于这种缓慢的 MySQL 查询,最好的索引是什么? (InnoDB)

android - 在 ScrollView 中嵌套 RecyclerViews 或 RecyclerView?

r - 在R中的for循环中存储日期增量的输出

python - python中从列表中查找具有特定属性值的对象的最快方法?