Jeśli Twoim celem jest tylko, aby jeden przejazd, który jest bardzo proste do napisania w RCPP, nawet jeśli nie masz dużego doświadczenia z C++:
#include <Rcpp.h>
// [[Rcpp::export]]
Rcpp::LogicalVector single_pass(Rcpp::CharacterVector x, Rcpp::String a, Rcpp::String b) {
R_xlen_t i = 0, n = x.size();
Rcpp::LogicalVector result(n);
for (; i < n; i++) {
result[i] = (x[i] == a || x[i] == b);
}
return result;
}
dla takiego małego obiekt, który wykorzystano w przykładzie, niewielkiego narzutu .Call
(przypuszczalnie) maski prędkość wersji RCPP,
r_fun <- function(X) X == "A" | X == "B"
##
cpp_fun <- function(X) single_pass(X, "A", "B")
##
all.equal(r_fun(x), cpp_fun(x))
#[1] TRUE
microbenchmark::microbenchmark(
r_fun(x), cpp_fun(x), times = 1000L)
#Unit: microseconds
#expr min lq mean median uq max neval
#r_fun(x) 1.499 1.584 1.974156 1.6795 1.8535 37.903 1000
#cpp_fun(x) 1.860 2.334 3.042671 2.7450 3.1140 51.870 1000
Ale dla większych wektorów (jestem zakładając, to y nasze prawdziwe intencje), to znacznie szybciej:
x2 <- sample(LETTERS, 10E5, replace = TRUE)
##
all.equal(r_fun(x2), cpp_fun(x2))
# [1] TRUE
microbenchmark::microbenchmark(
r_fun(x2), cpp_fun(x2), times = 200L)
#Unit: milliseconds
#expr min lq mean median uq max neval
#r_fun(x2) 78.044518 79.344465 83.741901 80.999538 86.368627 149.5106 200
#cpp_fun(x2) 7.104929 7.201296 7.797983 7.605039 8.184628 10.7250 200
Oto quick attempt w uogólniając powyższe, jeśli masz jakieś zastosowanie dla niego.
co powiesz na: 'x% w% c (" A "," B ")' – MrFlick
@MrFlick Bawiło się z synchronizacją tych dwóch opcji i naprawdę nie widzę dużej różnicy. Skala jest w nanosekundach, nawet gdy zwiększam ją, więc jestem trochę stracona – joran
@joran Tak, nie wyobrażam sobie, że zobaczysz duży wzrost prędkości (i bardzo wątpię, wąskie gardło wydajności), ale jest to po prostu alternatywna składnia. – MrFlick