|
Rcpp Version 0.9.10
|
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