Prima di tutto, una dichiarazione di non responsabilità: io uso Rcpp tutto il tempo. Infatti, quando (essendo stato rinominato dal momento in cui Rcpp) RcppTemplate era già rimasto orfano e senza aggiornamenti per due anni, ho iniziato a mantenerlo sotto il suo nome iniziale di Rcpp (sotto il quale era stato contribuito a RQuantLib). È stato circa un anno fa e ho apportato un paio di modifiche incrementali che puoi trovare documentate nel ChangeLog.
Ora RcppTemplate è tornato molto recentemente dopo trentacinque mesi senza alcun aggiornamento o correzione. Contiene un nuovo codice interessante, ma sembra che non sia retrocompatibile quindi non lo userò dove ho già usato Rcpp.
Rcppbind non è stato mantenuto molto attivamente ogni volta che ho controllato. Whit Armstrong ha anche un pacchetto di interfaccia basato su modelli chiamato rabstraction.
Inline è qualcosa di completamente diverso: facilita il ciclo di compilazione/collegamento "incorporando" il programma come stringa di caratteri R che viene quindi compilata, collegata e caricata. Ho parlato con Oleg di avere un supporto in linea Rcpp che sarebbe bello.
Swig è anche interessante. Joe Wang ha fatto un ottimo lavoro lì e ha avvolto tutto QuantLib per R. Ma quando l'ho provato l'ultima volta, non funzionava più a causa di alcuni cambiamenti in R internals. Secondo qualcuno del team di Swig, Joe potrebbe ancora lavorarci su. L'obiettivo di Swig è comunque librerie più grandi. Questo progetto potrebbe probabilmente fare con un risveglio, ma non è senza sfide tecniche.
Un'altra menzione dovrebbe andare a RInside che funziona con Rcpp e consente di incorporare R all'interno di applicazioni C++.
Quindi, per riassumere: Rcpp funziona bene per me, soprattutto per i piccoli progetti di esplorazione in cui si desidera semplicemente aggiungere una funzione o due. Il suo obiettivo è la facilità d'uso, e ti permette di "nascondere" alcuni dei R interni che non sono sempre divertenti da usare. Conosco un certo numero di altri utenti che ho aiutato su e via email. Quindi direi di andare per questo.
Le esercitazioni di "Intro to HPC with R" presentano alcuni esempi di Rcpp, RInside e inline.
Modifica: Quindi diamo un'occhiata ad un esempio concreto (tratto dalle diapositive 'HPC con R Intro' e preso in prestito da Stephen Milborrow che lo ha preso da Venables and Ripley). Il compito è enumerare tutte le possibili combinazioni del determinante di una matrice 2x2 contenente solo cifre singole in ciascuna posizione. Questo può essere fatto in modi Vectorised intelligenti (come vedremo nelle diapositive di tutorial) o con la forza bruta come segue:
#include <Rcpp.h>
RcppExport SEXP dd_rcpp(SEXP v) {
SEXP rl = R_NilValue; // Use this when there is nothing to be returned.
char* exceptionMesg = NULL; // msg var in case of error
try {
RcppVector<int> vec(v); // vec parameter viewed as vector of ints
int n = vec.size(), i = 0;
if (n != 10000)
throw std::length_error("Wrong vector size");
for (int a = 0; a < 9; a++)
for (int b = 0; b < 9; b++)
for (int c = 0; c < 9; c++)
for (int d = 0; d < 9; d++)
vec(i++) = a*b - c*d;
RcppResultSet rs; // Build result set to be returned as list to R
rs.add("vec", vec); // vec as named element with name 'vec'
rl = rs.getReturnList(); // Get the list to be returned to R.
} catch(std::exception& ex) {
exceptionMesg = copyMessageToR(ex.what());
} catch(...) {
exceptionMesg = copyMessageToR("unknown reason");
}
if (exceptionMesg != NULL)
Rf_error(exceptionMesg);
return rl;
}
Se si salva questo come, ad esempio, dd.rcpp.cpp
e hanno Rcpp installato, quindi è sufficiente utilizzare
PKG_CPPFLAGS=`Rscript -e 'Rcpp:::CxxFlags()'` \
PKG_LIBS=`Rscript -e 'Rcpp:::LdFlags()'` \
R CMD SHLIB dd.rcpp.cpp
per creare una libreria condivisa. Utilizziamo Rscript
(o r
) per chiedere a Rcpp l'intestazione e le posizioni delle librerie. Una volta costruito, siamo in grado di caricare e utilizzare questo da R come segue:
dyn.load("dd.rcpp.so")
dd.rcpp <- function() {
x <- integer(10000)
res <- .Call("dd_rcpp", x)
tabulate(res$vec)
}
Allo stesso modo, è possibile inviare vettori, Matrics, ... di vari R e C++ tipi di dati back-end indietro con facilità. Spero che questo aiuti un po '.
Edit 2 (circa cinque + anni più tardi):
Quindi questa risposta appena ricevuto un upvote e quindi gorgogliare nella mia coda. A il lotto di tempo è trascorso da quando l'ho scritto e Rcpp ha ottenuto un sacco più ricco di funzionalità. Così ho molto rapidamente scritto questo
#include <Rcpp.h>
// [[Rcpp::export]]
Rcpp::IntegerVector dd2(Rcpp::IntegerVector vec) {
int n = vec.size(), i = 0;
if (n != 10000)
throw std::length_error("Wrong vector size");
for (int a = 0; a < 9; a++)
for (int b = 0; b < 9; b++)
for (int c = 0; c < 9; c++)
for (int d = 0; d < 9; d++)
vec(i++) = a*b - c*d;
return vec;
}
/*** R
x <- integer(10000)
tabulate(dd2(x))
*/
che può essere utilizzato nel modo seguente con il codice in un file /tmp/dd.cpp
R> Rcpp::sourceCpp("/tmp/dd.cpp") # on from any other file and path
R> x <- integer(10000)
R> tabulate(dd2(x))
[1] 87 132 105 155 93 158 91 161 72 104 45 147 41 96
[15] 72 120 36 90 32 87 67 42 26 120 41 36 27 75
[29] 20 62 16 69 19 28 49 45 12 18 11 57 14 48
[43] 10 18 7 12 6 46 23 10 4 10 4 6 3 38
[57] 2 4 2 3 2 2 1 17
R>
Alcune delle differenze principali sono:
- più semplice costruire: basta
sourceCpp()
esso; anche esegue R codice di prova all'estremità
- pieno titolo
IntegerVector
tipo
- di gestione delle eccezioni involucro aggiunto automaticamente dal generatore di codice
sourceCpp()
Grazie per la risposta! Potresti chiarire cosa intendi con "codice nuovo interessante" in RcppTemplate. Come si differenzia il pacchetto da Rcpp? Non conosco quasi nulla di C++, come funzionano questi pacchetti? – Peter
Dirk, forse è il momento per la vignetta rapida parlata su come far funzionare C++ con R ... :(! – knguyen
Non è facile spiegare come differiscono così com'è ... nel C++ che differiscono –