2009-08-12 5 views
15

Ich möchte einen Speicherort lesen, ohne den Cache zu verschmutzen. Ich arbeite an X86 Linux Maschine. Ich habe versucht MOVNTDQA Assemblerbefehl mit:Wie kann ich Werte aus dem Speicher laden, ohne den Cache zu verschmutzen?

asm("movntdqa %[source], %[dest] \n\t" 
     : [dest] "=x" (my_var) : [source] "m" (my_mem[0]) : "memory"); 

my_mem ist ein int * mit neuen zugeordnet, my_var ist ein int.

Ich habe zwei Probleme mit diesem Ansatz:

  1. Der Code kompiliert, aber ich bin „Illegal Instruction“ Fehler bekommen, wenn es ausgeführt wird. Irgendwelche Ideen warum?
  2. Ich bin nicht sicher, welche Art von Speicher mit neuen zugeordnet ist. Ich würde diese WB annehmen. Laut Dokumentation funktioniert die MOVNTDQA-Anweisung nur für den USWC-Speichertyp. Woher weiß ich, an welchem ​​Speichertyp ich arbeite?

Zusammenfassend meine Frage ist:

Wie kann ich einen Speicherplatz lesen, ohne den Cache auf einer X86-Maschine verschmutzen? Ist meine Herangehensweise in die richtige Richtung und kann sie zur Arbeit gebracht werden?

Danke.

+0

Ist diese Frage verbunden? http: // Stapelüberlauf.com/questions/851286/how-to-use-movntdqa-zu vermeiden-cache-pollution – sharptooth

+1

Ich denke, es ist verwandt :), aber leider hilft mir diese Frage/Antwort nicht mit dieser Frage. – Anna

+0

Oh, noch eine Sache: Ich bin mir nicht sicher, ob das überhaupt möglich ist: -/Ich hoffe es ist es. – Anna

Antwort

0

MOVNTDQA ist nur mit SSE verfügbar.

Warum versuchen Sie, den Cache zu vermeiden? CPUs sind im Allgemeinen ziemlich gut darin, zu entscheiden, was aus dem Cache herausgeschmissen wird. Wenn es wirklich nötig wäre, wäre es eine Möglichkeit, dafür zu sorgen, dass ein Alias ​​des Speicherbereichs, aus dem Sie lesen, in Ihren Adressraum gemappt wird, wobei das Caching deaktiviert ist und von dort gelesen wird.

Wenn Sie versuchen, den Einfluss Ihres Codes auf den Arbeitssatz einer anderen Funktion zu minimieren, der zu diesem Zeitpunkt im Cache gehalten wird, sollte dies durch entsprechende Vorabruf- und Ungültigkeitsanweisungen möglich sein.

+0

Ich habe zwei Kerne in einem Prozess - einer von ihnen ist stark mit dem Cache, und der andere hat eine niedrigere Priorität, und ich versuche daher, seine Cache-Nutzung zu verringern. Auf dieser Maschine ist der L2-Cache für beide Kerne gemeinsam - also möchte ich, dass der Speicher direkt in L1 oder in die Register geladen wird (im Programm mit niedrigerer Priorität). Könnten Sie bitte erläutern, wie die Verwendung von Prefetch- und Invalidate-Anweisungen mir in diesem Fall helfen kann? Vielen Dank. – Anna

+0

Mein Gedanke war, dafür zu sorgen, dass der Prozess mit niedriger Priorität seine Cache-Zeilen explizit ausstieß, sobald sie fertig waren, sodass sie früher wieder aufgefüllt werden konnten, als es die Cache-Management-Richtlinie der CPU sonst erlauben würde, und arrangierte möglicherweise die Hochprioritätsverfahren, um Vorabrufe in besonders teuren Abschnitten auszugeben. Nicht sicher, wie sehr solch ein Ansatz in Ihrem Szenario jedoch helfen würde. – moonshadow

+3

@moonshadow: Prozessoren sind nicht immer gut zu entscheiden, was zu cachen ist. Das ist der ausdrückliche Grund, warum es eine Movntdqa-Anweisung gibt. Es wird für das Streaming von Daten, einmal verwendet, nie wieder berührt (zumindest nicht zu früh ;-)). Wie bei einem Hilfsthread könnte dies sinnvoll sein, wenn ein anderer Thread zur Verfügung steht, der sonst nicht vollständig genutzt werden kann - Hyperthreading kommt mir in den Sinn. In den meisten Fällen erhalten Sie jedoch ein besseres Ergebnis, wenn zwei Threads die volle Arbeit ausführen und explizite Prefetch-Anweisungen verwenden. – hirschhornsalz

7

Das Problem mit der MOVNTDQA-Anweisung mit %% XMM als Ziel (Laden aus dem Speicher) ist, dass diese Insn nur mit SSE4.1 und on verfügbar ist. Dies bedeutet neueren Core 2 (45 nm) oder i7 nur so weit. Anders herum (Speichern von Daten im Speicher) ist in früheren SSE-Versionen verfügbar.

Für diese Anweisung verschiebt der Prozessor die Daten in einen sehr kleinen von sehr wenigen Lesepuffern (Intel gibt nicht die genaue Größe an, sondern nimmt an, dass es im Bereich von 16 Bytes liegt), wo es leicht verfügbar ist. aber wird nach ein paar anderen Lasten rausgeschmissen.

Und es verschmutzt nicht die anderen Caches, also wenn Sie Streaming-Daten haben, ist Ihr Ansatz praktikabel.

Denken Sie daran, Sie müssen ein sfence insn danach verwenden.

Prefetching existiert in zwei Varianten: prefetch0 (Prefetch Daten in allen Caches) und prefetchnt (Prefetch nicht temporale Daten). Normalerweise ist das Vorabholen in allen Caches das Richtige, für eine Streaming-Datenschleife wäre Letzteres besser, wenn Sie die Streaming-Anweisungen konsequent anwenden.

Sie verwenden es mit der Adresse eines Objekts, das Sie in naher Zukunft verwenden möchten, normalerweise einige Iterationen voraus, wenn Sie eine Schleife haben. Der Prefetch-Befehl wartet nicht oder blockiert nicht, sondern veranlasst den Prozessor, die Daten am angegebenen Speicherort abzurufen.