Presentation laddar. Vänta.

Presentation laddar. Vänta.

Instruktionsschemaläggning ● Beroendegraf + schemaläggning inom block ● Global och interprocedurell registerallokering ● Kodblock (basic blocks) är ofta.

Liknande presentationer


En presentation över ämnet: "Instruktionsschemaläggning ● Beroendegraf + schemaläggning inom block ● Global och interprocedurell registerallokering ● Kodblock (basic blocks) är ofta."— Presentationens avskrift:

1 Instruktionsschemaläggning ● Beroendegraf + schemaläggning inom block ● Global och interprocedurell registerallokering ● Kodblock (basic blocks) är ofta små – förstora dem med loop unrolling ● Hoppgissning ger fler möjligheter – förstora kodblocken med trace scheduling – förstora med superblock generation – förstora med villkorliga instruktioner – förstora med flyttning av osäkra instruktioner

2 Slingupprullning (loop unrolling) ● Utgå från en slinga loopindex = 1; L:if( loopindex > MAX ) goto end; loopbody(); loopindex = loopindex + 1; goto L end: ● Målsättning: få större block att schemalägga

3 Slingan upprullad med faktor 2 ● Startkod loopindex = 1; if( loopindex > MAX ) goto end; ● Slingan upprullad L:loopbody(); loopindex = loopindex + 1; if( loopindex > MAX ) goto end; loopbody(); loopindex = loopindex + 1; if( loopindex > MAX ) goto end; goto L end: flyttad och duplicerad kod duplicerad kod

4 Ytterligare optimering 1 ● Om start- och slutvärde för loopindex är konstanter (kallas statiskt bestämda) så kan testet mitt i slingan tas bort L:loopbody(); loopindex = loopindex + 1; if( loopindex > MAX ) goto end; loopbody(); loopindex = loopindex + 1; if( loopindex > MAX ) goto end; goto L end:

5 Extrakod för udda antal varv ● Om antalet varv i slingan inte är jämnt delbart med upprullningsfaktorn så blir det extrakod i början före slingan loopindex = 1; loopbody(); loopindex = loopindex + 1; L:loopbody(); loopindex = loopindex + 1; loopbody(); loopindex = loopindex + 1; if( loopindex > MAX ) goto end; goto L end: behövs om antalet varv är udda när upprullnings- faktorn = 2

6 Ytterligare optimering 2 ● Ofta är loopbody ett eller ett par enkla uttryck ● Ofta ingår matriser i uttrycken – ändrat loopindex kan flyttas in i matrisuttrycken ● Exempel: om loopbody är satsen res[i] = a * x[i] + y[i] där i är loopindex ● [se nästa bild]

7 Utnyttja matrisuttryck ● Uppräkning mitt i slingan tas bort ● Ersätts med ändrade matrisuttryck L:res[i] = a * x[i] + y[i]; i = i + 1; res[i+1] = a * x[i+1] + y[i+1]; i = i + 2; if( i > MAX ) goto end; goto L end: ● Tar bort WAW- och WAR-beroenden på i

8 När övre gränsen inte är statiskt bestämd ● Övre gränsen N är okänd vid kompileringen ● Rulla upp slingan med en faktor K ● Startkoden innehåller en slinga: loopindex = 1; L:if( loopindex > N mod K ) goto end; loopbody(); loopindex = loopindex + 1; goto L end: ● Därefter kommer upprullad slinga som körs (N / K) gånger resten när N divideras med K

9 Statisk hoppgissning ● Predict Taken – alla hopp gissas på samma sätt: de tas – i Spec-sviten tas 66% av alla hopp totalt – stor variation: 41%–91% av hoppen tas ● Backwards Taken, Forwards Not Taken – alla hopp bakåt (negativt offset) gissas Taken – alla hopp framåt (positivt offset) gissas Not Taken – fungerar bra för vissa program och kompilatorer – i Spec-sviten tas mer än 50% av alla framåthopp vilket gör det bättre att gissa att alla hopp tas

10 Mera statisk hoppgissning ● Fisher & Freudenberger: Predicting conditional branch directions from previous runs of a program (1992) – Profilbaserad hoppgissning – Provkörning med prov-indata – Instrumenterad kod som samlar in statistik – Resultatet: en profil över hur programmet körs – Profilen används för att styra en ny kompilering där information om hopputfall används – Kompilering – körning – omkompilering: ganska seg process

11 Ball & Larus – heuristik ● Branch Prediction for Free (PLDI '93) ● Rekonstruera kontrollflödesgraf från exe- fil ● Utnyttja mera information – inte bara "är hoppet bakåt eller framåt" ● Första steg – hitta hopp som styr slingor – slingkontrollhopp är inte alltid bakåt – men oftast – gissning: att slingan fortsätter – den gissningen stämmer nästan jämt ● Huvudtema – vad göra med andra hopp (svårare att gissa förstås...)

12 Tumreglerna för hopp som inte ingår i slingor ● Opcode – bltz, blez NT / bgtz, bgez T ● Loop – hopp förbi en loop NT ● Call – hopp förbi ett subrutinanrop T ● Return – hopp förbi en subrutinretur T ● Guard – hopp som beror på variabel X, och som hoppar förbi användning av X NT ● Store – hopp förbi en store-instruktion T ● Pointer – hopp om en pekare = 0 NT

13 Rangordning av tumregler ● 5040 olika rangordningar möjliga ● För varje hopp testas tumreglerna i ordning ● Så fort en passar in så används den ● Sedan betraktas hoppet som färdiggissat, tumregler senare på listan testas inte ● Slutlig ordning efter provkörningar Pointer – Call – Opcode – Return – Store – Loop – Guard ● Cirka 25% felgissningar – vilket faktiskt är bättre än de 34% man får om man gissar att alla hopp tas i Spec-sviten

14 En observation ● Ball & Larus' analys utgår från körbara filen ● Rekonstruerar information om programflödet – if( p == 0 ) error( "..." ); svarar mot tumregeln Call – if( x < 0 ) return( -1 ); svarar mot tumregeln Return ● Kompilatorn har denna information ● Analysen återskapar informationen utifrån kunskap om kompilatorns sätt att koda den

15 VLIW Very Long Instruction Word ● Mycket Långt Instruktions-Ord ● Instruktionen styr funktionsenheter direkt ● Exempel: Heltals- operationer Flyttals- add och sub Flyttals- mul och div Hopp- instruktioner instruktion (fyra del-instruktioner)

16 VLIW ● Enkel avkodning ● Krånglig kompilering ● Omkompilering för varje ny processor ● Många No-op i binärkoden ● Utgångspunkt för andra idéer tid E E E FDEW E E E FDEW E E E FDEW

17 Grund-VLIW ● Stor kodexpansion – loop unrolling med stora faktorer – basic blocks slås ihop till stora block, men småblocken blir kvar som kompensationskod – no-ops i koden när inte alla funktionsenheter jobbar ● Slöseri med plats i instruktionscacheminnet! ● Den enkla avkodningen gav inte tillräckligt mycket bättre prestanda för att uppväga

18 VLIW – erfarenheter ● Forskning om VLIW-kompilatorer förde kompileringstekniken framåt ● Spårschemaläggning – trace scheduling – kompilatorn försöker hitta ett spår av instruktioner som troligen ska utföras allihop – Spåret schemaläggs som en enhet – Inhopp och uthopp krånglar till det – Kompensationskod vid inhopp och uthopp, återställer ändrade variabler med mera

19 Modifierad spårschemaläggning ● Superblock – ett spår som bara har ett inhopp, men som kan ha flera uthopp – minskar problemen som finns hos vanlig spårschemaläggning – lättare att hantera för kompilatorn

20 Enkelt exempel ● Slingkropp med villkor ● Troliga vägen är skuggad ● Rulla upp slingan ● Schemalägg troliga vägen

21 Spårschema- läggning ● Fyra ingångar ● Fyra utgångar ● Kompensationskod för varje in- och utgång ● Besvärligt att schemalägga

22 Super- block ● En ingång ● Flera utgångar ● Extrakod bredvid för osannolika fall ● Lättare att schema- lägga

23 Slingburna beroenden ● Beroende från ett varv i slingan till ett annat ● Exempel res[i] = a * x[i-1] + y[i-2] ● Kräver extra analys för att hittas

24 Software pipelining ● Bra om latens längre än körtiden för ett varv

25 Exempel ● En slinga L:LoadF0 <- 0(R1) ; läs M[i] Add.DF4 <- F0 + F2 ; addera konstant Store0(R1) <- F4 ; skriv M[i] DAddUIR1 <- R1 + 8 ; räkna upp i BneR1,R2,L ; fortsätt om i < N ● Antaganden – 1 cykel/instruktion – Latens för flyttalsoperation cirka 5 cykler

26 Slinga med software pipelining ● (Startkod utelämnad) L:Store0(R1) <- F4 ; skriv M[i] Add.DF4 <- F0 + F2 ; addera till M[i+1] LoadF0 <- 16(R1) ; läs M[i+2] DAddUIR1 <- R1 + 8 ; räkna upp i BneR1,R2,L ; fortsätt om i < N (Stoppkod utelämnad)

27 Startkoden ● Startkod LoadF0 <- 0(R1) ; läs M[0] Add.DF4 <- F0 + F2 ; addera till M[0] LoadF0 <- 8(R1) ; läs M[1] ● och här kommer slingan igen L:Store0(R1) <- F4 ; skriv M[i] Add.DF4 <- F0 + F2 ; addera till M[i+1] LoadF0 <- 16(R1) ; läs M[i+2] DAddUIR1 <- R1 + 8 ; räkna upp i BneR1,R2,L ; fortsätt om i < N ● (Stoppkod utelämnad)

28 Stoppkoden ● Startkod utelämnad, slingan igen Sista varvet, kommentarer med rött: r1 == i == N-1 L:Store0(R1) <- F4 ; skriv M[i] M[N-1] Add.DF4 <- F0 + F2 ; add till M[i+1] M[N] LoadF0 <- 16(R1) ; läs M[i+2] M[N+1] DAddUIR1 <- R1 + 8 ; räkna upp i Obs! BneR1,R2,L ; fortsätt om i < N ● Stoppkoden Nu: r1 == N; sista varvet: r1 == N-1, då lästes M[N+1] L:Store0(R1) <- F4 ; skriv M[N] Add.DF4 <- F0 + F2 ; addera till M[N+1] Store8(R1) <- F4 ; skriv M[N+1]

29 Villkorliga instruktioner – CMOV ● Exempel if( a == 0 ) s = t; ● Anta: a i R1, s i R2, t i R3 ● Vanlig översättning Bneqzr1,F ; om a != 0 så hoppa fram Copyr2 <- r3 ; kopiera från t till s F: ; fortsättning ● Översättning med CMOV Cmovzr1, s <- t ; om a == 0 så kopiera

30 Villkorliga instruktioner allmänt ● Inte bara CMOV – alla instruktioner kan göras villkorliga ● Exceptions – viktigt att instruktionen aldrig avbryter körningen om villkoret inte är uppfyllt ● CMOV finns i – Alpha, Mips, Power PC, Sparc, x86 ● Villkor för alla instruktioner finns i – IA-64 (Intel Itanium-serien)

31 Villkorliga instruktioner, + och – ● För – Minskar andelen hopp i koden – Gör att basic-blocks blir större – Bra om villkoret oftast är uppfyllt ● Emot – Om villkoret sällan är uppfyllt... – så körs onödiga instruktioner – som fyller upp instruktionscacheminnet – och använder resurser i processorn

32 Spekulation i samarbete mellan kompilator och processor ● Kompilatorn kan flytta instruktioner förbi hopp ● Utan samarbete ska flyttade instruktioner vara – Legal – skriver inte över viktiga värden – Safe – ger inte nya exceptions ● Samarbete kan göra flera instruktioner flyttbara

33 Metod 1 – ignorera vissa felavbrott ● Felavbrott delas in i två klasser – felavbrott som bara felaktiga program gör (exempelvis segmenteringsfel) – felavbrott som korrekta program kan göra (exempelvis sidfel) ● I korrekta program händer första klassens felavbrott bara i felspekulerade instruktioner ● Stäng av alla felavbrott i första klassen ● Felaktiga program ger nu felaktiga resultat – första klassens felavbrott borde ha stoppat körningen ● Korrekta program körs som vanligt men fortare

34 Metod 2 – felavbrottsfritt med kontroll ● Två varianter av instruktioner – normala som ger felavbrott vid behov – spekulativa som aldrig ger felavbrott ● När kompilatorn spekulerar lägger den ut spekulativa instruktioner ● Extra kontroll-instruktioner läggs till som undersöker om felavbrott borde inträffa ● Alla program körs korrekt ● Alla program drabbas av att köra de extra kontroll-instruktionerna vilket tar lite tid

35 Metod 3 – giftigbitar ● Alla register får en extra statusbit – giftigbiten, eller poison bit ● Två varianter av instruktioner – normala som ger felavbrott vid behov – spekulativa som aldrig ger felavbrott men som ettställer giftigbiten ● Om en normal (icke-spekulativ) instruktion läser ett register med ettställd giftigbit, så avbryts körningen med felavbrott ● Alla program körs korrekt ● Giftigbitarna ger extrajobb vid processbyte

36 Metod 4 – boosting ● Flyttade instruktioner flaggas som spekulativa ("boosted") ● Särskilda fält i instruktionen anger – hur många hopp instruktionen flyttats förbi (exempel: 3 hopp = "boosted 3 levels") – hur kompilatorn gissar att hoppen utfaller ● Processorn sparar instruktionens resultat – i omordningsbuffert eller liknande – tills hoppen har utförts så spekulationen kan kollas


Ladda ner ppt "Instruktionsschemaläggning ● Beroendegraf + schemaläggning inom block ● Global och interprocedurell registerallokering ● Kodblock (basic blocks) är ofta."

Liknande presentationer


Google-annonser