Varje processorinstruktion har flera steg i sin funktion. Var och en av dessa steg tar en enda CPU-cykel att slutföra. Dessa steg är Instruktionshämtning, Instruktionsavkodning, Execute, Minnesåtkomst och Writeback. Respektive dessa får den instruktion som behöver slutföras, skiljer operationen från de värden som drivs på, kör processen, öppna registret som resultatet kommer att skrivas på och skriv resultatet till det öppnade Registrera.
Historiska processorer i ordning
I tidiga datorer använde inte CPU: n en instruktionspipeline. I dessa CPU: er behövde varje encykeloperation ske för varje instruktion. Detta innebar att det tog fem klockcykler för den genomsnittliga instruktionen att bearbetas helt innan nästa kunde startas. Vissa operationer behöver kanske inte skriva ut något resultat till ett register, vilket innebär att minnesåtkomst- och återskrivningsstegen kan hoppas över.
![](/f/406367ad6ad60c219d99c9811628915a.png)
Det finns dock ett problem när man kör en komplett instruktion i ordning innan man kan gå vidare till nästa instruktion. Problemet är cachemissen. CPU: n lagrar data som den aktivt bearbetar i registret. Detta kan nås med en en-cykels latens. Problemet är att registret är litet eftersom det är inbyggt i processorkärnan. CPU: n måste gå till den större men långsammare L1-cachen om data inte redan har laddats. Om den inte finns där måste den gå till den större och långsammare L2-cachen igen. Nästa steg är L3-cachen; det sista alternativet är systemets RAM. Vart och ett av dessa alternativ tar fler och fler CPU-cykler att kontrollera.
Nu kan denna extra tillagda latens vara ett stort problem i ett system som måste slutföra varje instruktion i sin ordning innan nästa instruktion påbörjas. Det som hade varit en 5-cykel per instruktionsprocessor, kan plötsligt hänga på en instruktion under dussintals eller hundratals klockcykler. Hela tiden kan inget annat hända på datorn. Tekniskt sett kan detta lindras något genom att ha två oberoende kärnor. Inget hindrar dem båda från att göra samma sak, potentiellt samtidigt. Så att gå längs med flera kärnor fixar inte detta.
Den klassiska RISC Pipeline
RISC står för Reduced Instruction Set Computer. Det är en stil av processordesign som optimerar prestandan genom att göra avkodningen av varje instruktion enklare. Detta är i jämförelse med CISC eller Complex Instruction Set Computer, som designar mer komplexa instruktionsuppsättningar som tillåter färre instruktioner att behövas för att utföra samma uppgifter.
Den klassiska RISC-designen inkluderar en instruktionspipeline. Istället för att köra något av de fem instruktionsstegen i en given cykel, tillåter pipelinen att alla fem stegen utförs. Naturligtvis kan du inte köra alla fem stegen i en instruktion i en cykel. Men du kan köa fem på varandra följande instruktioner med en förskjutning på ett steg vardera. På så sätt kan en ny instruktion slutföras varje klockcykel. Erbjuder en potentiell 5x prestandaökning för en relativt låg ökning av kärnkomplexiteten.
![](/f/9aeb727a1c00f27c56abdd7a1366c80d.png)
Processorer som inte har en pipeline kan bara vara sub-skalära, eftersom de inte kan utföra en komplett instruktion per cykel. Med denna primära femstegspipeline kan du skapa en skalär CPU som kan slutföra en instruktion för varje process. Genom att skapa ännu mer långtgående pipelines kan du skapa superskalära processorer som kan utföra mer än en instruktion per klockcykel. Naturligtvis finns det fortfarande potentiella problem.
Fortfarande sekventiell
Inget av detta löser problemet med att vänta i många cykler på ett svar när man behöver fråga de olika nivåerna av cache och RAM. Det introducerar också ett nytt problem. Vad händer om en instruktion förlitar sig på resultatet från den föregående instruktionen? Dessa problem löses självständigt med en avancerad dispatcher. Den planerar noggrant utförandeordningen så att inga instruktioner som förlitar sig på en annans utdata är för nära varandra. Den hanterar också cachemissar genom att parkera en instruktion och ersätta den i pipeline med en annan instruktioner som är redo att köras och inte kräver dess resultat, och återupptar instruktionen när den finns redo.
Dessa lösningar kan fungera på unpipelined processorer, men de krävs för en superskalär processor som kör mer än en instruktion per klocka. En grenprediktor är också mycket användbar eftersom den kan försöka förutsäga resultatet av en instruktion med mer än ett potentiellt utfall och fortsätta att anta att det är korrekt om inte annat bevisas.
Slutsats
En pipeline gör att alla processorns distinkta funktioner kan användas i varje cykel. Den gör detta genom att köra olika stadier av olika instruktioner samtidigt. Detta tillför inte ens mycket komplexitet till CPU-designen. Det banar också väg för att tillåta mer än en instruktion att utföra ett enda steg per cykel.