Frage

Im Vergleich zu

  • Einfacher Speicherzugriff
  • Zugriff auf das Laufwerk
  • Der Speicherzugriff auf einem anderen Computer (auf dem gleichen Netzwerk)
  • Zugriff auf das Laufwerk auf einem anderen Computer (auf dem gleichen Netzwerk)

in C ++ unter Windows.

War es hilfreich?

Lösung

relativen Zeiten (sollte nicht ausgeschaltet werden um mehr als den Faktor 100; -)

  • Speicher-Zugriff im Cache = 1
  • Funktionsaufruf / Rückkehr in cache = 2
  • Speicher-Zugriff aus dem Cache = 10 .. 300
  • disk access = 1000 .. 1e8 (amortisiert, hängt von der Anzahl der übertragenen Bytes)
    • abhängig meist auf Zeiten suchen
    • die Übertragung selbst kann ziemlich schnell
    • sein
    • beinhaltet mindestens ein paar tausend ops, da der Benutzer / Systemschwelle mindestens zweimal gekreuzt werden müssen; eine E / A-Anforderung muss geplant werden, muss das Ergebnis zurückgeschrieben werden; möglicherweise sind Puffer zugewiesen ...
  • Netzwerk ruft = 1000 .. 1e9 (amortisiert, hängt von der Anzahl der übertragenen Bytes)
    • gleiche Argument wie bei disk i / o
    • die rohe Übertragungsgeschwindigkeit kann sehr hoch sein, aber einige Verfahren auf dem anderen Computer muss die eigentliche Arbeit tun

Andere Tipps

Ein Funktionsaufruf ist einfach eine Verschiebung der Rahmenzeiger im Speicher auf den Stapel und die Zugabe eines neuen Rahmens obendrein. Die Funktionsparameter verschoben werden, in der lokalen Register für die Verwendung und der Stapelzeiger wird auf die neue Spitze des Stapels zur Ausführung der Funktion vorgeschoben.

Im Vergleich mit der Zeit

Funktionsaufruf ~ einfachen Speicherzugriff
Funktionsaufruf Funktionsaufruf Funktionsaufruf

Im Vergleich zu einem einfachen Speicherzugriff -. Etwas mehr vernachlässigbar wirklich

Im Vergleich zu allem, was sonst aufgeführt -. Grßenordnungen weniger

Dies sollte für fast jede Sprache auf jedem Betriebssystem wahr halten.

Im Allgemeinen wird ein Funktionsaufruf wird etwas langsamer sein als Speicherzugriff, da es in der Tat hat mehrere Speicher zu tun, greift auf den Anruf auszuführen. Zum Beispiel mit __stdcall auf x86 mehr Schübe und Knacken des Stapels für die meisten Funktionsaufrufe erforderlich. Aber wenn Ihr Speicherzugriff auf eine Seite, die nicht einmal in der L2-Cache ist, kann der Funktionsaufruf viel schneller sein, wenn das Ziel und der Stapel ist alle in der Speicher-Caches der CPU.

Für alles andere, ein Funktionsaufruf viele (viele) Größen schneller.

Schwer zu beantworten, weil es viele Faktoren beteiligt sind.

Zu allererst "Simple Memory Access" ist nicht einfach. Da bei modernen Taktfrequenzen, ein CPU zwei Zahlen addieren kann schneller, als es eine Reihe von einer Seite des Chips auf den anderen zu erhalten (die Lichtgeschwindigkeit - Es ist nicht nur eine gute Idee, es ist das Gesetz)

So ist die Funktion innerhalb des CPU-Cache-Speicher aufgerufen wird? Ist der Speicherzugriff Sie vergleichen es auch?

Dann haben wir den Funktionsaufruf die CPU-Befehlspipeline wird klar, welche Geschwindigkeit in einer nicht-deterministischen Art und Weise beeinflussen wird.

Angenommen, Sie den Aufwand des Anrufs bedeuten selbst, sondern als das, was der Angerufene tun könnte, ist es auf jeden Fall viel, viel schneller als alle, aber der „einfachen“ Speicherzugriff.

Es ist wahrscheinlich langsamer als der Speicherzugriff, aber beachten, dass, da der Compiler inlining tun können, Funktionsaufruf Overhead ist manchmal Null. Selbst wenn nicht, dann ist es zumindest möglich, auf einigen Architekturen, dass einige Anrufe Code bereits in dem Befehls-Cache schneller sein könnten als main (uncached) Zugriff auf den Speicher. Es hängt davon ab, wie viele Register müssen, bevor sie den Anruf, und diese Art der Sache zu stapeln verschüttet werden. Fragen Sie Ihren Compiler und Aufrufkonvention Dokumentation, obwohl Sie es herauszufinden, schneller sein kaum in der Lage sind, als Demontage der Code emittiert wird.

Beachten Sie auch, dass „einfache“ Speicherzugriff ist manchmal nicht - wenn das Betriebssystem die Seite von der Festplatte zu bringen, hat dann haben Sie eine lange Wartezeit auf die Hände bekam. Das gleiche wäre der Fall, wenn Sie in den Code springen zur Zeit auf der Festplatte ausgelagert.

Wenn die zugrunde liegende Frage lautet: „Wann soll ich meinen Code optimieren machten die Gesamtzahl der Funktionsaufrufe zu minimieren?“, Dann ist die Antwort „ganz in der Nähe nie“.

Dieser Link kommt viel in Google auf. Für die Zukunft, lief ich ein kurzes Programm in C # auf die Kosten für einen Funktionsaufruf, und die Antwort lautet: „etwa sechs Mal die Kosten für inline“. Im Folgenden sind Einzelheiten finden Sie Ausgabe am unteren Rand //. UPDATE: Um besser zu vergleichen Äpfel mit Äpfeln, änderte es Class1.Method 'Leere' zurückzukehren, wie es so: public void Method1 () {// 0 zurück; }
Dennoch inline ist schneller durch 2x: inline (avg): 610 ms; Funktionsaufruf (avg): 1380 ms. So ist die Antwort, aktualisiert, ist "etwa zwei Mal".

using System; Verwendung System.Collections.Generic; Verwendung System.Linq; Verwendung System.Text; using System.Diagnostics;

Namespace FunctionCallCost {     Klasse-Programm     {         static void Main (string [] args)         {             Debug.WriteLine ( "stop1");             int Imax = 100000000; // 100M             Datetime funcCall1 = DateTime.Now;             Stoppuhr sw = Stopwatch.StartNew ();

        for (int i = 0; i < iMax; i++)
        {
            //gives about 5.94 seconds to do a billion loops, 
          // or 0.594 for 100M, about 6 times faster than
            //the method call.
        }

        sw.Stop(); 

        long iE = sw.ElapsedMilliseconds;

        Debug.WriteLine("elapsed time of main function (ms) is: " + iE.ToString());

        Debug.WriteLine("stop2");

        Class1 myClass1 = new Class1();
        Stopwatch sw2 = Stopwatch.StartNew();
        int dummyI;
        for (int ie = 0; ie < iMax; ie++)
        {
          dummyI =  myClass1.Method1();
        }
        sw2.Stop(); 

        long iE2 = sw2.ElapsedMilliseconds;

        Debug.WriteLine("elapsed time of helper class function (ms) is: " + iE2.ToString());

        Debug.WriteLine("Hi3");


    }
}

// Klasse 1 hier Verwendung System; Verwendung System.Collections.Generic; Verwendung System.Linq; using System.Text;

Namespace FunctionCallCost {     Klasse Class1     {

    public Class1()
    {
    }

    public int Method1 ()
    {
        return 0;
    }
}

}

// Output: stop1 verstrichene Zeit der Hauptfunktion (MS): 595 stop2 verstrichene Zeit von Hilfsklasse Funktion (ms) ist: 3780

stop1 verstrichene Zeit der Hauptfunktion (MS): 592 stop2 verstrichene Zeit von Hilfsklasse Funktion (ms) ist: 4042

stop1 verstrichene Zeit der Hauptfunktion (MS): 626 stop2 verstrichene Zeit von Hilfsklasse Funktion (ms) ist: 3755

Die Kosten für die tatsächlich die Funktion aufrufen, aber nicht in vollem Umfang ausgeführt wird? oder die Kosten der tatsächlich Ausführen der Funktion? einfach einen Funktionsaufruf der Einrichtung ist kein kostspieliger Vorgang (aktualisieren Sie den PC?). aber offensichtlich die Kosten für eine Funktion in vollem Umfang ausgeführt wird, hängt von der Funktion tut.

Lassen Sie uns nicht vergessen, dass C ++ virtuelle Anrufe hat (deutlich teurer, etwa x10) und Windows können Sie erwarten, VS Anrufe Inline (0 Kosten definitionsgemäß, da kein Anruf im binären links ist)

Abhängig von, was das funktioniert, wäre es die 2. auf Ihrer Liste fallen, wenn es Logik Objekte im Speicher zu tun wurde. wenn es weiter unten in der Liste enthalten Platte / Netzwerkzugriff.

Ein Funktionsaufruf in der Regel nur ein paar Speicherkopien (oft in die Register, also sollten sie nicht viel Zeit dauern) und dann eine Sprungoperation. Dies wird langsamer sein als ein Speicherzugriff, aber schneller als alle anderen Operationen, die oben erwähnt wurde, weil sie die Kommunikation mit anderen Hardware erfordern. Das gleiche sollte in der Regel zutreffen, auf jedem Betriebssystem / Sprachkombination.

Wenn die Funktion bei der Kompilierung inlined ist, die Kosten für die Funktion wird equivelant auf 0

0 natürlich Sein, was Sie nicht mit einem Funktionsaufruf bekommen hätten, das heißt:. Inlined it yourself

Das klingt natürlich übermäßig klar, wenn ich es so schreiben.

Die Kosten für einen Funktionsaufruf ist abhängig von der Architektur. x86 ist deutlich langsamer (ein paar Takte plus eine Uhr oder so pro Funktionsargument), während 64-Bit ist viel weniger, weil die meisten Funktionsargumente in Registern übergeben werden, anstatt auf dem Stapel.

Funktionsaufruf ist eigentlich eine Kopie der Parameter auf den Stapel (mehrere Speicherzugriff), registrieren Sie speichern, die tatsächliche Codeausführung und schließlich Ergebnis kopieren und und Register wiederherzustellen (die Register Speichern / Wiederherstellen auf dem System abhängen).

So .. sprechen relativ:

  • Funktionsaufruf> Einfacher Speicherzugriff.
  • Funktionsaufruf << Festplattenzugriff -. Verglichen mit Speicher kann es mehrere hundert Mal teurer sein
  • Funktionsaufruf << Speicherzugriff auf einem anderen Computer - die Netzwerk-Bandbreite und Protokoll sind die großen Zeitkiller hier
  • .
  • Funktionsaufruf <<< Festplattenzugriff auf einem anderen Computer - alle oben genannten und mehr:)

Nur Speicherzugriff ist schneller als ein Funktionsaufruf.

Aber kann der Anruf vermieden werden, wenn Compiler mit Inline-Optimierung (für GCC Compiler (n) und nicht nur er aktiviert wird, wenn der Pegel unter Verwendung von 3-Optimierung (O3)).

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