一切都在问题中!我只是尝试进行一些优化,并确定瓶颈,出于好奇,我尝试了:
t1 <- rnorm(10)
microbenchmark(
mean(t1),
sum(t1)/length(t1),
times = 10000)
结果是 mean() 比“手动”计算慢 6 倍以上!
它是源于调用 Internal(mean) 之前 mean() 代码中的开销,还是 C 代码本身较慢?为什么?是否有充分的理由并因此是一个很好的用例?
一切都在问题中!我只是尝试进行一些优化,并确定瓶颈,出于好奇,我尝试了:
t1 <- rnorm(10)
microbenchmark(
mean(t1),
sum(t1)/length(t1),
times = 10000)
结果是 mean() 比“手动”计算慢 6 倍以上!
它是源于调用 Internal(mean) 之前 mean() 代码中的开销,还是 C 代码本身较慢?为什么?是否有充分的理由并因此是一个很好的用例?
这是由于 s3 查找方法,然后对 mean.default 中的参数进行必要的解析。(以及其他平均代码)
sum
并且length
都是原始函数。所以会很快(但是你如何处理 NA 值?)
t1 <- rnorm(10)
microbenchmark(
mean(t1),
sum(t1)/length(t1),
mean.default(t1),
.Internal(mean(t1)),
times = 10000)
Unit: nanoseconds
expr min lq median uq max neval
mean(t1) 10266 10951 11293 11635 1470714 10000
sum(t1)/length(t1) 684 1027 1369 1711 104367 10000
mean.default(t1) 2053 2396 2738 2739 1167195 10000
.Internal(mean(t1)) 342 343 685 685 86574 10000
的内部位mean
甚至比sum
/还要快length
。
有关更多详细信息(以及避免使用的 data.table 解决方案),请参阅http://rwiki.sciviews.org/doku.php?id=packages:cran:data.table#method_dispatch_takes_time ( mirror.Internal
)。
请注意,如果我们增加向量的长度,那么原始方法是最快的
t1 <- rnorm(1e7)
microbenchmark(
mean(t1),
sum(t1)/length(t1),
mean.default(t1),
.Internal(mean(t1)),
+ times = 100)
Unit: milliseconds
expr min lq median uq max neval
mean(t1) 25.79873 26.39242 26.56608 26.85523 33.36137 100
sum(t1)/length(t1) 15.02399 15.22948 15.31383 15.43239 19.20824 100
mean.default(t1) 25.69402 26.21466 26.44683 26.84257 33.62896 100
.Internal(mean(t1)) 25.70497 26.16247 26.39396 26.63982 35.21054 100
现在方法分派只是所需总“时间”的一小部分。
mean
由于以下几个原因,比“手动”计算要慢:
NA
处理第 1 点和第 2 点已经讲过了。第 3 点在R 使用什么算法计算均值中讨论?. 基本上,mean
对向量进行 2 次传递以纠正浮点错误。sum
只对向量进行 1 次传递。
请注意,这identical(sum(t1)/length(t1), mean(t1))
可能是FALSE
由于这些精度问题。
> set.seed(21); t1 <- rnorm(1e7,,21)
> identical(sum(t1)/length(t1), mean(t1))
[1] FALSE
> sum(t1)/length(t1) - mean(t1)
[1] 2.539201e-16