c++ - velocidad - ventajas memoria cache
¿Cómo marcar algunos rangos de memoria como no cacheable desde C++? (4)
Estaba leyendo la wikipedia en el caché de la CPU aquí: http://en.wikipedia.org/wiki/CPU_cache#Replacement_Policies
Marcar algunos rangos de memoria como no almacenables en caché puede mejorar el rendimiento, al evitar el almacenamiento en caché de regiones de memoria a las que rara vez se accede. Esto evita la sobrecarga de cargar algo en el caché, sin tener que reutilizarlo.
Ahora, he estado leyendo y aprendiendo sobre cómo escribir programas con un mejor rendimiento de caché (consideraciones generales, generalmente no específicas de C ++), pero no sabía que el código de alto nivel puede interactuar con el comportamiento del almacenamiento en caché de la CPU explícitamente. Entonces, mi pregunta, ¿hay una manera de hacer lo que cité de ese artículo, en C ++?
Además, agradecería recursos sobre cómo mejorar el rendimiento del caché específicamente en C ++, incluso si no usan ninguna función que se relacione directamente con los cachés de la CPU. Por ejemplo, me pregunto si el uso de niveles excesivos de indirección (por ejemplo, un contenedor de punteros a contenedores de punteros) puede dañar el rendimiento del caché.
Algunas plataformas tienen soporte para cargas no temporales y almacenes que evitan los cachés. Eso evita el costo de perder lo que estaba previamente en el caché. Por lo general, no están disponibles para idiomas de nivel superior directamente y usted tiene que escribir su propio código de ensamblaje. Pero como incluso la existencia de la memoria caché es específica de la plataforma, la existencia de formas de controlar el uso de la memoria caché también es específica de la plataforma. SSE4 incluye cargas no temporales .
Como programador, que generalmente trata con plataformas x86 distintas de Windows, este artículo sobre intrínsecos GCC x86 y x86-64 es probablemente el más útil.
Una regla de oro para optimizar los accesos al caché es: agrupar las cargas y almacenarlas en la misma dirección . Por ejemplo, el siguiente código:
for (size_t i=0; i<A.size(); ++i)
B[i] = func1(A[i]);
for (size_t i=0; i<A.size(); ++i)
C[i] = func2(A[i]);
Se puede optimizar para acceder al caché de manera más eficiente:
for (size_t i=0; i<A.size(); ++i) {
B[i] = func1(A[i]); // A[i] is fetched to the cache
C[i] = func2(A[i]); // Good chance that A[i] remains in the cache
}
Las CPU modernas son bastante buenas para predecir el acceso a la memoria con patrones regulares en los bucles, y son capaces de obtener la memoria en caché y acelerar la ejecución. Por lo tanto, otra regla de oro sería: preferir usar std :: vector y std :: array sobre otros contenedores .
En Windows, puede usar VirtualProtect(ptr, length, PAGE_NOCACHE, &oldFlags)
para configurar el comportamiento de almacenamiento en caché de la memoria para evitar el almacenamiento en caché.
Con respecto a demasiadas conexiones indirectas: sí, pueden dañar el rendimiento de la memoria caché, si accede a diferentes partes de la memoria con mucha frecuencia (que es lo que suele ocurrir). Sin embargo, es importante tener en cuenta que si no hace referencia sistemáticamente al mismo conjunto de, por ejemplo, 8 bloques de memoria y solo el 9º bloque difiere, entonces generalmente no habrá una diferencia, ya que los 8 bloques se almacenarán en caché después del primer acceso. .
- Creo que esta es una buena idea : lo que todo programador debe saber sobre la memoria .
- This es otra pregunta sobre SO que puede ayudar.
- También hay un enlace here que habla sobre la función
pgprot_noncached
dedrivers/char/mem.c
en sistemas Linux. Aquí está la source .