Was sind Stalled-Cycles-Frontend und Stalled-Cycles-Backend im Ergebnis 'Perf Stat'?

83

Weiß jemand, was die Bedeutung von Blocked-Cycle-Frontend und Stalled-Cycle-Backend im Perf-Stat-Ergebnis bedeutet? Ich habe im Internet gesucht, aber keine Antwort gefunden. Vielen Dank

$ sudo perf stat ls                     

Performance counter stats for 'ls':

      0.602144 task-clock                #    0.762 CPUs utilized          
             0 context-switches          #    0.000 K/sec                  
             0 CPU-migrations            #    0.000 K/sec                  
           236 page-faults               #    0.392 M/sec                  
        768956 cycles                    #    1.277 GHz                    
        962999 stalled-cycles-frontend   #  125.23% frontend cycles idle   
        634360 stalled-cycles-backend    #   82.50% backend  cycles idle
        890060 instructions              #    1.16  insns per cycle        
                                         #    1.08  stalled cycles per insn
        179378 branches                  #  297.899 M/sec                  
          9362 branch-misses             #    5.22% of all branches         [48.33%]

   0.000790562 seconds time elapsed
Dafan
quelle
Ich bin mir nicht sicher, was die eigentliche Frage hier ist. Fragen Sie sich, was das Frontend und Backend einer CPU sind? Bitte lesen Sie diese sehr hochrangige Einführung . Beantwortet das deine Frage?
Ali
Ich suchte und suchte nach einer ähnlichen Antwort ... Dies war die hilfreichste Ressource, die ich von Intel gefunden habe: software.intel.com/en-us/articles/…
Jmoney38
Nein, fast niemand weiß, was diese wirklich bedeuten. Aber das Verweisen auf das Handbuch (wie in Manuel Selvas Antwort) in Kombination mit diesem Beitrag (den ich noch nicht vollständig verstehe) ist der nächste, den ich gefunden habe: sites.utexas.edu/jdm4372/2014/06/04/…
Jberryman

Antworten:

59

Die Theorie:

Beginnen wir damit: Heutzutage sind die CPUs superskalar, was bedeutet, dass sie mehr als einen Befehl pro Zyklus (IPC) ausführen können. Neueste Intel-Architekturen können bis zu 4 IPC (4 x86-Befehlsdecoder) verwenden. Lassen Sie uns die Makro- / Mikrofusion nicht zur Diskussion stellen, um die Dinge noch komplizierter zu machen :).

In der Regel erreichen Workloads aufgrund verschiedener Ressourcenkonflikte nicht IPC = 4. Dies bedeutet, dass die CPU Zyklen verschwendet (die Anzahl der Anweisungen wird von der Software gegeben und die CPU muss sie in so wenigen Zyklen wie möglich ausführen).

Wir können die von der CPU verbrauchten Gesamtzyklen in drei Kategorien einteilen:

  1. Zyklen, in denen Anweisungen eingestellt werden (nützliche Arbeit)
  2. Zyklen, die im Back-End verbracht werden (verschwendet)
  3. Zyklen im Front-End (verschwendet).

Um einen IPC von 4 zu erhalten, muss die Anzahl der auslaufenden Zyklen nahe an der Gesamtzahl der Zyklen liegen. Beachten Sie, dass in dieser Phase alle Mikrooperationen (uOps) aus der Pipeline ausscheiden und ihre Ergebnisse in Register / Caches übertragen. Zu diesem Zeitpunkt können sogar mehr als 4 uOps in den Ruhestand gehen, da diese Anzahl durch die Anzahl der Ausführungsports angegeben wird. Wenn Sie nur 25% der Zyklen haben, die 4 uOps ausfallen, haben Sie einen Gesamt-IPC von 1.

Die im Back-End blockierten Zyklen sind eine Verschwendung, da die CPU auf Ressourcen (normalerweise Speicher) warten oder Anweisungen mit langer Latenz (z. B. Transcedentals - sqrt, reziproke, Divisionen usw.) beenden muss.

Die im Front-End blockierten Zyklen sind eine Verschwendung, da das Front-End das Back-End nicht mit Mikrooperationen versorgt. Dies kann bedeuten, dass Sie Fehler im Anweisungscache haben oder komplexe Anweisungen, die nicht bereits im Mikrooperationscache dekodiert sind. Just-in-Time-kompilierter Code drückt dieses Verhalten normalerweise aus.

Ein weiterer Grund für das Abwürgen ist das Fehlen einer Verzweigungsvorhersage. Das nennt man schlechte Spekulation. In diesem Fall werden uOps ausgegeben, aber verworfen, weil der BP falsch vorhergesagt hat.

Die Implementierung in Profilern:

Wie interpretieren Sie die blockierten BE- und FE-Zyklen?

Unterschiedliche Profiler haben unterschiedliche Ansätze für diese Metriken. In vTune addieren sich die Kategorien 1 bis 3 zu 100% der Zyklen. Das ist vernünftig, weil entweder Ihre CPU blockiert ist (keine uOps gehen in den Ruhestand) oder nützliche Arbeit (uOps) in den Ruhestand geht. Weitere Informationen finden Sie hier: https://software.intel.com/sites/products/documentation/doclib/stdxe/2013SP1/amplifierxe/snb/index.htm

In der Perfektion passiert dies normalerweise nicht. Das ist ein Problem, denn wenn 125% der Zyklen im Frontend stehen bleiben , wissen Sie nicht, wie Sie das wirklich interpretieren sollen. Sie könnten die Metrik> 1 mit der Tatsache verknüpfen, dass es 4 Decoder gibt. Wenn Sie jedoch die Argumentation fortsetzen, stimmt der IPC nicht überein.

Noch besser, Sie wissen nicht, wie groß das Problem ist. 125% von was? Was bedeuten die #Zyklen dann?

Ich persönlich sehe ein bisschen misstrauisch gegenüber den BE- und FE-Zyklen von perf aus und hoffe, dass dies behoben wird.

Wahrscheinlich erhalten wir die endgültige Antwort, indem wir den Code von hier aus debuggen: http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/tools/perf/builtin-stat.c

VAndrei
quelle
Welche Ereignisse werden in VTune als FE und BE verwendet? Manuel hat Events von perf auf Sandy Bridge gepostet. Manchmal kann der Decoder 4 Anweisungen nicht decodieren ( realworldtech.com/sandy-bridge/4 - es gibt 3 einfache Decoder, die komplexe Befehle nicht decodieren können).
Osgx
Es gibt zwar auch einen komplexen Decoder, aber möglicherweise können auch einfache Anweisungen decodiert werden. Ich habe meinen Beitrag mit einem Link zu vTune-Zählern aktualisiert. Es verwendet die gleichen Zähler wie perf, aber ich denke, vTune kombiniert anders.
VAndrei
4
Vtune verwendet software.intel.com/en-us/articles/… "IDQ_UOPS_NOT_DELIVERED.CORE / SLOTS" als "Frontend-gebunden" und "1 - (Front-End-gebunden + Ruhestand + schlechte Spekulation)" als "Backend-gebunden", wobei " Retiring = UOPS_RETIRED.RETIRE_SLOTS / SLOTS "," Bad Speculation = (UOPS_ISSUED.ANY - UOPS_RETIRED.RETIRE_SLOTS + 4 * INT_MISC.RECOVERY_CYCLES) / SLOTS "und" SLOTS = 4 * CPU_CL " ".
Osgx
1
Und für das Optimierungshandbuch von Sandy Bridge Intel gibt intel.com/content/dam/www/public/us/en/documents/manuals/… dasselbe in "B.3.2 Hierarchische Top-Down-Leistungscharakterisierungsmethode" "% FE_Bound = 100 * an (IDQ_UOPS_NOT_DELIVERED.CORE / N);% Bad_Speculation = 100 * ((UOPS_ISSUED.ANY - UOPS_RETIRED.RETIRE_SLOTS + 4 * INT_MISC.RECOVERY_CYCLES) / N);% Retiring = 100 * (UOR_ = * (1 - (FE_Bound + Retiring + Bad_Speculation)); N = 4 * CPU_CLK_UNHALTED.THREAD "
osgx
@osgx Danke. Jetzt wissen wir, was die Metriken in vTune bedeuten und dass sie sich zu 100% summieren. Die nächste Frage ist, warum Perf sie anders berechnet. Ist es ein Fehler oder steckt dahinter eine Bedeutung?
VAndrei
43

So konvertieren Sie generische Ereignisse, die von perf exportiert wurden, in Rohereignisse Ihrer CPU-Dokumentation, die Sie ausführen können:

more /sys/bus/event_source/devices/cpu/events/stalled-cycles-frontend 

Es wird dir so etwas zeigen

event=0x0e,umask=0x01,inv,cmask=0x01

Laut der Intel-Dokumentation SDM Volume 3B (ich habe einen Core i5-2520):

UOPS_ISSUED.ANY:

  • Erhöht in jedem Zyklus die Anzahl der von der RAT an RS ausgegebenen Uops.
  • Setzen Sie Cmask = 1, Inv = 1, Any = 1, um blockierte Zyklen dieses Kerns zu zählen.

Für das Blocked-Cycles-Backend-Ereignis, das auf meinem System in event = 0xb1, umask = 0x01 übersetzt wird, heißt es in derselben Dokumentation:

UOPS_DISPATCHED.THREAD:

  • Zählt die Gesamtzahl der Uops, die pro Thread pro Zyklus versendet werden sollen
  • Setzen Sie Cmask = 1, INV = 1, um die Stillstandszyklen zu zählen.

In der Regel sind blockierte Zyklen Zyklen, in denen der Prozessor auf etwas wartet (z. B. Speicher, der nach dem Ausführen eines Ladevorgangs eingespeist wird) und keine anderen Aufgaben zu erledigen hat. Darüber hinaus ist der Frontend-Teil der CPU die Hardware, die für das Abrufen und Dekodieren von Anweisungen (Konvertieren in UOPs) verantwortlich ist, während der Backend-Teil für die effektive Ausführung der UOPs verantwortlich ist.

Manuel Selva
quelle
Danke für deine Antwort. Was ist der Unterschied zwischen festgefahren und untätig?
Dafan
2
Stillstand und Leerlauf sind gleich. Die CPU ist inaktiv, da sie blockiert ist, da sich die Befehlspipeline nicht bewegt.
Milind Dumbare
@Milind, sollte es keinen Unterschied geben, sollte "Wir kommen nicht weiter, weil die nächste Stufe es nicht zulässt" und Leerlauf sollte "es gibt nichts zu verarbeiten" sein?
Surt
13

Ein CPU-Zyklus wird "blockiert", wenn die Pipeline währenddessen nicht vorrückt.

Die Prozessor-Pipeline besteht aus vielen Stufen: Das Front-End ist eine Gruppe dieser Stufen, die für die Abruf- und Dekodierungsphasen verantwortlich ist, während das Back-End die Anweisungen ausführt. Es gibt einen Puffer zwischen Front-End und Back-End. Wenn das erstere blockiert ist, kann das letztere noch einige Arbeiten erledigen.

Entnommen aus http://paolobernardi.wordpress.com/2012/08/07/playing-around-with-perf/

Milind Dumbare
quelle
2
Wie können wir mehr Stände als Zyklen haben?
Osgx
11

Laut Autor dieser Ereignisse sind sie lose definiert und werden durch verfügbare CPU-Leistungsindikatoren angenähert. Wie ich weiß, unterstützt perf keine Formeln zum Berechnen eines synthetischen Ereignisses basierend auf mehreren Hardwareereignissen, daher kann es keine Front-End- / Back-End-Stall-gebundene Methode aus dem Intel-Optimierungshandbuch (in VTune implementiert) http: // verwenden. www.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-optimization-manual.pdf "B.3.2 Hierarchische Top-Down-Leistungscharakterisierungsmethode"

%FE_Bound = 100 * (IDQ_UOPS_NOT_DELIVERED.CORE / N ); 
%Bad_Speculation = 100 * ( (UOPS_ISSUED.ANY – UOPS_RETIRED.RETIRE_SLOTS + 4 * INT_MISC.RECOVERY_CYCLES ) / N) ; 
%Retiring = 100 * ( UOPS_RETIRED.RETIRE_SLOTS/ N) ; 
%BE_Bound = 100 * (1 – (FE_Bound + Retiring + Bad_Speculation) ) ; 
N = 4*CPU_CLK_UNHALTED.THREAD" (for SandyBridge)

Die richtigen Formeln können mit einigen externen Skripten verwendet werden, wie dies in Andi Kleens pmu-tools ( toplev.py) getan wurde : https://github.com/andikleen/pmu-tools (Quelle), http://halobates.de/blog/ S. 262 (Beschreibung):

% toplev.py -d -l2 numademo  100M stream
...
perf stat --log-fd 4 -x, -e
{r3079,r19c,r10401c3,r100030d,rc5,r10e,cycles,r400019c,r2c2,instructions}
{r15e,r60006a3,r30001b1,r40004a3,r8a2,r10001b1,cycles}
numademo 100M stream
...
BE      Backend Bound:                      72.03%
    This category reflects slots where no uops are being delivered due to a lack
    of required resources for accepting more uops in the    Backend of the pipeline.
 .....
FE      Frontend Bound:                     54.07%
This category reflects slots where the Frontend of the processor undersupplies
its Backend.

Commit, das blockierte-Zyklen-Frontend- und blockierte-Zyklen-Backend-Ereignisse anstelle des ursprünglichen Universums einführte stalled-cycles:

http://git.kernel.org/cgit/linux/kernel/git/tip/tip.git/commit/?id=8f62242246351b5a4bc0c1f00c0c7003edea128a

author  Ingo Molnar <mingo@el...>   2011-04-29 11:19:47 (GMT)
committer   Ingo Molnar <mingo@el...>   2011-04-29 12:23:58 (GMT)
commit  8f62242246351b5a4bc0c1f00c0c7003edea128a (patch)
tree    9021c99956e0f9dc64655aaa4309c0f0fdb055c9
parent  ede70290046043b2638204cab55e26ea1d0c6cd9 (diff)

Perf-Ereignisse: Fügen Sie generische Ereignisdefinitionen für blockierte Front-End- und Back-End-Zyklen hinzu. Fügen Sie zwei generische Hardware-Ereignisse hinzu: blockierte Front-End- und Back-End-Zyklen.

Diese Ereignisse messen die Bedingungen, unter denen die CPU Code ausführt, ihre Funktionen jedoch nicht vollständig genutzt werden. Das Verstehen und Analysieren solcher Situationen ist eine wichtige Unteraufgabe von Codeoptimierungs-Workflows.

Beide Ereignisse schränken die Leistung ein: Die meisten Front-End-Stalls werden in der Regel durch Verzweigungsfehler oder Cachemiss beim Abrufen von Anweisungen verursacht. Back-End-Stalls können durch verschiedene Ressourcenknappheit oder ineffiziente Anweisungsplanung verursacht werden.

Front-End-Stalls sind die wichtigeren: Code kann nicht schnell ausgeführt werden, wenn der Anweisungsstrom nicht aufrechterhalten wird.

Ein überlastetes Back-End kann zu Verzögerungen im Front-End führen und muss daher ebenfalls im Auge behalten werden.

Die genaue Zusammensetzung hängt stark von der Programmlogik und dem Befehlsmix ab.

Wir verwenden die Begriffe "Stall", "Front-End" und "Back-End" lose und versuchen, die besten verfügbaren Ereignisse von bestimmten CPUs zu verwenden, die sich diesen Konzepten annähern.

Cc: Peter Zijlstra Cc: Arnaldo Carvalho de Melo Cc: Frederic Weisbecker Link: http://lkml.kernel.org/n/[email protected] Unterzeichnet von: Ingo Molnar

    /* Install the stalled-cycles event: UOPS_EXECUTED.CORE_ACTIVE_CYCLES,c=1,i=1 */
-       intel_perfmon_event_map[PERF_COUNT_HW_STALLED_CYCLES] = 0x1803fb1;
+       intel_perfmon_event_map[PERF_COUNT_HW_STALLED_CYCLES_BACKEND] = 0x1803fb1;

-   PERF_COUNT_HW_STALLED_CYCLES        = 7,
+   PERF_COUNT_HW_STALLED_CYCLES_FRONTEND   = 7,
+   PERF_COUNT_HW_STALLED_CYCLES_BACKEND    = 8,
osgx
quelle
Also ist es am Ende ein Fehler in der Leistung? Weil FE + BE +? Fügen Sie keinen bekannten theoretischen Wert hinzu, es ist schwer zu beurteilen, wie groß das Problem Ihres Codes ist. Wenn 75% FE zum Stillstand kommen, muss dies mit etwas verglichen werden. Wenn 75% von 100% gesagt werden, ist der Code in FE oder BE blockiert und hat eine ganz andere Bedeutung und einen anderen Wert. Soweit ich weiß, hat sogar toplev.py das gleiche Problem. Wenn dies kein Problem ist, wie interpretieren wir die Metriken? Was macht die Metriken hoch oder niedrig?
VAndrei
VAndrei, haben Sie ein kurzes und reproduzierbares Beispiel für SandyBridge (+ -1 Generation)? sowohl für perf statmit FE> 100% als auch für toplev.py? Ich habe gerade mit kurzen einfachen Schleifen begonnen und habe 3G-Zyklen für 3G-Anweisungen (1G sind Zweige mit einer Fehlerrate von 0,00%) mit 2G FE-Ständen ( perf stat) und 1G BE-Ständen (IPC = 1,00). Ich denke, das Problem besteht darin, "Stall" für den komplexen OOO-Kern richtig zu definieren, und ein anderes darin, die toplev.pyErgebnisse richtig zu interpretieren .
Osgx
Der Code, den ich hier gepostet habe: stackoverflow.com/questions/28961405/… sollte an das Front-End gebunden sein. Es gibt viele Verzweigungsfehler, so dass FE-Stände entstehen würden. In Bezug auf BE-gebunden benötigen Sie eine Arbeitslast, die auf RAM-Daten wartet. Weisen Sie die Hälfte Ihrer physischen Speichergröße in einem Puffer zu und verwenden Sie eine LCG (wie in meinem Code), um eine Lese- / Änderungs- / Schreiboperation an einer zufälligen Stelle im Puffer durchzuführen. Dies erzeugt neben der RMW-Transaktion eine kleine Anzahl von Anweisungen, und der Kern bleibt im BE stehen und wartet auf RAM-Daten.
VAndrei
Das Generieren von FE-gebundenen Workloads ist eine ziemliche Herausforderung. Bitte versuchen Sie, ob das verzweigte Mikrobenchmark funktioniert, aber wenn nicht, benötigen Sie etwas Komplexeres. Der FE-Stall würde durch Cache-Fehlschläge mit hoher Anzahl von Befehlen erzeugt. Dazu benötigen Sie einen großen Code mit weit entfernten Sprüngen, um zu mehreren I $ -Fehlern zu führen. Ich habe zu diesem Zeitpunkt noch keine Idee, wie eine FE-gebundene Arbeitslast in einem Mikrobenchmark erstellt werden kann.
VAndrei
Ich denke, Sie wären an diesem Link interessiert: stackoverflow.com/questions/1756825/… Sie können einige der besprochenen Techniken verwenden, um die I $ zu spülen und damit FE-Stalls zu generieren.
VAndrei