I loop in R sono lenti per lo stesso motivo per cui qualsiasi linguaggio interpretato è lento: ogni operazione porta con sé un sacco di bagagli extra.
Guarda R_execClosure
ineval.c
(questa è la funzione chiamata per chiamare una funzione definita dall'utente). È lungo quasi 100 righe ed esegue tutti i tipi di operazioni: creazione di un ambiente per l'esecuzione, assegnazione di argomenti nell'ambiente, ecc.
Pensa quanto meno accade quando chiami una funzione in C (push args on to stack, jump, pop args).
Quindi questo è il motivo per cui ottieni tempi come questi (come ha sottolineato joran nel commento, in realtà non apply
è veloce; è il ciclo C interno mean
che è veloce. apply
È solo un normale vecchio codice R):
A = matrix(as.numeric(1:100000))
Utilizzando un ciclo: 0,342 secondi:
system.time({
Sum = 0
for (i in seq_along(A)) {
Sum = Sum + A[[i]]
}
Sum
})
Utilizzando sum: incommensurabilmente piccolo:
sum(A)
È un po 'sconcertante perché, asintoticamente, il loop è buono quanto sum
; non c'è motivo pratico che dovrebbe essere lento; sta solo facendo più lavoro extra ogni iterazione.
Quindi considera:
system.time({
I = 0
while (I < 100000) {
10
I = I + 1
}
})
system.time({
I = 0
while (I < 100000) {
((((((((((10))))))))))
I = I + 1
}
})
(Quell'esempio è stato scoperto da Radford Neal )
Perché (
in R è un operatore e in realtà richiede una ricerca del nome ogni volta che lo usi:
> `(` = function(x) 2
> (3)
[1] 2
Oppure, in generale, le operazioni interpretate (in qualsiasi lingua) hanno più passaggi. Naturalmente, questi passaggi offrono anche vantaggi: non potresti fare quel (
trucco in C.
system.time
guerre nelle risposte inizino ...