¿por qué es importante la alineación de la estructura de datos para el rendimiento?


¿Puede alguien darme una explicación breve y plausible de por qué el compilador agrega relleno a las estructuras de datos para alinear sus miembros? Sé que se hace para que la CPU pueda acceder a los datos de manera más eficiente, pero no entiendo por qué es así.

Y si esto solo está relacionado con la CPU, ¿por qué se alinea un doble 4 bytes en Linux y 8 bytes en Windows?

 26
Author: aledalgrande, 2010-01-05

4 answers

La alineación ayuda a la CPU a obtener datos de la memoria de una manera eficiente: menos errores de caché/vaciado, menos transacciones de bus, etc.

Algunos tipos de memoria (por ejemplo, RDRAM, DRAM, etc.) necesitan ser accedidos de una manera estructurada ("palabras" alineadas y en "transacciones de ráfaga", es decir, muchas palabras a la vez) con el fin de obtener resultados eficientes. Esto se debe a muchas cosas entre las cuales:

  1. tiempo de configuración: tiempo que tardan los dispositivos de memoria en acceder a las ubicaciones de memoria
  2. bus arbitraje sobrecarga es decir, muchos dispositivos podrían querer acceso al dispositivo de memoria

"Padding" se utiliza para corregir la alineación de estructuras de datos con el fin de optimizar la eficiencia de transferencia.


En otras palabras, acceder a una estructura "mal alineada" producirá un rendimiento general más bajo. Un buen ejemplo de tal trampa: supongamos que una estructura de datos está mal alineada y requiere que el Controlador de CPU / Memoria realice 2 transacciones de bus (en lugar de 1) para obtener dicho estructura, el rendimiento es por lo tanto en consecuencia menor.

 16
Author: jldupont,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-01-05 16:52:54

La CPU obtiene datos de la memoria en grupos de 4 bytes (actualmente depende del hardware sus 8 u otros valores para algunos tipos de hardware, pero permite seguir con 4 para mantenerlo simple), todo está bien si los datos comienzan en una dirección que es divisible por 4, la CPU va a la dirección de memoria y carga los datos.

Ahora supongamos que los datos comienzan en una dirección no divisible por 4 por ejemplo, en aras de la simplicidad en la dirección 1, la CPU debe tomar datos de la dirección 0 y luego aplicar algunos algoritmo para volcar el byte en la dirección 0, para obtener acceso a los datos reales en el byte 1. esto lleva tiempo y por lo tanto reduce actuación. por lo tanto, es mucho más eficiente tener todas las direcciones de datos alineadas.

 12
Author: Alon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-01-05 14:21:20

Una línea de caché es una unidad básica de almacenamiento en caché. Típicamente es de 16-64 bytes o más.

Pentium IV: 64 bytes; Pentium Pro/II: 32 bytes; Pentium I: 32 bytes; 486: 16 bytes.

myrandomreader:
  ; ...
  ; ten instructions to generate next pseudo-random
  ; address in ESI from previous address
  ; ...
  MOV EAX, DS:[ESI]   ; X
  LOOP myrandomreader

Donde dice memoria debe decir a caballo entre dos cachelines:

(para el error de caché L1) el procesador debe esperar a que se lea toda la línea de caché 1 desde L2- > L1 en el procesador antes de que pueda solicitar la segunda línea de caché, causando un corto bloqueo de ejecución

(para L2 cache miss) el el procesador debe esperar a que se completen dos lecturas de ráfaga de la caché L3 (si está presente) o la memoria principal en lugar de una

El procesador se detiene

  • Una lectura aleatoria de 4 bytes se extenderá por un límite de cacheline aproximadamente el 5% del tiempo para cachelines de 64 bytes, el 10% para las de 32 bytes y el 20% para las de 16 bytes.

  • Puede haber gastos generales de ejecución adicionales para algunas instrucciones sobre datos desalineados, incluso si están dentro de una línea de caché. Se habla de esto en Intel sitio web para algunas instrucciones de SSE.

  • Si está definiendo las estructuras usted mismo, puede tener sentido mirar la lista de todos los campos de datos struct para que se reduzca la sobrecarga de relleno o, alternativamente, revisar si es mejor activar o desactivar el empaque para una estructura en particular.

  • En MIPS y muchas otras plataformas usted no tiene la opción y debe align - kernel exception si no lo hace!!

  • La alineación también puede importar extra especialmente para usted si está haciendo E/S en el bus o utilizando operaciones atómicas como incremento / decremento atómico o si desea ser capaz de portar su código a no-Intel.

  • Solo en Intel (!) código, una práctica común es definir un conjunto de estructuras empaquetadas para la red y el disco, y otro conjunto acolchado para la memoria y tener rutinas para convertir datos entre estos formatos (también considere "endianidad" para los formatos de disco y red).

 7
Author: martinr,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-01-28 17:30:51

Además de la respuesta de jldupont, algunas arquitecturas tienen instrucciones de carga y almacenamiento (las que se usan para leer/escribir desde y hacia la memoria) que solo operan en límites alineados con palabras, por lo que para cargar una palabra no alineada desde la memoria se necesitarían dos instrucciones de carga, una instrucción de cambio y luego una instrucción de máscara, ¡mucho menos eficiente!

 3
Author: James,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-01-05 13:34:17