教育 - 用Rcpp理解递归函数的可变性能

时间:2015-11-11 22:11:16

标签: c++ r function rcpp fibonacci

问题不是实际问题,我只是在寻找对观察到的事件的合理解释。我正在读Dirk Eddelbuettel的 Seamless R and C++ Integration with Rcpp (Use R!) 。在介绍之后,我正在研究两个简单的“Fibonacci函数”。

在RStudio中,我有一个以下结构的cpp文件

fib_fun.cpp

#include <Rcpp.h>

// [[Rcpp::export]]
int fibonacci(const int x) {
    if (x < 2)
        return x;
    else
        return (fibonacci(x -1)) + fibonacci(x-2);
}

/*** R
# Call the fib function defined in R
fibonacci(10)
*/

我还有一个相同功能的内联实现:

inline_fib.R

# Inline fib implementation
incltxt <- "int fibonacci(const int x) {
            if (x == 0) return(0);
            if (x == 1) return(1);
            return fibonacci(x - 1) + fibonacci(x - 2);
            }"

# Inline call
require(inline)
fibRcpp <- cxxfunction(signature(xs = "int"), plugin = "Rcpp",
                       includes = incltxt,
                       body = "int x = Rcpp::as<int>(xs);
                               return Rcpp::wrap(fibonacci(x));")

当我对功能进行基准测试时,我得到以下结果:

> microbenchmark(fibonacci(10), fibRcpp(10), times = 10)
Unit: microseconds
          expr   min    lq   mean median    uq    max neval
 fibonacci(10) 3.121 3.198 5.5192  3.447 3.886 23.491    10
   fibRcpp(10) 1.176 1.398 3.9520  1.558 1.709 25.721    10

问题

  1. 我想了解为什么这两个函数之间的性能存在显着差异?
  2. 关于使用Rcpp的实用性,通常认为是一种好的做法?在我的天真,我的第一个预感是编写一个函数并通过sourceCpp来源,但这个解决方案看起来要慢得多。
  3. 基准代码

    require(microbenchmark); require(Rcpp); require(inline)
    sourceCpp("fib_fun.cpp"); source("inline_fib.R")
    microbenchmark(fibonacci(10), fibRcpp(10), times = 10)
    

    评论回复

    我使用unsigned int代替int尝试了这些功能,结果:

    Unit: microseconds
              expr   min    lq   mean median    uq    max neval
     fibonacci(10) 2.908 2.992 5.0369  3.267 3.598 20.291    10
       fibRcpp(10) 1.201 1.263 6.3523  1.424 1.639 50.536    10
    

1 个答案:

答案 0 :(得分:3)

以上所有好评。

该功能在x=10方式过于轻量级,您需要更频繁地调用方式而不是times=10才能找到有意义的内容。你在测量噪音。

至于风格,我们大多数人喜欢fibonacci()通过Rcpp属性......