R中的内置函数通常是否经过优化?

时间:2011-07-12 16:48:02

标签: function r optimization

我有一些书面代码来计算R中的相关系数。 但是,我发现'boot'包提供了一个corr() 执行相同工作的功能。 R中是内置函数 通常比我们的同等效率更高,更快 从头开始写?

谢谢。

4 个答案:

答案 0 :(得分:5)

我认为这个问题没有一个具体的答案,因为它会根据您询问的具体功能而有很大差异。为方便起见,添加了贡献包中的一些函数,它们只是基本函数的包装器。添加其他内容以扩展基本功能或解决基本功能中的一些其他感知缺陷。您建议添加一些以改善计算时间或提高效率。还有一些是因为贡献软件包的作者认为基础R中的解决方案在某种程度上是错误的。

对于stats:::corboot:::corr,看起来后者增加了加权功能。它看起来不一定更快:

> dat <- matrix(rnorm(1e6), ncol = 2)
> system.time(
+ cor(dat[, 1],dat[, 2])
+ )
   user  system elapsed 
   0.01    0.00    0.02 
> system.time(
+ corr(dat)
+ )
   user  system elapsed 
   0.11    0.00    0.11 

答案 1 :(得分:3)

这更多(即不计算糟糕的代码)归结为某个过程是在R中实现还是作为C(++)或Fortran代码的问题 - 如果函数包含对{{1}的调用},.Internal.External.C.Fortran这意味着这是第二种情况,可能会更快。请注意,这与函数来自基本R或包的问题天气是正交的。

但是,你必须始终记住,效率是一个相对的东西,必须始终在整个任务的背景下被感知,并且需要程序员加快速度所需的努力。将执行时间从1秒减少到10毫秒是一个同等的废话,只是因为包是邪恶的或者在优化功能A上花费几个小时而重新使用基础,而90%的实际执行时间隐藏在功能B中

答案 2 :(得分:2)

扩展大通的答案,我不仅认为这个问题没有单一答案,而且这个问题不是那么好。这是非常不明确的。有关要问的问题,请参阅here 此外,我感觉OP不知道基础R的cor函数,请参阅?cor

我的回答:有一些特殊功能非常快,例如rowSumsapply sum相比plyr。另一方面,存在可以避免的慢速构建(如果您愿意投入一些时间来深入了解基础知识),但是由于设计决策而构建。 Radford Neal正在争论这个角落,例如one of his latest posts on the topic

总而言之,我想这个问题的答案就是我认为R背后的哲学:R不是比赛中最快的马,但绝对是用最少的代码实现最多的马,如果它是关于数据。

一般来说,我认为状态并没有错,功能越专业,它的速度就越快(用C或Fortran编写)。函数越普遍和抽象就越慢(比较Hadley Wickham的apply与基础{{1}}家族的速度)。

答案 3 :(得分:2)

还有一点是,内置R函数通常有很多“包装”材料,可以进行错误检查,重新排列数据等。例如,lmglm各自执行一次在分别交给lm.fitglm.fit进行实际数字运算之前,有很多东西。在您的特定情况下,cor调用.Internal(cor(x, y, na.method, FALSE))了解Pearson相关性。如果(1)你真的需要速度和(2)你愿意自己适当地安排数据,并放弃错误检查,你有时可以通过自己调用内部函数来节省一些时间:

library(rbenchmark)
x <- y <- runif(1000)
benchmark(cor(x,y),.Internal(cor(x,y,4,FALSE)),replications=10000)
                            test replications elapsed relative user.self
1                      cor(x, y)        10000   1.131 5.004425     1.136
2 .Internal(cor(x, y, 4, FALSE))        10000   0.226 1.000000     0.224

但这又取决于:当矩阵很大时,我们根本没有获得太多收益,如上例所示(因此相对于进行计算所花费的错误检查时间要大得多)......

x <- y <- rnorm(5e5)
benchmark(cor(x,y),.Internal(cor(x,y,4,FALSE)),replications=500)
                            test replications elapsed relative user.self
1                      cor(x, y)          500   5.402 1.013889     5.384
2 .Internal(cor(x, y, 4, FALSE))          500   5.328 1.000000     5.316