Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is seq(x) so much slower than 1:length(x)?

Tags:

I recently answered a question pertaining to for loops. Upon testing my code's speed, I noticed that the use of seq() as opposed to : in the for loop slowed the speed down considerably.

Have a look at this very simple example. The only difference between f1() and f2() is a change in the for loop sequence, yet f1() is over twice as fast as f2().

f1 <- function() {     x <- 1:5; y <- numeric(length(x))     for(i in 1:length(x)) y[i] <- x[i]^2     y }  f2 <- function() {     x <- 1:5; y <- numeric(length(x))     for(i in seq(x)) y[i] <- x[i]^2     y }  library(microbenchmark) microbenchmark(f1(), f2()) # Unit: microseconds #  expr    min      lq  median     uq    max neval #  f1() 10.529 11.5415 12.1465 12.617 33.893   100 #  f2() 25.052 25.5905 26.0385 28.759 78.553   100 

Why is seq(x) so much slower in a for loop than 1:length(x) ?

like image 454
Rich Scriven Avatar asked Jun 13 '14 23:06

Rich Scriven


2 Answers

seq is a generic S3 method, so probably some time is lost dispatching. seq.default is almost 100 lines long!

You're probably already aware of seq_along, which calls a .Primitive directly and is bit better than 1:length(x) and the best method I have found for long loops:

f3 <- function(){       x <- 1:5; y <- numeric(length(x))       for(i in seq_along(x)) y[i] <- x[i]^2       y   } >  microbenchmark(f1(), f3()) Unit: microseconds  expr    min     lq median     uq    max neval  f1() 27.095 27.916 28.327 29.148 89.495   100  f3() 26.684 27.505 27.916 28.327 36.538   100 
like image 137
dardisco Avatar answered Oct 14 '22 05:10

dardisco


Using seq_len you get nearly the same time as the : operator:

f3 <- function(){   x <- 1:5; y <- numeric(length(x))   for(i in seq_len(length(x))) y[i] <- x[i]^2   y }  library(microbenchmark) microbenchmark(f1(), f2(),f3())  Unit: microseconds  expr    min      lq  median     uq    max neval  f1()  9.988 10.6855 10.9650 11.245 50.704   100  f2() 23.257 23.7465 24.0605 24.445 88.140   100  f3() 10.127 10.5460 10.7555 11.175 18.857   100 

Internally seq is doing many verifications before calling : or seq_len.

like image 22
agstudy Avatar answered Oct 14 '22 05:10

agstudy