Erzwingen Funktionszeiger das Löschen einer Befehlspipeline?

Lesezeit: 5 Minuten

Benutzer-Avatar
abelenki

Moderne CPUs verfügen über umfangreiches Pipelining, d. h. sie laden notwendige Anweisungen und Daten, lange bevor sie die Anweisung tatsächlich ausführen.

Manchmal werden die in die Pipeline geladenen Daten ungültig, und die Pipeline muss gelöscht und mit neuen Daten neu geladen werden. Die Zeit, die zum Auffüllen der Pipeline benötigt wird, kann beträchtlich sein und zu einer Leistungsverlangsamung führen.

Wenn ich einen Funktionszeiger in C aufrufe, ist die Pipeline intelligent genug, um zu erkennen, dass der Zeiger in der Pipeline ein Funktionszeiger ist und diesem Zeiger für die nächsten Anweisungen folgen sollte? Oder führt ein Funktionszeiger dazu, dass die Pipeline gelöscht und die Leistung verringert wird?

Ich arbeite in C, aber ich stelle mir vor, dass dies in C++ noch wichtiger ist, wo viele Funktionsaufrufe über V-Tabellen erfolgen.


bearbeiten

@JensGustedt schreibt:

Um ein echter Performance-Hit für Funktionsaufrufe zu sein, muss die aufgerufene Funktion extrem kurz sein. Wenn Sie dies beim Messen Ihres Codes beobachten, sollten Sie Ihr Design definitiv überdenken, damit dieser Aufruf inliniert werden kann

Leider könnte das die Falle sein, in die ich getappt bin.

Ich habe die Zielfunktion aus Leistungsgründen klein und schnell geschrieben.

Aber er wird von einem Funktionszeiger referenziert, so dass er leicht durch andere Funktionen ersetzt werden kann (machen Sie den Zeiger einfach auf eine andere Funktion referenzieren!). Da ich über einen Funktionszeiger darauf verweise, glaube ich nicht, dass es inline sein kann.

Ich habe also eine extrem kurze, nicht eingebettete Funktion.

  • Ich denke, es hängt bis zu einem gewissen Grad von der Plattform ab; Können wir davon ausgehen, dass Sie von x86 sprechen?

    – Oliver Charlesworth

    25. Mai 2012 um 15:34 Uhr

  • Ja, x86. (64-Bit, Core2, um genauer zu sein)

    – abelenky

    25. Mai 2012 um 15:35 Uhr

  • Unterscheidet sich ein Funktionszeiger von einem normalen Funktionsaufruf?

    – Martin Beckett

    25. Mai 2012 um 15:39 Uhr

  • @MartinBeckett: Nun, es beinhaltet eine zusätzliche Ebene der Umleitung …

    – Oliver Charlesworth

    25. Mai 2012 um 15:43 Uhr

  • @OliCharlesworth – und es kann zur Kompilierzeit nicht vorhergesagt werden, nehme ich an

    – Martin Beckett

    25. Mai 2012 um 15:59 Uhr

  • Dies ist ein sehr interessanter Beitrag, aber es sollte betont werden, dass es auf die Architektur ankommt. Aus Ihrem Beitrag (der Link ist übrigens veraltet) geht hervor, dass Sie IBM Xenon-Prozessoren getestet haben. Ich würde auch davon ausgehen, dass dasselbe für eingebettete Mikrocontroller der unteren Preisklasse gelten könnte, aber Intel- und AMD-Prozessoren haben seit ~ 2004 oder so eine Art Vorhersage für indirekte Sprünge. Selbst heutige ARM-Prozessoren sollten nicht die gesamte Pipeline ohne eine Fehlvorhersage löschen.

    – Groo

    6. Juni 2016 um 10:44 Uhr

  • Nehmen wir zur Erläuterung an, ein Prozessor versucht, in jedem Zyklus vier oder mehr Befehle abzurufen (was er auch tut). Verzweigungen stellen ein Problem dar, da sich der Befehlszeiger nun seltsam bewegt hat, sodass der Prozessor vorhersagen muss, wohin er gehen wird. Es verwendet zwei Strukturen: den Verzweigungsprädiktor und den Verzweigungszielpuffer (BTB). Bei indirekten Verzweigungen liegen die tatsächlichen Kosten im BTB, da es oft nur das letzte Ziel für die Verzweigung gespeichert hat. Wenn also der Prozessor das nächste Mal auf die Verzweigungsanweisung trifft (in diesem Fall Aufruf des Funktionszeigers), nimmt der Prozessor an, dass derselbe Aufruf wie beim letzten Mal erfolgt ist.

    – Brian

    25. Mai 2012 um 17:50 Uhr

  • Ja, ich habe das Branch-Target-Buffer-Zeug vergessen (es ist schon eine Weile her, seit ich mich mit diesem Zeug beschäftigt habe). Es ist eine Art Cache (mit dessen genauer Beschaffenheit ich mich nie befasst habe), sodass der Prozessor dort nachsehen kann, anstatt nach der tatsächlichen Zweigadresse zu suchen (die möglicherweise noch nicht verfügbar ist). Dies ist in der Tat eine haarsträubende bedingte Verzweigungsvorhersage, da die Annahme, dass dasselbe Ziel erneut verwendet wird, falsch sein kann und daher tatsächlich dazu führen kann, dass die Pipeline in dem Umfang “gereinigt” werden muss, in dem Code vorhanden ist den vorhergesagten Pfad vorab ausgeführt.

    – Heiße Licks

    25. Mai 2012 um 21:08 Uhr


  • Verzweigungsprädiktoren behandeln statische Verzweigungen (der Offset befindet sich im Befehlsstrom) ganz anders als indirekte Verzweigungen (das Ziel befindet sich in einem Register). Wenn die Verzweigung statisch ist – wie ein gewöhnlicher Funktionsaufruf oder ein unbedingtes GOTO (bei Mikrocode ist das dasselbe), dann kann der Verzweigungsprädiktor sie in 100 % der Fälle durch die Befehlsdecodierungsstufe der Pipeline richtig machen. Wenn sich die Zieladresse in einem Register befindet, hat die Verzweigungseinheit keine Möglichkeit zu wissen, wohin der Sprung gehen wird, bis das Ziel berechnet worden ist. Bestenfalls kann der Prädiktor erraten, dass es an die gleiche Stelle gehen wird wie beim letzten Mal.

    – Absturz

    5. Juni 2012 um 0:11 Uhr

  • CPUs nehmen immer ihr Vorhersageergebnis und folgen ihm voll aggressiv. AFAIK, keine CPUs machen “schwächere” Sachen, wenn sie sich der Vorhersagen nicht sicher sind. Siehe Warum nicht einfach beide Zweige vorhersagen? und die Diskussion in Kommentaren (in den Chat verschoben) über die Verwendung von Vorhersagekonfidenz zur Steuerung des Vorabrufs (für CPUs, die dies nicht tun). ausführen spekulativ).

    – Peter Cordes

    29. April 2018 um 12:22 Uhr


  • CPUs folgen ihren Vorhersagen im Allgemeinen immer aggressiv, aber das bedeutet nicht, dass es nicht verschiedene Arten von Fehlvorhersagen geben kann: Moderne Chips können eine Vielzahl von „Schweregraden“ von Fehlvorhersagen haben. Beispielsweise könnte das Front-End auf Chips mit komplexen, langsamen Prädiktoren zunächst eine schnelle Vorhersage basierend auf der aktuellen Abrufadresse durchführen, wobei eine langsamere, aber bessere Vorhersage ein oder zwei Zyklen später eintrifft. Diese Art von Re-Steer kann möglicherweise vollständig im Front-End gehandhabt werden, was einige Zyklen von Blasen beim Abrufen/Decodieren verursacht, aber nicht den ROB oder irgendeinen komplexen OoO-Zustands-Rollback einbezieht.

    – BeeOnRope

    27. Mai 2018 um 21:38 Uhr

1370450cookie-checkErzwingen Funktionszeiger das Löschen einer Befehlspipeline?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy