Pętle w R są powolne z tego samego powodu, dla którego każdy język interpretowany jest powolny: każda operacja niesie ze sobą dużo dodatkowego bagażu.
Spójrz na R_execClosure
weval.c
(jest to funkcja o nazwie wywołać funkcję zdefiniowaną przez użytkownika). Ma prawie 100 linii i wykonuje różnego rodzaju operacje - tworzenie środowiska do wykonywania, przypisywanie argumentów do środowiska itp.
Pomyśl, o ile mniej się dzieje, gdy wywołujesz funkcję w C (wstawiaj argumenty do stosu, przeskakuj, zmieniaj argumenty).
Dlatego otrzymujesz takie czasy (jak zauważył joran w komentarzu, tak naprawdę nie apply
jest to szybkie; to wewnętrzna pętla C mean
jest szybka. apply
To zwykły stary kod R):
A = matrix(as.numeric(1:100000))
Korzystanie z pętli: 0,342 sekundy:
system.time({
Sum = 0
for (i in seq_along(A)) {
Sum = Sum + A[[i]]
}
Sum
})
Korzystanie z sumy: niewymiernie małe:
sum(A)
To trochę niepokojące, ponieważ asymptotycznie pętla jest tak samo dobra jak sum
; nie ma praktycznego powodu, dla którego powinno być wolne; po prostu robi więcej dodatkowej pracy w każdej iteracji.
Więc rozważ:
system.time({
I = 0
while (I < 100000) {
10
I = I + 1
}
})
system.time({
I = 0
while (I < 100000) {
((((((((((10))))))))))
I = I + 1
}
})
(Ten przykład odkrył Radford Neal )
Ponieważ (
w R jest operatorem i faktycznie wymaga wyszukiwania nazwy za każdym razem, gdy go używasz:
> `(` = function(x) 2
> (3)
[1] 2
Lub, ogólnie rzecz biorąc, operacje interpretowane (w dowolnym języku) mają więcej kroków. Oczywiście te kroki również przynoszą korzyści: nie można zrobić tej (
sztuczki w C.
system.time
wojny w odpowiedziach się zaczną ...