Циклы в R медленные по той же причине, по которой любой интерпретируемый язык работает медленно: каждая операция несет с собой много лишнего багажа.
Посмотрите R_execClosure
вeval.c
(это функция , которая вызывается , чтобы вызвать определенную пользователем функцию). Он состоит из почти 100 строк и выполняет всевозможные операции - создание среды для выполнения, присвоение аргументов среде и т. Д.
Подумайте, насколько меньше происходит, когда вы вызываете функцию в C (вставлять аргументы в стек, переходить, выдавать аргументы).
Вот почему вы получаете такие моменты времени (как указал Джоран в комментарии, на самом деле apply
это не так быстро; это внутренний цикл C, mean
который является быстрым. apply
Это просто обычный старый код R):
A = matrix(as.numeric(1:100000))
Используя цикл: 0,342 секунды:
system.time({
Sum = 0
for (i in seq_along(A)) {
Sum = Sum + A[[i]]
}
Sum
})
Используя сумму: неизмеримо малая:
sum(A)
Это немного сбивает с толку, потому что асимптотически цикл ничем не хуже sum
; нет никакой практической причины, по которой он должен быть медленным; он просто выполняет больше дополнительной работы с каждой итерацией.
Итак, рассмотрим:
system.time({
I = 0
while (I < 100000) {
10
I = I + 1
}
})
system.time({
I = 0
while (I < 100000) {
((((((((((10))))))))))
I = I + 1
}
})
(Этот пример был обнаружен Рэдфордом Нилом )
Потому что (
в R - это оператор, который фактически требует поиска имени каждый раз, когда вы его используете:
> `(` = function(x) 2
> (3)
[1] 2
Или, как правило, интерпретируемые операции (на любом языке) содержат больше шагов. Конечно, эти шаги также приносят пользу: вы не смогли бы проделать такой (
трюк в C.
system.time
начнутся войны в ответах ...