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 que se deben agregar para alinear el siguiente bloque? tamaño acolchado? Las entradas de stack overflow / blogs tampoco están claras.
¿Alguien puede explicarlo claramente alignof
y alignas
?
c++
c++11
x86-64
memory-alignment
Offirmo
fuente
fuente
alignof
página (lo hace ahora, en la página del objeto de trabajo en progreso ). No veo la relevancia de cplusplus.com.Respuestas:
La alineación es una restricción sobre qué posiciones de memoria se pueden almacenar el primer byte de un valor. (Es necesario para mejorar el rendimiento de los procesadores y permitir el uso de ciertas instrucciones que funcionan solo en datos con una alineación particular, por ejemplo, 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 múltiplos de 16 son las únicas direcciones válidas.
alignas
forzar la alineación al número requerido de bytes. Solo puedes alinear a 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 tu 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 está necesariamente alineado a 1, 2, 4, 8 bytes pero
assert(alignof(b) == 32); // fail.
Entonces, para ser más precisos, "alignof" devuelve la mayor potencia de 2 con la que algo está alineado.
También alignof es una buena manera de conocer de antemano el requisito de alineación mínimo para tipos de datos básicos (probablemente devolverá 1 para caracteres, 4 para flotante, etc.).
Todavía legal:
alignas(alignof(float)) float SqDistance;
Algo con una alineación de 16 se colocará en la siguiente dirección disponible que sea un múltiplo de 16 (puede haber un relleno implícito de la última dirección utilizada).
fuente
sizeof
,alignof
solo se puede aplicar a untype-id
.alignof()
(y la contrapartealignas()
) en tiempo de compilación, por lo que no hay gastos generales de tiempo de ejecución?alignof
es una constante en tiempo de compilación.alignas
no lo es, y tendrá que ser respaldado por su implementación denew
(requisito del estándar), o por un asignador estándar personalizado .struct
y miembros de la estructura que sonstatic
.alignas
está resultando ser mucho más delicado que__attribute__((aligned))
, especialmente en compiladores como Clang.La alineación no es relleno (aunque a veces se introduce relleno para satisfacer los requisitos de alineación). Es una propiedad intrínseca de tipo C ++. Para ponerlo en standardese (
3.11[basic.align]
)fuente
struct X { char a; char b}
tiene tamaño 2 y requisito de alineación 1, en sistemas cuerdos (se puede asignar en cualquier dirección porque se puede asignar un carácter en cualquier dirección)alignof(std::max_align_t)
, que está16
en mi linux (independientemente de si se compila -m32 o -m64), pero puede hacerlo más estricto conalignas
Cada tipo tiene un requisito de alineación. Generalmente, esto es para que se pueda acceder de manera eficiente a las variables del tipo, sin tener que hacer que la CPU genere más de un acceso de lectura / escritura para llegar a cualquier miembro dado del tipo de datos. Además, también asegura una copia eficiente de toda la variable.
alignof
devolverá el requisito de alineación para el tipo dado.alignas
se usa para forzar una alineación en un tipo de datos (siempre que no sea menos estricto que loalignof
que devolvería dicho tipo de datos)fuente
La alineación es una propiedad relacionada con la dirección de memoria. Simplemente podemos decir que si una dirección X está alineada con Z, entonces x es un múltiplo de Z, es decir, X = Zn + 0. Aquí lo importante es que Z siempre es una potencia de 2.
La declaración anterior se encuentra en la referencia de Microsoft C ++.
Si un elemento de datos se almacena en la memoria con una dirección que está alineada con su tamaño, entonces se dice que ese elemento de datos está alineado naturalmente , de lo contrario, desalineado. Por ejemplo: si una variable entera con un tamaño de 4 bytes se almacena en una dirección que está alineada con 4, entonces podemos decir que la variable está naturalmente alineada, es decir, la dirección de la variable debe ser un múltiplo de 4.
Los compiladores siempre intentan evitar desalineamientos. Para tipos de datos simples, las direcciones se eligen de manera que sea un múltiplo del tamaño de la variable en bytes. El cumplidor también se rellena de forma adecuada en el caso de estructuras para una alineación y acceso naturales, aquí la estructura se alineará al máximo de los tamaños de los diferentes elementos de datos en la estructura, por ejemplo:
struct abc { int a; char b; };
Aquí, la estructura abc se alinea con 4, que es el tamaño del miembro int que obviamente es mayor que 1 byte (tamaño del miembro char).
alinear
Este especificador se usa para alinear tipos definidos por el usuario como estructura, clase, etc. a un valor particular que es una potencia de 2.
alinear
Este es un tipo de operador para obtener el valor con el que se alinea la estructura o el tipo de clase. p.ej:
#include <iostream> struct alignas(16) Bar { int i; // 4 bytes int n; // 4 bytes short s; // 2 bytes }; int main() { std::cout << alignof(Bar) << std::endl; // output: 16 }
fuente