Wie zähle ich Zyklen?

7

Ich versuche, die relativen Vorzüge von zwei kleinen Funktionen in C zu finden. Eine, die um eine Schleife ergänzt, eine, die um explizite Variablen ergänzt. Die Funktionen sind selbst irrelevant, aber ich möchte, dass mir jemand beibringt, wie man Zyklen zählt, um die Algorithmen zu vergleichen. Also wird f1 10 Zyklen dauern, während f2 8 sein wird. Das ist die Art von Argumentation, die ich gerne machen würde. Keine Leistungsmessungen (z. B. gprof Experimente) zu diesem Zeitpunkt, nur gute alte Instruktionen zählen.

Gibt es einen guten Weg, dies zu tun? Gibt es Werkzeuge? Dokumentation? Ich schreibe C, kompiliere mit gcc auf einer x86-Architektur.

    
Dervin Thunk 25.02.2011, 19:00
quelle

9 Antworten

7

Ссылка

  

PAPI_get_real_cyc (3) - gibt die Gesamtanzahl der Zyklen seit einem beliebigen Startpunkt zurück

    
Anycorn 25.02.2011, 19:13
quelle
5

Assembler-Anweisung rdtsc (Read Time-Stamp Counter) erneut in EDX: EAX registriert die aktuelle CPU-Tick-Zählung, die beim Zurücksetzen der CPU gestartet wurde. Wenn Ihre CPU mit 3GHz läuft, dann ist ein Tick 1 / 3GHz.

BEARBEITEN: Unter MS-Fenstern gibt der API-Aufruf QueryPerformanceFrequency die Anzahl der Ticks pro Sekunde zurück.

    
GJ. 25.02.2011 19:08
quelle
4

Leider ist das Timing des Codes so fehleranfällig wie das visuelle Zählen von Befehlen und Taktzyklen. Sei es ein Debugger oder ein anderes Tool oder kompilieren Sie den Code mit einem erneuten Durchlauf 10000000 Mal und Zeit es Art von Sache, Sie ändern, wo die Dinge landen in der Cache-Zeile, die Häufigkeit der Cachetreffer und vermisst, etc. Sie können mindern Sie einige davon, indem Sie Code vor dem Modul des zu testenden Codes hinzufügen oder entfernen (um einige Anweisungen hinzuzufügen und zu entfernen, die die Ausrichtung Ihres Programms und manchmal Ihrer Daten ändern).

Mit Erfahrung können Sie ein Auge für die Leistung entwickeln, indem Sie sich die Demontage (sowie den Code auf hoher Ebene) anschauen. Es gibt keinen Ersatz für das Timing des Codes, das Timing des Codes ist fehleranfällig. Die Erfahrung kommt aus vielen Experimenten und versucht zu verstehen, warum das Hinzufügen oder Entfernen einer Anweisung keine oder dramatische Unterschiede ergab. Warum Code in einem völlig anderen Bereich des zu testenden Moduls hinzugefügt oder entfernt wurde, führte zu enormen Leistungsunterschieden auf dem zu testenden Modul.

    
old_timer 25.02.2011 22:20
quelle
2

Wie GJ in einer anderen Antwort geschrieben hat, empfehle ich auch, die Anweisung "rdtsc" zu verwenden (anstatt irgendeine Betriebssystemfunktion aufzurufen, die richtig aussieht).

Ich habe einige Antworten zu diesem Thema geschrieben. Rdtsc erlaubt es Ihnen, die verstrichenen Taktzyklen in der "natürlichen" Ausführungsumgebung des Codes zu berechnen, anstatt auf zehn Millionen Aufrufe zurückgreifen zu müssen, was möglicherweise nicht durchführbar ist, da nicht alle Funktionen schwarze Kästchen sind.

Wenn Sie die abgelaufene Zeit berechnen möchten, sollten Sie die Energiesparfunktion auf den CPUs ausschalten. Wenn es nur um Taktzyklen geht, ist dies nicht notwendig.

    
Olof Forshell 01.03.2011 08:25
quelle
1

Wenn Sie versuchen, die Leistung zu vergleichen, ist der einfachste Weg, Ihren Algorithmus in eine Schleife zu setzen und 1000 oder 1000000 Mal auszuführen.

Sobald Sie es genügend oft ausgeführt haben, dass die kleinen Unterschiede angezeigt werden, führen Sie time ./my_program aus, was Ihnen die Menge an Prozessorzeit gibt, die es verwendet hat.

Tun Sie dies ein paar Mal, um eine Stichprobe zu erhalten und die Ergebnisse zu vergleichen.

Der Versuch, Anweisungen zu zählen, hilft Ihnen nicht bei der x86-Architektur. Dies liegt daran, dass unterschiedliche Anweisungen sehr viel Zeit in Anspruch nehmen können.

    
Alan Geleynse 25.02.2011 19:08
quelle
1

Ich würde empfehlen, Simulatoren zu verwenden. Schauen Sie sich PTLsim an, es gibt Ihnen die Anzahl der Zyklen, ansonsten möchten Sie vielleicht einen Blick auf einige Werkzeuge werfen, um die Anzahl der Ausführungen einer Fertigungslinie zu zählen.

    
Syntax_Error 26.02.2011 08:45
quelle
0

Verwenden Sie gcc -S your_program.c . -S teilt gcc mit, den Assembly-Eintrag mit dem Namen your_program.s zu generieren.

    
ChrisJ 25.02.2011 19:04
quelle
0

Es gibt viele Hochleistungsuhren herum. QueryPerformanceCounter ist Microsofts. Der allgemeine Trick besteht darin, die Funktion zehntausende von Zeit und Zeit auszuführen, wie lange es dauert. Teilen Sie dann die Zeit durch die Anzahl der Schleifen. Sie werden feststellen, dass jede Schleife eine etwas andere Zeit benötigt, so dass dieses Testen über mehrere Durchgänge der einzige Weg ist, um herauszufinden, wie lange es dauert.

    
Goz 25.02.2011 19:07
quelle
0

Das ist keine wirklich triviale Frage. Lass mich versuchen zu erklären:

Es gibt verschiedene Tools auf verschiedenen Betriebssystemen, um genau das zu tun, was Sie wollen, aber diese Tools sind normalerweise Teil einer größeren Umgebung. Jeder Befehl wird in eine bestimmte Anzahl von Zyklen übersetzt, abhängig von der CPU, auf der der Compiler lief, und von der CPU, in der das Programm ausgeführt wurde.

Ich kann Ihnen keine definitive Antwort geben, da ich nicht genügend Daten habe, um mein Urteil zu fällen, aber ich arbeite für IBM im Datenbankbereich und wir verwenden Tools, um Zyklen und Anweisungen für unseren Code und diese Spuren zu messen gelten nur für die eigentliche CPU, auf der das Programm kompiliert wurde und läuft. Abhängig von der internen Struktur des Pipelining Ihrer CPU und von der Effizienz Ihres Compilers wird der resultierende Code höchstwahrscheinlich weiterhin Cache-Fehler und andere Bereiche aufweisen, um die Sie sich Sorgen machen müssen. (In diesem Fall möchten Sie vielleicht in FDPR schauen ...)

Wenn Sie wissen möchten, wie viele Zyklen Ihr Programm auf Ihrer CPU ausführen muss (was mit Ihrem Compiler kompiliert wurde), müssen Sie verstehen, wie die CPU funktioniert und wie der Compiler den Code erstellt hat.

Es tut mir leid, wenn die Antwort nicht ausreicht, um Ihr Problem zu lösen. Du hast gesagt, dass du gcc auf einem x86-Arch verwendest. Ich würde damit arbeiten, den Assemblercode auf Ihre CPU zu übertragen. Ich bin sicher, Sie werden einige Bereiche finden, in denen gcc eine bessere Arbeit geleistet hätte ...

    
tessus 01.03.2011 08:59
quelle

Tags und Links