TDT4160 Datamaskiner Grunnkurs Forelesning 8.11 Forgreningspredikering Kap 4.5 Superskalaritet Kap 4.5 Spekulativ utføring Kap 4.5
Dagens tema Forgreningspredikering (4.5) Hoppinstruksjoner og samlebånd Utsatt hoppinstruksjon Predikeringsteknikker Superskalaritet (4.5) Parallellitet og avhengigheter Ut-av-rekkefølge utføring Registeromdøping Spekulativ utføring (4.5)
Samlebånd og hoppinstruksjoner For å hente instruksjon tidlig, må adresse være klar Som regel: Sekvensielt Unntak: Hoppinstruksjoner (15-20%) Spesielt: Betinget (=forgreningsinstruksjoner) I1 I2 I3 I4 I5 I6 Normal sekvensiell utføring I1 I2 I3 I4 I5 I6 I15 I16 I17 Effekt av betinget hoppinstruksjon
Effekt av betinget hoppinstr.
Kodeeksempel BNE Else betinget hoppinstruksjon Hopp hvis i ulik 0 (Not Equal) BR Next ubetinget hoppinstruksjon Hopp alltid til Next Enkelt? Tar tid å dekode instruksjon og finne Nextadresse Vanskelig å hente rett instruksjoner inn tidlig!
Utsatt hoppinstruksjon I Hent Instr. E Utfør D - Hovedlager Setter inn NOOP (gjør ingenting) etter ubetinget hoppinstruksjon Slipper dermed å tømme samlebånd Enkelt, men ikke effektivt Fjerner NOOP og bytter rekkefølge. Utfører alltid instruksjon etter hoppinstr. Mer effektivt, men mer komplisert
Forgreningspredikering?? Gjett hvilken målinstruksjon som kommer til å bli valgt av betinget hoppinstruksjon og hent denne Gjette-teknikker : Statiske: Tar ikke hensyn til programhistorie Dynamiske: Ser på hva programmet har gjort tidligere Veldig mye brukt
Statisk FP Aldri anta hopp Alltid anta hopp Studier viser at dette er mer enn 50% riktig Gjett basert på type forgreningsinstruksjon Eks: BNE hopper alltid, BEQ hopper aldri Korrekthet på mer enn 75% rapportert Gjett basert på hoppretning Eks: Anta hopp bakover, anta aldri hopp fremover Hint fra kompilator (f.eks. ved løkker)
DFP: Bruk av 1 historiebit (1/2) Når ny betinget hoppinstruksjon blir utført Bruk 1 bit til å lagre om det ble hopp eller ikke Neste gang: Anta at det samme vil skje Hvis rett: Gjett det samme neste gang også Hvis feil: Bytt gjetting
DFP: Bruk av 1 historiebit (2/2) I1: i=0 I2:...... I5: i=i+1 I6: if i < 5 jump I2 I7:... Anta at vi starter i tilstand Predict not taken To gale gjettinger: Første gjennomløp (gjetter ikke hopp) Når i = 5 (gjetter hopp)
DFP: Lagring av historiebits Tabell over betingede hoppinstruksjoner som er utført Organisert på adresse Ser på historiebits for å gjette, oppdaterer etter utføring
DFP: Bruk av 2 historiebits Endrer ikke gjett på bakgrunn av bare en feilpred. Fungerer litt bedre på eksempelkode I1: i=0 I2:...... I5: i=i+1 I6: if i < 5 jump I2 I7:...
DFP: Bruk av historietabell For enkelte hoppinstr. kjenner man ikke måladr. før operandene er klare. Hva om vi bufrer måladr.? Historietabell... 101 ADD k, l 102 CMP k, i 103 BNE 101... 200 CMP m, 0 201 BEQ 215... Adresse 103 201 Måladr. 101 215 Historiebits Hopp Ikke hopp
Superskalaritet Et samlebånd er bra, flere er enda bedre! Eksempel Henter to instruksjoner om gangen Dupliserer steg 2-5 Har dermed opptil 10 instruksjoner under utføring Figuren tilsvarer ca. den første Pentium-prosessoren
Problemer ved superskalaritet Ikke alt kan utføres i parallell I1: R3 = R3 * R5 I2: R4 = R3 + 1 ;Trenger resultatet fra I1 Resultatet må bli lik sekvensiell utføring Forskjellige begrensninger på parallellitet: Sanne dataavhengigheter Les-etter-skriv (RAW) Utavhengigheter Skriv-etter-skriv (WAW) Antiavhengigher Skriv-etter-les (WAR) Ressurskonflikter (Hoppinstruksjoner)
Sanne dataavhengigheter Eksempel: I1: R3 = R3 * R5 I2: R4 = R3 + 1 En instruksjon trenger resultatet av en tidligere Også et problem ved vanlige samlebånd
Utavhengigheter Skriv-etter-skriv (WAW) Eksempel: I1: R3 = R3 * R5 I2: R4 = R3 + 1 I3: R3 = R5 + 1 I4: R7 = R3 * R4 I3 må fullføre etter I1 for at R3 skal bli rett Bare et problem dersom to instruksjoner skriver resultat samtidig eller ute av rekkefølge
Antiavhengigheter Skriv-etter-les (WAR) Eksempel: I1: R3 = R3 * R5 I2: R4 = R3 + 1 I3: R3 = R5 + 1 I4: R7 = R3 * R4 I2 må lese R3 før verdien blir overskrevet av I3 Bare et problem hvis en instruksjon skriver resultat før en tidligere får lest operander
Dagens oppgave Finn: Sanne dataavh. (RAW) Utavhengigheter (WAW) Antiavhengigheter (WAR) Program: I1: R3 = R0 * R1 I2: R4 = R0 + R2 I3: R5 = R0 + R1 I4: R6 = R1 + R4 I5: R7 = R1 * R2 I6: R1 = R0 R2 I7: R3 = R3 * R1 I8: R1 = R4 + R4
Ressurskonflikter Flere instruksjoner ønsker å bruke samme ressurs Eksempel (gitt kun en ALU): I1: R4 = R2 + 1 I2: R5 = R3 + 1 Ressurser: Lager, hurtigbuffer, busser, registre... Løsning: Vent eller dupliser ressurs
Scoreboard Avhengigheter gjør at prosessor av og til må vente. Hvordan skal den finne ut når? Scoreboard: Oversikt over instruksjoner under utføring og bruk av registre Vent med ny instruksjon hvis: Operand skrives av en aktiv instr. (RAW) Resultat skrives av en aktiv instr. (WAW) Resultat leses av en aktiv instr. (WAR)
Scoreboard: Eksempel Program: I1: R3 = R0 * R1 I2: R4 = R0 + R2 I3: R5 = R0 + R1 I4: R6 = R1 + R4 I5: R7 = R1 * R2 I6: R1 = R0 R2 I7: R3 = R3 * R1 I8: R1 = R4 + R4 Eksempelprosessor: 8 registre (R0-R7) Tildeling ( issue ) skjer i rekkefølge Fullføring ( retire ) skjer i rekkefølge 2 instr. kan tildeles hver klokkesyklus Addisjon/subtraksjon tar 2 klokkesykler, multiplikasjon tar 3
Ut-av-rekkefølge utføring Må instruksjoner utføres i programrekkefølge? I1: R1 = R2 + R3 I2: R4 = R1 + R6 I3: R7 = R8 + R9 Endring av rekkefølge kan bedre ytelse Endring av tildeling oppstart av utførsel Endring av fullføring tilbakeskriving av resultat Gir upresise avbrudd. Hvor skal vi returnere? Derfor ofte bare ut-av-rekkefølge tildeling Eneste krav: Resultatet må bli riktig!
Registeromdøping (1/2) Ut- og Anti-avhengigheter egentlig ressurskonflikter To instruksjoner ønsker å bruke samme register Ressurskonflikter løses ved duplisering Prosessoren har flere registre enn de som er synlig Dynamisk allokering Hver gang et register skrives til, bytter prosessor register Men: Hjelper ikke mot sanne dataavhengigheter! R3 = R3 * R5 R4 = R3 + 1 R3 = R5 + 1 R7 = R3 * R4 R3 = R3 * R5 R4 = R3 + 1 S1 = R5 + 1 R7 = S1 * R4
Registeromdøping (2/2) Program (gammel): I1: R3 = R0 * R1 I2: R4 = R0 + R2 I3: R5 = R0 + R1 I4: R6 = R1 + R4 I5: R7 = R1 * R2 I6: R1 = R0 R2 I7: R3 = R3 * R1 I8: R1 = R4 + R4 Program (ny): I1: R3 = R0 * R1 I2: R4 = R0 + R2 I3: R5 = R0 + R1 I4: R6 = R1 + R4 I5: R7 = R1 * R2 I6: S1 = R0 R2 I7: R3 = R3 * S1 I8: S2 = R4 + R4
Ut-av-rekkefølge tildeling & Ut-av-rekkefølge fullføring
Ut-av-rekkefølge og hoppinstr. Har sett: Endring av rekkefølge kan øke ytelse Avhengigheter begrenser endringsmuligheter Men hva med betingede hoppinstruksjoner? I1: IF R2 < 10 JUMP I7 I2: R3 = R3 + R1 Kan I2 utføres før I1? Så langt: Nei, bare bytting innenfor basic blocks Basic block: Kode til og med hoppinstruksjon
Basic blocks
Spekulativ utføring Opprinneligprogram: I1: <instr1> I2: <instr2> I3: load r1, X I4: add r3 = r1, r4 Ønsket program: I1: load r1, X I2: <instr1> I3: <instr2> I4: add r3 = r1, r4 Anta at henting fra hovedlager tar to sykler Bytter for å unngå forsinkelse Hva hvis <instr2> er en betinget hoppinstr.? Ikke sikkert at load skal utføres! Hva hvis load gir en exception? Spekulativ utføring av load