教育 - 使用 Rcpp 了解递归函数的可变性能
Educational - understanding variable performance of recursive functions with Rcpp
这个问题不是实际问题,我只是在寻找对观察到的事件的合理解释。我正在阅读 Dirk Eddelbuettel 的 Seamless R and C++ Integration with Rcpp (Use R!)。在介绍之后,我正在看两个简单的 "Fibonacci functions".
在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
问题
- 我想了解为什么这两个函数在性能上有显着差异?
- 关于使用 Rcpp 的实用性,什么通常被认为是好的做法?出于天真,我的第一个直觉是编写一个函数并通过
sourceCpp
获取它,但这种解决方案似乎要慢得多。
基准代码
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
以上都是好评。
该函数 在 x=10
上太轻了,你需要比 times=10
更频繁地调用 ] 找到任何有意义的东西。您正在测量噪音。
至于样式,我们大多数人更喜欢 fibonacci()
通过 Rcpp 属性...
这个问题不是实际问题,我只是在寻找对观察到的事件的合理解释。我正在阅读 Dirk Eddelbuettel 的 Seamless R and C++ Integration with Rcpp (Use R!)。在介绍之后,我正在看两个简单的 "Fibonacci functions".
在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
问题
- 我想了解为什么这两个函数在性能上有显着差异?
- 关于使用 Rcpp 的实用性,什么通常被认为是好的做法?出于天真,我的第一个直觉是编写一个函数并通过
sourceCpp
获取它,但这种解决方案似乎要慢得多。
基准代码
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
以上都是好评。
该函数 在 x=10
上太轻了,你需要比 times=10
更频繁地调用 ] 找到任何有意义的东西。您正在测量噪音。
至于样式,我们大多数人更喜欢 fibonacci()
通过 Rcpp 属性...