Frage

Neu bei Rcpp: Ich teste, wie man eine verschachtelte Liste aus R mit bekannter Struktur abrufen und verwenden kann, ohne Teile der Liste erneut zu kopieren.Das kleine Codebeispiel (mit eingebettetem R-Code) scheint zu funktionieren (cout wird zum Debuggen verwendet).

Die von R abgerufene Liste rL kann sehr groß sein, daher möchte ich keinen Speicher neu zuweisen (Teile von rL kopieren).Kopiert der aktuelle Code Teile von rL?

Bester Lars

#include <Rcpp.h>
#include <iostream>
using namespace Rcpp;
using namespace std;

// [[Rcpp::export]]
SEXP testing(const List rL) {
   List L(rL);
   SEXP sL2(L["L2"]);
   List L2(sL2);

   SEXP sStateGrpL2(L2["stateGroups"]);
   List stateGrpL2(sStateGrpL2);
   SEXP sStateAllocL2(L2["stateAlloc"]);   
   CharacterVector stateAllocL2(sStateAllocL2);

   SEXP sActionGrpL2(L2["actionGroups"]);
   List actionGrpL2(sActionGrpL2);
   SEXP sActionAllocL2(L2["actionAlloc"]);
   List actionAllocL2(sActionAllocL2);

   vector<string> stateLabels; 
   vector<string> actionLabels;
   CharacterVector actionNames;

   for(int n2 = 0; n2< as<int>(L2["stages"]); n2++) {
      stateLabels = as< vector<string> >(stateGrpL2[as<string>(stateAllocL2[n2])]);
      int s2Size = stateLabels.size(); 
      SEXP sAllocA(actionAllocL2[n2]);
      List allocA(sAllocA);
      actionNames = as<CharacterVector>(allocA[0]);
      cout << "stage:" << n2 << " sN:" << as<string>(stateAllocL2[n2]) << "\n";
      for (int s2=0; s2<s2Size; ++s2) { 
        cout << " s:" << stateLabels[s2] << " aN:" << actionNames[s2] << "\n";
        actionLabels = as< vector<string> >(actionGrpL2[ as<string>(actionNames[s2]) ]);
        int a2Size = actionLabels.size();
        for (int a2=0; a2<a2Size; ++a2) {
           cout << "    a:" << actionLabels[a2] << "\n";
        }
      }
   }

   return wrap(0);
}


/*** R 
L <- list( L2=list(stages=2, 
                   stateGroups=list(s1Grp=c("a","b","c"),s2Grp=c("d","e")), 
                   stateAlloc = c(rep("s1Grp",1),rep("s2Grp",1)), 
                   actionGroups = list(a1Grp=c("terminate","keep"), a2Grp=c("finish")),
                   actionAlloc = list(list( rep("a1Grp",3) ),
                                       list( c("a1Grp","a2Grp") )
                                       )
                   )
     )
testing(L)
*/
War es hilfreich?

Lösung

Sie schreiben:

Die Liste RL ist möglicherweise sehr groß, also möchte ich keinen neuen Speicher verwenden (Kopie Teile von RL).Ist das der Weg, es zu tun?

ziemlich viel (soweit ich von einem Blick auf Ihren Code erkennen kann).

Alle Exchange mit r verwendet SEXP -typen, in denen der generationstabellenetagcode für Zeiger steht - diese sind flache Proxy-Objekte, die nicht kopiert werden .Es verwendet / nutzt den Robust-Speicher.

Wenn Sie also, wenn Sie Profil / Speicherprofil handelt, sollte es sich ähnlich für n= 10 und n= 1e5 verhalten.Aber der Beweis ist in der Pudding ...

Andere Tipps

Ein paar Dinge :

  • Der Schleifentest n2< as<int>(L2["stages"]) ist sowohl schwer zu lesen als auch ineffizient, da es bei jeder Iteration berechnet wird.Sie sollten es auf jeden Fall nur einmal tun.

  • Alle deine as< vector<string> > Erstellen Sie tiefe Kopien und nutzen Sie den String -Cache des R nicht.Kannst du nicht a verwenden?CharacterVector stattdessen ?

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top