2016-09-28 2 views
0

Betrachten wir diesen Vergleich:Warum ist diese vereinfachte Version der cpp-Funktion langsamer?

require(Rcpp) 
require(microbenchmark) 

cppFunction('int cppFun (int x) {return x;}') 
RFun = function(x) x 

x=as.integer(2) 
microbenchmark(RFun=RFun(x),cppFun=cppFun(x),times=1e5) 

Unit: nanoseconds 
    expr min lq  mean median uq  max neval cld 
    RFun 302 357 470.2047 449 513 110152 1e+06 a 
cppFun 2330 2598 4045.0059 2729 2879 68752603 1e+06 b 

cppFun langsamer als RFun scheint. Wieso ist es so? Unterscheiden sich die Zeiten für den Aufruf der Funktionen? Oder ist es die Funktion selbst, die sich in der Laufzeit unterscheidet? Ist es Zeit für Argumente und Argumente? Gibt es eine Datenkonvertierung oder ein Datenkopieren? Ich weiß nicht, wann die Daten an (oder von) cppFun übergeben werden?

+11

Fremdfunktion Schnittstelle hat Overhead, das sollte keine Überraschung sein. Wenn Ihre Funktion anfängt, tatsächlich nützliche Arbeit zu leisten, werden Sie wahrscheinlich niemals den Overhead bemerken. Aber im Moment kostet deine Funktion nichts außer dem Overhead. –

+5

Stellen Sie sich vor, Sie sind R und CPP ist Ihr hart arbeitender Kollege. Was ist schneller: Wiederholen Sie jeden Satz, der Ihnen gegenüber gesprochen wird, sofort oder gehen Sie zu Ihrem Kollegen und bitten Sie ihn, dies für Sie zu tun? Ändern Sie nun "einen Satz wiederholen" zu "Steuererklärungen machen" und die Dinge könnten sich ändern. (Haftungsausschluss: Ich habe nie versucht, Steuererklärungen in C++ zu machen. Es kann schneller sein, ist aber wahrscheinlich auch komplizierter als in R). –

+0

@JeroenMostert Als Doktorand sind meine Steuererklärungen ziemlich einfach zu handhaben;) Danke für die Metapher! –

Antwort

12

Dies ist einfach keine gut gestellte oder durchdachte Frage, wie die obigen Kommentare zeigen.

Die angenommene Grundlinie einer leeren Funktion ist einfach keine. Jede Funktion, die über cppFunction() und andere erstellt wird, ruft eine R-Funktion Schnittstelle zu einige C++ Funktion. Das kann einfach nicht sein.

Hier ist ein etwas sinnvoller Vergleich. Für den Anfang, lassen Sie uns die R-Funktion mit Curlies abschließen. Zweitens, nennen wir einen anderen Compiler (intern) Funktion:

require(Rcpp) 
require(microbenchmark) 

cppFunction('int cppFun (int x) {return x;}') 
RFun1 <- function(x) { x } 
RFun2 <- function(x) { .Primitive("abs")(x) } 

print(microbenchmark(RFun1(2L), RFun2(2L), cppFun(2L), times=1e5)) 

Auf meiner Box sehe ich a) eine engere Lücke zwischen den Versionen 1 und 2 (oder die C++ Funktion) und b) kleine Strafe über die interne Funktion. Aber Aufruf einer beliebigen kompilierten Funktion von R kostet.

Unit: nanoseconds 
     expr min lq  mean median uq  max neval 
    RFun1(2L) 171 338 434.136 355 408 2659984 1e+05 
    RFun2(2L) 683 937 1334.046 1257 1341 7605628 1e+05 
cppFun(2L) 721 1131 1416.091 1239 1385 8544656 1e+05 

Wie wir sagen in der realen Welt: es ist kein freies Mittagessen.

+0

Oh, das macht vollkommen Sinn. Ist dies der "Overhead", auf den sich @BenVoigt in den Kommentaren bezieht? Danke –

+1

Ja, unter anderem. 'cppFun()' und 'RFun2()' haben tatsächlich einen Körper mit Code zum Ausführen. 'RFun1()' nicht. Wie könnten sie in der Laufzeit möglicherweise gleich sein? Sie machen auch einen Anfängerprofilfehler, wenn Sie versuchen, "leer" zu messen. Das macht wirklich keinen Sinn, wenn man es so darstellt. –

+0

Ok, ich denke es ergibt für mich Sinn +1. Danke vielmals! –

Verwandte Themen