2016-07-15 14 views
0

Ich habe eine Funktion, die sehr wenig liest, aber viel in RAM schreiben. Wenn ich es mehrere Male auf dem gleichen Kern (dem Hauptthread) ausführe, läuft es ungefähr 5x so schnell, als wenn ich die Funktion für einen neuen Thread bei jedem Lauf starte (was nicht garantiert, dass derselbe Kern zwischen Läufen verwendet wird) Ich starte und verbinde mich zwischen Läufen.Welche Rolle spielt der Cache beim Schreiben in den Speicher?

Dies deutet darauf hin, dass der Cache stark für den Schreibvorgang verwendet wird, aber ich verstehe nicht, wie. Ich dachte, der Cache wäre nur für Lesevorgänge nützlich.

+1

Wenn Sie Ihren Schreibpuffer mit Schreibvorgängen auf partielle Cachezeilen füllen, werden Sie anhalten, bis die Cachezeilen aus dem Speicher geladen werden. Sie können dies möglicherweise vermeiden, indem Sie nicht temporäre Speicher verwenden und/oder immer vollständige Cachezeilen schreiben. – EOF

+0

Das klingt nach einer * Antwort * zu mir, EOF ... Was meinst du mit "nicht-zeitlichen Speichern" und so weiter. Hört sich an, als hättest du hier viel zu sagen. **: -) ** –

Antwort

0

Moderne Prozessoren haben normalerweise Schreibpuffer. Der Grund ist, dass Schreibvorgänge in erster Näherung reine Senken sind. Der Prozessor muss normalerweise nicht warten, bis der Speicher die kohärente Speicherhierarchie erreicht, bevor er den nächsten Befehl ausführt.

(abgesehen. Offensichtlich Geschäfte sind nicht reines Kungen A gelesen später von dem geschrieben zu Speicherplatz sollte den schriftlichen Wert zurück, so muss der Prozessor die Schreibpuffer schnüffelt, und entweder abgewürgt die Lese- oder weiterleiten geschriebener Wert dazu)

Offensichtlich sind solche Puffer von begrenzter Größe, wenn also die Puffer voll sind, kann der nächste Speicher im Programm nicht ausgeführt werden und bleibt stehen, bis ein Slot im Puffer von einem verfügbar gemacht wird älterer Laden wird architektonisch sichtbar.

Normalerweise wird die Art und Weise ein Schreib den Puffer verlässt, ist, wenn der Wert in den Cache geschrieben wird (da eine Menge schreibt sind tatsächlich wieder schnell, man denke an die Programmstapel als Beispiel lesen). Wenn der Schreibvorgang nur einen Teil der Cacheline einstellt, muss der Rest der Cacheline unverändert bleiben, so dass er folglich aus der Speicherhierarchie geladen werden muss.



Es gibt Möglichkeiten, wie nicht-temporal Läden Laden die alte Cache-Zeile, um zu verhindern, schreiben kombinierenden Speicher oder Cache-Line-Nullstellen Anweisungen.

Nicht-temporale Speicher und Schreibkombinationsspeicher kombinieren benachbarte Schreibvorgänge, um eine ganze Cache-Line zu füllen, wobei die neue Cache-Line an die Speicherhierarchie gesendet wird, um die alte zu ersetzen.

POWER verfügt über eine Anweisung, die eine vollständige Cacheline (dcbz) auf Null setzt, wodurch auch die Notwendigkeit entfällt, den alten Wert aus dem Speicher zu laden.

x86 mit AVX512 hat Cache-Line-sized Register, was darauf hindeutet, dass eine ausgerichtete zmm -Register store konnte vermeiden das alte Cache-Line-Laden (obwohl ich weiß nicht, ob es der Fall ist).

Beachten Sie, dass viele dieser Techniken nicht mit der üblichen Speicherordnung der jeweiligen Prozessorarchitekturen konsistent sind. Ihre Verwendung erfordert möglicherweise zusätzliche Zäune/Barrieren im Multithread-Betrieb.