0

Von Agner Fog's "Optimizing Assembly" guide, Abschnitt 12.7: eine Schleife Beispiel. Einer der Absätze den Beispielcode zu diskutieren:Abhängigkeitskettenanalyse

[...] Analyse für Pentium M: ... 13 Uops bei 3 pro Takt = eine Iteration pro 4.33c Ruhestand Zeit.

Es gibt eine Abhängigkeitskette in der Schleife. Die Latenzen sind: 2 für Speicher lesen, 5 für Multiplikation, 3 für Subtraktion und 3 für Speicher schreiben, was insgesamt 13 Taktzyklen ergibt. Dies ist dreimal so viel wie die Ruhestandszeit, aber es ist keine Loop-getragene Abhängigkeit, weil die Ergebnisse von jeder Iteration im Speicher gespeichert und nicht in die nächste Iteration wiederverwendet werden. Der Out-of-Order-Ausführungsmechanismus und Pipelining ermöglichen, dass jede Berechnung starten kann, bevor die vorhergehende Berechnung beendet ist. Die einzige schleifengeführte Abhängigkeitskette ist add eax,16 die

## Example 12.6b. DAXPY algorithm, 32-bit mode 
[...] ; not shown: initialize some regs before the loop 
L1: 
    movapd xmm1, [esi+eax] ; X[i], X[i+1] 
    mulpd xmm1, xmm2  ; X[i] * DA, X[i+1] * DA 
    movapd xmm0, [edi+eax] ; Y[i], Y[i+1] 
    subpd xmm0, xmm1  ; Y[i]-X[i]*DA, Y[i+1]-X[i+1]*DA 
    movapd [edi+eax], xmm0 ; Store result 
    add eax, 16    ; Add size of two elements to index 
    cmp eax, ecx    ; Compare with n*8 
    jl L1     ; Loop back 

Ich kann nicht verstehen, eine Latenzzeit von nur 1

hat warum die Abhängigkeitskette nicht eine ganze Durchsatz erhöhen. Ich weiß, dass es nur wichtig ist, den schlimmsten Engpass zu finden. Der größte Engpass, der vor der Betrachtung von Abhängigkeitsketten identifiziert wurde, war der Durchsatz von Fused-Domain-Uploads mit 4,33 Zyklen pro Iteration. Ich kann nicht verstehen, warum die Abhängigkeitskette kein größerer Engpass ist.

  1. Ich sehe, dass der Autor erklärt, dass es mit Out-of-Order-Ausführung und Pipelining verbunden ist, aber ich kann es nicht sehen. Ich meine jedoch, nur Multiplikation verursacht Latenz 5 Zyklen, so dass nur dieser Wert größer als 4 Zyklen ist.

  2. Ich kann auch nicht verstehen, warum der Autor nicht über die Abhängigkeit hier schert: add eax, 16 -> cmp eax, ecx -> jl L1 Schließlich muss zusätzlich ausgeführt werden, bevor cmp und cmp muss vor jl ausgeführt werden.


PS: späteren Absätzen identifizieren die größte Engpass für Pentium M als dekodieren, um es zu einer Iteration pro 6c zu begrenzen, weil 128b Vektor ops zu zwei Uops je dekodieren. Für den Rest der Analyse und Analyse + Tuning für Core2, FMA4 Bulldozer und Sandybridge siehe den Agner Fog-Leitfaden.

+0

Das Vergleich/Zweig-Paar würde vorhergesagt werden, so dass es nicht wirklich zählt. Abgesehen davon bin ich nicht sicher, was Sie fragen – harold

+1

Können Sie bitte Agners Dokument verknüpfen und angeben, auf welchen Abschnitt und auf welches Beispiel Sie verweisen? –

Antwort

2
  1. die MUL ist nicht Teil einer Abhängigkeitskette schlaufen getragen, so kann es auf einmal mulpd insns von mehreren Iterationen im Flug sein. Die Latenz einer einzelnen Anweisung ist hier überhaupt nicht das Problem, es ist die Abhängigkeit Kette. Jede Iteration hat eine separate 13c Abhängigkeitskette von load, mulpd, subpd, store. Out-of-Order-Ausführung ermöglicht es, dass sich mehrere Iterationen gleichzeitig im Flug befinden.

  2. Die cmp/jl in jeder Iteration hängen von den add von dieser Iteration, aber die add in der nächsten Iteration hängt nicht von den cmp.Spekulative Ausführung und Verzweigungsvorhersage bedeuten, dass Steuerungsabhängigkeiten (bedingte Verzweigungen und indirekte Sprünge/Aufrufe) nicht Teil der Datenabhängigkeitsketten sind. Aus diesem Grund können Anweisungen von einer Iteration ausgeführt werden, bevor die jl aus der vorhergehenden Iteration in den Ruhestand geht.

    cmovist eine Datenabhängigkeit anstelle einer Abhängigkeit von der Steuerung, so dass Verzweigungsloops Schleifen-getragene Abhängigkeitsketten haben. Dies ist tendenziell langsamer als eine Verzweigung, wenn die Verzweigung gut vorhersagt.

    Jede Schleifeniteration hat eine separate cmp/jl Abhängigkeitskette, genau wie die FP-Abhängigkeitskette.


Ich kann nicht verstehen, warum Abhängigkeitskette nicht eine ganze Durchsatz erhöhen.

Ich habe keine Ahnung, was dieser Satz bedeutet. Ich glaube, ich war in der Lage, all deine anderen Wörter und Phrasen zu verstehen. (z. B. "Kettenabhängigkeit" anstelle von "Abhängigkeitskette".) Sehen Sie sich meine Änderungen zu Ihrer Frage an; Einige von ihnen könnten dir auch helfen, dein Verständnis zu verstehen.

+0

Danke :). Zu erst Ihr Punkt: Ok, es ist klar, dass mehrere Iterationen gleichzeitig im Flug sein können. Aber, wenn es nur zu einer Iteration kommt, insbesondere zu einer Iteration. Warum Latenz von mulpd (5 Zyklen) spielt keine Rolle? Schließlich muss "subpd xmm0, xmm1" gefolgt werden von "mulpd xmm1, xmm2" (in einer Abhängigkeitskette für eine Iteration). Sorry für mein Englisch, ich weiß, dass es problematisch sein kann. 2. Agner Fog sagt, dass 'add eax, 16' Loop-Übertragungen sind und 1 Zyklus (Latenz) kostet. – Gilgamesz

+1

@Gilgamesz: 2. Das ist richtig. 'add' ->' add' ist die loop-getragene Abhängigkeitskette, nicht 'add -> cmp -> jl -> add'. –

+1

zu: erster Punkt: Können Sie genauer darüber sein, warum Sie denken, dass es * wichtig ist? Wir berechnen den Durchsatz, * nicht * die Latenzzeit einer einzelnen Iteration. Solange der out-of-order-insn-Scheduler und der ReOrder-Puffer groß genug sind, um die Parallelität zwischen Iterationen aufzudecken, ist die Latenz der dep-Kette innerhalb einer Iteration irrelevant. (Eine sehr lange Dep-Kette würde einen großen Scheduler und ROB benötigen). Die Latenz bestimmter Anweisungen in dieser Dep-Kette ist noch weniger relevant. –