简体   繁体   中英

Why R code with `{}` is faster than that with `()`?

Why is the R code with {} in general faster than the one with () , example below ?

n=10000000
w1=numeric(n)
w2=numeric(n)
r=rnorm(n)


t1=Sys.time()
for(i in 1:n)
w1[i]=((r[i]^2))*(1*1)
t1-Sys.time()


t1=Sys.time()
for(i in 1:n)
w2[i]={{r[i]^2}}*{1*1}
t1-Sys.time()

baptiste already linked Radford Neal 's blog in the comments.
But since the SE people don't like links to external sites, let me quote an interesting comment of the author himself (comment 33):

Yes, parentheses are still slower than curly brackets in R 2.13.1, and in the latest R 2.14.1, though not by as much as before (a patch I suggested to reduce general overhead in built-in functions was incorported in later releases, which reduced this difference).

There's no good reason for parentheses to be slower. I suggested another change (to just a couple lines of code) that would speed up parentheses. Luke Tierney responded that this patch should on no account be incorporated into R, on the basis that parentheses are an operator just like sqrt , and that there should therefore be nothing in the code implementing parentheses that departs from how operators like sqrt are implemented.

Knowing that, ( ) appears to be an operator - much like a function doing basically nothing -
while { } is a language construct.
The parentheses ( ) incorporate some overhead code common to all operators which is actually of no need for them.

Lukas answered the question nicely, but here are some timings on the overhead for those interested (which can be effectively removed by vectorising your code).

brace <- function(n){
w1=numeric(n)
w2=numeric(n)
r=rnorm(n)
for(i in 1:n)
w1[i]=((r[i]^2))*(1*1)
}


curly <- function(n){
w1=numeric(n)
w2=numeric(n)
r=rnorm(n)
for(i in 1:n)
w2[i]={{r[i]^2}}*{1*1}
}



microbenchmark( curly(1e5) , brace(1e5) , times = 50 ) 
Unit: milliseconds
         expr      min       lq   median       uq      max neval
 curly(1e+05) 311.4245 318.8916 324.1990 335.0928 400.8555    50
 brace(1e+05) 315.5428 323.8860 328.7982 350.7268 406.5785    50

Around a 5 millisecond difference at 1e5 loop lengths. So let's remove the loops:

braceV <- function(n){
w1=numeric(n)
w2=numeric(n)
r=rnorm(n)
w1=((r^2))*(1*1)
}


curlyV <- function(n){
w1=numeric(n)
w2=numeric(n)
r=rnorm(n)
w2={{r^2}}*{1*1}
}

microbenchmark( curlyV(1e5) , braceV(1e5) , times = 50 )
Unit: milliseconds
          expr      min       lq    median       uq      max neval
 curlyV(1e+05) 9.014361 9.284532  9.666867 10.81317 37.82510    50
 braceV(1e+05) 9.029408 9.373773 10.293302 10.83487 37.76596    50

The difference is now around ~0.5 milliseconds.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM