Procesoriaus instrukcijų konvejeris (pipelining): apibrėžimas ir veikimas
Sužinokite, kas yra procesoriaus instrukcijų konvejeris (pipelining): apibrėžimas, veikimo principai, RISC etapai ir pralaidumo didinimo metodai aiškiai ir suprantamai.
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:
- Instrukcijos paėmimas
- Instrukcijų dekodavimas ir registrų surinkimas
- Vykdyti
- Prieiga prie atminties
- 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/logininiai 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ą.

Pagrindinė penkių pakopų RISC mašinos konvejerinė linija (IF = instrukcijos paėmimas, ID = instrukcijos atkodavimas, EX = vykdymas, MEM = prieiga prie atminties, WB = registro įrašymas atgal). Vertikalioji ašis - nuoseklios instrukcijos, horizontalioji - laikas. Taigi žaliame stulpelyje anksčiausia instrukcija yra WB etape, o vėliausia instrukcija yra instrukcijų gavimo etape.
Vamzdžių jungimo privalumai ir trūkumai
Vamzdžių jungimo privalumai:
- Sutrumpėja procesoriaus ciklo trukmė, todėl padidėja instrukcijų našumas. Vamzdžių išdėstymas nesutrumpina laiko, reikalingo instrukcijai įvykdyti; vietoj to jis padidina vienu metu ("vienu metu") apdorojamų instrukcijų skaičių ir sumažina uždelsimą tarp įvykdytų instrukcijų (vadinamas "pralaidumu").
Kuo daugiau vamzdyno pakopų turi procesorius, tuo daugiau instrukcijų jis gali apdoroti "vienu metu" ir tuo mažesnė uždelsimo trukmė tarp užbaigtų instrukcijų. Visuose šiandien gaminamuose
vyraujančiuose bendrosios paskirties mikroprocesoriuose naudojami bent 2 iki 30 ar 40 pakopų vamzdynai. - Jei naudojamas pipeliningas, procesoriaus aritmetinis loginis blokas gali būti suprojektuotas greičiau, tačiau jis bus sudėtingesnis.
- Teoriškai, lyginant su nepipelių branduoliu, našumas padidėja pakopų skaičiaus koeficientu (darant prielaidą, kad taktinis dažnis taip pat padidėja tuo pačiu koeficientu), o kodas yra idealiai pritaikytas vykdyti per konvejerį.
- Vamzdeliniai procesoriai paprastai dirba didesniu taktiniu dažniu nei operatyviosios atminties taktinis dažnis (nuo 2008 m. technologijų operatyvioji atmintis dirba mažesniu dažniu nei procesoriai), todėl padidėja bendras kompiuterių našumas.
Vamzdžių jungimo trūkumai:
Nors procesoriai ir kompiliatorių kūrėjai naudoja daugybę metodų daugumai trūkumų pašalinti, toliau pateikiamas dažniausiai pasitaikančių trūkumų sąrašas:
- Nebranduolinio procesoriaus konstrukcija yra paprastesnė ir pigesnė, nebranduolinis procesorius vienu metu vykdo tik vieną instrukciją. Taip išvengiama šakų vėlavimo (Pipelining'e kiekviena šaka vėluoja), taip pat problemų, kai vienu metu vykdomos nuoseklios instrukcijos.
- Vamzdeliniame procesoriuje tarp modulių įterpus flip flopus, instrukcijų vėlinimas padidėja, palyginti su nevamzdeliniu procesoriumi.
- Neipeline procesoriaus instrukcijų pralaidumas bus apibrėžtas. Daug sunkiau prognozuoti konvejerinio procesoriaus našumą ir jis gali labai skirtis skirtingoms programoms.
- Daugelyje konstrukcijų yra 7, 10, 20, 31 ir net daugiau pakopų vamzdynų; ilgo vamzdyno trūkumas yra tas, kad kai programa šakojasi, reikia išplauti (išvalyti) visą vamzdyną. Didesnis vamzdynų pralaidumas nepasiteisina, kai vykdomame kode yra daug atšakų: procesorius negali iš anksto žinoti, kur skaityti kitą instrukciją, ir turi laukti, kol atšakos instrukcija bus baigta, o už jos esantis vamzdynas lieka tuščias. Šį trūkumą galima sumažinti numatant, ar sąlyginė šakojimo instrukcija šakosis, remiantis ankstesne veikla. Po to, kai išsišakojimas išsprendžiamas, kita instrukcija turi nueiti visą kelią per vamzdyną, kol jos rezultatas tampa prieinamas ir procesorius vėl pradeda "dirbti". Tokiais kraštutiniais atvejais konvejerinio procesoriaus našumas gali būti prastesnis už nekonvejerinio procesoriaus našumą.
- Deja, ne visi nurodymai yra nepriklausomi. Paprastame konvejeryje instrukcijai įvykdyti gali prireikti 5 etapų. Kad šis konvejeris veiktų visu pajėgumu, jam reikės vykdyti 4 vėlesnes nepriklausomas instrukcijas, kol bus baigiama pirmoji. Bet kuri iš šių 4 instrukcijų gali priklausyti nuo pirmosios instrukcijos išvesties, todėl vamzdyno valdymo logika turi laukti ir į vamzdyną įterpti stabdymą arba nereikalingą taktinį ciklą, kol priklausomybė bus išspręsta. Laimei, tokie metodai kaip persiuntimas gali gerokai sumažinti atvejų, kai reikia stabdyti, skaičių.
- Savarankiškai modifikuojančios programos gali būti netinkamai vykdomos konvejerinėje architektūroje, kai modifikuojamos instrukcijos yra netoli vykdomų instrukcijų. Taip gali atsitikti dėl to, kad instrukcijos jau gali būti išankstinėje įvesties eilėje (Prefetch Input Queue), todėl modifikavimas gali neįsigalioti būsimoms instrukcijoms vykdyti. Instrukcijų spartinančioji atmintinė šią problemą dar labiau apsunkina.
- Pavojai: Kai programuotojas (arba kompiliatorius) rašo asemblerio kodą, jis paprastai daro prielaidą, kad kiekviena instrukcija įvykdoma prieš vykdant kitą instrukciją. Kai ši prielaida nepatvirtinama konvejeriniu būdu, programa elgiasi neteisingai, tokia situacija vadinama pavojumi. Egzistuoja
įvairūs pavojaus sprendimo arba apėjimo būdai, pavyzdžiui, persiuntimas ir vėlavimas (įterpiant stabdymą arba praleistą taktinį ciklą).
Pavyzdžiai
Bendrasis vamzdynas
Dešinėje pavaizduotas bendras vamzdynas su keturiais etapais:
- Parsisiųsti
- Iššifruoti
- Vykdyti
- Įrašymas atgal
Viršutiniame pilkame langelyje yra instrukcijų, laukiančių vykdymo, sąrašas, apatiniame pilkame langelyje - įvykdytų instrukcijų sąrašas, o viduriniame baltame langelyje - vamzdynas.
Vykdymas yra toks:
| Laikas | Vykdymas |
| 0 | Laukiama keturių instrukcijų vykdymo |
| 1 |
|
| 2 |
|
| 3 |
|
| 4 |
|
| 5 |
|
| 6 |
|
| 7 |
|
| 8 |
|
| 9 | Vykdomi visi nurodymai |
Burbulas
Įvykus vykdymo "užstrigimui" (pertraukai), vamzdyne susidaro "burbulas", kuriame nieko naudingo neįvyksta. 2 cikle violetinės instrukcijos surinkimas vėluoja, o 3 ciklo dekodavimo etape dabar yra "burbulas". Viskas, kas yra už violetinės instrukcijos, taip pat vėluoja, tačiau viskas, kas yra prieš violetinę instrukciją, toliau vykdoma.
Akivaizdu, kad lyginant su pirmiau pateiktu vykdymu, burbulas užtikrina ne 7, o 8 laikrodžio taktų bendrą vykdymo laiką.
"Burbulai" yra tarsi užlaikymai (vėlavimai), kai nieko naudingo neįvyksta paėmimo, atkodavimo, vykdymo ir įrašymo atgal metu. Tai tarsi NOP (trumpinys nuo No OPeration) kodas.
1 pavyzdys
Tipiška dviejų skaičių sudėjimo instrukcija gali būti ADD A, B, C, kuri sudeda atminties vietose A ir B esančias reikšmes ir rezultatą įrašo į atminties vietą C. Vamzdeliniame procesoriuje vamzdynų valdiklis šią instrukciją suskaidytų į keletą užduočių, panašių į:
Vietos "R1" ir "R2" yra procesoriaus registrai. Atminties vietose, pažymėtose "A" ir "B", saugomos vertės įkeliamos (nukopijuojamos) į šiuos registrus, tada sudedamos ir rezultatas įrašomas į atminties vietą, pažymėtą "C".
Šiame pavyzdyje vamzdynas susideda iš trijų etapų - įkėlimo, vykdymo ir saugojimo. Kiekvienas iš šių etapų vadinamas vamzdyno etapais.
Procesoriuje, kuris nėra daugiapakopis, vienu metu gali veikti tik vienas etapas, todėl visa instrukcija turi būti baigta, kad būtų galima pradėti kitą instrukciją. Procesoriuje su vamzdeliu visos pakopos vienu metu gali dirbti su skirtingomis instrukcijomis. Taigi, kai ši instrukcija yra vykdymo etape, kita instrukcija bus dekodavimo etape, o trečioji - surinkimo etape.
2 pavyzdys
Kad geriau suprastume šią sąvoką, galime pažvelgti į teorinį trijų pakopų vamzdyną:
| Etapas | Aprašymas |
| Krovinys | Instrukcijos skaitymas iš atminties |
| Vykdyti | Instrukcijos vykdymas |
| Parduotuvė | Rezultato išsaugojimas atmintyje ir (arba) registruose |
ir pseudokodo asemblerio sąrašą, kuris turi būti vykdomas:
Taip jis būtų vykdomas:
| Laikrodis 1 | ||
| Krovinys | Vykdyti | Parduotuvė |
| ĮKROVIMAS |
|
|
LOAD instrukcija paimama iš atminties.
| Laikrodis 2 | ||
| Krovinys | Vykdyti | Parduotuvė |
| MOVE | ĮKROVIMAS |
|
Vykdoma LOAD instrukcija, o MOVE instrukcija paimama iš atminties.
| Laikrodis 3 | ||
| Krovinys | Vykdyti | Parduotuvė |
| ADD | MOVE | ĮKROVIMAS |
LOAD instrukcija yra saugojimo etape, kurio rezultatas (skaičius 40) bus įrašytas į registrą A. Tuo tarpu vykdoma MOVE instrukcija. Kadangi ji turi perkelti A turinį į B, ji turi laukti LOAD instrukcijos pabaigos.
| Laikrodis 4 | ||
| Krovinys | Vykdyti | Parduotuvė |
| PARDUOTUVĖ | ADD | MOVE |
STORE instrukcija įkeliama, o MOVE instrukcija baigiama ir ADD skaičiuojama.
Ir taip toliau. Atkreipkite dėmesį, kad kartais instrukcija priklauso nuo kitos instrukcijos rezultato (pvz., mūsų pavyzdys MOVE). Kai daugiau nei viena instrukcija nurodo tam tikrą operando vietą, ją skaitydama (kaip įvestį) arba rašydama (kaip išvestį), šių instrukcijų vykdymas kitokia nei pradinė programos tvarka gali sukelti pavojingą situaciją (minėta pirmiau).

Bendras 4 pakopų vamzdynas; spalvoti langeliai žymi viena nuo kitos nepriklausomas instrukcijas

3 ciklo burbulas atideda vykdymą
Susiję puslapiai
- Vamzdynas (kompiuterija)
- Lygiagretieji skaičiavimai
- Instrukcijų lygmens lygiagretumas
Klausimai ir atsakymai
Klausimas: Kas yra instrukcijų konvejerizacija?
A: Instrukcijų išvedžiojimas - tai šiuolaikinių mikroprocesorių, mikrovaldiklių ir centrinių procesorių projektavimo metodas, naudojamas instrukcijų našumui padidinti, padalijant procesoriaus instrukcijos apdorojimą į kelis nepriklausomus etapus, kiekvieno etapo pabaigoje juos saugant.
Klausimas: Kaip veikia konvejerinis paskirstymas?
A: Vamzdynų sujungimas veikia skaidant logiką į mažesnes dalis ir įterpiant flip flopus tarp logikos dalių, todėl sutrumpėja laikas, reikalingas logikai iššifruoti vertes, kol ji sugeneruoja galiojančius išėjimus, priklausančius nuo šių verčių. Tai leidžia pagreitinti laikrodžio periodus.
K.: Kokie yra keli vamzdynų pavyzdžiai?
A: Vienas iš vamzdynų pavyzdžių yra RISC vamzdynas, kuris yra suskirstytas į penkis etapus, o tarp kiekvieno etapo yra flip flopų rinkinys.
K: Kaip konvejeriai padidina instrukcijų pralaidumą?
A. Vamzdynų sujungimas padidina instrukcijų pralaidumą, nes leidžia procesoriaus moduliams dirbti lygiagrečiai, todėl sutrumpėja neveikimo laikas per instrukcijų ciklą ir pailgėja bendras apdorojimo laikas.
K.: Ar kiekvienas vamzdynas yra visiškai sujungtas su vamzdynais?
Atsakymas: Ne, ne kiekvienas vamzdynas yra visiškai sujungtas; kai kuriuose vamzdynuose yra laukimo ciklų, dėl kurių vėluojama judėti vamzdynu.
Ieškoti