2017-02-17 3 views
-1

Ich bin ein Anfänger mit Rcpp. Zur Zeit habe ich einen Rcpp-Code geschrieben, der auf zwei 3-dimensionalen Arrays angewendet wurde: Array1 und Array2. Angenommen, Array1 hat Dimension (1000, 100, 40) und Array2 hat Dimension (1000, 96, 40).Rcpp Programmierung Effizienz

Ich möchte wilcox.test ausführen mit:

wilcox.test(Array1[i, j,], Array2[i,,]) 

In R, ich verschachtelt schrieb for Schleifen, die die Berechnung in etwa einer halben Stunde abgeschlossen.

Dann schrieb ich es in Rcpp. Die Berechnung in Rcpp dauerte eine Stunde, um die gleichen Ergebnisse zu erzielen. Ich dachte, es sollte schneller sein, da es in C++ geschrieben ist. Ich denke, dass meine Art der Codierung die Ursache für die geringe Effizienz ist.

Das Folgende ist mein Rcpp-Code, würde es Ihnen etwas ausmachen, mir zu helfen, herauszufinden, welche Verbesserung ich bitte machen sollte? Ich schätze es!

// [[Rcpp::depends(RcppArmadillo)]] 
#include <RcppArmadillo.h> 
using namespace Rcpp; 

// [[Rcpp::export]] 
NumericVector Cal(NumericVector Array1,NumericVector Array2,Function wilc) { 

    NumericVector vecArray1(Array1); 
    IntegerVector arrayDims1 = vecArray1.attr("dim"); 

    NumericVector vecArray2(Array2); 
    IntegerVector arrayDims2 = vecArray2.attr("dim"); 

    arma::cube cubeArray1(vecArray1.begin(), arrayDims1[0], arrayDims1[1],  arrayDims1[2], false); 

    arma::cube cubeArray2(vecArray2.begin(), arrayDims2[0], arrayDims2[1], arrayDims2[2], false); 

    arma::mat STORE=arma::mat(arrayDims1[0], arrayDims1[1]); 

    for(int i=0;i<arrayDims1[1];i++) 
    { 

    for(int j=0;j<arrayDims1[0];j++){ 
     arma::vec  v_cl=cubeArray1.subcube(arma::span(j),arma::span(i),arma::span::all); 

     //arma::mat  tem=cubeArray2.subcube(arma::span(j),arma::span::all,arma::span::all); 

     //arma::vec v_ct=arma::vectorise(tem); 

     arma::vec v_ct=arma::vectorise(cubeArray2.subcube(arma::span(j),arma::span::all,arma::span::all)); 

     Rcpp::List resu=wilc(v_cl,v_ct); 
     STORE(j,i)=resu[2]; 

    } 

    } 


    return(Rcpp::wrap(STORE)); 

} 

Die Funktion wilc wird wilcox.test von R sein.

Das folgende ist ein Teil meiner R Code für die obige Idee der Umsetzung, wo CELLS und CTRLS sind zwei 3D-Array in R.

for(i in 1:ncol(CELLS)) { 
    if(T){ print(i) } 
    for (j in 1:dim(CELLS)[1]) { 
    wtest = wilcox.test(CELLS[j,i,], CTRLS[j,,]) 
    TSTAT_clcl[j,i] = wtest$p.value 
    } 
} 
+0

Der Aufruf von R ++ in jeder Schleife ist ... ziemlich genau so wie das Schreiben in R. Sie hatten die falsche Ausgangsannahme: die Schleifen, die Sie umgeschrieben haben, waren nicht der Flaschenhals. Das nächste Mal, vielleicht Profil zuerst. –

+0

Hallo @DirkEddelbuettel, danke für deinen Kommentar! Ich habe es in R mit foreach umgeschrieben und benutze doSNOW, um Code parallel zu implementieren. Bei einem Array von 1000 * 100 * 40 dauert es 18 Minuten, um ein Ergebnis zu erhalten. Es ist jedoch immer noch nicht ideal. Es ist eine Herausforderung für jemanden, der nicht über Informatikwissen wie mich verfügt, um die Leistung des Codes zu verbessern. Jedenfalls finde ich es auch interessant! –

Antwort

1

Dann schrieb ich es in RCPP. Die Berechnung in Rcpp dauerte eine Stunde, um die gleichen Ergebnisse zu erzielen. Ich dachte, es sollte schneller sein, da es in C++ geschrieben ist.

Die erforderliche Haftungsausschluss:

Embedding R Code in C++ und eine Geschwindigkeit von bis erwarten ist ein Spiel Narr. Sie müssen wilcox.test voll in C++ umschreiben, anstatt einen Anruf an R. Sonst verlierst du den Vorteil, den du bekommst.

Insbesondere schrieb ich in R eine post illustriert dieses Rätsel in Bezug auf die Verwendung der diff Funktion auf. Innerhalb der Post, detaillierter Beschreibung der I eine reines C++ Implementierung vergleicht, eine C++ Implementierung unter Verwendung eine R Funktion innerhalb der Routine, und eine reine R Implementierung. Diebstahl des microbenchmark veranschaulicht das obige Problem.

expr  min  lq  mean  median uq  max   neval 
arma_fun 26.117 27.318 37.54248 28.218 29.869 751.087  100 
r_fun  127.883 134.187 212.81091 138.390 151.148 1012.856 100 
rcpp_fun 250.663 265.972 356.10870 274.228 293.590 1430.426 100 

So eine reineC++ Umsetzung hatte die größte Geschwindigkeit auf.

Daher ist die wegzunehmen ist die Notwendigkeit, den wilcox.testR Routine-Code zu einer reinen C++ Umsetzung zu übersetzen, die Laufzeit zu fallen. Ansonsten ist es sinnlos, den Code in C++ zu schreiben, weil die C++ Komponente stoppen müssen und warten auf Ergebnisse von R bevor Sie fortfahren. Dies hat traditionell eine Los Overhead, um sicherzustellen, dass die Daten gut geschützt sind.

+0

Vielen Dank! Ich fand einen Wilcoxon signed-rank-Test, der in C++ [ALGLIB] (http://www.alglib.net/hypothesisstesting/wilcoxonsignedrank.php) implementiert wurde. Darf ich Ihre Meinung dazu haben? Ist es einen Versuch wert? Ich schätze es. –

+0

Es gibt derzeit keinen Wrapper für die Verwendung von ALGLIB innerhalb des _R_-Ökosystems. (http://stackoverflow.com/questions/27775923/is-it-possible-to-use-alglib-with-rcpp) Sie müssen wahrscheinlich selbst implementieren. – coatless

+0

Das sind schlechte Nachrichten. Wie auch immer, vielen Dank! Es ist das erste Mal, dass ich Fragen auf dieser Website stelle, ich habe nicht erwartet, dass ich so schnell Feedback bekommen kann, danke @coatless! –