c++ - Alineación de memoria: cómo usar alignof/alignas?
c++11 x86-64 (3)
Cada tipo tiene un requisito de alineación. En general, esto es para que se pueda acceder a las variables del tipo de manera eficiente, sin tener que hacer que la CPU genere más de un acceso de lectura / escritura para alcanzar a cualquier miembro dado del tipo de datos. Además, también garantiza una copia eficiente de toda la variable. alignof
devolverá el requisito de alineación para el tipo dado.
alignas
se utiliza para forzar una alineación en un tipo de datos (siempre que no sea menos estricto que lo que alignof
dicho tipo de datos)
Trabajo con memoria compartida en este momento.
No puedo entender alignof
y alignas
.
cppreference no está claro: alignof
devuelve "alineación" pero, ¿qué es "alineación"? número de bytes para agregar para el próximo bloque que se alineará? tamaño acolchado? Las entradas de desbordamiento de pila / blogs tampoco son claras.
¿Alguien puede explicar claramente alignof
y alignas
?
La alineación es una restricción en la que la memoria coloca el primer byte de un valor. (Es necesario para mejorar el rendimiento en los procesadores y para permitir el uso de ciertas instrucciones que solo funcionan en datos con una alineación particular, por ejemplo, la SSE debe alinearse a 16 bytes, mientras que AVX a 32 bytes).
La alineación de 16 significa que las direcciones de memoria que son un múltiplo de 16 son las únicas direcciones válidas.
alignas
fuerza la alineación al número requerido de bytes (cppreference no lo menciona, pero creo que solo puede alinearse con potencias de 2: 1, 2, 4, 8, 16, 32, 64, 128, ...)
#include <cstdlib>
#include <iostream>
int main() {
alignas(16) int a[4];
alignas(1024) int b[4];
printf("%p/n", a);
printf("%p", b);
}
ejemplo de salida:
0xbfa493e0
0xbfa49000 // note how many more "zeros" now.
// binary equivalent
1011 1111 1010 0100 1001 0011 1110 0000
1011 1111 1010 0100 1001 0000 0000 0000 // every zero is just a extra power of 2
la otra palabra clave
alignof
es muy conveniente, no puedes hacer algo como
int a[4];
assert(a % 16 == 0); // check if alignment is to 16 bytes: WRONG compiler error
pero puedes hacer
assert(alignof(a) == 16);
assert(alignof(b) == 1024);
tenga en cuenta que en realidad esto es más estricto que una simple operación de "%" (módulo). De hecho, sabemos que algo alineado a 1024 bytes se alinea necesariamente con 1, 2, 4, 8 bytes pero
assert(alignof(b) == 32); // fail.
Para ser más precisos, "alignof" devuelve la mayor potencia de 2 a la que algo está alineado.
También alignof es una buena forma de saber por adelantado el requisito mínimo de alineación para los tipos de datos básicos (probablemente devolverá 1 para caracteres, 4 para elementos flotantes, etc.).
Aún legal:
alignas(alignof(float)) float SqDistance;
Entonces, se colocará algo con una alineación de 16 en la siguiente dirección disponible que es un múltiplo de 16 (puede haber un relleno implícito de la última dirección utilizada).
La alineación no es un relleno (aunque el relleno a veces se introduce para satisfacer los requisitos de alineación). Es una propiedad intrínsica de un tipo C ++. Para ponerlo en standardese ( 3.11[basic.align]
)
Los tipos de objeto tienen requisitos de alineación (3.9.1, 3.9.2) que imponen restricciones a las direcciones a las que se puede asignar un objeto de ese tipo. Una alineación es un valor entero definido por la implementación que representa el número de bytes entre las direcciones sucesivas a las que se puede asignar un objeto determinado. Un tipo de objeto impone un requisito de alineación en cada objeto de ese tipo; se puede solicitar una alineación más estricta utilizando el especificador de alineación (7.6.2).