Search code examples
rrcpp

Why is this Rcpp code not faster than pure R?


Setting up

I tried some R and Rcpp benchmarks with Fibonacci numbers.

Pure R

We use the fibR function for the code that was written in pure R.

fibR <- function(n) {
    if (n < 2)
       n
    else
       fib(n - 1) + fib(n - 2)
}

Rcpp

We use another fib function for the code written in Rcpp.

library(Rcpp)

Rcpp::cppFunction('int fib(int x) {
    if((x < 2)) 
       return(x);
    else 
       return(fib(x-1) + fib(x-2));
   }')

The results

Here are the results according to several benchmarks tests.

library(rbenchmark)

After that, I did several tests.

benchmark(fib(30), fibR(30))[,1:3]
      test replications elapsed
1  fib(30)          100    0.46
2 fibR(30)          100    0.45
benchmark(fib(31), fibR(31))[,1:3]
      test replications elapsed
1  fib(31)          100    0.77
2 fibR(31)          100    0.80
benchmark(fib(32), fibR(32))[,1:3]
      test replications elapsed
1  fib(32)          100    1.37
2 fibR(32)          100    1.33
benchmark(fib(33), fibR(33))[,1:3]
      test replications elapsed
1  fib(33)          100    1.88
2 fibR(33)          100    2.02
benchmark(fib(34), fibR(34))[,1:3]
      test replications elapsed
1  fib(34)          100    3.09
2 fibR(34)          100    3.26
benchmark(fib(35), fibR(35))[,1:3]
      test replications elapsed
1  fib(35)          100    5.57
2 fibR(35)          100    5.60
benchmark(fib(36), fibR(36))[,1:3]
      test replications elapsed
1  fib(36)          100    8.95
2 fibR(36)          100    8.51
benchmark(fib(37), fibR(37))[,1:3]
      test replications elapsed
1  fib(37)          100   16.94
2 fibR(37)          100   14.47
benchmark(fib(38), fibR(38))[,1:3]
      test replications elapsed
1  fib(38)          100   22.92
2 fibR(38)          100   23.67
benchmark(fib(39), fibR(39))[,1:3]
      test replications elapsed
1  fib(39)          100   35.80
2 fibR(39)          100   38.83

I would expect that the Rcpp code is steadily faster than the equivalent R code, but no – it is sometimes slower!

Why does it work like this, and what am I missing?


Solution

  • When something can't be true you should check closely what is going on :)

    Here your R function called your C++ function as you were not careful about where fib() was coming from. A repaired, more explicit version follow.

    Code

    fibR <- function(n) {
        if (n < 2)
            n
        else
            fibR(n - 1) + fibR(n - 2)
    }
    
    library(Rcpp)
    Rcpp::cppFunction('int fibRcpp(int x) {
       if ((x < 2))
           return(x);
       else
           return(fibRcpp(x-1) + fibRcpp(x-2));
    }')
    
    library(rbenchmark)
    benchmark(fibRcpp(30), fibR(30))[,1:3]
    

    Output

             test replications elapsed
    2    fibR(30)          100  80.846
    1 fibRcpp(30)          100   0.153
    

    This is a rather well-studied example. Look at the directory examples/Misc/ in your Rcpp installation for examples last updated years ago. Also look at prior questions here on SO.