Ejecución desordenada

En los primeros microprocesadores, cada instrucción ocupaba toda la atención del chip, teniendo que terminar su ejecución antes de pasar a la siguiente instrucción del program, y si necesitaba datos de la memoria, primero tenía que leerlos antes de poder ejecutarse. Con el 8086/8088, Intel dividió el chip en dos partes que podían funcionar independientemente. La primera parte se ocupaba de las operaciones de memoria tales como leer la siguiente instrucción a ejecutar y leer los datos necesarios para los cálculos. Mientras que la segunda parte se encargaba de ejecutar las instrucciones. Como cada parte era independiente del otro, se obtenía más trabajo hecho cada vez que el reloj hacía "tick".

En el Pentium 4, se continúa la idea de tener varias secciones independientes. La primera sección (front-end) se encarga de leer de memoria y decodificar las instrucciones de los programas. Esto se hace necesario porque, aunque eficiente en memoria, las instrucciones de la familia x86 (o IA-32 como lo llama Intel) son complicadas. El resultado de esta decodificación son micro-operaciones. Cada instrucción IA-32 se traduce a uno o más micro-ops que son almacenados en el Execution Trace Cache. Estas secuencias de micro-ops son utilizados para alimentar la siguiente sección, la de ejecución.

La sección de ejecución, o Out-of-order core como lo llama Intel, se encarga de ejecutar las micro-ops. Para esto dispone de varias unidades de ejecución con funciones especializadas:

El nombre "out-of-order core" puede sonar extraño pero se debe a que las micro-ops no se ejecutan necesariamente en el mismo orden con que fueron decodificadas. A primera vista, esto no suena lógico ni tiene sentido. Pero pensemos un poco. Supongamos que tenemos la siguiente secuencia de instrucciones:

(1) b = 3 * 27

(2) c = b * b - 100

(3) a = b * c

(4) e = (70 - 32) * 5 / 9

Fijémonos que la tercera instrucción no se puede ejecutar hasta que no estén disponibles los valores b y c, o sea, tiene que esperar a que se ejecuten las primeras dos instrucciones. Caso muy diferente es la cuarta instrucción que no depende de las tres instrucciones anteriores. Las secuencias de instrucciones (4)(1)(2)(3), (1)(4)(2)(3), (1)(2)(4)(3) y (1)(2)(3)(4) producen el mismo resultado. Por tanto, cualquiera de estas secuencias puede funcionar.

Lo mismo pasa con el "out-of-order core". El Execution Trace Cache puede mandar hasta 3 micro-ops por cada tick del reloj, pero no necesariamente son atendidos inmediatamente. Los que ya tienen todo lo necesario pasan a la unidad de ejecución correspondiente. Con esto, las unidades de ejecución se mantienen ocupadas, realizando un trabajo en vez de esperar a que los micro-ops estén listos.

Pero, si la ejecución no respeta el orden del programa, entonces ¿para qué nos sirve un procesador así? Precisamente el trabajo de la tercera sección del procesador es el de ordenar los resultados, de manera que lo desordenado por la sección anterior ahora aparece tal y como fué especificado en el programa.

Y para complicar un poco más el panorama, el Pentium 4 también es capaz de ejecución especulativa. Como tiene un pipeline con muchos pasos, un salto condicional es un acontecimiento catastrófico pero desafortunadamente muy común. Un salto es una interrupción del flujo normal de las instrucciones, haciendo que el procesador continúe en otro punto del programa ("salta" a otra parte del programa). Un salto condicional es una instrucción (más bien una familia de instrucciones) que realiza el salto si se cumple una condición determinada con anterioridad. El problema es que el procesador no sabe si se realizará el salto o no hasta que se evalúa la condición y si esto ocurre en la mitad del pipeline, es posible que tenga que borrar el pipeline y comenzar de nuevo en el nuevo punto de ejecución, perdiendo tiempo y trabajo.

Para evitar interrumpir el pipeline, el procesador trata de adivinar si se tomará el salto o no, y seguir leyendo/decodificando/ejecutando las instrucciones de acuerdo a su escogencia. Claro que no toma la decisión al azar, sino que utiliza circuitos adicionales que guardan la historia de estos saltos y un algoritmo (no revelado) que lo ayuda a elegir. Además, los programadores que construyen los compiladores tienen que seguir unas reglas que Intel ha especificado para ayudar al procesador a realizar una decisión inteligente.

<<<< Primera página
^^^^ Página principal
Aprovechando los recursos >>>>

Última actualización: 30/01/2003