Instruktionspipelining i CPU: Så fungerar pipeline-arkitektur
Instruktionspipelining är en teknik som används vid utformningen av moderna mikroprocessorer, mikrokontroller och CPU:er för att öka deras instruktionsgenomströmning (antalet instruktioner som kan utföras på en tidsenhet). Genom att dela upp bearbetningen av en instruktion i flera delsteg får man högre parallellism och bättre utnyttjande av processorresurserna.
Huvudidén är att dela upp (så kallad "split") behandlingen av en CPU-instruktion, enligt definitionen i instruktionsmikrokoden, i en serie oberoende steg av mikrooperationer (även kallade "mikroinstruktioner", "micro-op" eller "µop"), med lagring i slutet av varje steg. Detta gör det möjligt för processorns styrlogik att arbeta med varje steg i takt med den klockperiod som krävs för det långsammaste delsteget, vilket ofta ger högre klockfrekvens och bättre total genomströmning jämfört med att utföra hela instruktionen som ett enda långt steg.
Termen pipeline syftar på det faktum att varje steg innehåller en enda mikroinstruktion (som en vattendroppe) och att varje steg är kopplat till ett annat steg (analogi; liknande vattenledningar). Stegen bildar en kedja där varje steg arbetar på en annan instruktion samtidigt — precis som flera objekt som förflyttas längs ett löpande band.
Hur pipelining utnyttjar klockan och flip-flops
De flesta moderna processorer drivs av en klocka. CPU:n består internt av logik och minne (flipflops). När klocksignalen anländer lagrar flipflopsen sitt nya värde, varefter logiken behöver en viss tid för att avkoda flipflopsen nya värden. Därefter kommer nästa klockpuls och flip-flopsen lagrar ytterligare ett värde, och så vidare. Genom att dela upp logiken i mindre delar och sätta in flip-flops mellan logikdelarna minskas den tid som logiken behöver (från registret uppdateras tills giltiga utgångar genereras). På detta sätt kan klockperioden minskas och klockfrekvensen höjas.
Exempel: femstegs RISC-pipeline
En vanlig enkel RISC-pipeline delas ofta upp i fem steg med en uppsättning flip-flops mellan varje steg:
- Hämtning av instruktioner
- Instruktionsavkodning och registerhämtning
- Utför
- Tillgång till minnet
- Registrera tillbaka
Kort förklaring av varje steg:
- Hämtning av instruktioner (IF): Programräknaren (PC) läser nästa instruktion från minnet eller cache. Här bestäms adressen för nästa instruktion.
- Instruktionsavkodning och registerhämtning (ID): Instruktionen tolkas och operander läses ut från registerfilen. Eventuell omkodning till mikrooperationer (µops) sker i denna fas i vissa arkitekturer.
- Utför (EX): ALU-operationer, adresseringsberäkningar eller jämförelser utförs. I komplexa processorer kan flera funktionella enheter finnas för parallell exekvering.
- Tillgång till minnet (MEM): Minne läses eller skrivs om instruktionen kräver det (t.ex. laddning/lagra). Cachelatens påverkar detta steg.
- Registrera tillbaka (WB): Beräknade resultat skrivs tillbaka till registerfilen så att senare instruktioner kan använda dem.
Varför pipelining förbättrar prestanda
Processorer med pipelining består av steg (moduler) som mer eller mindre oberoende kan arbeta med separata mikroinstruktioner. Varje steg är kopplat till nästa steg genom flip-flops (som en "kedja") så att stegets utgång blir nästa stegs ingång tills arbetet med att bearbeta instruktionerna är klart. En sådan organisationsmodell minskar instruktionscykelns totala genomströmningstid genom ökad parallellism — medan ett steg arbetar på instruktion N, arbetar nästa steg på N−1, osv.
En arkitektur utan pipeline är inte lika effektiv eftersom vissa CPU-moduler är inaktiva medan en annan modul är aktiv under instruktionscykeln. Pipelineringen tar inte helt bort alla perioder då CPU:n är ledig, men eftersom CPU-modulerna arbetar parallellt ökar instruktionsgenomströmningen avsevärt.
Begränsningar: hazards och fördröjningar
Pipelining inför också problem som måste hanteras:
- Strukturella hinder (structural hazards): Uppstår när två steg behöver samma hårdvaruresurs samtidigt, till exempel om minnet inte kan hantera både instruktion- och datatillgångar samtidigt.
- Datahazards: Uppstår när en instruktion behöver resultat som ännu inte skrivits tillbaka av en tidigare instruktion. Lösningar inkluderar stall (införa väntecykler), forwarding (även kallat bypassing) där resultat skickas direkt från en pipeline-stage till en annan, och registerinterlocks i hårdvaran.
- Kontrolhazards (branch hazards): Greninstruktioner (if-satser, hopp) skapar osäkerhet om nästa hämtade instruktion. Det minskar pipelineeffektiviteten om man måste tömma eller vänta. Tekniker för att mildra detta är grenprediktion, förutsägelse och spekulativ exekvering samt att använda snabba återställningsmekanismer vid felprediktion.
Lösningar och avancerade tekniker
Moderna processorer använder flera tekniker för att öka pipelinens effektivitet:
- Data forwarding/bypassing för att undvika väntecykler vid datahazards.
- Grenprediktion och spekulativ exekvering för att minska kostnaden av kontrolhazards.
- Out-of-order execution där instruktioner exekveras i en annan ordning än programordningen för att undvika tomgång; resultat skrivs tillbaka i ordnat läge.
- Superskalar arkitektur som tillåter flera instruktioner att startas i varje klockcykel (flera pipelines parallellt).
- Ökad pipeline-depth (fler och kortare steg) kan ge högre klockfrekvens men gör pipelinen mer känslig för branches och ger svårare latensstyrning.
Prestandamått och designavvägningar
Vid utvärdering av pipelinedesign används bland annat följande mått:
- CPI (Cycles Per Instruction): genomsnittligt antal klockcykler per instruktion. Pipelining minskar ofta CPI nära 1 om inga hinder uppstår.
- IPC (Instructions Per Cycle): antal utförda instruktioner per klockcykel — höga IPC-värden eftersträvas i superskalära och out-of-order designers.
- Klockfrekvens: kortare pipeline-steg kan öka maximal frekvens, men ökar kostnad och komplexitet för hazard-hantering.
Vad betyder "helt pipelinerad"?
En instruktionspipeline sägs vara helt pipelinerad om den kan ta emot en ny instruktion varje klockcykel. I praktiken innebär detta att inga strukturella beroenden eller väntetider tvingar pipeline att pausa vid steady state. En pipeline som inte är helt pipelinerad har väntecykler som fördröjer pipelinjens framskridande, vilket ökar CPI.
Olika arkitekturstilar och mikroops
I vissa CISC-processorer (t.ex. äldre x86-designs) avkodas komplexa instruktioner till en eller flera interna mikrooperationer (µops) innan de körs i pipelinen. Dessa µops kan flyta genom separata interna pipelines, vilket möjliggör moderna optimeringar trots ett komplext instruktionsset.
Sammanfattning
Instruktionspipelining är en central teknik i modern processorarkitektur som genom att dela upp instruktionsexekvering i flera steg ökar genomströmning och utnyttjande av hårdvaruresurser. Pipelining ger betydande prestandaförbättringar, men kräver också mekanismer för att hantera hazards, grenutmaningar och resurskonflikter. Kombinationen av pipelining med tekniker som forwarding, branch prediction, out-of-order execution och superskalar samtidighet är vad som gör dagens CPU:er både snabba och effektiva.


Grundläggande pipeline i fem steg i en RISC-maskin (IF = hämta instruktioner, ID = avkoda instruktioner, EX = utföra, MEM = minnesåtkomst, WB = skriva tillbaka register). Den vertikala axeln är successiva instruktioner, den horisontella axeln är tid. I den gröna kolumnen befinner sig den tidigaste instruktionen i WB-stadiet och den senaste instruktionen är i färd med att hämta instruktioner.
Fördelar och nackdelar med pipelining
Fördelar med pipelining:
- Processorns cykeltid minskas, vilket ökar genomströmningen av instruktioner. Pipelining minskar inte den tid det tar att slutföra en instruktion, utan ökar antalet instruktioner som kan behandlas samtidigt ("på en gång") och minskar fördröjningen mellan avslutade instruktioner (kallas "genomströmning").
Ju fler pipeline-steg en processor har, desto fler instruktioner kan den bearbeta "samtidigt" och desto mindre är fördröjningen mellan avslutade instruktioner. Varje vanlig mikroprocessor för
allmänt bruk som tillverkas idag använder minst två pipeline-steg och upp till 30 eller 40 steg. - Om pipelining används kan CPU:s aritmetiska logikenhet utformas snabbare, men den blir mer komplex.
- Pipelining ökar i teorin prestandan jämfört med en kärnan utan pipelining med en faktor som motsvarar antalet steg (om man antar att klockfrekvensen ökar med samma faktor) och koden är idealisk för pipeline-utförande.
- Processorer med pipeliner arbetar i allmänhet med en högre klockfrekvens än RAM-frekvensen (från och med 2008 års teknik arbetar RAM med låga frekvenser jämfört med CPU-frekvenser), vilket ökar datorns totala prestanda.
Nackdelar med pipelining:
Pipelining har många nackdelar, även om det finns många tekniker som används av processor- och kompilatorkonstruktörer för att övervinna de flesta av dem; nedan följer en lista över vanliga nackdelar:
- En icke-pipelinerad processor är enklare och billigare att tillverka, eftersom den endast utför en enda instruktion åt gången. Detta förhindrar fördröjning av förgreningar (i Pipelining fördröjs varje förgrening) och problem när seriella instruktioner utförs samtidigt.
- I en pipelinerad processor ökar instruktionsfördröjningen genom att flipflops sätts in mellan modulerna jämfört med en icke-pipelinerad processor.
- En icke-pipelinerad processor kommer att ha en definierad instruktionsgenomströmning. Prestandan hos en pipelinerad processor är mycket svårare att förutsäga och kan variera kraftigt för olika program.
- Många konstruktioner innehåller pipelines som är så långa som 7, 10, 20, 31 eller ännu fler steg; en nackdel med en lång pipeline är att när ett program förgrenar sig måste hela pipelinen spolas (rensas). Den högre genomströmningen hos pipelines blir inte tillräcklig när den exekverade koden innehåller många förgreningar: processorn kan inte veta i förväg var nästa instruktion ska läsas och måste vänta på att förgreningsinstruktionen avslutas, vilket gör att pipelinen bakom den blir tom. Denna nackdel kan minskas genom att förutsäga om en villkorlig greninstruktion kommer att grena baserat på tidigare aktivitet. Efter att förgreningen är avklarad måste nästa instruktion resa hela vägen genom pipeline innan dess resultat blir tillgängligt och processorn fortsätter att "arbeta" igen. I sådana extrema fall kan prestandan hos en pipelineprocessor vara sämre än hos en icke-pipelineprocessor.
- Tyvärr är inte alla instruktioner oberoende. I en enkel pipeline kan det krävas fem steg för att slutföra en instruktion. För att kunna arbeta med full prestanda måste denna pipeline köra fyra efterföljande oberoende instruktioner medan den första avslutas. Någon av dessa fyra instruktioner kan vara beroende av den första instruktionens resultat, vilket gör att pipelinekontrolllogiken måste vänta och lägga in ett stopp eller en bortkastad klockcykel i pipelinen tills beroendet har lösts. Lyckligtvis kan tekniker som forwarding avsevärt minska antalet fall där det krävs fördröjning.
- Självmodifierande program kan misslyckas med att exekvera korrekt på en pipelined-arkitektur när instruktionerna som modifieras ligger nära de instruktioner som utförs. Detta kan orsakas av att instruktionerna kanske redan finns i Prefetch Input Queue, så att ändringen kanske inte får effekt för den kommande exekveringen av instruktionerna. Instruktionscacher gör problemet ännu värre.
- Faror: När en programmerare (eller kompilator) skriver assemblerkod utgår de i allmänhet från att varje instruktion utförs innan nästa instruktion utförs. När detta antagande inte bekräftas genom pipelining leder det till att ett program beter sig felaktigt. Det finns
olika tekniker för att lösa faror eller för att kringgå dem, t.ex. forwarding och fördröjning (genom att lägga in ett stopp eller en bortkastad klockcykel).
Exempel
Generisk pipeline
Till höger visas en generisk pipeline med fyra steg:
- Hämta
- Avkoda
- Utför
- Återskrivning
Den övre grå rutan är listan över instruktioner som väntar på att utföras, den nedre grå rutan är listan över instruktioner som har slutförts och den mittersta vita rutan är pipelinen.
Utförandet sker på följande sätt:
Tid | Genomförande |
0 | Fyra instruktioner väntar på att utföras |
1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 | Alla instruktioner utförs |
Bubbla
När en "hicka" (avbrott) i utförandet inträffar skapas en "bubbla" i pipelinen där inget användbart händer. I cykel 2 försenas hämtningen av den lila instruktionen och avkodningssteget i cykel 3 innehåller nu en bubbla. Allt som ligger bakom den lila instruktionen försenas också, men allt som ligger framför den lila instruktionen fortsätter att utföras.
Jämfört med utförandet ovan ger bubblan en sammanlagd utföringstid på 8 klockticks i stället för 7.
Bubblor är som en fördröjning, där inget användbart händer under hämtning, avkodning, exekvering och återskrivning. Det är som en NOP-kod (förkortning för No OPeration).
Exempel 1
En typisk instruktion för att addera två tal kan vara ADD A, B, C
, som adderar värdena i minnesplatserna A och B och sedan placerar resultatet i minnesplats C. I en pipelineprocessor skulle pipelinecontrollern dela upp detta i en serie uppgifter som liknar följande:
Platserna "R1" och "R2" är register i CPU:n. De värden som finns lagrade på minnesplatserna "A" och "B" laddas (kopieras) till dessa register, adderas sedan och resultatet lagras på minnesplatsen "C".
I det här exemplet består pipelinen av tre steg: ladda, utföra och lagra. Varje steg kallas pipeline-steg.
På en icke-pipelinerad processor kan endast ett steg arbeta åt gången, så hela instruktionen måste slutföras innan nästa instruktion kan påbörjas. På en pipelined-processor kan alla steg arbeta samtidigt med olika instruktioner. Så när denna instruktion är i utförandestadiet kommer en andra instruktion att vara i avkodningsstadiet och en tredje instruktion kommer att vara i hämtarstadiet.
Exempel 2
För att bättre förstå konceptet kan vi titta på en teoretisk pipeline i tre steg:
Scen | Beskrivning |
Ladda | Läs instruktion från minnet |
Utför | Utför instruktion |
Butik | Lagra resultatet i minnet och/eller register |
och en pseudokod som ska exekveras:
Så här skulle det genomföras:
Klockan 1 | ||
Ladda | Utför | Butik |
LOAD |
|
|
LOAD-instruktionen hämtas från minnet.
Klockan 2 | ||
Ladda | Utför | Butik |
MOVE | LOAD |
|
LOAD-instruktionen utförs medan MOVE-instruktionen hämtas från minnet.
Klockan 3 | ||
Ladda | Utför | Butik |
LÄGG TILL | MOVE | LOAD |
LOAD-instruktionen befinner sig i Store-stadiet, där dess resultat (siffran 40) kommer att lagras i register A. Under tiden utförs MOVE-instruktionen. Eftersom den måste flytta innehållet i A till B måste den vänta på att LOAD-instruktionen avslutas.
Klockan 4 | ||
Ladda | Utför | Butik |
STORE | LÄGG TILL | MOVE |
STORE-instruktionen laddas, medan MOVE-instruktionen avslutas och ADD beräknas.
Och så vidare. Observera att en instruktion ibland är beroende av resultatet av en annan instruktion (som i vårt exempel MOVE). När mer än en instruktion hänvisar till en viss plats för en operand, antingen genom att läsa den (som en ingång) eller skriva den (som en utgång), kan utförandet av dessa instruktioner i en ordning som skiljer sig från den ursprungliga programordningen leda till den ovan nämnda riskfyllda situationen.


Generisk 4-stegs pipeline; de färgade rutorna representerar instruktioner som är oberoende av varandra.


En bubbla i cykel 3 fördröjer utförandet
Relaterade sidor
- Pipeline (databehandling)
- Parallell beräkning
- Parallellism på instruktionsnivå
Frågor och svar
F: Vad är instruktionspipelining?
S: Instruktions-pipelining är en teknik som används vid utformningen av moderna mikroprocessorer, mikrokontroller och CPU:er för att öka deras instruktionsgenomströmning genom att dela upp behandlingen av en CPU-instruktion i en serie oberoende steg med lagring i slutet av varje steg.
F: Hur fungerar pipelining?
S: Pipelining fungerar genom att logiken delas upp i mindre bitar och genom att flipflops sätts in mellan logikdelarna, vilket minskar den tid som krävs för logiken att avkoda värden tills den genererar giltiga utgångar beroende på dessa värden. Detta möjliggör snabbare klockperioder.
F: Vilka är några exempel på pipelines?
S: Ett exempel på en pipeline är RISC-pipeline, som är uppdelad i fem steg med en uppsättning flipflops mellan varje steg.
F: Hur ökar pipelineringen instruktionsgenomströmningen?
S: Pipelining ökar instruktionsgenomströmningen genom att CPU-moduler kan arbeta parallellt, vilket minskar tomgångstiden under en instruktionscykel och ökar den totala bearbetningstiden.
F: Är varje pipeline helt pipelinerad?
S: Nej, alla pipelines är inte helt pipelinerade. Vissa pipelines har väntecykler som fördröjer framstegen i pipelinen.