utilizar todos toda procesador nucleos microprocesador memoria los como caracteristicas cache bueno activar c performance memory memory-management alignment

todos - microprocesador



AlineaciĆ³n de memoria en procesadores modernos? (4)

A menudo veo código como el siguiente cuando, por ejemplo, representa un mapa de bits grande en la memoria:

size_t width = 1280; size_t height = 800; size_t bytesPerPixel = 3; size_t bytewidth = ((width * bytesPerPixel) + 3) & ~3; /* Aligned to 4 bytes */ uint8_t *pixelData = malloc(bytewidth * height);

(es decir, un mapa de bits asignado como un bloque contiguo de memoria que tiene un bytewidth de bytes alineado a un cierto número de bytes, más comúnmente 4.)

Un punto en la imagen se da a través de:

pixelData + (bytewidth * y) + (bytesPerPixel * x)

Esto me lleva a dos preguntas:

  1. ¿Alinear un buffer como este tiene un impacto en el rendimiento de los procesadores modernos? ¿Debo preocuparme por la alineación, o el compilador manejará esto?
  2. Si tiene un impacto, ¿podría alguien señalarme un recurso para encontrar la alineación ideal de bytes para varios procesadores?

Gracias.


Depende de muchos factores. Si solo está accediendo a los datos de píxel de un byte a la vez, la alineación no cambiará la mayoría de las veces. Para leer / escribir un byte de datos, a la mayoría de los procesadores no les importará si ese byte está en un límite de 4 bytes o no.

Sin embargo, si está accediendo a los datos en unidades más grandes que un byte (por ejemplo, en unidades de 2 bytes o 4 bytes), definitivamente verá los efectos de alineación. Para algunos procesadores (por ejemplo, muchos procesadores RISC), es completamente ilegal acceder a datos no alineados en ciertos niveles: intentar leer una palabra de 4 bytes de una dirección que no está alineada con 4 bytes generará una excepción de acceso a datos (o excepción de almacenamiento de datos) ) en un PowerPC, por ejemplo.

En otros procesadores (por ejemplo, x86), se permite el acceso a direcciones desalineadas, pero a menudo viene con una penalización de rendimiento oculto. Las cargas / tiendas de memoria a menudo se implementan en microcódigo, y el microcódigo detectará el acceso no alineado. Normalmente, el microcódigo obtendrá la cantidad correcta de 4 bytes de la memoria, pero si no está alineado, tendrá que buscar dos ubicaciones de 4 bytes de la memoria y reconstruir la cantidad de 4 bytes deseada de los bytes correspondientes de las dos ubicaciones. La obtención de dos ubicaciones de memoria es obviamente más lenta que una.

Sin embargo, eso es solo para cargas simples y tiendas. Algunas instrucciones, como las de los conjuntos de instrucciones MMX o SSE, requieren que sus operandos de memoria se alineen correctamente. Si intenta acceder a la memoria desalineada usando esas instrucciones especiales, verá algo así como una excepción de instrucción ilegal.

Para resumir, realmente no me preocuparía demasiado acerca de la alineación a menos que esté escribiendo un código súper crítico para el rendimiento (por ejemplo, en el montaje). El compilador te ayuda mucho, por ejemplo, rellenando las estructuras para que las cantidades de 4 bytes estén alineadas en los límites de 4 bytes, y en x86, la CPU también te ayuda cuando se trata de accesos no alineados. Dado que los datos de píxeles con los que lidias están en cantidades de 3 bytes, casi siempre estarás haciendo accesos de un solo byte de todos modos.

Si decide que desea acceder a los píxeles en los accesos singulares de 4 bytes (en oposición a los 3 accesos de 1 byte), sería mejor usar píxeles de 32 bits y tener cada píxel individual alineado en un límite de 4 bytes. Alinear cada fila a un límite de 4 bytes, pero no a cada píxel, tendrá poco o ningún efecto.

Según su código, supongo que está relacionado con la lectura del formato de archivo de mapa de bits de Windows: los archivos de mapa de bits requieren que la longitud de cada línea de exploración sea un múltiplo de 4 bytes, por lo que la configuración de los almacenamientos intermedios de datos de píxel con esa propiedad puede leer todo el mapa de bits de una sola vez en su búfer (por supuesto, todavía tiene que lidiar con el hecho de que las líneas de exploración se almacenan de abajo hacia arriba en vez de arriba hacia abajo y que los datos de píxeles son BGR en lugar de RGB). Sin embargo, esto no es una gran ventaja, no es mucho más difícil de leer en el mapa de bits una línea de exploración a la vez.


La alineación del buffer tiene un impacto. La pregunta es: ¿es un impacto significativo? La respuesta puede ser altamente específica de la aplicación . En las arquitecturas que no admiten de forma nativa el acceso no alineado, por ejemplo, el 68000 y el 68010 (el 68020 agrega acceso desalineado) es realmente un problema de rendimiento y / o mantenimiento ya que la CPU generará fallas o puede interceptar a un controlador para realizar un acceso no alineado .

Se puede estimar la alineación ideal para varios procesadores: la alineación de 4 bytes es apropiada para arquitecturas con una ruta de datos de 32 bits. Alineación de 8 bytes para 64 bits. Sin embargo, el almacenamiento en caché L1 tiene un efecto . Para muchas CPU esto es de 64 bytes, aunque sin duda cambiará en el futuro.

Una alineación demasiado alta (es decir, ocho bytes donde solo se necesitan dos bytes) no causa ineficiencia en el rendimiento para ningún sistema más estrecho, incluso en un microcontrolador de 8 bits. Simplemente desperdicia (potencialmente) unos pocos bytes de almacenamiento.

Su ejemplo es bastante peculiar: los elementos de 3 bytes tienen un 50% de posibilidades de desalinearse individualmente (a 32 bits), por lo que alinear el búfer parece inútil, al menos por razones de rendimiento. Sin embargo, en el caso de una transferencia masiva de todo, optimiza el primer acceso. Tenga en cuenta que un primer byte sin alinear también puede tener un impacto en el rendimiento en la transferencia a un controlador de video.


Sí, la alineación tiene un impacto en el rendimiento de los procesadores modernos, digamos x86. En general, las cargas y las existencias de datos ocurren en los límites naturales de alineación; si obtiene un valor de 32 bits en un registro, será más rápido si ya está alineado en un límite de 32 bits. Si no lo es, el x86 se "ocupará de ti", en el sentido de que la CPU seguirá cargando, pero tomará un número significativamente mayor de ciclos para hacerlo, porque habrá disputas internas para " volver a alinear "el acceso.

Por supuesto, en la mayoría de los casos, esta sobrecarga es trivial. Las estructuras de datos binarios a menudo se empaquetan juntas de forma desalineada para el transporte a través de la red o para la persistencia en el disco, y los beneficios de tamaño del almacenamiento empaquetado superan cualquier impacto de rendimiento de operar ocasionalmente con estos datos.

Pero particularmente con grandes almacenamientos intermedios de datos uniformes a los que se accede aleatoriamente y donde el rendimiento agregado es realmente importante, como en el buffer de píxeles anterior, mantener alineadas las estructuras de datos puede ser beneficioso.

Tenga en cuenta que en el caso del ejemplo anterior, solo se alinea cada "línea" de datos de píxeles. Los píxeles en sí todavía tienen 3 bytes de longitud y, a menudo, están desalineados dentro de las "líneas", por lo que no hay mucho beneficio aquí. Hay formatos de textura, por ejemplo, que tienen 3 bytes de datos reales por píxel y, literalmente, desperdician un byte adicional en cada uno para mantener los datos alineados.

Hay más información general aquí: http://en.wikipedia.org/wiki/Data_structure_alignment

(Las características específicas varían entre las arquitecturas, tanto en lo que son las alineaciones naturales, si la CPU maneja cargas / tiendas no alineadas automáticamente, y en qué tan costosas terminan siendo. En los casos donde la CPU no maneja el acceso mágicamente, a menudo el compilador / C runtime hará lo posible por hacer este trabajo por usted).


  • ¿Alinear un buffer como este tiene un impacto en el rendimiento de los procesadores modernos?

Sí. Por ejemplo, si memcpy está optimizado usando instrucciones SIMD (como MMX / SSE) algunas operaciones serán más rápidas con la memoria alineada. En algunas arquitecturas hay instrucciones (de procesador) que fallan si los datos no están alineados, por lo tanto, es posible que algo funcione en su máquina pero no en otra.

Con los datos alineados también hace un mejor uso de las memorias caché de la CPU.

  • ¿Debo preocuparme por la alineación, o el compilador manejará esto?

Debería preocuparme por la alineación cuando uso memoria dinámica y el compilador no puede manejar esto (ver la respuesta a este comentario).

Para otras cosas en tu código, tienes la bandera de malignidad y el atributo alineado para jugar.