L'alignement de la mémoire est le placement de données en mémoire à des adresses multiples d'un certain nombre d'octets, correspondant à l'architecture ou au type de données. Un bon alignement est critique pour les performances, le bon fonctionnement avec le matériel et certaines instructions du processeur.
Historique.
Dans les premiers ordinateurs, les violations d'alignement entraînaient des pannes matérielles (erreur de bus) et la puissance de calcul des processeurs était sensible aux adresses de données non alignées. Même dans les architectures modernes, un alignement correct permet d'accéder aux données en 1 cycle sans pénalité.
Problème.
Si une structure est placée sans tenir compte de l'alignement, la lecture/écriture peut être plus lente ou impossible (par exemple, crash sur ARM ou MIPS). De plus, cela nuit à l'interaction avec les API de bas niveau, les périphériques ou la sérialisation des données pour transmission sur le réseau.
Solution.
En C++, pour contrôler l'alignement, il existe le mot-clé alignas (C++11) et std::align, ainsi que des attributs de compilateur non standard (__attribute__((aligned(N))) dans GCC/Clang, __declspec(align(N)) dans MSVC).
Exemple de code :
struct alignas(16) MyStruct { int a; double b; char c; }; #include <iostream> #include <type_traits> int main() { std::cout << alignof(MyStruct) << std::endl; // 16 std::cout << sizeof(MyStruct) << std::endl; }
Caractéristiques clés :
L'ordre de déclaration des membres d'une structure influence-t-il la taille et l'alignement de la structure ?
Oui, l'ordre des membres détermine directement les « paddings » entre eux, ce qui peut ajouter des octets supplémentaires à la taille de la structure.
struct S1 { char a; int b; }; // généralement sizeof==8 (sur un alignement de 4 octets) struct S2 { int b; char a; }; // généralement sizeof==8, mais parfois moins de padding
Peut-on réduire la taille d'une structure sans violer l'alignement ?
Oui, en regroupant les membres de grande taille plus tôt, et les petits plus tard. Alignez efficacement les données en fonction de la taille des types :
struct S { double d; int i; char c; }; // meilleur que de les répartir séparément
Que se passe-t-il si l'on travaille avec des adresses non alignées manuellement via des pointeurs ?
La norme C++ déclare un tel comportement indéfini (undefined behavior), certains CPU peuvent générer SIGBUS ou similaire.
Un programmeur a implémenté sa propre structure pour travailler avec SIMD, sans spécifier d'alignement. En conséquence, le programme plante sur certains appareils ARM lors des opérations sur des données non alignées.
Avantages :
Inconvénients :
Dans un projet travaillant avec des données vidéo (SSE/AVX), alignas a été utilisé pour les structures de tampon, ce qui a permis d'utiliser efficacement les instructions SIMD.
Avantages :
Inconvénients :