Jak mówi Dirk, skompilowany kod może być znacznie szybszy. Musiałem to zrobić w jednym z moich projektów i byłem zaskoczony przyspieszeniem: ~ 40x szybciej niż rozwiązanie Andrie.
> a <- runif(10000)
> b <- runif(10000)
> system.time(convolveFast(a, b))
user system elapsed
7.814 0.001 7.818
> system.time(convolveC(a, b))
user system elapsed
0.188 0.000 0.188
Zrobiłem kilka prób to przyspieszyć w R zanim zdecydowałem, że za pomocą kodu C nie może być tak źle (uwaga: to naprawdę nie było). Wszystkie moje były wolniejsze niż Andrie i były wariantami, które odpowiednio dodawały produkt krzyżowy. Podstawową wersję można zrobić w zaledwie trzech liniach.
convolveNotAsSlow <- function(x, y) {
xyt <- x %*% t(y)
ds <- row(xyt)+col(xyt)-1
tapply(xyt, ds, sum)
}
Ta wersja tylko trochę pomaga.
> a <- runif(1000)
> b <- runif(1000)
> system.time(convolveSlow(a, b))
user system elapsed
6.167 0.000 6.170
> system.time(convolveNotAsSlow(a, b))
user system elapsed
5.800 0.018 5.820
Moja najlepsza wersja była to:
convolveFaster <- function(x,y) {
foo <- if (length(x)<length(y)) {y %*% t(x)} else { x %*% t(y) }
foo.d <- dim(foo)
bar <- matrix(0, sum(foo.d)-1, foo.d[2])
bar.rc <- row(bar)-col(bar)
bar[bar.rc>=0 & bar.rc<foo.d[1]]<-foo
rowSums(bar)
}
To było trochę lepiej, ale nadal nie tak szybko, jak Andrie na
> system.time(convolveFaster(a, b))
user system elapsed
0.280 0.038 0.319
Wygląda na to, że używasz list wektorów jednoelementowych zamiast wektorów. – mbq