1 / 23

How to Speed Up Your R Code With Virtually No Effort

How to Speed Up Your R Code With Virtually No Effort. Alec Stephenson. What I am Talking About. Basic Principals system.time(), benchmark() in rbenchmark Profiling R Code Rprof() Parallel Programming mclapply() parLapply() in parallel Using R With Amazon EC2.

markku
Download Presentation

How to Speed Up Your R Code With Virtually No Effort

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. How to Speed Up Your R Code With Virtually No Effort Alec Stephenson

  2. What I am Talking About • Basic Principals system.time(), benchmark() in rbenchmark • Profiling R Code Rprof() • Parallel Programming mclapply() parLapply() in parallel • Using R With Amazon EC2

  3. What I am Not Talking About • Writing complied code (e.g. C/C++) • Parallelizing compiled code (e.g. OpenMP) • Byte code compiler for R • Is code optimization worth your time? • Is code optimization worth turning your code into an unreadable mess?

  4. Basic Principals • Vectorize rather than loop • Allocate memory up front • Get to the compiled code faster .C .Fortran .External .Internal .Call .Primitive • R can be unpredictable

  5. Vectorize rather than loop x <- rnorm(1e06); y <- rnorm(1e06) 0.01s, Good: z <- x + y 6.23s, Bad: z <- numeric(1e06) for(i in 1:1e06) z[i] <- x[i] + y[i]

  6. Allocate memory up front x <- rnorm(1e06); y <- rnorm(1e06) 0.01s, Good: z <- x + y One Hour, Terrible: z <- NULL for(i in 1:1e06) z[i] <- x[i] + y[i]

  7. Get to the compiled code faster

  8. Get to the compiled code faster

  9. Get to the compiled code faster Could you: • Use pmax() rather than ifelse() • Use tabulate() rather than table() • Use lapply(split()) rather than tapply() • etc...

  10. Get to the compiled code faster x <- rnorm(1e07); y <- rnorm(1e07) 0.42s, Good: pmax(x, y) 3.09s, Bad: ifelse(x < y, y, x)

  11. R can be unpredictable x <- rnorm(1e08); y <- rnorm(50); n <- 100000 0.14s, 0.11s, Good: sum(x)/length(x), for(i in 1:n) sum(y)/length(y) 0.28s, 0.98s, Not So Good: mean(x), for(i in 1:n) mean(y)

  12. R can be unpredictable x <- rnorm(1e08); y <- rnorm(50); n <- 100000 0.28s, 0.98s, Not So Good: mean(x), for(i in 1:n) mean(y) 0.28s, 0.26s, Improves In Loop: mean.default(x), for(i in 1:n) mean.default(y) 0.28s, 0.06s, Improves A Lot In Loop: .Internal(mean(x)), for(i in 1:n) .Internal(mean(y))

  13. R can be unpredictable x <- rnorm(50); y <- rnorm(50); n <- 100000 0.06s: for(i in 1:n) x + y 0.12s, Seriously!: for(i in 1:n) (((((x + y)))))

  14. Profiling R Code • Very simple do to and always useful • Often surprising (R can be unpredictable) • Indicates where to concentrate your optimization efforts • Large potential gains for virtually no effort • A small piece of code often takes up virtually all the running time

  15. Profiling R Code Rprof() ## run some code here e.g. BadIdea(100000) Rprof(NULL) summaryRprof()

  16. This function is stupid BadIdea <- function(n) { x <- seq(-1, 1, length=n) y <- numeric(n) for (i in 1:n) y[i] <-((det(as.matrix(x[i]))*2)^1.1)/n y }

  17. Profiling R Code $by.self self.time self.pct total.time total.pct as.matrix 1.14 20.00 1.96 34.39 determinant 0.96 16.84 3.78 66.32 determinant.matrix 0.76 13.33 0.86 15.09 det 0.72 12.63 5.16 90.53 $ 0.66 11.58 0.66 11.58 array 0.62 10.88 0.70 12.28 BadIdea 0.44 7.72 5.70 100.00 as.matrix.default 0.12 2.11 0.82 14.39 ^ 0.10 1.75 0.10 1.75 as.vector 0.08 1.40 0.08 1.40 ncol 0.06 1.05 0.06 1.05 nrow 0.04 0.70 0.04 0.70

  18. Profiling R Code $by.total total.time total.pct self.time self.pct BadIdea 5.70 100.00 0.44 7.72 det 5.16 90.53 0.72 12.63 determinant 3.78 66.32 0.96 16.84 as.matrix 1.96 34.39 1.14 20.00 determinant.matrix 0.86 15.09 0.76 13.33 as.matrix.default 0.82 14.39 0.12 2.11 array 0.70 12.28 0.62 10.88 $ 0.66 11.58 0.66 11.58 ^ 0.10 1.75 0.10 1.75 as.vector 0.08 1.40 0.08 1.40 ncol 0.06 1.05 0.06 1.05 nrow 0.04 0.70 0.04 0.70

  19. Parallel Programming Multicore: single machine, not windows Snow: multiple machines, any OS Parallel: snow plus multicore mclapply(x, FUN, ..., mc.cores) parLapply(cl, x, FUN) Foreach: front-end for easier coding

  20. Parallel Programming fn <- function(a) a * 1:10 lapply(c(22,56,70,43), fn) mclapply(c(22,56,70,43), fn, mc.cores = 4) cl <- makeCluster(4) parLapply(cl, c(22,56,70,43), fn) stopCluster(cl)

  21. Parallel Programming Parallel random forest function (multicore type): parRandomForest<- function(xx, ..., ntree = 500, mc = 1) { rfwrap<- function(ntree, xx, ...) randomForest(x=xx, ntree=ntree, ...) rfpar<- mclapply(rep(ceiling(ntree/mc), mc), rfwrap, xx=xx, ..., mc.cores = mc) do.call(combine, rfpar) # not very fast }

  22. Amazon EC2 • Like Hiring One or More Powerful Computers By The Hour • Start Amazon EC2 Instance(s) • AMIs available with R and R Studio Server pre-installed • $1.8 per hour (or part hour) for quadruple extra large high memory instance with linux 64-bit OS: 68.4 GB of memory 26 EC2 Compute Units (8 virtual cores)

  23. Important Talk Clarification: When I answered ‘it’s important to turn it off’ I should have said ‘it’s important to turn off the instance explicitly by terminating (or stopping) it’. If you only turn off your computer, the EC2 instance will continue to run and you will continue to be charged by the hour. Thanks for attending, Alec.

More Related