Toru (arvutustehnika)

Toru ehk konveier (inglise keeles pipeline) on kogum jadamisi ühendatud andmete töötlemise elemente, kus ühe elemendi väljund on järgmise elemendi sisendiks. Tihti tehakse sealjuures operatsioone samaaegselt.

Konveierite kasutamine on tänapäeva maailmas laialdaselt levinud. Kõige lihtsamaks näiteks võib siia tuua autotööstuse, kus konveierliini peal tehakse iga protsess oma tööjaama juures. Ühes kohas lisatakse juurde mootor, sealt edasi lisatakse rattad jne. Selle eeliseks on see, et kui ühele autole saab mingi detail lisatud saab selle mööda liini edasi saata ning asuda tööle uue auto kallal.

Arvutitehnikaga seotud torud:

Tavalised RISC torud, mis on kasutusel kesktöötlemisseadmetes ning teistes mikroprotsessorites. Neid kasutatakse peamiselt selleks, et täitsa samaaegselt mitmeid käske ühes vooluringis, mis on omakorda jaotatud etappideks, kus iga etapp töötleb mingit kindlat osa ette antud juhisest, andes samal ajal edasi osalisi tulemusi järgmisse staadiumi.

Graafilised torud, mis on kasutusel graafikaprotsessorites (GPU-des). Sarnaselt kesktöötlemisseadmete torudega on graafilised torud jaotatud etappideks, mille alusel käske täidetakse. Üldiselt on selliste torude eesmärgiks töötelda eelnevalt loodud 3D mudeli põhjal pilt kuvarile. Kuna selliste sammude läbi viimine sõltub suuremas osas sellest, mis tarkvara ja riistvara kasutatakse ei ole olemas ka ühte universaalset graafilist toru, mis oleks sobiv kõikideks juhtudeks.

Tarkvara torud, mis koosnevad üksteise järgel paikenvatest arvuti poolt läbi viidavatest käskudest (käsud, töötavad programmid, ülesanded, lõimed jne).

HTTP torud, kus kasutatakse tehnikat mitme erineva HTTP taotluse saatmiseks läbi ühe ja sama TCP ühenduse. Selle tõttu ei pea ootama kui eelnev taotlus lõpetatakse vaid saab saata uue peale.[1]

TööpõhimõteRedigeeri

Arvutis, kus on kasutusel torud liiguvad käsud läbi kesktöötlemisseadmete etappide kaupa. Tavaliselt on sellistes arvutites pipeline registrid, kuhu pärast igat etappi salvestatakse informatsiooni täidetud käskudest ning tehtud arvutustest selleks, et saaks minna edasi järgmise sammu juurde.

Selline korraldus laseb CPU-l viia läbi käsklusi ühe takti jooksul. On levinud, et paaris arvulised etapid töötavad ristkülik signaali ühes ääres ning paaritu arvulised etapid signaali teises ääres. Selline korraldus võimaldab suuremat kesktöötlemisseadme läbilaskmisvõimet kindlal taktsagedusel, kuid võib suurendada ka latentsust.

 
Viie-etapiline käsukonveier RISC-arhitektuuris

Käsu töötlemise saab jagada näiteks viieks etapiks:

  • käsu lugemine (IF)
  • käsu dekodeerimine (ID)
  • käsu täitmine (EX)
  • mälu poole pöördumine (MEM)
  • tulemuste salvestamine (WB)

Sellise jaotuse tulemusena saame protsessoris korraga täita viit käsku, kuigi iga käsu täitmine on igal ajahetkel erinevas etapis. Ühte käsku loeme, sellele eelnenud käsku dekodeerime, veel varasemat käsku täidame ja sellele eelnenud käsu tulemusi kirjutame salvestuskohta (mällu, ...).[2]

Iga etapp täidetakse ära ühe takti jooksul. Erinevate etappide täitmisele kuluv aeg on erinev. Kui mõne etapiga saadakse kiiremini ühele poole, on seade ülejäänud aja ooterežiimis. Seega on toru efektiivne ligikaudu ühepikkuste etappide korral. Kriitiline operatsioon on mälust lugemine:

Seetõttu on iga põhimälust lugemise ajal protsessori töö teatud ajaks seisatud (ingl processor stalls).


Käsu lugemine (inglise keeles instruction fetch) toimub olenevalt selle asukohast läbi program counteri, mis siis näitab kus maal programm hetkeseisul on. Sellest võib mõelda kui registrist, mis hoiab endas käsu aadressi. See suubub PC predictorisse, mis omakorda saadab selle käsu lugemise etappi. Samal ajal suurendab see oma väärtust 4 võrra (tuleneb sellest, et käsud on 4 baiti pikad) ning ennustab järgmise käsu aadressi. Kui tegemist on hargnemise või hüppega, siis PC predictori ennustus on vale. Uuemad arvutid kasutavad juba rohkem arenenuid süsteeme selle probleemiga tegelemiseks. [2]

Käsu dekoteerimise (Instruction decode) ülesandeks on saada aru, mida tuleb torus teha. Üldiselt kõige vähem aeganõudvam etapp.

Käsu täitmise (Execute) etapis toimub arvudega töötlemine. Tüüpiliselt on selles elemendis aritmeetika-loogikaplokk, mis viib läbi boolean operatsioone (and, or, not, nand, nor jne.) ning samuti teeb liitmise ja lahutamise tehteid.

AjaluguRedigeeri

Torude kasutamine algas 1970-nendate aastate lõpus enamasti superarvutites nagu näiteks vector protsessorites ning array protsessorites. Üks esimeseid superarvuteid oli Cyper series, mis oli ehitatud Control Data Corporationi poolt. Selle peamine arhitekt oli Seymour Cray. Tema tegi XMP superarvutid, mis kasutasid torusid korrutamis, liitmis ning lahutamis funktsioonideks. Hiljem lõi selline ettevõte nagu Star technologies paralleelismi, kus töötasid mitu toru käsku samaaegselt. Torude kasutamine ei olnud limiteeritud ainult superarvutitele vaid kõikidele arvuti tüüpidele. [3]

Riskid (Hazards)Redigeeri

  • Strukturaalne risk. Tekib näiteks siis, kui kaks seadet soovivad sama sammu ajal kasutada sama riistvararessurssi.
  • Andmerisk. Kahe järjestikuse käsu puhul, mida torus täidetakse, ei pruugi esimese käsu tulemus veel olla kättesaadav enne järgmise käsu alustamist.
  • Käsurisk. Hargnemise käsk kutsub toruga arvutis esile seisaku, kuna enne hargnemist on juba alustatud ilma hargnemiseta täitmisele tulevate käskude sisselugemist, dekoteerimist või täitmist.


Andmeriskide vältimiseks on võimalik kasutada kahte erinevat lahendust.

Esimeseks lahenduskeks on kasutada Bypassi ehk eesti keeles shunti. Seda tuntakse ka veel teise nime all, milleks on argumendi edastamine (operand forwarding).

SUB r3,r4 -> r10     ; Writes r3 - r4 to r10
AND r10,r3 -> r11    ; Writes r10 & r3 to r11

Joonisel on näidatud kuidas liiguvad käsud kasutades operand forwarding tehnikat läbi toru.


Tavalises torus, kus ei kasutada bypass tehnikat loetakse käsud sisse järgmiselt:

Kolmanda takti ajal arvutab käsk SUB (lahutamine) registrisse r10 uue väärtuse. Sama takti ajal dekoteerikase käsk AND ning loetakse registrist sisse r10-ne väärtus. Kuigi eelnevalt läbi viidud SUB käsk ei ole veel kirjutatud r10-nesse. Alles viienda takti ajal kirjutatakse uus väärtus sisse, mistõttu on eelnevalt registrist loetud väärtus vale.

Selleks, et antud olukorda välitda tuleb andmed, mis arvutati SUB käsu poolt viia tagasi käsu täitmise (EX) etappi. Lahendusena saab kasutada mõnda bypass multiplekserit, mis asetatakse käsu dekoteerimise etappi lõppu, mille väljundid suunatakse ALU sisenditesse. Iga multiplekser valib kolme võimaluse vahel nagu on näidatud joonisel.

Dekoteerimise etapi loogika seob omavahel andmeid, mis on sisse kirjutatud käsu lugemisel ja dekoteerimisel. Neid võrreldakse registritega, mis on loetud käsu lugemise ja dekoteerimise ajal ( ehk eristab sisse loetud ning kirjutatud andmeid) ning võrdleb neid omavahel. Selle tulemusena valib multiplekser kõige hiljutisemad andmed ning toimub nende edastamine. Sellised bypass multipleksrid võimaldavad läbi viia lihtsaid käske vaid ALU, multipleksri ning flip-flopi latentsusega.[2]

Toru ei tee üksiku käsu täitmist kiiremaks. Suureneb täidetud käskude arv ajaühikus. Teoreetiline ülempiir on “üks käsk iga sammu ajal”, praktikas ei ole see saavutatav.


Teiseks võimaluseks riskide vältimiseks on toru blokeerida (pipeline interlock).

Kasutame illustreerimiseks järgmist näidet.

LD  adr    -> r10
AND r10,r3 -> r11
Bypassing backwards in time Problem resolved using a bubble
   


Andmed mis loetakse sisse aadressilt adr on valed seni kuni pole täidetud andmete salvestamise käsk. Selle aja mõõdudes on AND käsk läbinud juba ALU ja kuna andmeid saab saata ainult ajas edasi, siis esimesel pildid toodud lahendus on vale. Selle lahendamiseks saab ühe takti sisse viia viivituse, mis siis viivitaks AND käsku ühe takti võrra. Nüüd loetakse alguses kasu dekoteerimise ajal sisse ikkagi valed andmed, aga kuna oleme viivitanud töö tsüklit ühe takti võrra, siis annab see aega multiplekseril lugeda sisse mälust uued ning õiged andmed. Käsu täitmise (EX), lugemise (IF) ning tulemuste salvesamise (WB) etapid näevad seda kui no-operation käsku (NOP).[2]

Käsuriskide lahendamiseks on neli võimalikku moodust.

Hargnemine vähetõenäoline: Sellises olukorras võetakse käsk kindlasti pärast hargnemist käsu vahemälust (Instruction cache), aga täidetakse ainult sellisel juhul kui hargnemist ei võeta. Kui hargnemist ei toimu püsib toru nii öelda täis. Hargnemise esinemise korral märgitakse käsk kui no-operation ning võimalus täita käsk ühe takti jooksul kaob.

Hargnemine tõenäoline: Sellises olukorras võetakse käsk kindlasti pärast hargnemist käsu vahemälust, aga täidetakse ainult sellisel juhul kui hargnemine toimub. Kompilaator saab alati täita ajastuspesa sellises harus ja kuna suurema tõenäosusega ka hargnemine toimub, siis on sellisel juhul väikem IPC karistus kui eelmisel varjandil.

Ajastuspesa: Sellises olukorras võetakse käsk kindlasti pärast hargnemist, käsu vahemälust ja alati täidetakse see isegi siis kui hargnemist ei toimu.

Hargnemiste ennustamine: Paralleelselt sellega, et otsitakse käske, proovitakse arvata kas käsk on hargnemine või hüpe ning leitakse ka sihtmärk. Kui oletus on vale, kustutatakse valesti valitud sihtmärk.[2]

Harud (Branches)Redigeeri

Kui toru puutub kokku harudega, siis sellega koos käivad ka riskid. Kui tavaliselt on ette antud üks käsklus, siis harudega võib esineda neid rohkem kui üks, mistõttu tekivad ka erinevad probleemid. Kui protsessor suudab haruga tegeleda ühe takti jooksul, siis probleeme ei teki, aga kui ei suuda siis see jääbki käske võtma järjestikku.

Ajatuspesa (Branch delay slot) - aadress, mis asub vahetult hargnemiskäsu järel. Neid võib olla rohkem kui üks. Hargnemisele järgnevad käsud loetakse alati protsessorisse (selletõttu et antud hetkel ei ole veel teada kas hargnemine leiab aset). Selliste hargnemiste täitmine ei põhjusta protsessorile täiendavat ajakulu.

Tingimuslik hargnemine. Siin sõltub hargnemine või mitte-hargnemine tingimuslippude väärtusest, mida me ei pruugi enne teiste käskude täitmise lõpetamist teada. Kõige lihtsam oleks siinkohal eeldada, et hargnemist ei toimu.

ViitedRedigeeri

  1. https://en.wikipedia.org/wiki/Pipeline_(computing), Richard Weiss, 30.04.2020, Pipeline(computing)
  2. 2,0 2,1 2,2 2,3 2,4 https://en.wikipedia.org/wiki/Classic_RISC_pipeline, Ira Leviton, 30.04.2020, Classic RISC pipeline
  3. https://en.wikipedia.org/wiki/Instruction_pipelining, Bernando Sulzbach, 30.04.2020, Instructin pipelineing