La contaminación de la memoria caché describe situaciones en las que un programa informático en ejecución carga datos en la memoria caché de la CPU de forma innecesaria, [1] lo que provoca que otros datos útiles se expulsen de la memoria caché y pasen a niveles inferiores de la jerarquía de memoria , lo que degrada el rendimiento. Por ejemplo, en un procesador multinúcleo , un núcleo puede reemplazar los bloques obtenidos por otros núcleos en la memoria caché compartida, o los bloques obtenidos previamente pueden reemplazar los bloques obtenidos a demanda de la memoria caché.
Consideremos la siguiente ilustración:
T[0] = T[0] + 1; para i en 0.. tamaño de (CACHE) C[i] = C[i] + 1; T[0] = T[0] + C[tamañode(CACHE)-1];
(Las suposiciones aquí son que el caché se compone de un solo nivel, está desbloqueado, la política de reemplazo es pseudo-LRU , todos los datos se pueden almacenar en caché, la asociatividad establecida del caché es N (donde N > 1) y, como máximo, un registro de procesador está disponible para contener los valores del programa).
Justo antes de que comience el bucle, se obtendrá T[0] de la memoria y se colocará en la caché, y su valor se actualizará. Sin embargo, a medida que se ejecuta el bucle, debido a que la cantidad de elementos de datos a los que hace referencia el bucle requiere que toda la caché se llene hasta su capacidad máxima, el bloque de caché que contiene T[0] debe ser desalojado. Por lo tanto, la próxima vez que el programa solicite que se actualice T[0], la caché falla y el controlador de caché debe solicitar al bus de datos que extraiga nuevamente el bloque de caché correspondiente de la memoria principal .
En este caso, se dice que la caché está "contaminada". Si se cambia el patrón de acceso a los datos, colocando la primera actualización de T[0] entre el bucle y la segunda actualización, se puede eliminar la ineficiencia:
para i en 0.. tamaño de (CACHE) C[i] = C[i] + 1; T[0] = T[0] + 1; T[0] = T[0] + C[tamañode(CACHE)-1];
Además de la reestructuración del código mencionada anteriormente, la solución a la contaminación de la memoria caché es garantizar que solo se almacenen en ella datos de alta reutilización. Esto se puede lograr mediante el uso de instrucciones especiales de control de la memoria caché , compatibilidad con el sistema operativo o compatibilidad con el hardware.
Ejemplos de instrucciones de hardware especializadas incluyen "lvxl" proporcionada por PowerPC AltiVec . Esta instrucción carga un valor de 128 bits de ancho en un registro y marca el bloque de caché correspondiente como "menos usado recientemente", es decir, como el candidato principal para la expulsión cuando sea necesario expulsar un bloque de su conjunto de caché. Para usar apropiadamente esa instrucción en el contexto del ejemplo anterior, los elementos de datos a los que hace referencia el bucle tendrían que cargarse utilizando esta instrucción. Cuando se implementa de esta manera, no se produciría contaminación de la caché, ya que la ejecución de dicho bucle no causaría la expulsión prematura de T[0] de la caché. Esto se evitaría porque, a medida que progresara el bucle, las direcciones de los elementos en C se asignarían a la misma vía de caché, dejando los datos realmente más antiguos (pero no marcados como "menos usados recientemente") intactos en la(s) otra(s) vía(s). Solo los datos más antiguos (no pertinentes para el ejemplo dado) se expulsarían de la caché, de la que T[0] no es miembro, ya que su actualización ocurre justo antes del inicio del bucle.
De manera similar, utilizando el soporte del sistema operativo (OS), las páginas en la memoria principal que corresponden a la matriz de datos C se pueden marcar como "almacenamiento en caché inhibido" o, en otras palabras, no almacenables en caché. De manera similar, a nivel de hardware, se pueden utilizar esquemas de omisión de caché que identifican datos de baja reutilización según el patrón de acceso del programa y los omiten de la caché. Además, la caché compartida se puede particionar para evitar interferencias destructivas entre aplicaciones en ejecución. La desventaja de estas soluciones es que los esquemas basados en el SO pueden tener una gran latencia que puede anular la ganancia alcanzable mediante la prevención de la contaminación de la caché (a menos que la región de memoria no haya sido almacenable en caché desde el principio), mientras que las técnicas basadas en hardware pueden no tener una visión global del flujo de control del programa y el patrón de acceso a la memoria .
El control de la contaminación de la memoria caché ha ido cobrando importancia debido a que las penalizaciones causadas por el llamado " muro de memoria " siguen aumentando. Los fabricantes de chips siguen ideando nuevos trucos para superar la latencia relativa cada vez mayor entre la memoria y la CPU. Lo hacen aumentando el tamaño de la memoria caché y proporcionando formas útiles para que los ingenieros de software controlen la forma en que los datos llegan y permanecen en la CPU. El control de la contaminación de la memoria caché es uno de los numerosos dispositivos disponibles para el programador (principalmente de sistemas integrados). Sin embargo, también se utilizan otros métodos, la mayoría de los cuales son propietarios y muy específicos del hardware y de la aplicación.