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:
- Zyklen, in denen Anweisungen eingestellt werden (nützliche Arbeit)
- Zyklen, die im Back-End verbracht werden (verschwendet)
- 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