Question

Je l'ai vu récemment ce que je pense est un faux problème de partage dans ma demande, et je l'ai regardé article Sutter sur la façon d'aligner mes données sur les lignes de cache. Il suggère le code C ++:

// 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 ];
};

Je peux voir comment cela fonctionnerait quand CACHE_LINE_SIZE > sizeof(T) est vrai - le cache_line_storage struct termine juste en prenant une ligne complète de cache de la mémoire. Cependant, lorsque le sizeof(T) est plus grande qu'une seule ligne de cache, je pense que nous devrions rembourrer les données par octets de CACHE_LINE_SIZE - T % CACHE_LINE_SIZE, de sorte que la struct résultant a une taille qui est un multiple entier de la taille de la ligne de cache. Quel est le problème avec ma compréhension? Pourquoi padding avec 1 octet suffit?

Était-ce utile?

La solution

Vous ne pouvez pas avoir des tableaux de taille 0, donc 1 est nécessaire pour faire la compilation. Toutefois, le projet de version actuelle de la spécification dit que ce rembourrage est unecessary; le tampon doit compilateur jusqu'à l'alignement du struct.

Notez également que ce code est mal formé si CACHE_LINE_SIZE est plus petite que alignof(T). Pour résoudre ce problème, vous devriez probablement utiliser [[align(CACHE_LINE_SIZE), align(T)]], qui assurera qu'un alignement plus petit est jamais pris.

Autres conseils

Imaginez

#define CACHE_LINE_SIZE 32
sizeof(T) == 48

Maintenant, examiner comment [[ align(CACHE_LINE_SIZE) ]], fonctionne. par exemple:

[[ align(32) ]] Foo foo;

Cela forcera sizeof(Foo) == 32n pour certains n. à-dire aligner () pad volonté pour vous, si nécessaire, pour que les choses comme Foo foo[10]; avoir chaque foo[i] aligné sur demande.

Ainsi, dans notre cas, avec sizeof(T) == 48, cela signifie sizeof(cache_line_storage<T>) == 64.

Alors l'alignement vous donne le rembourrage que vous espériez.

Cependant, ceci est une « erreur » dans le modèle. Considérez ce cas:

#define CACHE_LINE_SIZE 32
sizeof(T) == 32

nous nous retrouvons ici avec char pad[1];. Ce qui signifie que sizeof(cache_line_storage<T>) == 64. Probablement pas ce que vous voulez!

Je pense que le modèle devrait être quelque peu modifiée:

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;
};

ou quelque chose comme ça.

« Vous ne pouvez pas avoir des tableaux de taille 0, donc 1 est nécessaire pour faire la compilation » - GNU C ne permet des tableaux dimensionnées zéro. Voir aussi http://gcc.gnu.org/ onlinedocs / gcc-4.1.2 / gcc / Zero-Length.html

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top