【发布时间】:2019-01-14 12:51:05
【问题描述】:
我正在编写一个函数,它需要调用一个函数g,该函数作为参数传递给列表的每个元素,迭代。
我想知道如何尽可能快地做到这一点。我可以使用Rcpp 和特定类型的g (用Cpp 编写所有内容)达到可接受的速度,但我不知道是否可以通过R 函数作为参数达到类似的速度。
正在做一些测试以找出 R 速度较慢的原因,并发现了一些非常出乎意料的结果:
minus <- function(x) -x
minus_vec <- Vectorize(minus, "x")
使用一些简单的函数来反转符号进行测试。
f0 <- function(x) {
sapply(x, minus)
}
f1 <- function(x) {
for(i in seq_along(x)){
x[i] <- -x[i]
}
x
}
f2 <- function(x) {
for(i in seq_along(x)){
x[i] <- minus(x[i])
}
x
}
我得到了以下结果:
a <- 1:10^5
library(rbenchmark)
benchmark(f0(a), f1(a), f2(a), minus_vec(a), minus(a))[,c(1,4)]
test relative
1 f0(a) 454.842
2 f1(a) 25.579
3 f2(a) 178.211
4 minus_vec(a) 523.789
5 minus(a) 1.000
我想对以下几点进行一些解释:
为什么
f1和f2的速度不一样?写代码-x[i]和调用函数minus(x[i])做同样的事情真的应该有这么大的区别吗?为什么
f0比f2慢?我一直认为apply函数比for循环更有效,但从来没有真正理解为什么,现在我什至找到了一个反例。我可以使用函数
minus使函数像f1一样快吗?为什么矢量化
minus(不必要,因为-已经矢量化,但可能并非总是如此)让它变得如此糟糕?
【问题讨论】:
-
apply并不总是比自写循环更有效,这实际上取决于任务和循环编写的好坏。另外,您可以考虑vapply,它是apply系列中效率最高的。 -
对于 f1 和 f2 而
-x是“内置”,minus是另一个函数,因此每次迭代中都会嵌套另一个函数调用。 -
不,你可能无法让你的编辑功能和“内置”一样快,但你可以通过使用 JIT 字节码
compiler包 - homepage.divms.uiowa.edu/~luke/R/compiler/compiler.pdf -
如果你试图将一些非常基本的东西(如减号)加速到更复杂的东西上,你会误入歧途。你的函数实际上是做什么的?
标签: r performance function