2016-05-19 8 views
0

Meine CPU ist IvyBridge. Betrachten wir ein Beispiel von Agners Fog optimizing_assembly, meine ich. 12.6 Kapitel und das 12.10a Beispiel:Zwei Loop-getragene Abhängigkeitskette. Welcher ist wichtig?

movsd xmm2, [x] 
    movsd xmm1, [one] 
    xorps xmm0, xmm0 
    mov eax, coeff  

    L1: 
     movsd xmm3, [eax] ; c[i] 
     mulsd xmm3, xmm1 ; c[i]*x^i 
     mulsd xmm1, xmm2 ; x^(i+1) 
     addsd xmm0, xmm3 ; sum += c[i]*x^i 
     add eax, 8 
     cmp eax, coeff_end 
     jb L1 

Und das Frontend kein Engpass ist (es ist offensichtlich wegen der Latenz der Multiplikation).

Wir haben zwei schleifengeführte Abhängigkeiten (I übersprungenen add eax, 8): 1. mulsd xmm1, xmm2 Latenz von 5 Zyklen 2. addsd xmm0, xmm3 Latenzzeit von 3 Zyklen

BTW, ich habe einen proble entscheiden: Soll ich zusammenzufassen (5 + 3 = 8) oder um den größten, dh 5 Zyklus zu bekommen?

Ich habe es für 10000000 Elemente Array getestet. Und es dauert 6,7 Zyklen pro Iteration (nach perf) und 5,9 Zyklen pro Iteration nach Agner-Tool.

Bitte erklären Sie, warum es statt nur 5 Zyklen 6/7 Zyklen dauert?

+1

Sie können die Kosten für das Laden der Daten aus dem RAM nicht ignorieren. –

+2

Können Sie versuchen, nützlichere Fragetitel zu schreiben? "Loop zu langsam" sagt nichts weiter, außer dass Sie die Tags [optimization] oder [performance] hätten verwenden sollen. Einige deiner vorherigen Fragen hatten auch wirklich schreckliche Titel wie "Zu viele Zyklen". –

+1

Sieht so aus, als wäre die längste schleifenverschleppte dep-Kette die 'mulsd xmm1, xmm2'. Der 'mul' der nächsten Iteration kann beginnen, bevor 'addsd' dieser Iteration beendet ist, weil sie nicht von' xmm0' abhängt. Die anderen Instruktionen hängen von dieser Schleifen-getragenen Mul-Kette ab, aber sie verzweigen für jede Iteration eine separate Dep-Kette (mit Ausnahme des "addsd", das ebenfalls eine Schleife trägt, aber eine niedrigere Latenz hat). –

Antwort

1

Wahrscheinlich Ressourcenkonflikte verzögern manchmal die Schleife getragen mulsd. UOP-Scheduling wählt Älteste-zuerst (aus Ups, die ihre Eingaben bereit haben), nicht Critical-Path-First, so dass die mulsd xmm3, xmm1 wahrscheinlich den Ausführungsport stiehlt und die durch die Schleife getragene mulsd xmm1, xmm2 gelegentlich durch einen Zyklus verzögert.

Es gibt wahrscheinlich auch gelegentliche Pipeline-Blockierungen von Cache-Fehlschlägen, da Hardware-Prefetching nicht über Seitengrenzen hinweg funktioniert. Testen Sie dies, indem Sie eine äußere Wiederholungsschleife um eine innere Schleife über ~ 128 kB Daten (1/2 L2-Cache-Größe) legen.

Prefetch sollte kein Problem haben, mit Ihrer Schleife normal zu bleiben, obwohl: Eine 64B Last pro 5 Zyklen ist etwa 1/5 der Hauptspeicherbandbreite.

Sie können auch Ihre Daten haben keine denormals verwenden float statt double


Hat? Das sind langsam (but NaN isn't, with SSE).