Frage

wird meine Funktion tausende Male aufgerufen werden. Wenn ich es schneller machen möchten, werden die lokalen Funktionsvariablen zu statisch irgend zu ändern? Meine Logik dahinter ist, dass, weil statische Variablen persistent zwischen Funktionsaufrufe sind, werden sie nur das erste Mal zugewiesen, und somit wird jeder nachfolgenden Aufruf nicht Speicher für sie zuweisen und schneller werden wird, da die Speicherzuweisung Schritt nicht erfolgt.

Auch wenn die oben wahr ist, dann würde mit globalen Variablen anstelle von Parametern schneller werden, um Informationen zu der Funktion, die sie aufgerufen wird jedes Mal passieren? Ich denke, Platz für Parameter auch bei jedem Funktionsaufruf zugeordnet ist, für Rekursion zu ermöglichen (deshalb Rekursion verbraucht mehr Speicher), aber da meine Funktion nicht rekursiv ist, und wenn meine Argumentation richtig ist, dann Parameter abheben wird in der Theorie machen es schneller.

weiß, dass ich diese Dinge, die ich will schrecklichen Programmiergewohnheiten tun, aber bitte, mir sagen, ob es klug ist. Ich werde es trotzdem versuchen, aber bitte geben Sie mir Ihre Meinung.

War es hilfreich?

Lösung

Der Aufwand von lokalen Variablen ist Null. Jedes Mal, wenn Sie eine Funktion aufrufen, sind Sie bereits den Stapel für die Einstellung der Parameter, Rückgabewerte usw. Hinzufügen von lokalen Variablen bedeutet, dass Sie eine etwas größere Zahl an den Stapelzeiger sind Zugabe (eine Zahl, die zum Zeitpunkt der Kompilierung berechnet wird) .

Auch lokale Variablen sind wahrscheinlich schneller aufgrund von Cache-Lokalität.

Wenn Sie nur Ihre Funktion „Tausende“ Mal aufrufen (nicht Millionen oder Milliarden), dann sollten Sie in Ihrem Algorithmus werden der Suche nach Optimierungsmöglichkeiten nach Sie haben einen Profiler laufen.


Re: Cache-Ort ( lesen Sie hier mehr ): Häufig zugegriffen globale Variablen wahrscheinlich zeitliche Lokalität haben. Sie können auch während der Funktionsausführung in ein Register kopiert werden, wird aber wieder in den Speicher (Cache) geschrieben werden nach Funktion gibt (sonst würden sie mit nichts anderem zugänglich sein; Register keine Adressen haben).

Lokale Variablen hat in der Regel sowohl die zeitlichen und räumlichen Ort (sie bekommen, dass die durch auf dem Stapel erstellt werden). Zusätzlich können sie „zugeordnet“ direkt zu den Registern werden und nie in den Speicher geschrieben werden.

Andere Tipps

Der beste Weg ist, um herauszufinden, um tatsächlich einen Profiler laufen. Dies kann so einfach sein wie mehr zeitlich abgestimmten Tests Ausführung beiden Methoden und die Ergebnisse gemittelt und zu vergleichen, oder Sie können ein ausgewachsenes Profilierungswerkzeug betrachten, die mich im Laufe der Zeit aus Speichernutzung auf ein Verfahren und Grafiken legen und die Ausführungsgeschwindigkeit.

Nehmen Sie keinen zufälligen Mikrocode-Tuning, weil Sie ein gut haben sie das Gefühl schneller sein wird. Compiler alle leicht unterschiedliche Implementierungen der Dinge haben und was auf der einen Compiler auf eine Umgebung wahr ist, kann auf einer anderen Konfiguration falsch sein.

Um diesen Kommentar über weniger Parameter angehen: den Prozess der „inlining“ Funktionen im Wesentlichen die auf den Aufruf einer Funktion bezogenen Gemein entfernt. Die Chancen sind eine kleine Funktion automatisch durch den Compiler in ausgekleideten sein wird, aber Sie kann vorschlagen, eine Funktion als auch inlined werden.

In einer anderen Sprache, C ++, der neue Standard unterstützt herauskommen perfekt Forwarding und perfekte Bewegung Semantik mit rvalue Referenzen, die die Notwendigkeit von Provisorien in bestimmten Fällen entfernt, die die Kosten für den Aufruf einer Funktion reduzieren.

Ich vermute, du bist vorzeitig zu optimieren, aber Sie sollten dies nicht mit Leistung betroffen sein, bis Sie Ihre echte Engpässe entdeckt haben.

Absolutly nicht! Der einzige „Leistung“ Unterschied ist, wenn Variablen initialisiert

    int anint = 42;
 vs
    static int anint = 42;

Im ersten Fall wird die ganze Zahl bis 42 jedes Mal eingestellt werden, die Funktion, im zweiten Fall aufgerufen wird Ot auf 42 gesetzt wird, wenn das Programm geladen ist.

Allerdings ist der Unterschied so trivial, wie es kaum wahrnehmbar zu sein. Es ist ein verbreiteter Irrtum, dass Speicher hat für „automatisches“ Variablen bei jedem Aufruf zugeteilt werden. Das ist nicht so C den bereits zugewiesenen Platz in dem Stapel für diese Variablen verwendet.

Statische Variablen können verlangsamen Sie tatsächlich nach unten als einige aggresive Optimierungen auf statische Variablen nicht möglich sind. Auch Einheimische in einem zusammenhängenden Bereich des Stapels ist, sind sie leichter zu Cache effizient.

Es gibt keine Antwort auf diese Frage. Es wird mit der CPU variieren, der Compiler, die Compiler-Flags, die Anzahl der lokalen Variablen, die Sie haben, was die CPU, bevor Sie die Funktion aufrufen, getan, und möglicherweise die Phase des Mondes.

Betrachten wir zwei Extremen; wenn Sie nur eine oder wenige lokale Variablen haben, es / sie könnten leicht in Registern gespeichert werden, anstatt Speicherplätze überhaupt zugeordnet werden. Wenn das Register „Druck“ ist ausreichend niedrig, dass dies ohne die Ausführung irgendwelche Anweisungen überhaupt passieren kann.

Am anderen Extrem gibt es ein paar Maschinen (zum Beispiel IBM Mainframe), die nicht über Stapel überhaupt. In diesem Fall, was würden wir normalerweise denken als Stack-Frames werden als eine verknüpfte Liste auf dem Heap tatsächlich zugeordnet. Wie Sie wahrscheinlich erraten würde, so kann dieser ganz langsam.

Wenn es um die Variablen für den Zugriff kommt, dann ist die Situation etwas ähnlich - der Zugang zu einem Maschinenregister ist ziemlich gut garantiert schneller als in Speicher zugewiesen, etwas zu sein, kann mögliche Hoffnung auf. OTOH, ist es möglich, den Zugriff auf Variablen auf dem Stack ziemlich langsam zu sein - es ist normalerweise so etwas wie ein indiziertes indirekter Zugang erfordert, die (vor allem bei älteren CPUs) ziemlich langsam zu sein tendiert. OTOH, Zugang zu einem globalen (die eine statisch ist, obwohl sein Name nicht global sichtbar ist) erfordert in der Regel eine absolute Adresse bildet, die einige CPUs penalize bis zu einem gewissen Grad auch.

Fazit: Auch der Rat den Code profilieren kann verlegt werden - der Unterschied leicht so klein sein, dass auch ein Profiler es nicht erkennen, wird zuverlässig, und die nur Weg, um sicher zu sein, ist die Assembler-Sprache zu untersuchen, die (und verbringen ein paar Jahren lernen Assemblersprache gut genug sagen, etwas zu wissen, wann Sie tun Blick auf sie) produziert wird. Die andere Seite ist, dass, wenn Sie mit einem Unterschied zu tun haben Sie nicht einmal zuverlässig messen kann, sind die Chancen, dass es einen wesentlichen Einfluss auf die Geschwindigkeit des echten Code haben werde, ist so abgelegen, dass es wahrscheinlich nicht der Mühe wert.

Es sieht aus wie die statische vs nicht-statischen vollständig abgedeckt wurde, aber auf dem Thema der globalen Variablen. Oft werden diese eher eine Programme Ausführung verlangsamen als beschleunigen sie.

Der Grund dafür ist, dass die dicht scoped Variablen macht es einfach für die Compiler zu stark optimieren, wenn die Compiler alle über Ihre Anwendung aussehen muss für Fälle, wo ein global verwendet werden könnte, dann wird seine Optimierung nicht so gut sein.

Dies wird verstärkt, wenn Sie Zeiger vorstellen, sagen Sie den folgenden Code haben:

int myFunction()
{
    SomeStruct *A, *B;
    FillOutSomeStruct(B);
    memcpy(A, B, sizeof(A);
    return A.result;
}

Der Compiler weiß, dass der Zeiger A und B können niemals überlappen und so ist es die Kopie zu optimieren. Wenn A und B global sind, dann könnten sie möglicherweise überlappenden oder identischen Speicher zeigen, bedeutet dies, muss der Compiler ‚auf der sicheren Seite‘, was langsamer ist. Das Problem ist in der Regel ‚Zeiger Aliasing‘ genannt und in vielen Situationen nicht nur Speicherkopien auftreten kann.

http://en.wikipedia.org/wiki/Pointer_alias

Ja, statische Variablen eine Funktion ein kleines bisschen schneller machen. Dies wird jedoch zu Problemen führen, wenn Sie jemals Ihr Programm mit mehreren Threads machen wollen. Da statische Variablen zwischen Funktionsaufrufen gemeinsam genutzt werden, wird die Funktion zeitgleich in verschiedenen Threads Aufrufen in undefinierten Verhalten führen. Multi-Threading ist die Art der Sache, die Sie wünschen können, um wirklich die Geschwindigkeit Ihren Code in der Zukunft zu tun.

Die meisten Dinge, die Sie erwähnt werden als Mikro-Optimierungen bezeichnet. Im Allgemeinen ist sich Gedanken über diese Art von Dingen ein schlechte Idee . Es macht den Code schwerer zu lesen, und schwieriger zu pflegen. Es ist auch sehr wahrscheinlich, Fehler einzuführen. Sie werden wahrscheinlich mehr für Ihr Geld Optimierungen auf einem höheren Niveau erhalten zu tun.

Wie M2TM Vorschläge, einen Profiler läuft, ist auch eine gute Idee. Schauen Sie sich gprof für eine, die zu verwenden ist ganz einfach .

Sie können jederzeit Ihre Anwendungszeit wirklich zu bestimmen, was am schnellsten ist. Hier ist, was ich verstehe: (all dies auf der Architektur des Prozessors abhängt, btw)

C-Funktionen erstellen Stapelrahmen, die ist, wo übergebenen Parameter gesetzt werden, und lokale Variablen setzen, sowie die Rückkehr Zeiger zurück, wo der Anrufer die Funktion aufgerufen. Es gibt keine Speicherverwaltung Zuordnung hier. Es in der Regel eine einfache Zeigerbewegung und das ist es. Daten vom Stapel Zugriff ist auch ziemlich schnell. Strafen in der Regel ins Spiel kommen, wenn man es zu tun mit Zeigern.

Wie für die globalen oder statische Variablen, sind sie das gleiche ... vom Standpunkt, dass sie in dem gleichen Speicherbereich zugeordnet sein werden. Zugriff auf diese eine andere Methode der Zugriff als lokale Variablen verwenden können, hängt von der Compiler.

Der wesentliche Unterschied zwischen Ihren Szenarien Speicherbedarf, nicht so viel Geschwindigkeit.

Die Verwendung von statischen Variablen können tatsächlich Code deutlich langsamer machen. Statische Variablen müssen in einem ‚Daten‘ Speicherbereich vorhanden sind. Um diese Variable zu verwenden, muss die Funktion eine Ladeanweisung auszuführen, aus dem Hauptspeicher oder einen Speicherbefehl zu schreiben, um sie zu lesen. Wenn dieser Bereich nicht im Cache ist, verliert man viele Zyklen. Eine lokale Variable, dass Leben auf dem Stapel wird die meisten sicherlich eine Adresse hat, die im Cache ist, und sogar in einem CPU-Register sein könnte, überhaupt nicht im Speicher erscheinen.

Ich stimme mit den anderen Kommentaren über Profilierungs Sachen wie das zu erfahren, aber im Allgemeinen, Funktion statische Variablen langsamer sein sollten. Wenn Sie wollen, was Sie wirklich nach sind, ist ein global. Funktion Statik Insert Code / Daten überprüfen, ob das, was bereits initialisiert wurde, dass jedes Mal Ihre Funktion aufgerufen wird ausgefuehrt wird.

Profilieren kann den Unterschied nicht sehen, Zerlegen und zu wissen, was für Macht zu suchen.

Ich vermute, Sie wollen nur eine Variation so viel wie ein paar Taktzyklen pro Schleife erhalten (im Durchschnitt je nach Compiler usw.). Manchmal wird die Änderung dramatische Verbesserung oder dramatisch langsamer, und das wird nicht unbedingt sein, da die Variablen nach Hause / vom Stapel bewegt hat. Lassen Sie uns sagen Sie für 10000 Anrufe auf einem 2GHz Prozessor vier Taktzyklen pro Funktionsaufruf speichern. Sehr grobe Berechnung: 20 Mikrosekunden gespeichert. 20 Mikrosekunden viel oder wenig im Vergleich zu Ihrer aktuellen Ausführungszeit?

Sie werden wahrscheinlich erhalten mehr eine Leistungsverbesserung durch alle Ihre Zeichen und kurze Variablen in Ints unter anderem zu machen. Mikro-Optimierung ist eine gute Sache zu wissen, nimmt aber viel Zeit zu experimentieren, Demontage, um die Ausführung des Codes Timing, zu verstehen, dass weniger Befehle nicht notwendigerweise schneller bedeuten zum Beispiel.

Nehmen Sie Ihr spezifisches Programm, auseinanderbauen sowohl die Funktion in Frage und den Code, der es nennt. Mit und ohne statisch. Wenn Sie nur ein oder zwei Anweisungen gewinnen, und das ist die einzige Optimierung Sie tun werden, ist es wahrscheinlich nicht wert. Sie können nicht in der Lage sein, den Unterschied zu sehen, während Profilierung. Änderungen in dem die Cache-Zeilen trafen auftauchen könnte in Profilieren vor Änderungen im Code zum Beispiel.

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