Benchmarking a computationally demanding function in R and C++
The Fibonacci sequence mathematically defined as \[F_n = \begin{cases} n, & n\le 2\\ F_{n-1} + F_{n-2}, & n>2 \end{cases}\]
R implementation
f <- function(n){
if (n < 2) return(n)
return(f(n - 1)+f(n - 2))
}
sapply(1:10, f)
## [1] 1 1 2 3 5 8 13 21 34 55
Rscores <- benchmark(f(10),f(15), f(20), f(25), f(30))[,1:4]
Rscores
## test replications elapsed relative
## 1 f(10) 100 0.00 NA
## 2 f(15) 100 0.08 NA
## 3 f(20) 100 0.76 NA
## 4 f(25) 100 8.58 NA
## 5 f(30) 100 95.69 NA
p <- Rscores %>%
filter(elapsed>0) %>%
ggplot(aes(test,elapsed, group = 1))+
geom_line()+theme_minimal()+
labs(title = "Fibonacci function benchmarked in R",
y = "time elapsed (seconds)",
x = "Function and iteration")
print(p)

C++ implementation
The function defined above can be written within C++ as shown below and is callable from R through the Rcpp package. Rcpp::sourceCpp() is an option to source C++ files directly. Alternatively, the C++ function can be written within its own chunk using the Rcpp engine by using ```{Rcpp} as a code chunk header.
# Rcpp::sourceCpp("g.cpp")
#include <Rcpp.h>
//[[Rcpp::export]]
int g(int n) {
if (n < 2) return(n);
return(g(n-1) + g(n-2));
}
sapply(0:10, g)
## [1] 0 1 1 2 3 5 8 13 21 34 55
Cscores <- benchmark(g(10),g(15), g(20), g(25),g(30))[,1:4]
Cscores
## test replications elapsed relative
## 1 g(10) 100 0.00 NA
## 2 g(15) 100 0.00 NA
## 3 g(20) 100 0.00 NA
## 4 g(25) 100 0.03 NA
## 5 g(30) 100 0.22 NA
p <- Cscores %>%
ggplot(aes(test,elapsed, group = 1))+
geom_line()+ theme_minimal()+
labs(title = "Fibonacci function benchmarked in C++",
y = "time elapsed (seconds)",
x = "Function and iteration")
print(p)

Conclusion
The speed in calculating the 30th iteration of the Fibonacci sequence within C++ (0.22 seconds) massively outperforms R (95.69 seconds).
Pushing C++ further
Cscores <- benchmark(g(10),g(15), g(20), g(25),g(30),g(35),g(40))[,1:4]
Cscores %>%
ggplot(aes(test,elapsed))+
geom_point()+
labs(title = "Pushing C++ further")+
theme_minimal()
The function \(f(35)\) takes around 35 minutes to complete in R. C++ can handle \(g(40)\) in just 26 seconds. test5