Allineamento della memoria — è il posizionamento dei dati in memoria su indirizzi che sono multipli di un certo numero di byte, corrispondente all'architettura o al tipo di dati. Un corretto allineamento è critico per le performance, il corretto funzionamento con l'hardware e alcune istruzioni del processore.
Storia del problema.
Nei computer più antichi, violazioni dell'allineamento portavano a malfunzionamenti hardware (bus error), e la potenza di calcolo dei processori era sensibile agli indirizzi non multipli. Anche nelle architetture moderne, un corretto allineamento garantisce accesso ai dati in 1 ciclo senza penalità.
Problema.
Se una struttura è posizionata senza considerare l'allineamento, la lettura/scrittura potrebbe essere più lenta o impossibile (ad esempio, crash su ARM o MIPS). Inoltre, l'interazione con API a basso livello, dispositivi o serializzazione dei dati per la trasmissione in rete viene compromessa.
Soluzione.
In C++, per controllare l'allineamento si usano la parola chiave alignas (C++11) e std::align, oltre a attributi non standard del compilatore (__attribute__((aligned(N))) in GCC/Clang, __declspec(align(N)) in MSVC).
Esempio di codice:
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; }
Caratteristiche principali:
Influisce l'ordine delle dichiarazioni dei membri di una struct sulla dimensione e sull'allineamento della struttura?
Sì, l'ordine dei membri determina direttamente i "padding" tra di loro, il che può aggiungere byte supplementari alla dimensione della struttura.
struct S1 { char a; int b; }; // di solito sizeof==8 (con allineamento di 4 byte) struct S2 { int b; char a; }; // di solito sizeof==8, ma a volte meno padding
È possibile ridurre la dimensione di una struttura senza compromettere l'allineamento?
Sì, raggruppando i membri più grandi prima e quelli più piccoli dopo. È efficace allineare i dati tenendo conto della dimensione:
struct S { double d; int i; char c; }; // migliore che in modo sparso
Cosa succede se si lavora con indirizzi non allineati manualmente tramite puntatori?
Lo standard C++ dichiara tale comportamento non definito (undefined behavior), alcuni CPU possono generare SIGBUS o cose simili.
Un programmatore ha implementato una propria struttura per lavorare con SIMD, senza specificare l'allineamento. Di conseguenza, il programma si blocca su alcuni dispositivi ARM durante il tentativo di operazioni su dati non allineati.
Pro:
Contro:
In un progetto che lavora con dati video (SSE/AVX), è stato utilizzato alignas per le strutture del buffer, consentendo di utilizzare sempre in modo efficiente le istruzioni SIMD.
Pro:
Contro: