Не полный ответ, но вот несколько заметок
1 minus(x)
против -x
: Ничто не лучше, чем что-то делать
Ваша функция minus
вызывает `-`
, поэтому добавленный шаг добавляет время вычисления. Я, честно говоря, не знаю, кто, что и когда конкретно, другими словами, я бы не знал, сколько еще времени вычислений следует ожидать.
Вот пример, подчеркивающий это: у нас есть четыре функции, все квадратные числа
fa <- function (n) n^2
fb <- function (n) fa(n)
fc <- function (n) fb(n)
fd <- function (n) fc(n)
Fa <- function (n) {
for (i in seq_along(n)) n[i] <- fa(i)
n
}
Fb <- function (n) {
for (i in seq_along(n)) n[i] <- fb(i)
n
}
Fc <- function (n) {
for (i in seq_along(n)) n[i] <- fc(i)
n
}
Fd <- function (n) {
for (i in seq_along(n)) n[i] <- fd(i)
n
}
А вот результаты бенчмаркинга
n <- 1:10^4
b <- benchmark(Fa(n),Fb(n),Fc(n),Fd(n), replications = 1000L)
b
# test replications elapsed relative user.self sys.self user.child sys.child
# 1 Fa(n) 1000 3.93 1.000 3.85 0.00 NA NA
# 2 Fb(n) 1000 7.08 1.802 6.94 0.02 NA NA
# 3 Fc(n) 1000 10.16 2.585 9.94 0.06 NA NA
# 4 Fd(n) 1000 13.68 3.481 13.56 0.00 NA NA
# looks rather even
diff(b$elapsed)
# [1] 3.15 3.08 3.52
Теперь вернемся к вашей minus
функции
a <- 1:10^5
b <- benchmark(f0(a), f1(a), f2(a), minus_vec(a), minus(a))
b$elapsed[b$test == 'f2(a)'] - b$elapsed[b$test == 'f1(a)']
# [1] 3.39
2 apply
против for
против Vectorize
:
@ NavyCheng предоставил хороший материал по этой теме. Теперь я понимаю, что семейство apply
(как и Vectorize
) зацикливается на R
(тогда как, если я не ошибаюсь, зацикливание за `-`
выполняется в C
).
Опять же, я не знаю точных деталей, но если apply/Vectorize
использовать R
петли, то в теории (и часто на практике) можно написать правильную for
цикл, который будет работать как хорошо или лучше.
3 A Функция так же быстро, как f1
:
Ad-hoc, закрытие, которое я придумал, было изменой с использованием пакета Rcpp
. ( обман , поскольку сначала пишется функция в c++
)
In C ++
#include <RcppArmadillo.h>
//[[Rcpp::depends(RcppArmadillo)]]
using namespace Rcpp;
// [[Rcpp::export]]
NumericVector minusCpp(NumericVector x) {
for (int k = 0; k < x.length(); ++k) {
x[k] = -x[k];
}
return x;
}
Теперь к bechmarks в R
a <- 1:10^5
b <- benchmark(f0(a), f1(a), f2(a), minus_vec(a), minus(a), minusCpp(a))
b
# test replications elapsed relative user.self sys.self user.child sys.child
# 1 f0(a) 100 9.47 NA 9.22 0.01 NA NA
# 2 f1(a) 100 0.53 NA 0.54 0.00 NA NA
# 3 f2(a) 100 4.23 NA 4.24 0.00 NA NA
# 5 minus(a) 100 0.00 NA 0.00 0.00 NA NA
# 4 minus_vec(a) 100 10.42 NA 10.39 0.02 NA NA
# 6 minusCpp(a) 100 0.05 NA 0.04 0.00 NA NA