您没有考虑为结果向量分配空间所需的时间Y1
。随着样本量的增加,分配所需的时间Y1
执行时间中所占的份额较大,而替换所花费的时间所占的份额较小。
sapply
总是为结果分配内存,因此这就是随着样本大小的增加而效率降低的原因之一。gagolews https://stackoverflow.com/questions/26430571/why-does-sapply-scale-slower-than-for-loop-with-sample-size/26430837#comment41506566_26430571还有一个很好的观点sapply
呼叫simplify2array
。这(可能)会添加另一个副本。
经过更多测试后,看起来像lapply
随着对象变大,它仍然与包含 for 循环的字节编译函数大致相同或更慢。我不知道如何解释这一点,除了可能的这一行do_lapply
:
if (MAYBE_REFERENCED(tmp)) tmp = lazy_duplicate(tmp);
或者可能有什么方法lapply
构造函数调用...但我主要是猜测。
这是我用来测试的代码:
k <- 20
t1 <- rep(0,k)
t2 <- rep(0,k)
t3 <- rep(0,k)
L <- round(10^seq(4,7,length=k))
L <- round(10^seq(4,6,length=k))
# put the loop in a function
fun <- function(X, L) {
Y1 <- rep(0,L)
for (j in 1:L)
Y1[j] <- exp(X[j])
Y1
}
# for loops often benefit from compiling
library(compiler)
cfun <- cmpfun(fun)
for (i in 1:k) {
X <- 2*1:L[i]
t1[i] <- system.time( Y1 <- fun(X, L[i]) )[3]
}
for (i in 1:k) {
X <- 2*1:L[i]
t2[i] <- system.time( Y2 <- cfun(X, L[i]) )[3]
}
for (i in 1:k) {
X <- 2*1:L[i]
t3[i] <- system.time( Y3 <- lapply(X, exp) )[3]
}
identical(Y1, Y2) # TRUE
identical(Y1, unlist(Y3)) # TRUE
plot(L, t1, type='l', col='blue', log="xy", ylim=range(t1,t2,t3))
lines(L, t2, col='red')
lines(L, t3, col='green')