Buena pregunta. Considere este tipo hipotética:
struct A {
int n;
bool flag;
};
Por lo tanto, un objeto de tipo A
debe tomar cinco bytes (cuatro para el int más uno para el bool), pero en realidad se tarda ocho. ¿Por qué?
La respuesta se ve si se utiliza el tipo de esta manera:
const size_t N = 100;
A a[N];
Si cada A
eran sólo cinco bytes, entonces a[0]
alinearía pero a[1]
, a[2]
y la mayoría de los otros elementos no lo haría.
Pero, ¿por qué la alineación incluso importa? Hay varias razones, todas relacionadas con el hardware. Una razón es que la memoria utilizada recientemente/recientemente se almacena en caché en líneas de caché en la CPU de silicio para un acceso rápido. Un objeto alineado más pequeño que una línea de caché siempre cabe en una sola línea (pero vea los comentarios interesantes que se adjuntan a continuación), pero un objeto desalineado puede dividirse en dos líneas, desperdiciando el caché.
En realidad, existen razones de hardware aún más fundamentales, que tienen que ver con la forma en que los datos direccionables por byte se transfieren a un bus de datos de 32 o 64 bits, aparte de las líneas de caché. La desalineación no solo obstruirá el bus con extra fetches (debido a que se montará a horcajadas), sino que también obligará a los registros a desplazar bytes a medida que entren. Lo que es peor, la desalineación tiende a confundir la lógica de optimización (al menos, el manual de optimización de Intel dice lo hace, aunque no tengo ningún conocimiento personal de este último punto). Entonces, la desalineación es muy mala desde el punto de vista del rendimiento.
Por lo general, vale la pena desperdiciar los bytes de relleno por estos motivos.
Actualización: Los comentarios a continuación son útiles. Los recomiendo
* Un objeto alineado más pequeño que una línea de caché siempre cabe en una sola línea, pero un objeto desalineado puede dividirse en dos líneas *> ** No **. Ya sea que esté alineado o no, un objeto podría estar a dos líneas. –
@MatthieuM., En realidad sí y no. Los tamaños de línea de caché son múltiplos del tamaño de datos más grande y cualquier otro tipo fundamental. Por lo tanto, todos (er, la mayoría) de los tipos _native_ alineados estarán naturalmente dentro de una sola línea de caché. Tenga en cuenta que cualquier tipo de alineación de 1,2,4,8,16 bytes se alineará automáticamente para ajustarse a una línea de caché de 64 o 128 bytes. Un sistema sería esencialmente inutilizable si este no fuera el caso. –
@ edA-qamort-ora-y: seguro, pero un objeto que es un compuesto de tipos fundamentales podría fácilmente abarcar dos líneas. Incluso si es más pequeño. Suponiendo una línea de 64 bytes, puedo tener un objeto de 48 bytes grande, y en una tabla de dichos objetos, al menos uno de dos se colocará en dos líneas de caché. –