Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Code runs faster with Rcpp than compiled with g++

I am running the exact same code in two ways: compiling it with the g++ compiler, and calling it from R with Rcpp. It turns out that it runs almost 4 times faster when I run it through R.

Why does this happen? Is it because the compiler used by Rcpp is different?

This is the code I'm running in c++:

#include <iostream>
#include <nlopt.hpp>
#include <time.h>
using namespace std;


int main()
{

  //--------------------------------//
  //         Initialization         //
  //--------------------------------//

  // Grid for x
  const int nx              = 60000;

  float xgrid[nx];
  const float xstep = 4 /(nx - 1);
  float it = 0;

  for(int i = 0; i < nx; i++){
    xgrid[i] = it*xstep;
    it++;
  }

  // Initialize value function V
  size_t sizeV     = nx*sizeof(float);
  float *V;
  V     = (float *)malloc(sizeV);


  //--------------------------------//
  //         Computation            //
  //--------------------------------//

  // Variables for computation time
  double t0  = clock();
  double t   = t0;

  float utility;
  float VV = pow(-10.0,5.0);

  for(int ix = 0; ix<nx; ix++){

    VV = pow(-10.0,5.0);

    for(int ixp = 0; ixp < nx; ixp++){

      utility = (xgrid[ix] + 1 - xgrid[ixp])*(xgrid[ix] + 1 - xgrid[ixp]);

      if(utility >= VV){
        VV = utility;
      }
    }

    V[ix] = VV;
  }

  t = clock() - t0;
  cout << "Time: " << ((float)t)/CLOCKS_PER_SEC << " seconds." << endl;

  return 0;
}

To run it I use:

g++ Cpp_main.cpp -o Cpp_main

The code in Rcpp is:

#include <iostream>
#include <nlopt.hpp>
#include <time.h>
using namespace std;


// [[Rcpp::export]]
vector<double> value(int nx){ 

  //--------------------------------//
  //         Grid creation          //
  //--------------------------------//

  float xgrid[nx];

  const float xstep = 4 /(nx - 1);
  float it = 0;

  for(int i = 0; i < nx; i++){
    xgrid[i] = it*xstep;
    it++;
  }

  // Initialize value function V
  vector<double> V;
  V.resize(nx);


  //--------------------------------//
  //           Computation          //
  //--------------------------------//

  // Variables for computation time
  double t0  = clock();
  double t   = t0;

  float utility;
  float VV = pow(-10.0,5.0);

  for(int ix = 0; ix<nx; ix++){

    VV = pow(-10.0,5.0);

    for(int ixp = 0; ixp < nx; ixp++){

      utility = (xgrid[ix] + 1 - xgrid[ixp])*(xgrid[ix] + 1 - xgrid[ixp]);

      if(utility >= VV){
        VV = utility;
      }
    }

    V[ix] = VV;
  }

  t = clock() - t0;
  cout << "Time: " << ((float)t)/CLOCKS_PER_SEC << " seconds." << endl;

  return V;
}

And I call it from R with:

library("Rcpp")
sourceCpp("Rcpp_main.cpp")

# Grid for x
nx            = 60000; 

V = value(nx);

The running time in c++ is twice the running time in Rcpp. Any clues why this happens?

like image 426
David Zarruk Valencia Avatar asked Mar 28 '18 21:03

David Zarruk Valencia


1 Answers

Just looking your main() we get this:

edd@rob:/tmp/soQ$ g++ -o main main.cpp 
edd@rob:/tmp/soQ$ ./main 
Time: 8.42708 seconds.
edd@rob:/tmp/soQ$ g++ -o main -O3 -march=native main.cpp 
edd@rob:/tmp/soQ$ ./main 
Time: 1.59151 seconds.
edd@rob:/tmp/soQ$ 

That is already a factor of 5.3, and one of the weirdest examples I have seen in some time for the impact of -O3.

For R, I get about the same time as R defaults to using -O3 here too.

R> Rcpp::sourceCpp("/tmp/soQ/rcppfunction.cpp")    
R> V <- value(60000)
Time: 1.65224 seconds.    
R>  

So no real mistery here. You used different options, and it mattered.

like image 132
Dirk Eddelbuettel Avatar answered Oct 20 '22 21:10

Dirk Eddelbuettel