|
Rcpp Version 0.9.10
|
00001 #!/usr/bin/r 00002 ## 00003 ## This example goes back to the following StackOverflow questions: 00004 ## http://stackoverflow.com/questions/7153586/can-i-vectorize-a-calculation-which-depends-on-previous-elements 00005 ## and provides a nice example of how to accelerate path-dependent 00006 ## loops which are harder to vectorise. It lead to the following blog 00007 ## post: 00008 ## http://dirk.eddelbuettel.com/blog/2011/08/23#rcpp_for_path_dependent_loops 00009 ## 00010 ## Thanks to Josh Ulrich for provided a first nice (R-based) answer on 00011 ## StackOverflow and for also catching a small oversight in my posted answer. 00012 ## 00013 ## Dirk Eddelbuettel, 23 Aug 2011 00014 ## 00015 ## Copyrighted but of course GPL'ed 00016 00017 00018 library(inline) 00019 library(rbenchmark) 00020 library(compiler) 00021 00022 fun1 <- function(z) { 00023 for(i in 2:NROW(z)) { 00024 z[i] <- ifelse(z[i-1]==1, 1, 0) 00025 } 00026 z 00027 } 00028 fun1c <- cmpfun(fun1) 00029 00030 00031 fun2 <- function(z) { 00032 for(i in 2:NROW(z)) { 00033 z[i] <- if(z[i-1]==1) 1 else 0 00034 } 00035 z 00036 } 00037 fun2c <- cmpfun(fun2) 00038 00039 00040 funRcpp <- cxxfunction(signature(zs="numeric"), plugin="Rcpp", body=" 00041 Rcpp::NumericVector z = Rcpp::NumericVector(zs); 00042 int n = z.size(); 00043 for (int i=1; i<n; i++) { 00044 z[i] = (z[i-1]==1.0 ? 1.0 : 0.0); 00045 } 00046 return(z); 00047 ") 00048 00049 00050 z <- rep(c(1,1,0,0,0,0), 100) 00051 ## test all others against fun1 and make sure all are identical 00052 all(sapply(list(fun2(z),fun1c(z),fun2c(z),funRcpp(z)), identical, fun1(z))) 00053 00054 res <- benchmark(fun1(z), fun2(z), 00055 fun1c(z), fun2c(z), 00056 funRcpp(z), 00057 columns=c("test", "replications", "elapsed", "relative", "user.self", "sys.self"), 00058 order="relative", 00059 replications=1000) 00060 print(res) 00061 00062 z <- c(1,1,0,0,0,0) 00063 res2 <- benchmark(fun1(z), fun2(z), 00064 fun1c(z), fun2c(z), 00065 funRcpp(z), 00066 columns=c("test", "replications", "elapsed", "relative", "user.self", "sys.self"), 00067 order="relative", 00068 replications=10000) 00069 print(res2) 00070 00071 00072 if (FALSE) { # quick test to see if Int vectors are faster: appears not 00073 funRcppI <- cxxfunction(signature(zs="integer"), plugin="Rcpp", body=" 00074 Rcpp::IntegerVector z = Rcpp::IntegerVector(zs); 00075 int n = z.size(); 00076 for (int i=1; i<n; i++) { 00077 z[i] = (z[i-1]==1.0 ? 1.0 : 0.0); 00078 } 00079 return(z); 00080 ") 00081 00082 z <- rep(c(1L,1L,0L,0L,0L,0L), 100) 00083 identical(fun1(z),fun2(z),fun1c(z),fun2c(z),funRcppI(z)) 00084 00085 res3 <- benchmark(fun1(z), fun2(z), 00086 fun1c(z), fun2c(z), 00087 funRcppI(z), 00088 columns=c("test", "replications", "elapsed", "relative", "user.self", "sys.self"), 00089 order="relative", 00090 replications=1000) 00091 print(res3) 00092 00093 z <- c(1L,1L,0L,0L,0L,0L) 00094 res4 <- benchmark(fun1(z), fun2(z), 00095 fun1c(z), fun2c(z), 00096 funRcppI(z), 00097 columns=c("test", "replications", "elapsed", "relative", "user.self", "sys.self"), 00098 order="relative", 00099 replications=10000) 00100 print(res4) 00101 }