32-Byte-Speicher Weiterleitung auf Sandy Bridge

8

In Agner Fogs ausgezeichneter Mikroarchitektur.pdf (Abschnitt 9.14) habe ich Folgendes gelesen:

  

Die Speicherweiterleitung funktioniert in den folgenden Fällen: [...] Wenn auf einen Schreibvorgang von 128 oder 256 Bits gefolgt wird, wird ein Lesevorgang derselben Größe und derselben Adresse ausgeführt, die mit 16 ausgerichtet sind.

Auf der anderen Seite, Intel's Architecture Optimization Reference Manual (2.2.5.2 Intel Sandy Bridge, L1 DCache) habe ich das gelesen

  

Speicher können in den folgenden Fällen nicht zu Ladevorgängen weitergeleitet werden: [...] Beliebige Last, die eine 16-Byte-Grenze eines 32-Byte-Speichers überschreitet.

Jegliche Ladung klingt auch wie 32-Byte-Ladung. Ich habe den folgenden einfachen Code geschrieben, um dies zu testen, und es scheint, dass 32-Byte-Speicher an nachfolgende 32-Byte-Ladungen auf der Sandy-Bridge-Architektur weitergeleitet werden . Hier ist der Code:

%Vor%

Das einzige, was in der Schleife gemacht wird, ist das Lesen / Schreiben von / zu einem 4k-ausgerichteten Speicherplatz und einem Vektorregister. Bei der Kompilierung mit dem AVX-Befehlssatz ( gcc -O3 -DTEST_AVX ) beträgt die Ausführungszeit 3.1s auf meinem 2.7GHz i7-2620M. Bei Verwendung des SSE2-Befehlssatzes beträgt die Zeit 2,5 Sekunden. Ich habe mir die Leistungsindikatoren angesehen. Im AVX-Fall zähle ich ein Speicherweiterleitungsblockereignis pro Iteration (Zähler 03H 02H LD_BLOCKS.STORE_FORWARD ). Der Zähler liest 0 für den SSE2-Fall.

Kann jemand etwas Licht darauf werfen? Unterstützt SB tatsächlich die Weiterleitung von 32-Byte-Speichern an 32-Byte-Ladungen? Wenn letzteres der Fall ist, scheint das Verschütten von ymm Registern ziemlich teuer zu sein.

    
angainor 03.03.2014, 12:34
quelle

1 Antwort

1

Es scheint, dass es bei Sandy Bridge kein Laden-Laden mit 32-Byte-Ladungen gibt. Betrachten Sie den folgenden modifizierten Schleifenkörper:

%Vor%

Die Änderung ist das Zielregister - ich verwende jetzt zwei verschiedene Register zum Laden und Speichern, so dass keine Abhängigkeit zwischen den beiden Befehlen und nachfolgenden Iterationen besteht. In diesem Fall dauert die SSE-Version 1 Zyklus pro Iteration, während die AVX-Version 2 Zyklen benötigt. Dies steht im Einklang mit der Tatsache, dass SB eine Kapazität von zwei 16-Byte-Ladungen pro Zyklus aufweist. Daher dauert das Laden von 32 Bytes zwei Zyklen - kein Blockieren.

Das Problem muss mit der Zählerlogik verbunden sein. Offensichtlich wird in dem AVX-Fall die LD_BLOCKS.STORE_FORWARD inkrementiert, obwohl kein Block stattfindet. Dies sollte bei der Leistungsanalyse mit den Zählern berücksichtigt werden.

    
angainor 12.03.2014, 09:09
quelle