2009-01-20 5 views
21

¿Cómo se puede disminuir el número de posibles fallas de caché al diseñar un programa en C++?fallas de caché decrecientes a través de un buen diseño

¿Las funciones de alineación ayudan cada vez? ¿o es bueno solo cuando el programa está limitado por la CPU (es decir, el programa está orientado a computación y no orientado a E/S)?

Respuesta

31

Aquí hay algunas cosas que me gustan al trabajar con este tipo de código.

  • Considere si desea "estructuras de matrices" o "matrices de estructuras". Lo que quiere usar dependerá de cada parte de los datos.
  • Trate de mantener las estructuras en múltiplos de 32 bytes para que empaqueten las líneas de caché de manera uniforme.
  • Particiona tus datos en elementos fríos y calientes. Si tiene una matriz de objetos de la clase o, y usa ox, oy, oz con frecuencia, pero solo ocasionalmente necesita acceder a oi, oj, ok, entonces considere poner ox, oy y oz juntos y mover el i, j, y k partes a una estructura de datos axilar paralela.
  • Si tiene matrices multidimensionales de datos, entonces con los diseños habituales de orden de filas, el acceso será muy rápido cuando se escanea a lo largo de la dimensión preferida y muy lento a lo largo de los demás. Asignarlo a lo largo de un space-fillingcurve en su lugar ayudará a equilibrar las velocidades de acceso al atravesar en cualquier dimensión. (Las técnicas de bloqueo son similares, son solo orden Z con una raíz más grande.)
  • Si debe incurrir en una falta de caché, intente hacer todo lo posible con esa información para amortizar el costo.
  • ¿Estás haciendo algo multihilo? Tenga cuidado con la ralentización de los protocolos de coherencia de caché. Bandejas de pad y pequeños contadores para que estén en líneas de caché separadas.
  • SSE en Intel proporciona algunos intrínsecos de captación previa si sabe a qué accederá con la suficiente antelación.
+1

+1. La idea de la curva de Hilbert es muy novedosa, ¿de dónde sacaste eso? ¿Es el tiempo necesario para convertir entre las coordenadas de la curva de hilbert y las coordenadas de la matriz estándar que realmente vale la eficacia de la memoria caché, o tal vez solo vale la pena si está realizando conversiones de coordenadas en una dirección, pero no en la otra? –

2

Deje que la CPU realice una captación de datos de manera eficiente. Por ejemplo, puede disminuir el número de memoria caché no procesa matrices multidimensionales por filas en lugar de por columnas, desenrollar bucles, etc.

Este tipo de optimización depende de la arquitectura del hardware, por lo que es mejor utilizar algún tipo de generador de perfiles específico de plataforma como Intel VTune para detectar posibles problemas con la memoria caché.

7

Hay un video muy bonito por Herb Sutter que menciona este tema here

para los datos de las operaciones con destino

  1. utilizar matrices & vectores más listas, mapas & conjuntos

  2. proceso por el filas sobre columnas

+0

Buena conversación de Sutter allí. Las diapositivas están disponibles aquí, lo que es bueno tener al lado del video ya que su calidad es un poco horrible. http://www.nwcpp.org/Downloads/2007/Machine_Architecture_-_NWCPP.pdf – Zoomulator

1

Evite usar memoria dinámica cuando no sea necesario. Usar nuevos, eliminar, punteros inteligentes, etc., tiende a extender los datos de su programa a través de la memoria. Eso no es bueno. Si puede mantener la mayoría de sus datos en conjunto (al declarar objetos en la pila, por ejemplo), su caché seguramente funcionará mucho mejor.

2

Las funciones de alineación pueden dañar la caché de instrucciones. Y si la memoria no se puede vincular, es poco probable que haga mucha (si la hay) diferencia.

Como siempre, cualquier optimización debe ser informada por perfiles en lugar de corazonadas. Sin mencionar que tendrá que comprender lo que el generador de perfiles le está diciendo, lo que implica familiaridad con el lenguaje ensamblador y las características particulares de la plataforma para la que está optimizando.

Un poco viejo ahora, pero el "Libro negro de programación de gráficos" de Mike Abrash todavía tiene muchos buenos consejos generales.

2

Además, si realiza C++ y multihebra, debe tener en cuenta el uso compartido falso, la localidad y el calor de los datos en la memoria caché de cada procesador. Eso puede hacer una gran diferencia. También especialmente en la computación multiproceso, las cosas de manera LIFO son más eficientes que la computación de una manera FIFO, pero también son válidas en la arquitectura de un solo procesador.

Cuestiones relacionadas