2012-04-25 7 views

risposta

7

Buona domanda. Considerare questo tipo ipotetico:

struct A { 
    int n; 
    bool flag; 
}; 

Quindi, un oggetto di tipo A dovrebbe prendere cinque byte (quattro per l'int più uno per il bool), ma in realtà ci vogliono otto. Perché?

La risposta è visto, se si utilizza il tipo in questo modo:

const size_t N = 100; 
A a[N]; 

Se ogni A erano solo cinque byte, quindi a[0] sarebbe allineare ma a[1], a[2] e la maggior parte degli altri elementi non sarebbe.

Ma perché l'allineamento è importante? Ci sono diversi motivi, tutti relativi all'hardware. Una ragione è che la memoria utilizzata di recente/frequentemente viene memorizzata nella cache nelle linee della cache sul silicio della CPU per un accesso rapido. Un oggetto allineato più piccolo di una riga della cache si adatta sempre a una singola riga (ma si vedano i commenti interessanti elencati di seguito), ma un oggetto non allineato può essere a cavallo di due righe, sprecando la cache.

In realtà ci sono ancora più motivi hardware fondamentali, che riguardano il modo in cui i dati indirizzabili in byte vengono trasferiti lungo un bus dati a 32 o 64 bit, a parte le linee della cache. Non solo il disallineamento bloccherà il bus con ulteriori recuperi (dovuti come prima a cavalcare), ma costringerà anche i registri a spostare i byte mentre entrano. Ancora peggio, il disallineamento tende a confondere la logica di ottimizzazione (almeno, il manuale di ottimizzazione di Intel dice che lo fa, anche se non ho alcuna conoscenza personale di quest'ultimo punto). Quindi, il disallineamento è molto negativo dal punto di vista delle prestazioni.

Di solito vale la pena di sprecare i byte di riempimento per questi motivi.

Aggiornamento: I commenti seguenti sono tutti utili. Li raccomando.

+1

* Un oggetto allineato più piccolo di una riga della cache si adatta sempre a una singola riga, ma un oggetto non allineato può essere a cavallo di due linee *> ** No **. Se allineato o meno un oggetto potrebbe trovarsi a cavallo di due linee. –

+1

@MatthieuM., In realtà sì e no. Le dimensioni della linea di cache sono multipli della dimensione massima dei dati e di qualsiasi altro tipo fondamentale. Quindi tutti i tipi _native_ allineati (più, più) saranno naturalmente all'interno di una singola linea di cache. Si consideri che qualsiasi tipo allineato 1,2,4,8,16 byte verrà automaticamente allineato per adattarsi all'interno di una linea di cache di 64 o 128 byte. Un sistema sarebbe essenzialmente inutilizzabile se questo non fosse il caso. –

+1

@ edA-qamort-ora-y: certo, ma un oggetto essendo un composto di tipi fondamentali potrebbe facilmente cavalcare due linee. Anche se è più piccolo. Supponendo una linea da 64 byte, posso avere un oggetto di 48 byte di grandi dimensioni, e in una tabella di tali oggetti, almeno uno su due si troverà a cavallo di due linee di cache. –

0

A causa di indirizzamento virtuale.

"... allineare una pagina su un limite di pagina di dimensioni permette la mappa hardware un indirizzo virtuale in un indirizzo fisico sostituendo i bit superiori nell'indirizzo, piuttosto che fare l'aritmetica complessa."

A proposito, ho trovato la pagina di Wikipedia su questo abbastanza ben scritto.

+1

Non correlato .... –

0

Se la dimensione del registro della CPU è di 32 bit, quindi può afferrare la memoria che si trova su limiti a 32 bit con una singola istruzione di assemblaggio. È più lento afferrare 32 bit e quindi ottenere il byte che inizia al bit 8.

BTW: Non è necessario che il padding sia presente. Puoi chiedere che le strutture siano imballate.

+1

L'imballaggio è specifico del compilatore, non nella lingua. L'imballaggio esploderà nei computer RISC, se il supporto CPU/kernel per la gestione di carichi e negozi disallineati non è presente o non è attivato. Allineamento solo per velocità; è un requisito difficile per alcune macchine. – Kaz

1

A seconda dell'hardware, potrebbe essere necessario un allineamento o semplicemente accelerare l'esecuzione.

C'è un certo numero di processori (ARM credo) in cui un accesso non allineato porta a un'eccezione hardware. Chiaro e semplice.

Anche se i processori x86 tipici sono più indulgenti, c'è ancora una penalità nell'accedere a tipi fondamentali non allineati, poiché il processore deve fare più lavoro per portare i bit nel registro prima di poter operare su di esso. I compilatori di solito offrono attributi/direttive specifici quando lo imballaggio è comunque desiderabile.

Problemi correlati