Frage

Was ist der beste Weg, die Verwendung einer C ++ Bibliothek in R, hoffentlich Erhaltung der C ++ Datenstrukturen zu machen. Ich bin nicht eine C ++ Benutzer, so dass ich nicht auf die relativen Vorteile der verfügbaren Ansätze klar bin. Das R-ext Handbuch scheint jedoch jede C ++ Funktion in C vorzuschlagen Einwickeln, mindestens vier oder fünf andere Mittel der C ++ exist enthält.

Zwei Wege sind Pakete w / ähnliche Linie, die RCPP (von der produktivsten overflower Dirk Eddelbuettel beibehalten) und RcppTemplate Pakete (beide auf CRAN), was sind die Unterschiede zwischen den beiden?

Ein weiteres Paket, rcppbind verfügbar, auf R schmieden, die Ansprüche auf die Bindung C einen anderen Ansatz zu nehmen ++ und R (Ich bin nicht gut informiert zu sagen).

Das Paket inline auf CRAN, Ansprüche Inline-C / C ++, damit ich bin nicht sicher, dass dies unterscheidet sich von der in der Funktionalität gebaut, beiseite zu ermöglichen, dass der Code inline w / R zu sein.

Und schließlich RSwig die im wilden zu sein scheint, aber es ist unklar, wie unterstützte es ist, wie der Autor Seite seit Jahren nicht mehr aktualisiert wird.

Meine Frage ist, was sind die relativen Vorteile der verschiedenen Ansätze. Welches sind die meisten tragbaren und robusten, die am einfachsten zu implementieren sind. Wenn Sie planen ein Paket auf CRAN zu verteilen, die von den Methoden würden Sie nutzen?

War es hilfreich?

Lösung

Zunächst einmal, ein Disclaimer: Ich benutze RCPP die ganze Zeit. In der Tat, wenn (nach der Zeit von RCPP umbenannt wurde) hatte RcppTemplate bereits verwaist und ohne Updates für zwei Jahre, begann ich sie unter ihrem ursprünglichen Namen RCPP zu halten (unter denen es a href beigetragen hatte zu <=“ http://dirk.eddelbuettel.com/code/rquantlib.html“rel = "noreferrer"> RQuantLib ). Das war vor etwa einem Jahr, und ich habe ein paar inkrementellen Änderungen, die Sie im Changelog dokumentiert finden können.

Jetzt RcppTemplate hat sich vor kurzem nach einer vollen 35 Monate zurück, ohne Update oder fix. Es enthält interessanten neuen Code, aber es scheint, dass es nicht rückwärtskompatibel ist, so will ich es nicht verwenden, wo ich bereits RCPP verwendet.

Rcppbind war nicht sehr aktiv gepflegt, wenn ich überprüft. Whit Armstrong hat auch ein Templat-Interface-Paket namens rabstraction .

Inline ist etwas ganz anderes: Es erleichtert die Kompilierung / link Zyklus durch das Programm als R Zeichenkette Einbetten im dass dann kompiliert wird, verbunden, und geladen. Ich habe Oleg sprach über Inline-Unterstützung RCPP hat, die schön wäre.

Swig ist zu interessant. Joe Wang hat großartige Arbeit dort und alle QuantLib für R. gewickelt Aber als ich es das letzte mal versucht, es nicht mehr funktionierte aufgrund einiger Änderungen in R-Interna. Nach jemandem aus dem Team Swig, Joe kann immer noch daran arbeiten. Das Ziel der Swig größer Bibliotheken sowieso. Dieses Projekt könnte wahrscheinlich mit einer Wiederbelebung tun, aber es ist nicht ohne technische Herausforderungen.

sollten weitere Erwähnung gehen auf RInside , die mit RCPP arbeitet und lässt Sie R innen einbetten von C ++ Anwendungen.

Also um es zusammenzufassen: RCPP funktioniert gut für mich, vor allem für kleine Sondierungs Projekte, bei denen Sie nur eine Funktion oder zwei hinzufügen möchten. Es konzentriert sich einfache Bedienung und ermöglicht es Ihnen zu ‚verstecken‘ einige der R-Interna, die nicht immer Spaß an der Arbeit mit sind. Ich kenne eine Reihe von anderen Nutzern, die ich dazu beigetragen haben, auf und ab und per E-Mail. Also ich würde sagen, für diesen einen gehen.

Meine 'Intro to HPC mit R' Tutorials haben einige Beispiele für RCPP, RInside und Inline.

Edit: Lassen Sie uns also einen Blick auf ein konkretes Beispiel (aus der 'HPC mit R Intro' Dias und entlehnt Stephen Milborrow, die es von Venables und Ripley nahm). Die Aufgabe ist es, alle möglichen Kombinationen der Determinante einer 2x2-Matrix aufzuzählen nur einzelne Ziffern in jeder Position enthalten. Dies kann auf clevere vektorisiert Arten erfolgen oder mit roher Gewalt (wie wir in dem Tutorial Dia diskutieren) wie folgt:

#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;
}

Wenn Sie speichern diese als, sagen wir, dd.rcpp.cpp und haben RCPP installiert , dann einfach Verwendung

PKG_CPPFLAGS=`Rscript -e 'Rcpp:::CxxFlags()'`  \
    PKG_LIBS=`Rscript -e 'Rcpp:::LdFlags()'`  \
    R CMD SHLIB dd.rcpp.cpp

eine gemeinsame Bibliothek zu bauen. Wir verwenden Rscript (oder r) fragen RCPP über seine Kopf- und Bibliotheksstandorte. Einmal gebaut, können wir dies aus R laden und verwenden Sie wie folgt vor:

dyn.load("dd.rcpp.so")

dd.rcpp <- function() {
    x <- integer(10000)
    res <- .Call("dd_rcpp", x)
    tabulate(res$vec)
}

Auf die gleiche Weise können Sie Vektoren senden, matrics, ... verschiedener R und C ++ Datentypen zurück mit Leichtigkeit Ende her. Hoffe, das hilft ein wenig.

Edit 2 (etwa fünf Jahre später +):

So diese Antwort bekam gerade einen upvote und damit in meiner Warteschlange sprudelte. A Los die Zeit ist vergangen, seit ich es geschrieben hätte, und RCPP hwie bekommen viel reicher an Funktionen. So schrieb ich sehr schnell dieses

#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) )
*/

, die wie folgt in einer Datei mit dem Code verwendet werden können /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> 

Einige der wichtigsten Unterschiede sind:

  • einfacher zu bauen: sourceCpp() es einfach; auch R-Test-Code am Ende führt
  • vollwertiges IntegerVector Typ
  • Ausnahmebehandlung Wrapper automatisch durch sourceCpp() Code-Generator hinzugefügt
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top