Estrategias de predicción dinámicas. Las técnicas que vamos a ver ahora para predicción de saltos se basan en información conocida sólo en tiempo de ejecución. Dos estructuras son necesarias para realizar una predicción estática: Branch History Table (BHT) o Tabla de Historia de los Saltos. Tabla que contiene información de lo sucedido en cada salto las últimas veces que fue tomado. A partir de esta información se predice si el salto será tomado o no. Branch Target Address Cache (BTAC) o Tabla de Direcciones de Salto. Como su nombre indica es una tabla donde se almacena las direcciones de salto destino de los últimos saltos evaluados. De esta forma, si un salto es predicho como tomada, se mira si esta en la tabla, y si es así, se obtiene la dirección destino. La base de la mayoría de los predictores dinámicos es el llamado Branch Target Buffer, que no es más que una tabla que combina los dos anteriores. Cada entrada posee bits para realizar la predicción y la posible dirección de salto. A partir de esta estructura básica se han diseñado muchos predictores, desde los más sencillos que veremos aquí, hasta muy sofisticados que utilizan dos niveles de predicción. Últimamente se están utilizando los predictores híbridos que combinan tanto técnicas estáticas como dinámicas, eligiendo en cada momento la que de un mejor resultado. Otro aspecto muy importante son las penalizaciones que puede sufrir un procesador por el hecho de equivocarse en una predicción. Se pueden presentar dos tipos de Penalizaciones: 1. Misfetch penalty o penalización por búsqueda errónea: los procesadores leen una instrucción de la cache realizando un búsqueda de instrucción, a continuación, si la instrucción es de salto, la evaluación del salto se realizará en el segmento de decodificación. Por ello, si nos equivocamos en la predicción, deberemos anular la instrucción e introducir una o más burbujas para vaciar los cauces de segmentación e iniciar la ejecución de una nueva instrucción en la dirección real de salto. 2. Mispredict penalty o penalización por predicado erróneo: sabemos que los procesadores para mantener alto el rendimiento realizan cargas especulativas de instrucciones en la memoria cache de instrucciones, correspondientes al posible bloque destino del salto. Si se comprueba que ha habido un fallo en la predicción, el procesador además de realizar un vaciado del cauce segmentado y restaurar los valores de los registros, deberá leer un nuevo predicado, es decir, deberá cargar la cache de Instrucciones o en su defecto, el buffer de lectura de instrucciones con nuevas instrucciones procedentes de la dirección de salto ya evaluada. Para comparar diversas arquitecturas de predicción dinámica de saltos, nos fijaremos en un parámetro conocido como la predicción de aciertos, es decir, el porcentaje de saltos que han sido bien predichos. Para las técnicas de predicción también será útil almacenar información general de los programas, del estilo tengo pocas instrucciones de saltos que se ejecutan muchas veces o tengo muchos saltos que se ejecutan pocas veces, pues esto influirá mucho en el rendimiento de las predicciones. Vicente Arnau Llombart 1 30/11/2006
A continuación se enumeran las 5 técnicas más importantes utilizadas en la predicción dinámica de los saltos: 1. Branch Target Buffer. Buffer de salto. Con información de la historia de cada salto. 2. Predictores basados en dos niveles de historia. 3. Predicción de la siguiente línea de cache a leer. 4. Predictores basados en el camino recorrido por el programa. 5. Predictores híbridos. Que combinan varias técnicas, incluso las estáticas. No tenemos tiempo para analizar con detalle cada una de estas técnicas, pero será suficiente con que veamos la primera de estas técnicas dinámicas para entender su funcionamiento. Buffer de predicción de saltos. Vamos a ver una versión muy sencilla, en la cual el buffer está formado por una pequeña memoria indexada con los bits menos significativos de la dirección de la instrucción de salto. Además contiene un bit para indicar si el salto fue tomado o no en su última evaluación. Puede suceder que una nueva instrucción de salto tenga sus bits de menor peso de su dirección coincidentes con otra instrucción de salto ya evaluada. No importa, se procede como si nada pasara y la predicción de la anterior instrucción y su dirección de salto son tomadas como buenas. En caso de que se produzca un fallo, se invertirá no solo el bit de predicción sino también se corregirá la dirección de salto del buffer de predicción. Con un solo bit, cada vez que estemos analizando una instrucción condicional de final de bucle, al cometer un error en su predicción, este será doble: al suponer que salto y no salta (última iteración del bucle) y la siguiente vez que lo evaluemos que lo hacemos a no salta y nos equivocaremos también pues si que saltará. Ejemplo: Sea el siguiente fragmento de programa en ensamblador. bubu: ADDI R8,R0,10 ADD R4, R5, R6 XOR R12, R4, R0... ADDI R8,R0,-1 bnez R8, bubu... ; salta si no es igual a cero Este bucle se repite 10 veces, y si se ejecuta muchas veces, ocurrirá que la primera y la última vez será evaluado erróneamente. Vicente Arnau Llombart 2 30/11/2006
Pero es fácil mejorar la predicción para estos casos, basta con utilizar cuatro posibles estados de predicción, es decir 2 bits en vez de uno. 11: efectivo con alta probabilidad. 10: efectivo probable. 01: no efectivo probable. 00: no efectivo con alta probabilidad. Tendremos un autómata finito con cuatro estados, de forma que para pasar de una predicción de salto a una de no salto, al menos se han de producir dos errores consecutivos. Veamos la forma que tendrá este autómata en la figura siguiente: Otra forma de realizar este esquema de predicción es utilizar como dirección de entrada al buffer toda la dirección de la instrucción de salto, en vez de solo sus bits menos significativos. Esto aumenta el rendimiento. Vicente Arnau Llombart 3 30/11/2006
Vicente Arnau Llombart 4 30/11/2006
;*********************************************** ; CLASE_01.S : Z(n) = Y(n) + CTE ;*********************************************** ; vector y.data 0X2000 y:.word 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ; vector z : 10 elementos z:.space 40 cte:.word 7.text 0x1000 start: addi r1, r0, y addi r2, r0, z loop: lw r4, cte addi r10,r1,#40 lw r20, 0(r1) add r21, r4, r20 sw 0(r2),r21 add r1,r1,#4 add r2,r2,#4 sub r11,r10,r1 bnez r11,loop trap #0 ; r1 = direccion de y ; r2 = direccion de z ; r4 = cte ; 10 elementos ; fin de programa 000 10 001 10 010 0x00001010 011 10 100 10 101 10 110 10 111 10 Vicente Arnau Llombart 5 30/11/2006
Vicente Arnau Llombart 6 30/11/2006
Vicente Arnau Llombart 7 30/11/2006
Vicente Arnau Llombart 8 30/11/2006
Vicente Arnau Llombart 9 30/11/2006