Все функции, которые вы используете, .Primitive
(поэтому уже вызываете скомпилированный код напрямую), поэтому будет сложно найти согласованный выигрыш в скорости вне перестроения R с оптимизированным BLAS. С учетом сказанного, вот один вариант, который может быть быстрее для больших векторов:
cosine_calc2 <- function(a,b,wts) {
a = a*wts
b = b*wts
crossprod(a,b)/sqrt(crossprod(a)*crossprod(b))
}
all.equal(cosine_calc1(a,b,w),cosine_calc2(a,b,w))
# [1] TRUE
# Check some timings
library(rbenchmark)
# cosine_calc2 is slower on my machine in this case
benchmark(
cosine_calc1(a,b,w),
cosine_calc2(a,b,w), replications=1e5, columns=1:4 )
# test replications user.self sys.self
# 1 cosine_calc1(a, b, w) 100000 1.06 0.02
# 2 cosine_calc2(a, b, w) 100000 1.21 0.00
# but cosine_calc2 is faster for larger vectors
set.seed(21)
a <- rnorm(1000)
b <- rnorm(1000)
w <- runif(1000)
benchmark(
cosine_calc1(a,b,w),
cosine_calc2(a,b,w), replications=1e5, columns=1:4 )
# test replications user.self sys.self
# 1 cosine_calc1(a, b, w) 100000 3.83 0
# 2 cosine_calc2(a, b, w) 100000 2.12 0
UPDATE:
Профилирование показывает, что на умножение каждого вектора на весовой вектор уходит совсем немного времени.
> Rprof(); for(i in 1:100000) cosine_calc2(a,b,w); Rprof(NULL); summaryRprof()
$by.self
self.time self.pct total.time total.pct
* 0.80 45.98 0.80 45.98
crossprod 0.56 32.18 0.56 32.18
cosine_calc2 0.32 18.39 1.74 100.00
sqrt 0.06 3.45 0.06 3.45
$by.total
total.time total.pct self.time self.pct
cosine_calc2 1.74 100.00 0.32 18.39
* 0.80 45.98 0.80 45.98
crossprod 0.56 32.18 0.56 32.18
sqrt 0.06 3.45 0.06 3.45
$sample.interval
[1] 0.02
$sampling.time
[1] 1.74
Если вы сможете выполнить взвешивание до того, как вызовете функцию миллионы раз, это может сэкономить вам немного времени. cosine_calc3
незначительно быстрее, чем ваша исходная функция с маленькими векторами. Байт-компиляция функции должна дать вам еще одно предельное ускорение.
cosine_calc3 <- function(a,b) {
crossprod(a,b)/sqrt(crossprod(a)*crossprod(b))
}
A = a*w
B = b*w
# Run again on the 1000-element vectors
benchmark(
cosine_calc1(a,b,w),
cosine_calc2(a,b,w),
cosine_calc3(A,B), replications=1e5, columns=1:4 )
# test replications user.self sys.self
# 1 cosine_calc1(a, b, w) 100000 3.85 0.00
# 2 cosine_calc2(a, b, w) 100000 2.13 0.02
# 3 cosine_calc3(A, B) 100000 1.31 0.00