加快重复的函数调用

时间:2013-01-24 07:05:05

标签: r vectorization

我正在尝试计算以下值:

1/N * sum[i=0 to N-1]( log(abs(r_i - 2 * r_i * x_i)) )

其中x_i是递归计算:

x_{i+1} = r_i * x_i * (1 - x_i)

在给出所有r_i的情况下(尽管它们随i而变化),并且给出了x_0。 (据我所知,没有棘手的数学方法可以将这个计算简化为非迭代公式,以加快它的速度)。

我的问题是它很慢,我想知道一些外部视角是否可以帮助我加快速度

# x0: a scalar. rs: a numeric vector, length N
# N: typically ~5000
f <- function (x0, rs, N) {
    lambda <- 0                                                                 
    x <- x0                                                                     
    for (i in 1:N) {                                                            
        r <- rs[i]                                                              
        rx <- r * x                                                             
        lambda <- lambda + log(abs(r - 2 * rx))                                 
        # calculate the next x value
        x <- rx - rx * x                                                        
    }                                                                           
    return(lambda / N)                                                          
}

现在它自己的功能非常快,我想称它为4,000,000次(2000 x 2000矩阵中的每个单元一次),每个都有不同的{{ 1}}向量。

但是,如果我将其称为偶数2500次(N = 1000),则需要约25秒,具有以下配置文件:

rs

是否有人知道如何加快速度?看起来乘法需要一段时间,但我已经预先缓存了任何重复的乘法。

我还尝试利用 self.time self.pct total.time total.pct "f" 19.98 81.22 24.60 100.00 "*" 2.00 8.13 2.00 8.13 "-" 1.32 5.37 1.32 5.37 "+" 0.70 2.85 0.70 2.85 "abs" 0.56 2.28 0.56 2.28 ":" 0.04 0.16 0.04 0.16 sum( log(stuff(i)) )相同来减少对log(prod(stuff(i))log的调用,但结果却不可行{{1} }是一个长度为abs(数千)且典型值至少为1的向量,因此stuff最终为N到R。

1 个答案:

答案 0 :(得分:5)

在我看来,瓶颈是你职能中的for循环。

我用Rcpp重写它如下:

# x0: a scalar. rs: a numeric vector, length N
# N: typically ~5000
x0 <- runif(1)
N <- 5000
rs <- rnorm(5000)
f <- function (x0, rs, N) {
    lambda <- 0                                                                 
    x <- x0                                                                     
    for (i in 1:N) {                                                            
        r <- rs[i]                                                              
        rx <- r * x                                                             
        lambda <- lambda + log(abs(r - 2 * rx))                                 
        # calculate the next x value
        x <- rx - rx * x                                                        
    }                                                                           
    return(lambda / N)                                                          
}

library(inline)
library(Rcpp)
f1 <- cxxfunction(sig=c(Rx0="numeric", Rrs="numeric"), plugin="Rcpp", body='
  double x0 = as<double>(Rx0);
  NumericVector rs(Rrs);
  int N = rs.size();
  double lambda = 0, x = x0, r, rx;
  for(int i = 0;i < N;i++) {
    r = rs[i];
    rx = r * x;
    lambda = lambda + log( fabs(r - 2 * rx) );
    x = rx - rx * x;
  }
  lambda /= N;
  return wrap(lambda);
  ')
f(x0, rs, N)
f1(x0, rs)

library(rbenchmark)

benchmark(f(x0, rs, N), f1(x0, rs))
在我上一次测试中,

f1f快140倍。

相关问题