Pipelining
![](http://upload.wikimedia.org/wikipedia/commons/thumb/2/21/Fivestagespipeline.png/220px-Fivestagespipeline.png)
![](http://upload.wikimedia.org/wikipedia/commons/thumb/c/ce/Superscalarpipeline.png/220px-Superscalarpipeline.png)
La segmentació de nivell d'instrucció , també anomenada pipelining, és una tècnica emprada en el disseny de processadors, basada en la divisió de l'execució de les instruccions en etapes, aconseguint així que una instrucció comenci a executar-se abans que hagin acabat les anteriors i, per tant, que hi hagi diverses instruccions En procés simultàniament.
Cadascuna de les etapes ha de completar les seves accions en un cicle de rellotge, passant els seus resultats a l'etapa següent i rebent de l'anterior. Per això és necessari emmagatzemar les dades en registres intermedis. Qualsevol valor que pugui ser necessari en una etapa posterior s'ha d'anar propagant a través d'aquests registres intermedis fins que ja no sigui necessari.
Per aconseguir la segmentació és necessari que una instrucció utilitzi només una etapa en cada cicle d'execució.
Ja que totes les etapes han de trigar el mateix en la seva execució, el temps de cicle serà el de l'etapa més lenta, més el del retard provocat per la utilització dels registres intermedis. Comparant aquest esquema amb el multicicle, el temps de cicle serà més lent, però el CPI (Cicles Per Instrucció) serà menor, cosa que provoca un augment del rendiment. Ja que si no tenim en compte els riscos estructurals (que poden provocar parades en el pipeline), en cada cicle de rellotge haurìem d'acabar d'executar una instrucció (CPI = 1).
Exemple
Un exemple senzill que utilitza aquesta tècnica és el processador DLX, amb 5 etapes (IF, ID, EX, MEM i WB). Una instrucció s'utilitza en un cicle només una d'aquestes etapes. Quan acaba aquest cicle, passa a la següent etapa, deixant lliure l'anterior, de manera que aquesta podria ser utilitzada en aquell moment per la següent instrucció.
Veient la llera d'execució es quedaria, idealment, així:
N º cicle | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
Instr 1 | IF | ID | EX | MEM | WB | |||||
Instr 2 | IF | ID | EX | MEM | WB | |||||
Instr 3 | IF | ID | EX | MEM | WB | |||||
Instr 4 | IF | ID | EX | MEM | WB | |||||
Instr 5 | IF | ID | EX | MEM | WB | |||||
Instr 6 | IF | ID | EX | MEM | WB |
D'aquesta manera s'aprecia que, un cop ha el pipeline ple, s'acaba d'executar una instrucció en cada cicle: En el cicle n º 5 finalitza la primera instrucció, en el n º 6 la segona, etc.
Riscos de Dades i de Control
![](http://upload.wikimedia.org/wikipedia/commons/thumb/0/09/Segmentaci%C3%B3n.jpg/220px-Segmentaci%C3%B3n.jpg)
L'ús d'aquesta tècnica comporta diversos riscos de dades, ja que en començar a executar instruccions abans d'acabar les anteriors pot provocar que es necessiti llegir/escriure un registre abans que aquest hagi estat escrit/llegit per la instrucció anterior/següent. Aquests riscos de dades es poden classificar com:
- RAW (read after write): una instrucció posterior tracta de llegir un operand abans que ho escrigui una anterior.
- WAR (write after read): una instrucció posterior tracta d'escriure el seu resultat abans que l'hagi llegit una anterior.
- WAW (write after write): una escriptura posterior es produeix abans que una altra escriptura anterior en el mateix destí.
La tècnica més senzilla per tal d'evitar riscos seria, quan es detecti un risc, aturar l'execució de la instrucció que hagi de causar el risc, (inserint instruccions NOP, o bombolles), fins que hagin acabat d'executar totes les instruccions anteriors. Aquesta tècnica suposa massa parades en l'execució, el que suposa una caiguda considerable del rendiment.
Una altra tècnica per solucionar els riscos RAW és la de l'avançament, consistent en copiar un valor d'un registre intermedi posterior en un d'anterior, perquè la instrucció que vingui darrere pugui utilitzar els valors, sense haver d'esperar que acabi del tot la instrucció anterior.
Per intentar solucionar els altres riscos es fan servir tècniques més avançades com la tècnica Tomasulo o la de Scoreboard (ambdues de predicció dinàmica).
D'una manera o altra, el que es pretén amb qualsevol d'aquestes tècniques és reduir el màxim possible els cicles de parada, ja que incrementen el CPI, que idealment és d'1. El compilador també influeix notablement en la recerca del CPI ideal, ja que una altra manera d'evitar riscos i, per tant, possibles cicles de parada, podria ser canviar l'ordre d'execució de les instruccions, evitant sempre, per descomptat, que no canviï el resultat del programa.
A part dels riscos de dades, també hi ha els riscos de control, provocats pels salts condicionals. Aquests processadors comencen a enviar instruccions a executar abans de saber si aquestes instruccions han d'executar-se (ja que fins que no es processa la condició de salt, no se sap si serà o no pres), per la qual cosa han de tenir maneres de desfer canvis, o de poder descartar, si han començat a executar instruccions que no corresponen, a més del rebuig de cicles que suposa el fet d'haver començat a executar instruccions inútils.
Per això, es fan servir tècniques per intentar predir si un salt condicional serà pres o no, i en cas d'equivocar-se, que la penalització sigui la mínima possible.
Per a això, hi ha tècniques de predicció estàtica (en cas d'un salt, sempre s'actuarà de la mateixa manera), o tècniques de predicció dinàmica (afegint maquinari addicional, que intenta "aprendre" el comportament del programa per saber que ha de fer en el proper salt). Exemples d'aquests últims són el predictor d'1 o 2 bits, predictors amb correlació, predictors de contesa i el BTB ( Branch Target Buffer , Buffer de destinació de salts).