Instrukcijų sujungimas į eilę (angl. pipelining) yra vienas iš pagrindinių šiuolaikinių mikroprocesorių, mikrovaldiklių ir centrinių procesorių projektavimo metodų, naudojamas didinti instrukcijų pralaidumą — t. y. daugiau instrukcijų, įvykdomų per laiko vienetą. Tai pasiekiama padalijus instrukcijos vykdymą į kelis tarpusavyje derančius etapus, taip leidžiant skirtingoms instrukcijoms būti apdorojamoms lygiagrečiai skirtinguose etapuose.

Kaip tai veikia

Pagrindinė idėja — suskaidyti (angl. split) procesoriaus instrukcijos apdorojimą, aprašytą instrukcijos mikrokode, į kelias mažesnes, logiškai nepriklausomas mikrooperacijas (dažnai vadinamas mikroinstrukcijomis arba mikrooperacijomis). Kiekvienas toks etapas turi savo logiką ir atminties elementus (pvz., registre esančius sinchroninius elementus). Tarp etapų įterpiami sinchroniniai saugojimo elementai — flip flopai), kurie fiksuoja etapo išvestis, todėl sekančiam etapui perduodama stabili informacija kiekvieno laikrodžio impulso metu. Tokiu būdu logiką galima suskaidyti į mažesnes dalis, sutrumpinti kritinį kelią ir padidinti taktinio laikrodžio dažnį.

Sąvoka „vamzdynas“ (angl. pipeline) kilusi iš analogijos su vandens vamzdžiu: kiekvienoje pakopoje esanti mikroinstrukcija lyg „vandens lašas“, o kiekviena pakopa perduoda rezultatą kitai — kaip lašai juda per vamzdį.

RISC konvejerio pavyzdys

Tipinis RISC procesorių konvejeris dažnai dalinamas į penkis pagrindinius etapus. Originalus sąrašas:

  1. Instrukcijos paėmimas
  2. Instrukcijų dekodavimas ir registrų surinkimas
  3. Vykdyti
  4. Prieiga prie atminties
  5. Registro įrašymas atgal

Kai kurias šių pakopų galime trumpai apibūdinti:

  • Instrukcijos paėmimas (IF) — adresas skaitomas iš programos skaitiklio (PC), instrukcija skaitoma iš atminties arba instrukcijų buferio.
  • Instrukcijų dekodavimas ir registrų surinkimas (ID) — instrukcija dekoduojama, nuskaitomi operandų registrai, apskaičiuojami poslinkiai/offset'ai.
  • Vykdymas / ALU (EX) — atliekami aritmetiniai/logi­niniai veiksmai, adresų skaičiavimas šakoms ir pan.
  • Prieiga prie atminties (MEM) — skaitymas arba įrašymas į duomenų atmintį, jei instrukcija reikalauja.
  • Registro įrašymas atgal (WB) — rezultatas įrašomas atgal į registrų rinkinį.

Pranašumai ir apribojimai

Vamzdyninė organizacija leidžia procesoriaus moduliams dirbti lygiagrečiai su skirtingomis instrukcijomis — kiekviena pakopa pusiau nepriklausomai apdoroja savo dalį. Tai mažina tuščio veikimo laiką, padidina instrukcijų pralaidumą ir pagerina laikrodžio dažnio panaudojimą. Tačiau vamzdynas nekeičia vienos instrukcijos latencijos (jis netgi gali ją padidinti dėl papildomų registrų), o dažniausiai pagerėja pralaidumas (instrukcijų/s taktą).

Be to, nuo vamzdynų neatsiranda visiškai „lyginis“ veikimas — kai kurie ciklai gali būti tušti arba užimti dėl įvairių konfliktų. Sakoma, kad konvejeris yra visiškai konvejerinis, jei gali priimti naują instrukciją kiekvieną taktinį ciklą; jei ne — jis nevisiškai konvejerinis ir reikalauja laukimo ciklų.

Pagrindinės problemos (konfliktai) ir jų sprendimai

Pipelining sukuria tris pagrindines problemas, į kurias reikia atkreipti dėmesį:

  • Duomenų konfliktai (data hazards) — kai viena instrukcija reikalingą operandą gauna iš kitos, dar nebaigusios jo įrašyti. Sprendimai: lašiniai (stalls) / „burbulai“, operandų perdavimo (forwarding / bypassing) grandinės, kompiliatoriaus vykdomos perstatymo (instruction scheduling) priemonės.
  • Valdymo konfliktai (control hazards) — šakų (branch) ir iškvietimų (jump) atvejai, kai nežinoma, kuri instrukcija bus vykdoma toliau. Sprendimai: šakų spėjimas (branch prediction), ankstyvas šakų vertinimas, spekuliatyvus vykdymas ir šakų atmetimas (flush) klaidos atveju.
  • Struktūriniai konfliktai (structural hazards) — du etapai reikalauja to paties aparatinio resurso (pvz., atminties skaitymo/rašymo portų). Sprendimai: duomenų takai su atskira atmintimi instrukcijoms ir duomenims, papildomi portai arba laikiniai laukimo ciklai.

Kiti pagerinimai ir sudėtingesnės technikos

Norint dar labiau didinti pralaidumą ir efektyvumą, naudojamos sudėtingesnės priemonės:

  • Registrų persiuntimas (forwarding) — sumažina duomenų konfliktus perduodant rezultatą tiesiai iš vieno etapo į kitą be rašymo ir skaitymo iš registrų failo.
  • Išankstinis vykdymas ir spekuliacija — procesorius vykdo instrukcijas, kurių rezultatų gali neprireikti, kad užpildytų vamzdyną; jei spėjimas klaidingas, rezultatai atmetami.
  • Dinaminis išstūmimas (out-of-order execution) — instrukcijos vykdomos ne būtinai programos tvarka, o pagal prieinamų operandų ir resursų būklę.
  • Superskalarumas — kelios paralelinės ALU vienetai leidžia per taktą priimti ir vykdyti kelias instrukcijas (dažnai kartu su pipelining).

Našumo metrika

Pagrindiniai rodikliai: instruktavimo pralaidumas (instrukcijos per taktą), CPI (cycles per instruction) ir individuali instrukcijos latencija. Pipelining paprastai sumažina CPI (artina jį prie 1), tačiau tai priklauso nuo konflikto dažnumo, šakų spėjimo tikslumo ir kitų architektūros ypatybių.

Išvados

Instrukcijų konvejeris yra efektyvus būdas padidinti procesoriaus pralaidumą ir leidžia efektyviau panaudoti aparatūros resursus, ypač RISC tipo architektūrose. Tačiau siekiant maksimalaus naudingumo reikia spręsti su tuo susijusias problemas — duomenų, valdymo ir struktūrinius konfliktus — bei taikyti papildomas technikas (pvz., forwarding, branch prediction, out-of-order execution). Visi šie metodai kartu lemia modernių procesorių našumą ir sudėtingumą.