为什么 R 代码使用 `{}` 比使用 `()` 更快?

5

为什么使用{}的R代码通常比使用()的代码更快,例如下面的示例?

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()

5
请查看Radford Neal的博客,链接为http://radfordneal.wordpress.com/2010/08/15/two-surpising-things-about-r/。 - baptiste
1
我也希望能够提供一个现实世界的例子,说明上述差异(顺便说一句,我无法复制)在如何处理任务方面会产生有形的影响。 - Chase
1
Radford Neal的博客提供了示例和解释。 - Manoel Galdino
4
减少毫秒级别的另一个技巧是使用 ** 代替 ^ - Rcoster
1
有趣的是,'{''('都被解析为具有原始函数的call对象。区别必须在C代码中。 - Ferdinand.kraft
显示剩余2条评论
2个回答

9
baptiste已经在评论中提供了Radford Neal的博客链接。 但是,由于SE的人不喜欢外部网站的链接,让我引用一下作者本人的有趣评论(第33条):
“是的,在R 2.13.1和最新的R 2.14.1中,圆括号仍然比花括号慢,尽管差异不如以前那么大(我建议减少内置函数中的通用开销的补丁被合并到后来的版本中,这减小了这种差异)。 没有理由认为圆括号会更慢。我建议另一个更改(只需几行代码)可以加快圆括号的速度。Luke Tierney回应说,决不能将此补丁纳入R,因为圆括号就像sqrt一样是一个运算符,并且在实现圆括号的代码中,不应该有任何与像sqrt这样的运算符实现不同的东西。”
知道这一点后,( )似乎是一个操作符——就像一个基本无作用的函数, 而{ }是一种语言结构。 括号( )包含一些所有操作符都共有的额外代码开销,实际上对它们毫无意义。

这个答案是不正确的:{现在也是R中的一个运算符,而不是语言结构!就像(一样,它也可以被重载。然而,自评论(和这个答案)被写出以来,这可能已经发生了改变。 - Konrad Rudolph

5

Lukas回答了问题,但对于那些感兴趣的人,这里有一些关于开销的时间(通过向量化您的代码可以有效地消除)。

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

在1e5循环长度时,差异大约为5毫秒。因此,让我们移除循环:
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

现在的差距大约为0.5毫秒。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接