10 Stimmen

Cache Line Alignment (Artikel muss geklärt werden)

Vor kurzem bin ich in meiner Anwendung auf ein Problem gestoßen, das meiner Meinung nach auf eine falsche Freigabe zurückzuführen ist, und ich habe nachgeschaut Sutters Artikel wie ich meine Daten an Cache-Zeilen ausrichten kann. Er schlägt den folgenden C++-Code vor:

// C++ (using C++0x alignment syntax)
template<typename T>
struct cache_line_storage {
   [[ align(CACHE_LINE_SIZE) ]] T data;
   char pad[ CACHE_LINE_SIZE > sizeof(T)
        ? CACHE_LINE_SIZE - sizeof(T)
        : 1 ];
};

Ich kann mir vorstellen, wie das funktionieren würde, wenn CACHE_LINE_SIZE > sizeof(T) wahr ist - die Struktur cache_line_storage nur eine volle Cache-Zeile des Speichers beansprucht. Wenn jedoch die sizeof(T) größer als eine einzelne Cache-Zeile ist, sollten wir die Daten um CACHE_LINE_SIZE - T % CACHE_LINE_SIZE Bytes, so dass die resultierende Struktur eine Größe hat, die ein ganzzahliges Vielfaches der Cache-Zeilengröße ist. Was ist an meinem Verständnis falsch? Warum reicht das Auffüllen mit 1 Byte aus?

7voto

coppro Punkte 14158

Sie können keine Arrays der Größe 0 haben, also ist 1 erforderlich, damit es kompiliert werden kann. Die aktuelle Entwurfsversion der Spezifikation besagt jedoch, dass ein solches Auffüllen nicht notwendig ist; der Compiler muss bis zur Ausrichtung der Struktur auffüllen.

Beachten Sie auch, dass dieser Code nicht formgerecht ist, wenn CACHE_LINE_SIZE kleiner ist als alignof(T) . Um dies zu beheben, sollten Sie wahrscheinlich [[align(CACHE_LINE_SIZE), align(T)]] , wodurch sichergestellt wird, dass niemals eine kleinere Ausrichtung gewählt wird.

3voto

tony Punkte 3547

Stellen Sie sich vor:

#define CACHE_LINE_SIZE 32
sizeof(T) == 48

Überlegen Sie nun, wie [[ align(CACHE_LINE_SIZE) ]] , funktioniert. z.B:

[[ align(32) ]] Foo foo;

Dies wird dazu führen, dass sizeof(Foo) == 32n für einige n . d.h. align() paddelt für Sie, wenn nötig, um Dinge wie Foo foo[10]; jeden zu haben foo[i] wie gewünscht angeglichen.

In unserem Fall also, mit sizeof(T) == 48 bedeutet dies sizeof(cache_line_storage<T>) == 64 .

Die Ausrichtung gibt Ihnen also die erhoffte Polsterung.

Dies ist jedoch ein "Fehler" in der Vorlage. Betrachten Sie diesen Fall:

#define CACHE_LINE_SIZE 32
sizeof(T) == 32

Hier kommen wir zu folgenden Ergebnissen char pad[1]; . Das bedeutet sizeof(cache_line_storage<T>) == 64 . Wahrscheinlich nicht das, was Sie wollen!

Ich denke, die Vorlage müsste etwas geändert werden:

template <typename T, int padding>
struct pad_or_not
{
   T data;
   char pad[padding];
};

// specialize the 0 case
// As it is late, I am SURE I've got the specialization syntax wrong...
template <typename T, int>
struct pad_or_not<0>
{
   T data;
};

template<typename T>
struct cache_line_storage {
   [[ align(CACHE_LINE_SIZE) ]] pad_or_not<T, (sizeof(T) > CACHE_LINE_SIZE ? 0 : CACHE_LINE_SIZE - sizeof(T) ) > data;
};

oder so ähnlich.

0voto

MikeW Punkte 41

"Man kann keine Arrays der Größe 0 haben, also ist 1 erforderlich, damit es kompiliert werden kann" - GNU C erlaubt Arrays mit der Größe Null. Siehe auch http://gcc.gnu.org/onlinedocs/gcc-4.1.2/gcc/Zero-Length.html

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X