Ich habe einen einfachen 32-Bit-Code, der das Produkt eines Arrays von 32-Bit-Ganzzahlen berechnet. Die innere Schleife sieht so aus:
%Vor%Ich versuche zu verstehen, warum der obige Code 6% schneller ist als diese beiden Versionen des Codes, der den redundanten Speicher-Round-Trip nicht ausführt:
%Vor%und
%Vor%Die beiden letzten Codeteile werden praktisch zur gleichen Zeit ausgeführt, und wie erwähnt sind beide um 6% langsamer als das erste Stück (165 ms gegenüber 155 ms, 200 Mio. Elemente).
Ich habe versucht, das Sprungziel manuell auf eine 16-Byte-Grenze auszurichten, aber das macht keinen Unterschied.
Ich betreibe dies auf einem Intel i7 4770k, Windows 10 x64.
Hinweis: Ich weiß, dass der Code verbessert werden kann, indem alle möglichen Optimierungen durchgeführt werden. Ich bin jedoch nur an den Leistungsunterschieden zwischen den obigen Codeabschnitten interessiert.
Ich vermute, kann aber nicht sicher sein, dass Sie einen Stillstand bei einer Datenabhängigkeit verhindern:
Der Code sieht so aus:
%Vor%Diese Zahlen in Klammern sind die Latenzzeiten der Anweisungen ... dass der Sprung 0 ist, wenn der Verzweigungsvorhersager richtig rät (was er meistens meistens macht).
Also: Während die Multiplikation noch läuft (3 Befehle), kommen wir nach 2 wieder an den Anfang der Schleife und versuchen, in den Speicher zu laden und müssen stehen bleiben. Oder wir könnten einen Laden machen ... den wir zur gleichen Zeit wie unsere Vermehrung machen können und dann überhaupt nicht stehen bleiben.
Was ist mit dem Dummy-Laden, den Sie fragen? Warum funktioniert das? Beachten Sie, dass Sie den kritischen Wert speichern, den wir zum Multiplizieren verwenden. Somit kann der Prozessor diesen Wert verwenden, der im Speicher gespeichert wird und das Register überlagert.
Warum kann der Prozessor das nicht trotzdem tun? Der Prozessor kann nicht mehr Speicherzugriffe erzeugen, als Sie verlangen, oder er könnte Multiprozessor-Programme stören (stellen Sie sich vor, dass die Cache-Zeile, die Sie schreiben, freigegeben ist und Sie sie auf anderen CPUs in jeder Schleife durch Schreiben löschen müssen ... autsch!).
All das ist pure Spekulation, aber es scheint zu allen Beweisen zu passen (Ihr Code und mein Wissen über die Intel Architektur ... und x86 Assembly). Hoffentlich kann jemand darauf hinweisen, wenn ich etwas falsch gemacht habe.
Tags und Links assembly x86 performance