2008-08-31 10 views
81

Dies ist eine etwas untergeordnete Frage. In x86 Montage gibt es zwei SSE-Befehle:Was ist die Bedeutung von "nicht temporären" Speicherzugriffen in x86

MOVDQA xmmi, m128

und

MOVNTDQA xmmi, m128

Die IA-32-Handbuch der Software-Entwickler sagt, dass der NT in MOVNTDQA steht für Nicht -Temporal, und das ist sonst das gleiche wie MOVDQA.

Meine Frage ist, was bedeutet Non-Temporal bedeuten?

+1

Beachten Sie, dass SSE4.1 'MOVNTDQA xmmi, m128' eine NT-Ladung ist, während alle anderen NT-Anweisungen gespeichert sind, mit Ausnahme von' prefetchnta'. Die akzeptierte Antwort hier scheint nur über Geschäfte zu sprechen. [Dies ist, was ich in der Lage gewesen, über NT-Lasten zu zeigen] (http://stackoverflow.com/questions/32103968/non-temporal-loads-and-the-hardware-prefetcher-do-they-work-together). TL: DR: Hoffentlich tut die CPU etwas Nützliches mit dem NT-Hinweis, um die Cache-Verschmutzung zu minimieren, aber sie überschreibt nicht die stark geordnete Semantik des "normalen" WB-Speichers, so dass sie den Cache verwenden müssen. –

+1

Update: NT * Lasten * möglicherweise nichts nützliches außer auf UCSW Speicherbereiche auf den meisten CPUs (z. B. Intel SnB-Familie). NT/streaming * stores * funktionieren jedoch definitiv auf normalem Speicher. –

+0

@Peter: Du meinst USWC Speicher richtig?Ich habe noch nie von UCSW oder USWC Speicher gehört. Das falsche Akronym zu googeln war nicht hilfreich :-) –

Antwort

106

Nicht-zeitliche SSE-Anweisungen (MOVNTI, MOVNTQ usw.) folgen nicht den normalen Cachekohärenzregeln. Daher muss den nicht temporären Speichern eine Anweisung von SFENCE folgen, damit ihre Ergebnisse von anderen Prozessoren rechtzeitig gesehen werden können.

Wenn Daten erzeugt werden und nicht (sofort) wieder konsumiert werden, ist die Tatsache, dass Speicheroperationen zuerst eine vollständige Cachezeile lesen und dann die zwischengespeicherten Daten ändern, nachteilig für die Leistung. Diese Operation schiebt Daten aus den Caches, die möglicherweise erneut benötigt werden, zugunsten von Daten, die nicht bald verwendet werden. Dies gilt insbesondere für große Datenstrukturen wie Matrizen, die gefüllt und später verwendet werden. Bevor das letzte Element der Matrix gefüllt wird, werden durch die schiere Größe die ersten Elemente entfernt, wodurch das Zwischenspeichern der Schreibvorgänge unwirksam wird.

Für diese und ähnliche Situationen bieten Prozessoren Unterstützung für nicht-temporale Schreiboperationen. Zeitlich bedeutet in diesem Zusammenhang, dass die Daten nicht bald wiederverwendet werden, daher gibt es keinen Grund, sie zwischenzuspeichern. Diese nicht temporalen Schreiboperationen lesen keine Cachezeile und modifizieren sie dann; stattdessen wird der neue Inhalt direkt in den Speicher geschrieben.

Quelle: http://lwn.net/Articles/255364/

+10

Schöne Antwort, ich möchte nur darauf hinweisen, dass auf der Art des Prozessors mit NT-Anweisungen, auch mit einer nicht-temporalen Anweisung (also einer normalen Anweisung), die Zeile steht Cache wird nicht "gelesen und dann geändert". Für einen normalen Befehl, der in eine Zeile schreibt, die nicht im Cache ist, wird eine Zeile im Cache reserviert und eine Maske zeigt an, welche Teile der Zeile aktuell sind. Diese Webseite nennt es "kein Stand im Laden": http://www.ptlsim.org/Documentation/html/node30.html. Ich konnte keine präziseren Referenzen finden, ich habe nur von Leuten gehört, deren Aufgabe es ist, Prozessor-Simulatoren zu implementieren. –

+2

Eigentlich http://www.ptlsim.org/ ist eine Website über einen zyklengenauen Prozessor-Simulator, genau die gleiche Art von Dingen, die die Leute, die mir von "kein Stand im Laden" erzählt haben, machen. Ich würde sie besser auch erwähnen, falls sie diesen Kommentar jemals sehen sollten: http://unisim.org/ –

+0

Aus den Antworten und Kommentaren hier https://stackoverflow.com/questions/44864033/make-previous-memory-stores- Sichtbar-zu-Folge-Speicher-Lasten scheint es, dass "SFENCE" möglicherweise nicht benötigt wird. Zumindest im selben Thread. Könntest du auch schauen? –

29

Espo ist so ziemlich Knall am Ziel. Wollte nur meine zwei Cents hinzufügen:

Die "nicht zeitliche" Phrase bedeutet fehlende zeitliche Lokalität. Caches nutzen zwei Arten von Lokalität aus - räumliche und zeitliche. Durch die Verwendung eines nicht-temporalen Befehls signalisieren Sie dem Prozessor, dass Sie nicht erwarten, dass das Datenelement in naher Zukunft verwendet wird.

Ich bin etwas skeptisch über die handcodierte Assembly, die die Cache-Steuerbefehle verwendet. Nach meiner Erfahrung führen diese Dinge zu schlimmeren Fehlern als jede effektive Leistungserhöhung.

+0

Frage über "handcodierte Assembly, die die Cache-Steueranweisungen verwendet." Ich weiß, dass Sie explizit "handcodiert" gesagt haben, was ist mit einer JavaVM? Ist das ein besserer Anwendungsfall? Der JavaVM/Compiler hat das statische und dynamische Verhalten des Programms analysiert und verwendet diese nicht-zeitlichen Anweisungen. – Pat

+1

Das Ausnutzen bekannter Lokalitäteigenschaften (oder deren Fehlen) der Problemdomäne, des Algorithmus oder der Anwendung sollte nicht gemieden werden. Die Vermeidung von Cache-Verschmutzung ist in der Tat eine sehr attraktive und effektive Optimierungsaufgabe. Auch warum die Abneigung gegen die Versammlung? Es gibt Unmengen an Möglichkeiten für Gewinne, die ein Compiler möglicherweise nicht aus –

+3

Kapital schlagen kann. Es ist definitiv wahr, dass ein sachkundiger Low-Level-Programmierer einen Compiler für kleine Kernel übertreffen kann. Das ist großartig für die Veröffentlichung von Artikeln und Blogposts und ich habe beides gemacht. Sie sind auch gute didaktische Werkzeuge und helfen zu verstehen, was "wirklich" vor sich geht. Meiner Erfahrung nach, in der Praxis, wo Sie ein reales System mit vielen Programmierern haben, die daran arbeiten und Korrektheit und Wartbarkeit wichtig sind, wird der Vorteil der Low-Level-Codierung fast immer durch die Risiken aufgewogen. – Pramod