**Liukuhihna** (engl. *instruction pipeline*) suorittimen käskykannassa lisää suorittimen suorituskykyä jakamalla käskyn suoritus useampaan vaiheeseen (engl. *stage*), jolloin joka vaiheessa voi suorittaa eri käskyä. Joka vaiheessa on vain osa käskyn tarvitsemasta logiikasta, jolloin kellotaajuus on käytännössä nopeampi: jokaisen käskyn suoritusaika on sama kuin ilman liukuhihnaa.

Esimerkiksi MIPS-arkkitehtuurissa vaiheet ovat:

1. käskyn haku (engl. *instruction fetch*)
2. käskyn purku (engl. *instruction decode*)
3. suoritus (engl. *execute*)
4. muistihaku (engl. *memory access*)
5. takaisinkirjoitus (engl. *write back*)

Useita liukuhihnan optimointiin tarkoitettuja tekniikoita kehitettiin IBM 7030:tä varten.
Liukuhihnoitus on jo varhaisissa mikroprosessoreissa tunnettu tekniikka. Esimerkiksi MOS 6502 ja Zilog Z80 osaavat hakea seuraavan käskyn muistista, kun edellisen suoritus on kesken (*prefetch*), eli nykytermein niillä on kaksivaiheinen liukuhihna. Intelin tekemä tutkimus havaitsi, että jo tämä yksinkertainen liukuhihnoitus paransi suorituskykyä 35 % lisäten transistorimäärää vain 15 %.

Suoritusjärjestys
-----------------

Yksinkertaisessa tapauksessa käskyt ovat *kiinteästi ajoitettuja* eli ne suoritetaan ohjelman järjestyksessä. Suoritin voi käyttää *dynaamista ajoitusta* eli epäjärjestyksessä suorittamista (engl. *out-of-order execution*) vähentääkseen suoritusajan hukkaamista.

Esimerkkitapaus, jossa on kaksi yhteenlaskua:

```
ld      r1, 0(r2)    // lataa r1 muistiin r2:n osoittamasta paikasta
add     r2, r1, r3   // r2 := r1 + r3
add     r4, r3, r5   // r4 := r3 + r5

```

Oletetaan, että r3 ja r5 ovat jo luettuna ja lataus (`ld`) aiheuttaa välimuistihutin, jolloin liukuhihna *sakkaa* latauksen ajaksi. Myöhempi yhteenlasku ei riipu r1:stä ja se voidaan suorittaa aiemmin.

Haarautuminen
-------------

Jotta liukuhihnasta saadaan paras hyöty on sen kaikki vaiheet hyödynnettävä (pidettävä täysinä). Useat tekijät kuten ehtolauseet ja toistorakenteet aiheuttavat liukuhihnan sarjamuotoisuudelle ongelmia.

Esimerkkitapaus:

```
if (x > 0) {
     a=0;
     b=1;
     c=2;
}
d=3;

```

Jos *x* on suurempi kuin nolla käskyt liukuhihnassa ovat oikein koska `if` lauseen runko suoritetaan. Jos taas *x* on pienempi tai yhtäsuuri kuin nolla `if` lauseen runkoa ei suoriteta ja liukuhihna on vähemmän tehokas koska se joutuu perumaan käskyjen tekemiä muutoksia suorittimen tilaan.

Ennakoimalla suorituksen tulosta voitaisiin liukuhihnan vaiheet pitää täysinä ja saada parempi suorituskyky.
Haarautumisen ennakointi (engl. *branch prediction*) pyrkii ennakoimaan miten ehtolause tullaan suorittamaan ja parhaassa tapauksessa liukuhihna pysyy täytenä.

Katso myös
----------

* Superskalaarinen suoritin

Lähteet
-------

1. 1 2  Harris, David Money & Harris, Sarah L.: *Digital Design and Computer Architecture*, s. 409. Second Edition. Morgan Kaufmann, 2013. ISBN 978-0-12-394424-5.
2. ↑  Andy D. Pimentel: 2. Processor micro-architecture: Implicit parallelism (PDF) *staff.fnwi.uva.nl*. Viitattu 21.10.2019. (englanniksi)
3. ↑  Mark Smotherman: IBM Stretch (7030) -- Aggressive Uniprocessor Parallelism *people.cs.clemson.edu*. Viitattu 26.1.2020. (englanniksi)
4. ↑
5. 1 2 3 4 5  Lecture 5: Out-of-order Execution *hpca23.cse.tamu.edu*.  Arkistoitu 5.9.2019. Viitattu 26.1.2020. (englanniksi)
6. 1 2 3 4 5 6 7  Branch Prediction *users.cs.fiu.edu*. Viitattu 26.1.2020. (englanniksi)

Aiheesta muualla
----------------

* Understanding Pipelining and Superscalar Execution (englanniksi)