Verificare l’allineamento di una variabile (alignment) – C/C++

In inglese viene chiamato memory alignment, ed è la proprietà di un dato (una variabile in memoria) di iniziare a un indirizzo multiplo di una certa quantità di bit.Per esempio, una variabile può essere allineata a 8, 16 o 32 bit. Questo significa che l’indirizzo di memoria in cui la variabile è collocata è un multiplo di 8, 16, o 32 bit.

Nelle architetture moderne, ogni dato è sempre allineato ad almeno 8 bit, per il semplice motivo che il computer non riesce a indirizzare una quantità di memoria inferiore (infatti il computer vede la memoria suddivisa in byte, non in gruppi di bit o in singoli bit). Se il dato, supponiamo un int, è allineato a 32 bit, allora un suo indirizzo in memoria potrebbe essere, plausibilmente, 0x000044440, 0x000044444, 0x000044448 (da notare gli incrementi di 4 alla fine, che indicano un incremento di 4 byte, ovvero di 32 bit).

Esistono due metodi per verificare facilmente se una variabile è allineata o meno a un dato valore.

Il primo, il più diretto e semplice, richiede di usare l’operatore di modulo (% in C e C++). Si tratta semplicemente di prendere l’indirizzo di una variabile (con l’operatore &, o senza operatore & se si tratta di un puntatore) e fare il modulo con il valore desiderato. Se il risultato è zero, vuol dire che l’indirizzo è un multiplo esatto di quel valore e la variabile risulta allineata. In termini di codice:

int* a;

if  !( a % 32) {/* La variabile è allineata */}  // Attenzione a testare con l’operatore NOT davanti

Il secondo metodo invece è più efficiente,e sfrutta un trucco dell’aritmetica booleana. Si tratta di usare l’operatore AND con una maschera di bit che abbia tanti 1 impostati quanto è il numero a cui dobbiamo elevare 2 per ottenere il valore di allineamento. In parole più semplici, se dobbiamo allineare a 8 bit, la maschera sarà 111, a 16 sarà 1111, a 32 sarà 11111 (due alla quinta) e così via (un interessante applicazione di ciò è che per testare se un numero è pari basta fare AND con 1). Attenzione, le maschere sono in codice binario, vanno riconvertite nel formato usato per codificare l’indirizzo: se si tratta di esadecimale, per 8 bit 0x7, per 16 0xf, per 32 0x20. Il codice risulta:

int*a;

if !( a & 0x20) { /* La variabile è allineata a 32 bit */ }

E’ dunque possibile verificare l’allineamento con una sola riga di codice. A cosa serve però controllare l’allineamento? Si tratta di prestazioni: il computer può accedere alla memoria solo per blocchi, e l’allineamento garantisce che le variabili non inizino a metà blocco, costringendo il calcolatore a laboriose operazioni di recupero dell’informazione. Alcuni esempi pratici che mostrano l’uso dell’allineamento sono alcune implementazioni della funzione memcpy() e le istruzioni SSE.

Fonti:

http://cboard.cprogramming.com/cplusplus-programming/118471-fast-checking-alignment.html
http://www.undolog.com/2008/05/31/loperazione-aritmetica-modulo/
http://stackoverflow.com/questions/1054657/memory-alignment-on-a-32-bit-intel-processor
http://www.embedded.com/shared/printableArticle.jhtml?articleID=19205567

Annunci
Verificare l’allineamento di una variabile (alignment) – C/C++

Rispondi

Inserisci i tuoi dati qui sotto o clicca su un'icona per effettuare l'accesso:

Logo WordPress.com

Stai commentando usando il tuo account WordPress.com. Chiudi sessione / Modifica )

Foto Twitter

Stai commentando usando il tuo account Twitter. Chiudi sessione / Modifica )

Foto di Facebook

Stai commentando usando il tuo account Facebook. Chiudi sessione / Modifica )

Google+ photo

Stai commentando usando il tuo account Google+. Chiudi sessione / Modifica )

Connessione a %s...