Des boucles de R sont lents pour la même raison un langage interprété est lent: toutes les
l'opération porte autour d'un lot de bagages supplémentaires.
Regardez - R_execClosure
en eval.c
(c'est la fonction appelée pour appeler un
fonction définie par l'utilisateur). C'est près de 100 lignes et effectue toutes sortes de
des opérations, de créer un environnement pour l'exécution, l'attribution des arguments dans
l'environnement, etc.
Pensez à combien se produit lorsque vous appelez une fonction en C (push args sur
pile, de sauter, de la pop args).
C'est pourquoi vous obtenez timings comme ceux-ci (comme joran souligné dans le commentaire,
ce n'est pas réellement apply
qui est rapide; c'est l'interne de la boucle C en mean
c'est d'être rapide. apply
est juste ordinaire ancienne R code):
A = matrix(as.numeric(1:100000))
À l'aide d'une boucle: 0.342 secondes:
system.time({
Sum = 0
for (i in seq_along(A)) {
Sum = Sum + A[[i]]
}
Sum
})
À l'aide de somme: unmeasurably petit:
sum(A)
C'est un peu déconcertant, car, asymptotiquement, la boucle est tout aussi bon
en tant que sum
; il n'y a aucune raison pratique, il doit être lente; il est juste de faire plus
travail supplémentaire à chaque itération.
Donc prendre en compte:
# 0.370 seconds
system.time({
I = 0
while (I < 100000) {
10
I = I + 1
}
})
# 0.743 seconds -- double the time just adding parentheses
system.time({
I = 0
while (I < 100000) {
((((((((((10))))))))))
I = I + 1
}
})
(Cet exemple a été découvert par Radford Neal)
Parce qu' (
dans R est un opérateur, et exige en fait une recherche de nom à chaque fois que vous l'utilisez:
> `(` = function(x) 2
> (3)
[1] 2
Ou, en général, interprété opérations (dans toutes les langues) ont plus d'étapes. Bien sûr, ces mesures fournissent des avantages: vous ne pouvez pas faire qu' (
truc en C.