Вы все еще не сказали нам достаточно, чтобы повторить свой вопрос, но, возможно, мой пример ниже работает. tl; dr Я могу сэкономить около 10%, заменив sum()
на length(which())
(я очень удивлен, что это было не больше ...) и получить 5-кратное ускорение, используя Rcpp
.
Сформировать пример данных:
set.seed(101)
n1 <- 1e4; n2 <- 1e3
gh2 <- data.frame(data_start=rnorm(n1),data_end=rnorm(n1))
Попробуйте как обычные кадры данных и tbl_df
из dplyr
(также, data_frame
является немного более удобным для генерации данных, поскольку она позволяет на лету преобразование).
library("dplyr")
A <- data_frame(V1=rnorm(n2),
V2=V1+runif(n2))
A0 <- as.data.frame(A)
функция первоначально и основа-R альтернатива использования sum()
:
fun1 <- function(x,y)
return(length(which(x<=gh2$data_start & y>=gh2$data_end)))
fun2 <- function(x,y)
return(sum(x<=gh2$data_start & y>=gh2$data_end))
проверка:
all.equal(with(A0, mapply(fun1, V1, V2)),
with(A, mapply(fun2, V1, V2))) ## TRUE
теперь Rcpp
версия. Это почти наверняка может быть сокращено/сделано скользким, но я не очень разбираюсь в этой структуре (вряд ли сделаю огромную разницу в скорости).
library("Rcpp")
cppFunction("
NumericVector fun3(NumericVector d_start, NumericVector d_end,
NumericVector lwr, NumericVector upr) {
int i, j;
int n1 = lwr.size();
int n2 = d_start.size();
NumericVector res(n1);
for (i=0; i<n1; i++) {
res[i]=0;
for (j=0; j<n2; j++) {
if (lwr[i]<=d_start[j] && upr[i]>=d_end[j]) res[i]++;
}
}
return res;
}
")
проверка:
f3 <- fun3(gh2$data_start,gh2$data_end, A$V1,A$V2)
f1 <- with(A0, mapply(fun1, V1, V2))
all.equal(f1,f3) ## TRUE
Benchmark:
library(rbenchmark)
benchmark(fun1.0= with(A0, mapply(fun1, V1, V2)),
fun2.0= with(A0, mapply(fun2, V1, V2)), ## data.frame
fun2 = with(A, mapply(fun2, V1, V2)), ## dplyr-style
fun3 = fun3(gh2$data_start,gh2$data_end, A$V1,A$V2),
columns=c("test", "replications", "elapsed", "relative"),
replications=30
)
## test replications elapsed relative
## 1 fun1.0 30 7.813 5.699
## 3 fun2 30 6.834 4.985
## 2 fun2.0 30 6.841 4.990
## 4 fun3 30 1.371 1.000
- нет большой разницы между
data.frame
и tbl_df
sum()
составляет 12% быстрее, чем length(which())
- Rcpp составляет около 5 раз быстрее, чем базовый R
Это может быть в принципе в сочетании с parallel::mcmapply
:
mcmapply(fun3,gh2$data_start,gh2$data_end, A$V1,A$V2,
mc.cores=4)
но для размеров в приведенном выше примере накладных расходов является слишком высокой, чтобы сделать его полезным ,
Если ваш код неэффективен, просто «применение» не поможет. Если вы хотите ускорить распараллеливание проблемы, см. 'Mcmapply' в пакете' parallel'. Возможно, это тоже полезно: http://stackoverflow.com/questions/8827437/is-there-an-efficient-way-to-parallelize-mapply – fishtank
То же самое произошло. Достигнут небольшой эффективный рычаг. Но не много. – Bharath