Todo procesador cuando ejecuta una instrucción la ha de localizar en memoria para poderla ejecutar. El tiempo de búsqueda de la misma y los datos a manipular es crucial para sacar el mayor rendimiento posible. ¿Y cuál es este? El realizar la mayor cantidad de instrucciones en el menor tiempo posible, y una forma de conseguirlo es recortar el tiempo de acceso a la memoria y en ello es clavé la caché TLB.
Si miráis las diapositivas de las diferentes arquitecturas de procesadores, y de forma independiente a la marca del mismo, veréis que aparece un tipo de caché titulada caché TLB. Pues bien, este tipo de caché al igual que la convencional está relacionada con el acceso de la CPU a la memoria RAM, pero al contrario que la convencional no tiene que ver con el acceso a los datos, sino a la búsqueda y localización de los mismos.
TLB, Translate Lookaside Buffer
Cuando un procesador necesita acceder a la RAM del sistema lo que hace es generar una dirección virtual que indica la posición del dato en la memoria desde el punto de vista de la CPU, la cual no tiene una coincidencia con la dirección física de memoria del sistema.
La unidad encargada de hacer el traslado de un tipo de dirección a otra es la MMU e inicialmente estas unidades lo que hacen es guardar en una parte de la RAM a la que accedían directamente para hacer el traslado de direcciones virtuales. Claro está que hemos de tener en cuenta que una dirección virtual se compone de tres componentes:
- Página, de tamaño fijo, que almacena unos cuantos kilobytes de memoria.
- Tabla de páginas, es obviamente, una tabla que almacena diferentes páginas.
- Directorio de páginas, la cual engloba todas las Page Tables.
Así pues cuando la MMU realiza la conversión de direcciones virtuales a físicas lo que hace es consultar estos tres apartados, estando el Page Directory en la unidad de almacenamiento y por tanto más alejada del procesador, pero este no se consulta, ya que la Page Table es copiada en la RAM. Pues bien, la caché TLB lo que almacena es el traslado de direcciones correspondiente a la página actual en la que se encuentra mirando la CPU en cada momento.
El motivo por el cual primero se busca la dirección de memoria es por el hecho de que en el caso de que la caché TLB no disponga de la dirección se preguntará por la misma a la Page Table en memoria. Dicho de otra manera, un procesador no pregunta primero sobre una instrucción o dato en concreto, sino su localización. El otro motivo tiene que ver con el hecho que siempre en RAM se busca donde se encuentra la información, no la información en sí.
El proceso de funcionamiento de la caché TLB
De manera muy simplificada ocurre de la siguiente manera:
- La CPU hace una petición a una dirección de memoria.
- La MMU haciendo uso de la caché TLB genera una dirección física.
- Se pregunta al primer nivel de la caché si existen los datos de esa dirección física de la RAM en su interior, si los datos se encuentran entonces se marca como un «hit» y se modifica o devuelve el dato a la CPU según sea necesario.
- En el caso de que la dirección buscada no se encuentre en el TLB entonces se procede a acceder a la Page Table en la RAM y se copia la siguiente página en el TLB para ver si la dirección se encuentra ahí.
Al igual que con las cachés y por tanto para acelerar el acceso a los datos nos podemos encontrar con varios niveles de TLB, por ejemplo y en algunos diseños avanzados de CPU existe un TLB por cada nivel de la jerarquía de cachés. En el caso de otros diseños lo que hacen es tener un TLB para datos y otro para instrucciones y los más complejos combinan ambos conceptos en la arquitectura.
El TLB es por tanto una memoria que almacena las últimas traducciones realizadas por la MMU, en la que por un lado almacena el direccionamiento virtual y por el otro lado el físico. Gracias a ello la MMU no tiene que volver a realizar el traslado de nuevo y le es tan sencillo como consultar esta pequeña caché para saber si dicha dirección se encuentra en la página actual.
Cachés virtuales, TLB y multinúcleo
El problema con el método que os hemos explicado es que por cada petición a memoria que se haga es necesario hacer un acceso a la caché TLB y muchas veces esto es contraproducente dado que aumentamos la latencia. ¿La solución a ello? La llamada caché virtual, la cual al contrario de lo que dice su nombre no es una caché inexistente y por tanto abstracta, sino que es una caché donde la información que contiene no está organizada según su direccionamiento físico sino por su direccionamiento virtual, por lo que el traslado de direcciones se ejecuta después de la búsqueda del dato en dicha caché y solo si se produce un «miss», que significa que el dato no se encuentra en la caché virtual.
El problema viene cuando dos hilos de ejecución de la CPU tienen cada uno de ellos su propio espacio de direccionamiento virtual, totalmente separado a nivel de direcciones físicas, pero con las mismas direcciones virtuales. De tal manera que si dos aplicaciones quieren utilizar la misma dirección virtual lo que harán será preguntar a la caché virtual si existe dicha dirección virtual en su interior aunque el contenido que se busca sea distinto. Lo cual es fatídico en un entorno multitarea como es el 100% de los casos en la actualidad en el que por motivos de seguridad todos los programas tienen su propio direccionamiento de memoria virtualizado.
La caché virtual no es común en todos los procesadores y supone una doble comprobación, lo que hace que al final se tenga que hacer uso del TLB para realizar el traslado de las instrucciones por parte de la MMU eliminando su ventaja. Todo esto elimina por completo la ventaja de tener una caché virtual, pero la mayoría de TLB contemporáneos hacen uso de algún tipo de caché virtual en su interior desde la que hacen la comprobación antes de realizar el traslado correspondiente, ganando rendimiento en el proceso. Dicho de otra manera, la mayoría de Trasnslate Lookaside Buffer que hay en las CPU a día de hoy integran el funcionamiento de la caché virtual.