Цикли в 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
війни у відповідях розпочнуться ...