L'alignement sur la ligne de cache et de connaissance de la taille de ligne de cache
Pour éviter les faux partage, je veux aligner chaque élément d'un tableau à une ligne de cache. Alors d'abord j'ai besoin de savoir la taille d'une ligne de cache, j'ai donc attribuer à chaque élément de cette quantité d'octets. Deuxièmement, je veux que le début de la matrice être aligné sur une ligne de cache.
Je suis sous Linux et 8-core plate-forme x86. D'abord comment puis-je trouver la taille de ligne de cache. Deuxièmement, comment puis-je aligner sur une ligne de cache en C. je suis en utilisant le compilateur gcc.
Ainsi, la structure serait la suite par exemple, en supposant une taille de ligne de cache de 64.
element[0] occupies bytes 0-63
element[1] occupies bytes 64-127
element[2] occupies bytes 128-191
et ainsi de suite, en supposant bien-sûr que 0-63 est aligné sur une ligne de cache.
- Peut-être cela peut vous aider: stackoverflow.com/questions/794632/...
- Mais il ne montre pas à s'aligner dans une cache à l'aide de gcc.
- Double Possible de par programmation obtenir la taille de ligne de cache?
- Ce n'est pas une mauvaise idée d'utiliser une constante de compilation de 64 octets que le cache de la ligne de taille, de sorte que le compilateur ne peut cuire que dans les fonctions que les soins à ce sujet. Faire le compilateur génère du code pour l'exécution, la variable de taille de ligne de cache pourrais en manger quelques-uns des avantages de l'alignement des choses, surtout dans le cas de l'auto-vectorisation où il permet au compilateur de faire un code de meilleure qualité si elle connaît un pointeur est aligné sur une ligne de cache de la largeur (qui est plus large que le SIMD vecteur de largeur).
Vous devez vous connecter pour publier un commentaire.
Pour connaître les tailles, vous devez le rechercher à l'aide de la documentation pour le processeur, autant que je sache, il n'y a pas de programatic façon de le faire. Sur le côté positif, cependant, la plupart des lignes de cache sont de taille standard, basé sur les intels normes. Sur x86 lignes de cache de 64 octets, cependant, pour éviter les faux partage, vous devez suivre les directives du processeur cible (intel a des notes sur sa netburst les processeurs à base de), général, vous devez aligner à 64 octets pour ce (intel indique que vous devez aussi éviter la traversée de 16 octets boundries).
Pour ce faire en C ou C++ nécessite l'utilisation de la norme
aligned_alloc
de la fonction ou de l'un de le compilateur spécifique des prescripteurs tels que__attribute__((align(64)))
ou__declspec(align(64))
. À la pad entre les membres dans une struct répartir sur les différentes lignes de cache, vous avez besoin lors de l'insertion d'un membre assez grand pour l'aligner sur le prochain 64 octets limite de__attributes__
CPUID
, et que de nombreuses révisions de l'Intel guides, lignes de cache ont été de 64 octets, IIRC même le P4 (qui est maintenant ancienne) avait de 64 octets cachelines (en fait, il n', voir: osronline.com/article.cfm?article=273). il n'est pas besoin de spam le lien, plutôt que de modifier votre commentaire.std::max_align_t
, qui est généralement l'alignement de l'exigence d'unelong double
, aka 8 ou 16 octets - pas 64 malheureusement. Voir par exemple stackoverflow.com/questions/49373287/...Passer la valeur comme une définition de macro pour le compilateur.
Au moment de l'exécution
sysconf(_SC_LEVEL1_DCACHE_LINESIZE)
peut être utilisé pour obtenir la taille du cache L1.sysconf()
s spécifié? POSIX / IEEE Std 1003.1-20xx ?man sysconf
. Linux n'est pas exactement POSIX compilant, de sorte que Linux documentation spécifique est souvent plus utile. Parfois, il est hors de date, de sorte que vousegrep -nH -r /usr/include -e '\b_SC'
.sysctl hw.cachelinesize
.Il n'y a pas complètement portatif de façon à obtenir le cacheline taille. Mais si vous êtes sur x86/64, vous pouvez appeler la
cpuid
instruction pour obtenir tout ce que vous devez savoir sur le cache - y compris la taille, cacheline taille, nombre de niveaux, etc...http://softpixel.com/~cwright/programming/simd/cpuid.php
(faites défiler vers le bas un peu, la page est sur le SIMD, mais il a une section d'obtenir le cacheline.)
Comme pour l'alignement de vos structures de données, il n'est pas non plus complètement portable façon de le faire. GCC et VS10 ont différentes façons de spécifier l'alignement d'une struct.
Une façon de "hack" c'est-à-pad de votre structure avec des variables inutilisées jusqu'à ce qu'il corresponde à l'alignement souhaité.
Pour aligner votre mallocs(), tous les intégrer des compilateurs ont également aligné malloc fonctions à cette fin.
Un autre moyen simple est juste de cat /proc/cpuinfo:
cat /proc/cpuinfo | grep cache_alignment
posix_memalign ou valloc peut être utilisé pour aligner la mémoire allouée à une ligne de cache.
mmap
fonctionne uniquement en termes de pages, et des pages sont toujours plus gros que les lignes de cache. Même dans certains théorique bizarre architecture, il y a de très bonnes raisons pour lesquelles les lignes de cache ne sera pas plus grand que les pages (les caches sont normalement physiquement marqués si une ligne ne peut pas être divisée en 2 pages virtuelles sans douleur extrême pour le CPU concepteurs).Si quelqu'un est curieux de voir comment le faire facilement en C++, j'ai construit une bibliothèque avec un
CacheAligned<T>
de la classe qui gère la détermination de la taille de ligne de cache ainsi que l'alignement de votreT
objet référencé par l'appel de.Ref()
sur votreCacheAligned<T>
objet. Vous pouvez également utiliserAligned<typename T, size_t Alignment>
si vous connaissez la taille de ligne de cache à l'avance, ou tout simplement pour coller avec le très courante valeur de 64 (en octets).https://github.com/NickStrupat/Aligned
unique_ptr
,alignas
, etc.alignas
en charge jusqu'à 16 octets, de sorte que toute hausse de la valeur ne sera pas portable. Et puisque presque tous les processeurs modernes ont une taille de ligne de cache de 64 octets,alignas
n'est pas utile, sauf si vous savez que votre compilateur prend en chargealignas(64)
.alignas
est également en C11, non seulement C++11.alignas
officiellement prend uniquement en charge l'alignement jusqu'à la taille du typestd::max_align_t
, qui est généralement l'alignement de l'exigence d'unelong double
, aka 8 ou 16 octets - pas 64 malheureusement.get_cachline_size
fonction est qu'il peut récupérer ces informations au moment de l'exécution. L'inconvénient est que vous perdez du possible, les optimisations du compilateur si le cache de la ligne de la taille est connue à la compilation.