【问题标题】:Condensing a for-loop in R在 R 中压缩 for 循环
【发布时间】:2014-03-07 19:06:29
【问题描述】:

我在R中有以下代码

library(mvtnorm)

m = matrix(rnorm(2000000),nrow=200)
A = matrix(rnorm(40000),ncol=200)
A = A%*%t(A)
C = array(A,c(200,200,10000))

B = 10000
S = 100

postpred = array(NA,c(200,S,B))
for(i in 1:B){
    postpred[,,i] = t(rmvnorm(S,m[,i],C[,,i],method="svd"))
}

但是这段代码非常慢,因为我必须循环 10,000 次,同时还要从多元法线模拟 100 次,mC 也可能非常大。所以我想做的是能够在循环之外计算postpred。我曾尝试使用 apply 功能,但无济于事。非常感谢任何帮助或建议。

【问题讨论】:

  • 由于您在循环中对rmvnorm 的每次调用都采用不同的均值和协方差矩阵,因此您仍然需要调用该函数 10,000 次,无论您是否在循环或使用apply。由于您已经预先分配了postpred,我猜你不会通过切换到apply 来获得那么多的加速。您的代码运行缓慢的原因可能是您试图从 10,000 个不同的多元正态分布中提取总共 2 亿个值。

标签: r for-loop apply


【解决方案1】:

其他人指出 apply(和类似功能)对您的情况没有多大帮助,他们是对的。

对于它的价值,我检查了您是否会通过编译代码来获得性能提升。这是我针对您的问题所做的一个小基准(我减小了矩阵的大小,否则我无法运行它们):

library(mvtnorm)

func = function()
{ 
  m = matrix(rnorm(200000),nrow=100)
  A = matrix(rnorm(10000),ncol=100)
  A = A%*%t(A)
  C = array(A,c(100,100,1000))

  B = 1000
  S = 10

  postpred = array(NA,c(1000,S,B))
  for(i in 1:B){
    postpred[,,i] = t(rmvnorm(S,m[,i],C[,,i],method="svd"))
  }
}

require(compiler)
func_compiled <- cmpfun(func)

require(microbenchmark)

microbenchmark(func_compiled(), func(), times=10) # grab a coffee, this takes some time

结果表明编译不会给你带来任何好处:

Unit: seconds
                 expr      min       lq   median       uq      max neval
 slow_func_compiled() 9.938632 10.12269 10.18237 10.48215 15.43299    10
          slow_func() 9.969320 10.07676 10.21916 15.44664 15.66109    10

(这是意料之中的,因为库 mvtnorm 应该已经编译好了)

总的来说,您只有两种方法可以优化 R 中的代码:

  1. 使用较小的数字(如果可以接受)
  2. 并行化您的代码

【讨论】:

    【解决方案2】:

    正如 Josillber 所说,vectorisation应用函数族)不会为你做太多事情,它确实有点像 R 神话显着的速度提升。

    建议你看看并行选项,有并行的 mcapply 和 snow 包。在此处阅读更多信息http://stat.ethz.ch/R-manual/R-devel/library/parallel/doc/parallel.pdf

    【讨论】:

    • 我认为您的意思是说“应用”而不是“矢量化”。前者通常不会加快速度,但后者会。
    猜你喜欢
    • 2018-04-11
    • 1970-01-01
    • 2020-11-22
    • 1970-01-01
    • 1970-01-01
    • 2018-03-19
    • 2018-07-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多