Ausrichtung auf die Cache-Zeile und Kenntnis der Cache-Zeilengröße

Lesezeit: 9 Minuten

Benutzeravatar von MetallicPriest
MetallicPriest

Um eine falsche Freigabe zu verhindern, möchte ich jedes Element eines Arrays an einer Cache-Zeile ausrichten. Also muss ich zuerst die Größe einer Cache-Zeile kennen, also weise ich jedem Element diese Menge an Bytes zu. Zweitens möchte ich, dass der Anfang des Arrays an einer Cache-Zeile ausgerichtet wird.

Ich verwende Linux und eine 8-Kern-x86-Plattform. Erstens, wie finde ich die Cache-Zeilengröße. Zweitens, wie richte ich mich an einer Cache-Zeile in C aus? Ich verwende den gcc-Compiler.

Die Struktur würde also beispielsweise wie folgt aussehen, wenn eine Cache-Zeilengröße von 64 angenommen wird.

element[0] occupies bytes 0-63
element[1] occupies bytes 64-127
element[2] occupies bytes 128-191

und so weiter, wobei natürlich angenommen wird, dass 0-63 auf eine Cache-Zeile ausgerichtet ist.

  • Vielleicht kann das helfen: stackoverflow.com/questions/794632/…

    – Toni der Löwe

    2. September 2011 um 9:46 Uhr

  • Aber es zeigt nicht, wie man sich mit gcc auf einen Cache ausrichtet.

    – MetallicPriest

    2. September 2011 um 9:53 Uhr

  • Mögliches Duplikat von Cache-Zeilengröße programmgesteuert abrufen?

    – Ciro Santilli OurBigBook.com

    16. März 2017 um 7:56 Uhr

  • Es ist keine schlechte Idee, eine Kompilierzeitkonstante von 64 Byte als Cache-Line-Größe zu verwenden, damit der Compiler dies in Funktionen einbinden kann, die sich darum kümmern. Den Compiler dazu zu bringen, Code für eine laufzeitvariable Cache-Zeilengröße zu generieren, könnte einige der Vorteile des Ausrichtens von Dingen auffressen, insbesondere in Fällen der automatischen Vektorisierung, wo es dem Compiler hilft, besseren Code zu erstellen, wenn er weiß, dass ein Zeiger auf eine Cache-Zeile ausgerichtet ist Breite (die breiter als die SIMD-Vektorbreite ist).

    – Peter Cordes

    12. März 2018 um 4:32 Uhr

Benutzeravatar von Maxim Egorushkin
Maxim Egorushkin

Ich verwende Linux und eine 8-Kern-x86-Plattform. Erstens, wie finde ich die Cache-Zeilengröße.

$ getconf LEVEL1_DCACHE_LINESIZE
64

Übergeben Sie den Wert als Makrodefinition an den Compiler.

$ gcc -DLEVEL1_DCACHE_LINESIZE=`getconf LEVEL1_DCACHE_LINESIZE` ...

Zur Laufzeit sysconf(_SC_LEVEL1_DCACHE_LINESIZE) kann verwendet werden, um die L1-Cachegröße zu erhalten.

  • Wo sind diese sysconf()ist angegeben? POSIX/IEEE-Standard 1003.1-20xx ?

    – Brian Kain

    16. Juni 2017 um 21:20 Uhr

  • @ BrianCain pubs.opengroup.org/onlinepubs/9699919799/functions/sysconf.html

    – Maxim Egorushkin

    16. Juni 2017 um 21:59 Uhr

  • @BrianCain Ich benutze Linux, also habe ich es gerade getan man sysconf. Linux ist nicht gerade POSIX-kompatibel, sodass eine Linux-spezifische Dokumentation oft sinnvoller ist. Manchmal ist es veraltet, so dass Sie einfach egrep -nH -r /usr/include -e '\b_SC'.

    – Maxim Egorushkin

    16. Juni 2017 um 22:01 Uhr


  • Verwenden Sie im Falle eines Mac sysctl hw.cachelinesize.

    – Dení

    21. Januar 2018 um 0:12 Uhr

  • Normalerweise ist es so viel besser, eine zur Kompilierzeit konstante Zeilengröße zu haben, dass ich lieber 64 hart codieren als aufrufen würde sysconf. Der Compiler wird nicht einmal wissen, dass es sich um eine Potenz von 2 handelt, also müssen Sie Dinge wie manuell tun offset = ptr & (linesize-1) für Rest oder Bit-Scan + Rechtsverschiebung zur Implementierung der Division. Sie können nicht einfach verwenden / in Code, der leistungsabhängig ist.

    – Peter Cordes

    29. November 2019 um 13:29 Uhr

Benutzeravatar von Necrolis
Nekrolis

Um die Größen zu kennen, müssen Sie sie anhand der Dokumentation für den Prozessor nachschlagen, afaik, es gibt keine programmatische Möglichkeit, dies zu tun. Auf der positiven Seite haben die meisten Cache-Zeilen jedoch eine Standardgröße, basierend auf den Intel-Standards. Auf x86-Cache-Zeilen sind 64 Bytes, aber um eine falsche Freigabe zu verhindern, müssen Sie die Richtlinien des Prozessors befolgen, auf den Sie abzielen (Intel hat einige spezielle Hinweise zu seinen Netburst-basierten Prozessoren). Im Allgemeinen müssen Sie sich dafür auf 64 Bytes ausrichten (Intel gibt an, dass Sie auch vermeiden sollten, 16-Byte-Grenzen zu überschreiten).

Um dies in C oder C++ zu tun, müssen Sie den Standard verwenden aligned_alloc Funktion oder einer der Compiler-spezifischen Bezeichner wie z __attribute__((align(64))) oder __declspec(align(64)). Um zwischen Mitgliedern in einer Struktur aufzufüllen, um sie auf verschiedene Cache-Zeilen aufzuteilen, müssen Sie ein Mitglied einfügen, das groß genug ist, um es an der nächsten 64-Byte-Grenze auszurichten

  • @MetallicPriest: gcc und g++ unterstützen beide __attributes__

    – Sebastian Mach

    2. September 2011 um 10:06 Uhr

  • @MetallicPriest: mmap & VirtualAlloc Weisen Sie seitenausgerichteten Speicher zu, im Allgemeinen beträgt die Seitenauflösung 64 KB (unter Windows), und da 64 KB eine Potenz von 64 ist, wird sie richtig ausgerichtet.

    – Nekrolis

    2. September 2011 um 10:45 Uhr

  • Sie können die Cache-Zeilengröße programmgesteuert abrufen. Überprüfe hier. Sie können auch nicht verallgemeinern, 64-Byte-Cache-Zeilen auf x86 zu haben. Es gilt nur für neuere.

    – tothphu

    20. Juni 2012 um 22:11 Uhr

  • C++11 fügt alignas hinzu, das ist eine portable Möglichkeit, die Ausrichtung anzugeben

    – NoSenseetAl

    19. Oktober 2018 um 2:43 Uhr

  • @NoSenseEtAl alignas unterstützt offiziell nur die Ausrichtung bis zur Größe des Typs std::max_align_twas typischerweise die Ausrichtungsanforderung von a ist long double, auch bekannt als 8 oder 16 Bytes – leider nicht 64. Siehe zum Beispiel stackoverflow.com/questions/49373287/…

    – Carlo Holz

    20. Juli 2019 um 15:40 Uhr


Benutzeravatar von Francesquini
Francesquini

Eine andere einfache Möglichkeit besteht darin, einfach die /proc/cpuinfo zu catern:

grep cache_alignment /proc/cpuinfo

  • Vielleicht möchten Sie eine nutzlose Verwendung von cat entfernen.

    – maxschlepzig

    6. Oktober 2019 um 17:57 Uhr

Es gibt keinen vollständig portablen Weg, um die Cacheline-Größe zu ermitteln. Aber wenn Sie auf x86/64 sind, können Sie die anrufen cpuid Anweisungen, um alles zu erfahren, was Sie über den Cache wissen müssen – einschließlich Größe, Cacheline-Größe, wie viele Ebenen usw.

http://softpixel.com/~cwright/programming/simd/cpuid.php

(Scrollen Sie ein wenig nach unten, die Seite handelt von SIMD, aber es gibt einen Abschnitt, in dem die Cacheline abgerufen wird.)

Was das Ausrichten Ihrer Datenstrukturen betrifft, so gibt es auch keine vollständig portable Möglichkeit, dies zu tun. GCC und VS10 haben unterschiedliche Möglichkeiten, die Ausrichtung einer Struktur anzugeben. Eine Möglichkeit, es zu “hacken”, besteht darin, Ihre Struktur mit unbenutzten Variablen aufzufüllen, bis sie der gewünschten Ausrichtung entspricht.

Um Ihre mallocs() auszurichten, haben alle Mainstream-Compiler auch malloc-Funktionen für diesen Zweck ausgerichtet.

posix_memalign oder valloc kann verwendet werden, um zugewiesenen Speicher an einer Cache-Zeile auszurichten.

  • Ich weiß, dass dies Ihre eigene Frage ist, aber für zukünftige Leser könnten Sie beide Teile beantworten 🙂

    – Steve Jessop

    2. September 2011 um 10:10 Uhr

  • Steve, weißt du, ob der von mmap zugeordnete Speicher auf eine Cache-Zeile ausgerichtet ist.

    – MetallicPriest

    2. September 2011 um 10:34 Uhr


  • Ich glaube nicht, dass es von Posix garantiert wird, aber ich wäre auch nicht im geringsten überrascht, wenn Linux immer Adressen auswählt, die seitenausgerichtet sind, geschweige denn nur Cache-Zeilen-ausgerichtet. Posix sagt, dass, wenn der Aufrufer den ersten Parameter (Adresshinweis) angibt, dieser seitenausgerichtet sein muss und die Abbildung selbst immer eine ganze Anzahl von Seiten ist. Das ist stark suggestiv, ohne wirklich etwas zu garantieren.

    – Steve Jessop

    2. September 2011 um 10:45 Uhr

  • Ja, mmap funktioniert nur in Bezug auf Seiten, und Seiten sind immer größer als Cache-Zeilen. Selbst in einigen theoretisch seltsamen Architekturen gibt es äußerst gute Gründe, warum Cache-Zeilen nicht größer als Seiten sind (Caches sind normalerweise physisch gekennzeichnet, sodass eine Zeile nicht ohne große Schmerzen für die CPU-Designer auf zwei virtuelle Seiten aufgeteilt werden kann).

    – Peter Cordes

    12. März 2018 um 4:29 Uhr

Benutzeravatar von zoecarver
zoecarver

Hier ist ein Tisch Ich habe das mit den meisten Arm/Intel-Prozessoren gemacht. Sie können es als Referenz verwenden, wenn Sie Konstanten definieren, sodass Sie die Cache-Zeilengröße nicht für alle Architekturen verallgemeinern müssen.

Für C++ werden wir hoffentlich bald sehen Hardwareschnittstellengröße Dies sollte ein genauer Weg sein, um diese Informationen zu erhalten (vorausgesetzt, Sie teilen dem Compiler Ihre Zielarchitektur mit).

  • Ich weiß, dass dies Ihre eigene Frage ist, aber für zukünftige Leser könnten Sie beide Teile beantworten 🙂

    – Steve Jessop

    2. September 2011 um 10:10 Uhr

  • Steve, weißt du, ob der von mmap zugeordnete Speicher auf eine Cache-Zeile ausgerichtet ist.

    – MetallicPriest

    2. September 2011 um 10:34 Uhr


  • Ich glaube nicht, dass es von Posix garantiert wird, aber ich wäre auch nicht im geringsten überrascht, wenn Linux immer Adressen auswählt, die seitenausgerichtet sind, geschweige denn nur Cache-Zeilen-ausgerichtet. Posix sagt, dass, wenn der Aufrufer den ersten Parameter (Adresshinweis) angibt, dieser seitenausgerichtet sein muss und die Abbildung selbst immer eine ganze Anzahl von Seiten ist. Das ist stark suggestiv, ohne wirklich etwas zu garantieren.

    – Steve Jessop

    2. September 2011 um 10:45 Uhr

  • Ja, mmap funktioniert nur in Bezug auf Seiten, und Seiten sind immer größer als Cache-Zeilen. Selbst in einigen theoretisch seltsamen Architekturen gibt es äußerst gute Gründe, warum Cache-Zeilen nicht größer als Seiten sind (Caches sind normalerweise physisch gekennzeichnet, sodass eine Zeile nicht ohne große Schmerzen für die CPU-Designer auf zwei virtuelle Seiten aufgeteilt werden kann).

    – Peter Cordes

    12. März 2018 um 4:29 Uhr

Benutzeravatar von Nick Strupat
Nick Strupat

Wenn jemand neugierig ist, wie man das einfach in C++ macht, ich habe eine Bibliothek mit einem erstellt CacheAligned<T> Klasse, die die Bestimmung der Cache-Zeilengröße sowie die Ausrichtung für Ihre übernimmt T Objekt, auf das durch Aufruf verwiesen wird .Ref() auf Ihrem CacheAligned<T> Objekt. Sie können auch verwenden Aligned<typename T, size_t Alignment> wenn Sie die Cache-Zeilengröße im Voraus kennen oder einfach bei dem sehr verbreiteten Wert von 64 (Bytes) bleiben möchten.

https://github.com/NickStrupat/Aligned

  • @James – alignas ist C++11. Es ist nicht für C++03 verfügbar. Und es funktioniert nicht auf einer Reihe von Apple-Plattformen. Auf einigen ihrer Betriebssysteme stellt Apple eine alte C++-Standardbibliothek bereit, die vorgibt, C++11 zu sein, aber fehlt unique_ptr, alignasetc.

    – jww

    13. Oktober 2015 um 15:59 Uhr


  • @James auch, der Standard erfordert nur alignas um bis zu 16 Byte zu unterstützen, sodass ein höherer Wert nicht portierbar ist. Und da praktisch alle modernen Prozessoren eine Cache-Zeilengröße von 64 Byte haben, alignas ist nicht nützlich, es sei denn, Sie wissen, dass Ihr Compiler unterstützt alignas(64).

    – Nick Strupat

    20. April 2016 um 6:09 Uhr

  • alignas ist auch in C11, nicht nur in C++11.

    – Alnitak

    14. November 2018 um 15:39 Uhr

  • alignas unterstützt offiziell nur die Ausrichtung bis zur Größe des Typs std::max_align_twas typischerweise die Ausrichtungsanforderung von a ist long doubleauch bekannt als 8 oder 16 Bytes – leider nicht 64.

    – Carlo Holz

    20. Juli 2019 um 15:41 Uhr

  • @NickStrupat Es scheint, dass C ++ 17 endlich Unterstützung für die Ausrichtung an Cache-Zeilengrößen hinzugefügt wurde. Mein letzter Kommentar scheint auch für C++17 nicht mehr korrekt zu sein (das Problem war lediglich, dass der Operator new nicht garantiert eine bessere Speicherausrichtung als std::max_align_t zurückgeben würde). Ich habe gerade das gefunden: de.cppreference.com/w/cpp/thread/…

    – Carlo Holz

    20. Juli 2019 um 16:14 Uhr

1416380cookie-checkAusrichtung auf die Cache-Zeile und Kenntnis der Cache-Zeilengröße

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy