Replicate() versus a for loop?
Asked Answered
P

4

8

Does anyone know how the replicate() function works in R and how efficient it is relative to using a for loop?

For example, is there any efficiency difference between...

means <- replicate(100000, mean(rnorm(50)))

And...

means <- c()
for(i in 1:100000) { 
   means <- c(means, mean(rnorm(50)))
}

(I may have typed something slightly off above, but you get the idea.)

Palmy answered 16/11, 2012 at 7:37 Comment(0)
A
16

You can just benchmark the code and get your answer empirically. Note that I also added a second for loop flavor which circumvents the growing vector problem by preallocating the vector.

repl_function = function(no_rep) means <- replicate(no_rep, mean(rnorm(50)))
for_loop = function(no_rep) {
   means <- c()
   for(i in 1:no_rep) { 
      means <- c(means, mean(rnorm(50)))
   }
   means
}
for_loop_prealloc = function(no_rep) {
   means <- vector(mode = "numeric", length = no_rep)
   for(i in 1:no_rep) { 
      means[i] <- mean(rnorm(50))
   }
   means
}

no_loops = 50e3
benchmark(repl_function(no_loops), 
          for_loop(no_loops), 
          for_loop_prealloc(no_loops), 
          replications = 3)

                         test replications elapsed relative user.self sys.self
2          for_loop(no_loops)            3  18.886    6.274    17.803    0.894                          
3 for_loop_prealloc(no_loops)            3   3.209    1.066     3.189    0.000                          
1     repl_function(no_loops)            3   3.010    1.000     2.997    0.000                          
  user.child sys.child
2          0         0                                                                                  
3          0         0                                                                                  
1          0         0 

Looking at the relative column, the un-preallocated for loop is 6.2 times slower. However, the preallocated for loop is just as fast as replicate.

Alesandrini answered 16/11, 2012 at 8:34 Comment(0)
Z
9

replicate is a wrapper for sapply, which itself is a wrapper for lapply. lapply is ultimately an .Internal function that is written in C and performs the looping in an optimised way, rather than through the interpreter. It's main advantages are efficient memory management, especially compared to the highly inefficient vector growing method you present above.

Zippora answered 16/11, 2012 at 7:46 Comment(1)
A preallocated for loop is just as fast as replicate. I think that is because the major part of the code is spent in R. Reimplementing the whole loop around mean, in e.g. C++ would probably speed things up quite a bit. See the benchmarks in my answer.Alesandrini
T
1

I have a very different experience with replicate which also confuses me. It often happens that my R crashes and my laptop hangs when I use replicate compared to for and this surprises me, as for the reasons mentioned above, I also expected a C-written function to outperform the for loop. For example, if you execute the functions below, you'll see that for loop is faster than replicate

system.time(for (i in 1:10) runif(1e7))
#    user  system elapsed 
#    3.340   0.218   3.558 

system.time(replicate(10, runif(1e7)))
#    user  system elapsed 
#    4.622   0.484   5.109

so with 10 replicates, the for loop is clearly faster. If you repeat it for 100 replicates you get similar results. So I wonder if anyone can come with an example that shows its practical privileges compared to for.

PS I also created a function for the runif(1e7) and that made no difference in the comparison. Basically I failed to come with any example that shows the advantage of replicate.

Tepper answered 25/4, 2016 at 17:33 Comment(1)
I think that your comparison is not fair since in the for loop you return the runif(1e7) each time where in replicateyou store also the results to a matrix of 1e7 x 10Limulus
T
1

Vectorization is the key difference between them. I will tray to explain this point. R is an high-level-interpreted computer language. It takes care of many basic computer tasks for you. When you write

x <- 2.0

you don’t have to tell your computer that

  • “2.0” is a floating-point number;
  • “x” should store numeric-type data;
  • it has to find a place in memory to put “5”;
  • it has to register “x” as a pointer to a certain place in memory.

R figures these things by itself.

But, for such comfortable issue, there is a price: it is slower than low level languages.

In C or FORTRAN, much of this "test if" would be accomplished during the compilation step, not during the program execution. They are translated into binary computer language (0/1) after they are written, BUT before they are run. This allows the compiler to organize the binary machine code in an optimal way for the computer to interpret.

What does this have to do with vectorization in R? Well, many R functions are actually written in a a compiled language, such as C, C++, and FORTRAN, and have a small R “wrapper”. This is the difference between yours approach. for loops add further test if operations that the machine has to do on data, making it slower

Tereasaterebene answered 26/4, 2016 at 12:7 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.