Ich weiß, dass Schleifen langsam sind R
und ich stattdessen versuchen sollte, Dinge vektorisiert zu machen.
Aber wieso? Warum sind Schleifen langsam und apply
schnell? apply
ruft mehrere Unterfunktionen auf - das scheint nicht schnell zu sein.
Update: Es tut mir leid, die Frage war schlecht gestellt. Ich habe Vektorisierung mit verwechselt apply
. Meine Frage hätte lauten sollen:
"Warum ist die Vektorisierung schneller?"
performance
r
apply
Isomorphismen
quelle
quelle
system.time
Kriege in den Antworten beginnen ...Antworten:
Schleifen in R sind aus demselben Grund langsam, aus dem jede interpretierte Sprache langsam ist: Jede Operation bringt viel zusätzliches Gepäck mit sich.
Schauen Sie
R_execClosure
ineval.c
(dies ist die Funktion, die aufgerufen wird, um eine benutzerdefinierte Funktion aufzurufen). Es ist fast 100 Zeilen lang und führt alle Arten von Operationen aus - Erstellen einer Ausführungsumgebung, Zuweisen von Argumenten zur Umgebung usw.Überlegen Sie, wie viel weniger passiert, wenn Sie eine Funktion in C aufrufen (Args auf Stack, Jump, Pop Args drücken).
Deshalb erhalten Sie Timings wie diese (wie Joran im Kommentar hervorhob, ist es nicht wirklich
apply
schnell; es ist die interne C-Schleifemean
, die schnell ist. Esapply
ist nur normaler alter R-Code):Verwenden einer Schleife: 0,342 Sekunden:
Mit Summe: unermesslich klein:
Es ist ein wenig beunruhigend, weil die Schleife asymptotisch genauso gut ist wie
sum
; Es gibt keinen praktischen Grund, warum es langsam sein sollte. Mit jeder Iteration wird nur mehr zusätzliche Arbeit geleistet.Also bedenken Sie:
(Dieses Beispiel wurde von Radford Neal entdeckt )
Weil
(
in R ein Operator ist und tatsächlich jedes Mal, wenn Sie ihn verwenden, eine Namenssuche erfordert:Oder im Allgemeinen haben interpretierte Operationen (in jeder Sprache) mehr Schritte. Natürlich bieten diese Schritte Vorteile auch: Sie konnte nicht tun , dass
(
Trick in C.quelle
for()
Schleifen machen wollen? Sie machen überhaupt nicht dasselbe. Diefor()
Schleife iteriert über jedes Element vonA
und summiert sie. Derapply()
Aufruf übergibt den gesamten VektorA[,1]
(SieA
haben eine einzelne Spalte) an eine vektorisierte Funktionmean()
. Ich sehe nicht, wie dies der Diskussion hilft und die Situation nur verwirrt.for()
vs-apply()
Beispiel zeigen wollten . Ich denke, Sie sollten dieses Beispiel entfernen, da die Summierung zwar den größten Teil der Berechnung des Mittelwerts ausmacht, Ihr Beispiel jedoch nur die Geschwindigkeit einer vektorisierten Funktionmean()
über die C-ähnliche Iteration über Elemente zeigt.Es ist nicht immer so, dass Schleifen langsam und
apply
schnell sind. Es gibt eine nette Diskussion darüber in der Mai 2008 Ausgabe von R News :Im Abschnitt "Loops!" (ab S. 48) heißt es:
Sie schlagen weiter vor:
Sie haben ein einfaches Beispiel, bei dem eine
for
Schleife 1,3 Sekunden dauert, aber nichtapply
genügend Speicherplatz hat.quelle
Die einzige Antwort auf die gestellte Frage lautet: Schleifen sind nicht langsam, wenn Sie einen Datensatz durchlaufen müssen, der eine Funktion ausführt, und diese Funktion oder die Operation nicht vektorisiert ist. Eine
for()
Schleife ist im Allgemeinen so schnell wieapply()
, aber möglicherweise etwas langsamer als einlapply()
Anruf. Der letzte Punkt wird beispielsweise in dieser Antwort ausführlich auf SO behandelt und gilt, wenn der Code, der beim Einrichten und Betreiben der Schleife erforderlich ist, einen wesentlichen Teil der gesamten Rechenlast der Schleife ausmacht .Viele Leute denken,
for()
Schleifen seien langsam, weil sie als Benutzer schlechten Code schreiben. Wenn Sie ein Objekt erweitern / vergrößern müssen, müssen Sie im Allgemeinen (obwohl es mehrere Ausnahmen gibt) auch kopieren, sodass Sie sowohl den Aufwand für das Kopieren als auch das Vergrößern des Objekts haben. Dies ist nicht nur auf Schleifen beschränkt, sondern wenn Sie bei jeder Iteration einer Schleife kopieren / wachsen, wird die Schleife natürlich langsam, da Sie viele Kopier- / Wachstumsoperationen ausführen.Die allgemeine Redewendung für die Verwendung von
for()
Schleifen in R lautet, dass Sie den erforderlichen Speicher zuweisen, bevor die Schleife beginnt, und dann das so zugewiesene Objekt ausfüllen. Wenn Sie dieser Redewendung folgen, werden die Schleifen nicht langsam sein. Dies ist es, wasapply()
für Sie verwaltet wird, aber es ist nur unsichtbar.Wenn für die Operation, die Sie mit der
for()
Schleife implementieren, eine vektorisierte Funktion vorhanden ist , tun Sie dies natürlich nicht . Ebenso nicht verwendenapply()
etc , wenn eine vektorisiert Funktion vorhanden ist (zBapply(foo, 2, mean)
wird besser über geführtcolMeans(foo)
).quelle
Nur zum Vergleich (lesen Sie nicht zu viel hinein!): Ich habe eine (sehr) einfache for-Schleife in R und in JavaScript in Chrome und IE 8 ausgeführt. Beachten Sie, dass Chrome die Kompilierung mit nativem Code und R mit dem Compiler durchführt Paket kompiliert zu Bytecode.
@ Gavin Simpson: Übrigens hat es in S-Plus 1162 ms gedauert ...
Und der "gleiche" Code wie JavaScript:
quelle