Rcpp Version 0.9.10
sugarBenchmarks.R
Go to the documentation of this file.
00001 #!/usr/bin/r -t
00002 
00003 suppressMessages(library(inline))
00004 suppressMessages(library(Rcpp))
00005 
00006 benchmark <- function(start = settings$start, 
00007                       hand.written = settings$hand.written, 
00008                       sugar = settings$sugar, 
00009                       expr = settings$expr, 
00010                       runs = settings$runs,
00011                       data = settings$data,
00012                       end = settings$end, 
00013                       inc = settings$inc, 
00014                       
00015                       settings = list( 
00016                                 start = "", hand.written = "", 
00017                                 sugar = "", expr = NULL, 
00018                                 runs = 500, 
00019                                 data = NULL , 
00020                                 end = "", 
00021                                 inc = ""
00022                                 )
00023                       ) {
00024 
00025 expr <- force(expr)
00026 inc  <- force( inc )
00027 
00028 src <- sprintf( '
00029     unsigned int runs = as<int>(runss);
00030         Environment e(env) ;
00031 
00032         %s
00033 
00034     Timer timer;
00035 
00036     // approach one
00037     timer.Start();
00038     for (unsigned int i=0; i<runs; i++) {
00039            %s
00040     }
00041     timer.Stop();
00042     double t1 = timer.ElapsedTime();
00043 
00044     // approach two
00045     timer.Reset(); timer.Start();
00046     for (unsigned int i=0; i<runs; i++) {
00047         %s
00048     }
00049     timer.Stop();
00050     double t2 = timer.ElapsedTime();
00051 
00052     Language call(expr) ;
00053 
00054     timer.Reset(); timer.Start();
00055     for (unsigned int i=0; i<runs; i++) {
00056         NumericVector res2 = Rf_eval( call, e ) ;
00057     }
00058     timer.Stop();
00059     double t3 = timer.ElapsedTime();
00060 
00061     %s
00062 
00063     return NumericVector::create(
00064         _["hand written"] = t1,
00065         _["sugar"] = t2,
00066         _["R"]     = t3
00067         ) ;
00068 ',
00069                paste( start, collapse = "\n" ) ,
00070                paste( hand.written, collapse = "\n" ),
00071                paste( sugar, collapse = "\n" ),
00072                paste( end, collapse = "\n" )
00073         )
00074 
00075         e <- environment()
00076         for( i in names(data) ){
00077                 assign( i, data[[i]], envir = e )
00078         }
00079 
00080         settings <- getPlugin("Rcpp")
00081         settings$env$PKG_CXXFLAGS <- paste("-I", getwd(), sep="")
00082 
00083         fun <- cxxfunction(signature(runss="integer", expr = "language", env = "environment" ),
00084                            src,
00085                            includes= sprintf( '#include "Timer.h"\n%s', paste( inc, collapse = "\n" ) ),
00086                            plugin="Rcpp",
00087                            settings=settings)
00088         results <- fun(runs, expr, environment() )
00089         cat( "-" )
00090         list( results = results, runs = runs, expr = deparse(expr) )
00091 }
00092 
00093 settings.ifelse <- list( start = '
00094         NumericVector x = e["x"] ;
00095         NumericVector y = e["y"] ;
00096 ', hand.written = '
00097         int n = x.size() ;
00098         NumericVector res1( n ) ;
00099         double x_ = 0.0 ;
00100         double y_ = 0.0 ;
00101         for( int i=0; i<n; i++){
00102         x_ = x[i] ;
00103         y_ = y[i] ;
00104         if( R_IsNA(x_) || R_IsNA(y_) ){
00105             res1[i] = NA_REAL;
00106         } else if( x_ < y_ ){
00107             res1[i] = x_ * x_ ;
00108         } else {
00109             res1[i] = -( y_ * y_)  ;
00110         }
00111     }
00112 
00113 ', sugar = '
00114     NumericVector res2 = ifelse( x < y, x*x, -(y*y) ) ;
00115 ', expr = quote(ifelse(x<y, x*x, -(y*y) )), 
00116    data = list( x = runif(1e5),  y = runif(1e5) )
00117 )
00118 
00119 settings.ifelse.nona <- list( start = '
00120         NumericVector x = e["x"] ;
00121         NumericVector y = e["y"] ;
00122 ', hand.written = '
00123         int n = x.size() ;
00124         NumericVector res1( n ) ;
00125         double x_ = 0.0 ;
00126         double y_ = 0.0 ;
00127         for( int i=0; i<n; i++){
00128         x_ = x[i] ;
00129         y_ = y[i] ;
00130         if( x_ < y_ ){
00131             res1[i] = x_ * x_ ;
00132         } else {
00133             res1[i] = -( y_ * y_)  ;
00134         }
00135     }
00136 
00137 ', sugar = '
00138     NumericVector res2 = ifelse( x < y, noNA(x)*noNA(x), -(noNA(y)*noNA(y)) ) ;
00139 ', expr = quote(ifelse(x<y, x*x, -(y*y) )), 
00140    data = list( x = runif(1e5),  y = runif(1e5) )
00141 )
00142 
00143 settings.sapply <- list( start =  '
00144         NumericVector x = e["x"] ;
00145         int n = x.size() ;
00146 
00147 ', hand.written = '
00148         NumericVector res1( n ) ;
00149         std::transform( x.begin(), x.end(), res1.begin(), square ) ;
00150 
00151 ', sugar = '
00152         NumericVector res2 = sapply( x, square ) ; 
00153 ',
00154         expr = quote(sapply(x,square)),
00155         runs = 500,
00156         data = list(
00157                 x = rnorm(1e5) ,
00158                 square = function(x) x*x
00159         ), 
00160         inc = '
00161         inline double square(double x){ return x*x ; }
00162         '
00163 )
00164 
00165 settings.any <- list( start = '
00166         NumericVector x = e["x"] ;
00167         NumericVector y = e["y"] ;
00168         int res ;
00169         SEXP res2 ;
00170 
00171 ', hand.written = '
00172         int n = x.size() ;
00173         bool seen_na = false ;
00174         bool result = false ;
00175         double x_ = 0.0 ;
00176         double y_ = 0.0 ;
00177         for( int i=0; i<n; i++){
00178                 x_ = x[i] ;
00179                 if( R_IsNA( x_ )  ){
00180                         seen_na = true ;
00181                 } else {
00182                         y_ = y[i] ;
00183                         if( R_IsNA( y_ ) ){
00184                                 seen_na = true ;
00185                         } else {
00186                                 /* both non NA */
00187                                 if( x_*y_ < 0.0 ){
00188                                         result = true ;
00189                                         break ;
00190                                 }
00191                         }
00192                 }
00193         }
00194         res = result ? TRUE : ( seen_na ? NA_LOGICAL : FALSE ) ;
00195 ', sugar = '
00196         res2 = any( x*y < 0 ) ;
00197 ',
00198         expr = quote(any(x*y<0)),
00199         runs = 5000,
00200         data = list(
00201                 x = seq( -1, 1, length = 1e05),
00202                 y = rep( 1, 1e05)
00203         )
00204 )
00205 raw.results <- list( 
00206         benchmark( settings = settings.any   , runs = 5000 ), 
00207         benchmark( settings = settings.ifelse, runs = 500 ), 
00208         benchmark( settings = settings.ifelse.nona, runs = 500 ), 
00209         benchmark( settings = settings.sapply, runs = 500 )
00210 )
00211 cat("\n")
00212 
00213 results <- do.call( rbind, lapply( raw.results, "[[", "results" ) )
00214 results <- data.frame( 
00215         runs = sapply( raw.results, "[[", "runs" ),
00216         expr = sapply( raw.results, "[[", "expr" ),
00217         as.data.frame( results, stringsAsFactors = FALSE )
00218         )
00219 
00220 results[[ "hand/sugar" ]] <- results[["hand.written" ]] / results[["sugar"]] 
00221 results[[ "R/sugar" ]]    <- results[["R" ]]            / results[["sugar"]] 
00222 # results <- results[ order( results[["expr"]], results[["runs"]] ), ]
00223 
00224 options( width = 300 )
00225 print( results )
00226 
 All Classes Namespaces Files Functions Variables Typedefs Enumerator Friends Defines