Pipeline - un método de organización de cálculos utilizado en los procesadores y controladores modernos para aumentar su rendimiento (aumentar el número de instrucciones ejecutadas por unidad de tiempo - operación de paralelismo a nivel de instrucción ), una tecnología utilizada en el desarrollo de computadoras y otros dispositivos electrónicos digitales.
La idea es ejecutar múltiples instrucciones de procesador en paralelo. Las instrucciones complejas del procesador se representan como una secuencia de pasos más simples. En lugar de ejecutar instrucciones secuencialmente (esperar a que se complete el final de una instrucción y pasar a la siguiente), la siguiente instrucción se puede ejecutar a través de varias etapas de ejecución de la primera instrucción. Esto permite que las cadenas de control del procesador reciban instrucciones a la velocidad de la etapa más lenta de procesamiento, pero al mismo tiempo, mucho más rápido que realizar un procesamiento completo exclusivo de cada instrucción de principio a fin.
La ilustración de la derecha muestra una tubería simple de cinco niveles en procesadores RISC . Aquí:
El eje vertical son instrucciones secuenciales independientes, el eje horizontal es el tiempo. La columna verde describe el estado del procesador en un momento dado, en ella la instrucción superior más antigua ya está en el estado de escritura en el registro, y la instrucción inferior más reciente está solo en el proceso de lectura.
El término "transportador" en sí proviene de la industria, que utiliza un principio de operación similar : el material se arrastra automáticamente a lo largo de la cinta transportadora hacia el trabajador, quien realiza las acciones necesarias con él, el trabajador que lo sigue realiza sus funciones en el resultante pieza de trabajo, la siguiente hace otra cosa. Así, al final de la tubería, la cadena de trabajadores completa todas las tareas asignadas, manteniendo una alta tasa de producción. Por ejemplo, si la operación más lenta tarda un minuto, cada pieza saldrá de la línea de montaje en un minuto. En los procesadores, el papel de trabajadores lo realizan módulos funcionales que forman parte del procesador.
La forma más simple de superposición de ejecución de instrucciones en el tiempo fue implementada en la máquina Z3 por Konrad Zuse en 1941 [2] .
El pequeño tubo ETSVM " Ural " ( 1957 , URSS ) tenía un transportador de operaciones de dos etapas. [3]
Los transportadores de etapas múltiples en la vista moderna se implementaron en la máquina M-100 de Anatoly Ivanovich Kitov (1959, URSS) [ especificar ] [4] , UNIVAC LARC (1960, EE. UU.), IBM Stretch (1961, EE. UU.) [5] , Atlas (1962, Gran Bretaña) y BESM-6 (1967, URSS). En el proyecto IBM Stretch, se propusieron los términos "fetch" ( ing. Fetch ), "decodificación" ( ing. Decode ) y "ejecución" ( ing. Execute ), que luego se volvieron de uso común.
Muchos procesadores modernos están controlados por un generador de reloj. El procesador interno consta de elementos lógicos y celdas de memoria: flip- flops . Cuando llega la señal del generador de reloj, los flip-flops toman su nuevo valor y la "lógica" tarda un tiempo en decodificar los nuevos valores. Luego llega la siguiente señal del generador de reloj, los flip-flops toman nuevos valores, y así sucesivamente. Al dividir las secuencias de elementos lógicos en secuencias más cortas y colocar biestables entre estas secuencias cortas, se reduce el tiempo requerido para que la lógica procese las señales. En este caso, la duración de un ciclo del procesador se puede reducir en consecuencia.
Por ejemplo, la tubería más simple de procesadores RISC se puede representar mediante cinco etapas con conjuntos de activadores entre etapas:
Las situaciones, llamadas conflictos de canalización ( peligro en inglés ), impiden la ejecución de la siguiente instrucción del flujo de instrucciones en el ciclo destinado a ella. Las colisiones reducen la velocidad real en el rendimiento de la canalización y pueden hacer que la canalización se detenga . La resolución de conflictos requiere que se permita que algunas instrucciones en la canalización continúen ejecutándose mientras que otras se retrasan.
Hay tres clases de conflictos [6] .
Los conflictos estructurales surgen debido a conflictos de recursos, cuando el hardware no puede soportar todas las combinaciones posibles de instrucciones ejecutadas simultáneamente [7] . Si no se admite alguna combinación de instrucciones, se dice que el procesador tiene un conflicto estructural . La mayoría de las veces, los conflictos estructurales ocurren cuando algún bloque funcional no está completamente canalizado. Por ejemplo, algunos procesadores comparten una única canalización de memoria para datos e instrucciones. Como resultado, cuando una instrucción contiene un acceso a la memoria de datos, entra en conflicto con una instrucción posterior. Para resolver este conflicto al acceder a la memoria para obtener datos, la canalización se detiene durante un ciclo.
Como alternativa a un conflicto estructural de este tipo, el desarrollador podría proporcionar acceso a la memoria de instrucciones separadas, ya sea dividiendo el caché en cachés de instrucciones y cachés de datos separados, o usando múltiples búferes llamados búferes de instrucciones para almacenar instrucciones, sin embargo, esto no se hace en orden. para evitar aumentar el costo del bloque [8] .
Los conflictos de datos ocurren cuando la dependencia de un comando en los resultados de uno anterior aparece cuando los comandos se combinan en una canalización. Estos conflictos ocurren cuando la canalización cambia el orden de los accesos de lectura/escritura a los operandos de modo que difiere del orden que existe para las instrucciones ejecutadas secuencialmente en un procesador sin canalización. Existe un método de resolución de conflictos de datos: reenvío ( reenvío de registros en inglés ) (a veces llamado bypass ) [9] . Desafortunadamente, no todos los posibles conflictos de datos se pueden manejar mediante una omisión, en cuyo caso la canalización se suspende hasta que se resuelva el conflicto.
Los conflictos de control ocurren cuando se ejecutan transferencias condicionales y otras instrucciones que cambian el valor del contador del programa . Hay muchas maneras de manejar una parada de tubería causada por un retraso en la transferencia de control, pero las tuberías profundas tienden a usar herramientas agresivas [10] como la predicción de transferencia de control .
La arquitectura sin canalización es mucho menos eficiente debido a la menor carga de los módulos funcionales del procesador , mientras que uno o un pequeño número de módulos realizan su función durante el procesamiento de instrucciones. La canalización no elimina por completo el tiempo de inactividad de los módulos en los procesadores y no reduce el tiempo de ejecución de cada instrucción específica, pero obliga a los módulos del procesador a trabajar en paralelo en diferentes instrucciones, lo que aumenta la cantidad de instrucciones ejecutadas por unidad de tiempo. y, por lo tanto, el rendimiento general de los programas.
Los procesadores con un conducto interno están diseñados para que el procesamiento de instrucciones se divida en una secuencia de etapas, asumiendo el procesamiento simultáneo de varias instrucciones en diferentes etapas. Los resultados del trabajo de cada una de las etapas se transfieren a través de las celdas de memoria a la siguiente etapa, y así sucesivamente hasta que se ejecuta la instrucción. Sin embargo, tal organización del procesador, con un ligero aumento en el tiempo promedio de ejecución de cada instrucción, proporciona un aumento significativo en el rendimiento debido a la alta frecuencia de finalización de la instrucción.
Sin embargo, no todas las instrucciones son independientes. En la tubería más simple, donde el procesamiento de instrucciones está representado por cinco etapas, para garantizar la carga completa, mientras se completa el procesamiento de la primera instrucción, idealmente, se deben procesar cuatro instrucciones independientes consecutivas más en paralelo. Si la secuencia contiene instrucciones que dependen de las que se están ejecutando actualmente, entonces la lógica de control de la tubería más simple suspende varias etapas iniciales de la tubería, colocando así una instrucción vacía ("burbuja") en la tubería, a veces repetidamente, hasta que se resuelva la dependencia. Hay una serie de trucos, como el reenvío, que reducen en gran medida la necesidad de pausar parte de la canalización en tales casos. Sin embargo, la dependencia entre instrucciones procesadas simultáneamente por el procesador no permite lograr un aumento de rendimiento múltiplo del número de etapas de la tubería en comparación con un procesador sin tubería.
La canalización no ayuda en todos los casos. Hay varias desventajas posibles. Una canalización de instrucciones se puede llamar "completamente canalizada" si puede aceptar una nueva instrucción en cada ciclo de máquina . De lo contrario, se deben forzar retrasos en la canalización que aplanan la canalización y degradan su rendimiento.
ventajas:
Defectos:
A la derecha se muestra una tubería general con cuatro etapas de trabajo:
El área gris superior es una lista de instrucciones a ejecutar. El área gris inferior es una lista de instrucciones que ya se han ejecutado. Y el área blanca del medio es la propia tubería.
La ejecución es así:
Ciclo | Comportamiento |
---|---|
0 | Cuatro instrucciones están pendientes de ejecución. |
una |
|
2 |
|
3 |
|
cuatro |
|
5 |
|
6 |
|
7 |
|
ocho |
|
9 | Se han seguido todas las instrucciones. |
Para resolver conflictos de canalización, el procesador se ve obligado a retrasar el procesamiento de la instrucción creando una "burbuja" en la canalización. El paso de la burbuja a través de los actuadores no va acompañado de ningún trabajo útil. En el segundo ciclo, el procesamiento de la instrucción púrpura se retrasa y ahora hay una burbuja en la etapa de decodificación en el tercer ciclo. Todas las instrucciones "después" de la instrucción violeta se retrasan un ciclo, mientras que las instrucciones "antes" de la instrucción violeta continúan ejecutándose.
Obviamente, la presencia de una burbuja en la canalización da un tiempo de ejecución total de 8 ciclos en lugar de 7 en el diagrama de ejecución que se muestra arriba.
Los actuadores deben realizar alguna acción en cada ciclo. Las burbujas son una forma de crear un retraso en el procesamiento de una instrucción sin detener la canalización. Cuando se ejecutan, no se produce ningún trabajo útil en las etapas de obtención, decodificación, ejecución y escritura del resultado. Se pueden expresar usando la instrucción del ensamblador NOP [11] [12] [13] .
Digamos que una instrucción típica para sumar dos números es СЛОЖИТЬ A, B, C. Esta instrucción suma los valores en las ubicaciones de memoria A y B y luego coloca el resultado en la ubicación de memoria C. En un procesador segmentado, el controlador puede dividir esta operación en tareas secuenciales de la forma
LOAD A , R1 LOAD B , R2 ADD R1 , R2 , R3 WRITE R3 , C carga la siguiente instrucciónLas celdas R1 , R2 y R3 son registros del procesador . Los valores que se almacenan en las ubicaciones de memoria, que llamamos A y B , se cargan (es decir, se copian) en estos registros, luego se suman y el resultado se escribe en la ubicación de memoria C.
En este ejemplo, la canalización consta de tres niveles: carga, ejecución y escritura. Estos pasos son obviamente llamados niveles o pasos de tubería .
En un procesador sin tubería, solo se puede ejecutar un paso a la vez, por lo que una instrucción debe completarse por completo antes de que pueda comenzar la siguiente instrucción. En un procesador segmentado, todos estos pasos se pueden realizar simultáneamente en diferentes instrucciones. Entonces, cuando la primera instrucción está en el paso de ejecución, la segunda instrucción estará en la etapa de decodificación y la tercera instrucción estará en la etapa de lectura.
La canalización no reduce el tiempo que lleva ejecutar una instrucción, pero aumenta la cantidad (número) de instrucciones que se pueden ejecutar al mismo tiempo y, por lo tanto, reduce la demora entre las instrucciones ejecutadas, lo que aumenta el llamado. rendimiento _ Cuantas más capas tenga una canalización, más instrucciones se pueden ejecutar al mismo tiempo y menor será el retraso entre las instrucciones completadas. Todos los microprocesadores que se fabrican en la actualidad utilizan al menos una canalización de dos niveles.
Tubería teórica de tres niveles:
Paso | inglés título | Descripción |
---|---|---|
Muestra | Buscar | Leer instrucción de memoria |
Ejecución | Ejecutar | Ejecutar instrucción |
Grabación | Respóndeme | Escribir resultado en memoria y/o registros |
Listado de pseudo-ensamblador a ejecutar:
CARGA 40, A ; cargue el número 40 en A COPY A , B ; copiar A a B AÑADIR 20, B ; agregue 20 a B WRITE B , 0x0300 ; escribir B en la ubicación de memoria 0x0300Cómo se ejecutará:
Tacto | Muestra | Ejecución | Grabación | Explicación |
---|---|---|---|---|
Medida 1 | DESCARGAR | La instrucción LOAD se lee de la memoria. | ||
Medida 2 | COPIAR | DESCARGAR | La instrucción LOAD se ejecuta, la instrucción COPY se lee de la memoria. | |
Medida 3 | DOBLAR | COPIAR | DESCARGAR | La instrucción LOAD está en el paso de escritura del resultado, donde su resultado (es decir, el número 40 ) se escribe en el registro A. Al mismo tiempo, se ejecuta la instrucción COPY. Dado que debe copiar el contenido del registro A en el registro B , debe esperar hasta el final de la instrucción LOAD. |
Medida 4 | REGISTRO | DOBLAR | COPIAR | Se carga la instrucción WRITE, mientras que la instrucción COPY se despide de nosotros, y actualmente se está calculando la instrucción ADD. |
Y así. Tenga en cuenta que a veces las instrucciones dependerán del resultado de otras instrucciones (como nuestra instrucción COPY, por ejemplo). Cuando más de una instrucción se refiere a una ubicación específica, ya sea leyéndola (es decir, usándola como un operando de entrada) o escribiéndola (es decir, usándola como un operando de salida), la ejecución de las instrucciones no está en orden. el orden previsto originalmente en el programa original. , puede causar un conflicto de canalización , (como se mencionó anteriormente). Existen varias técnicas comprobadas para prevenir conflictos o solucionarlos si ocurren.
Muchos esquemas incluyen pipelines de 7, 10 o incluso 20 niveles (como, por ejemplo, en el procesador Pentium 4 ). Los últimos núcleos Pentium 4 con nombre en código Prescott y Cedar Mill (y sus derivados Pentium D ) tienen una canalización de 31 niveles.
El procesador Xelerator X10q tiene una canalización de más de mil pasos [14] . El reverso de la moneda en este caso es la necesidad de restablecer toda la tubería en caso de que el flujo del programa haya cambiado (por ejemplo, por una declaración condicional). Los predictores de bifurcación intentan resolver este problema . La predicción de bifurcación por sí sola solo puede empeorar las cosas si la predicción se realiza de manera deficiente. En algunas aplicaciones, como la supercomputación , los programas se escriben específicamente para usar sentencias condicionales lo menos posible, por lo que las canalizaciones muy largas tendrán un efecto muy positivo en la velocidad general de los cálculos, ya que las canalizaciones largas están diseñadas para reducir el CPI ( número de ciclos ). a la instrucción ).
Si la bifurcación ocurre todo el tiempo, reorganizar las instrucciones de la máquina ayudará a reducir significativamente la pérdida de velocidad: las instrucciones que probablemente se necesitan se colocan en la tubería. Este método es más eficiente que tener que restablecer completamente la canalización cada vez. Los programas como gcov se pueden usar para determinar con qué frecuencia se ejecutan realmente las ramas individuales, utilizando una técnica conocida como análisis de cobertura de código . Aunque en la práctica, dicho análisis es la última medida en la optimización.
El alto rendimiento de las canalizaciones conduce a una disminución del rendimiento si el código ejecutable contiene muchos saltos condicionales: el procesador no sabe de dónde leer la siguiente instrucción y, por lo tanto, tiene que esperar a que finalice la instrucción de salto condicional, dejando un tubería vacía detrás de él. Una vez que se ha atravesado la rama y se sabe a dónde debe saltar el procesador a continuación, la siguiente instrucción tendrá que pasar por todo el conducto antes de que el resultado esté disponible y el procesador "funcione" nuevamente. En un caso extremo, el rendimiento de un procesador segmentado teóricamente podría caer al de un procesador sin segmentación, o incluso ser peor debido al hecho de que solo un nivel de la segmentación está ocupado y hay un pequeño retraso entre los niveles.
Si el procesador está equipado con una canalización, el código leído de la memoria no se ejecuta inmediatamente, sino que se coloca en una cola ( cola de entrada de captación previa ). Si se cambia el código contenido en la memoria, el código contenido en la cola de canalización seguirá siendo el mismo. Además, las instrucciones en el caché de instrucciones no cambiarán . Debe tenerse en cuenta que este problema es típico solo para programas automodificables y empaquetadores de archivos ejecutables .
Tecnologías de procesadores digitales | |||||||||
---|---|---|---|---|---|---|---|---|---|
Arquitectura | |||||||||
Set de instrucciones arquitectura | |||||||||
palabra maquina | |||||||||
Paralelismo |
| ||||||||
Implementaciones | |||||||||
Componentes | |||||||||
Administración de energía |