Varför inte köra alla instruktioner samtidigt? zMåste vänta på: yresultat från andra instruktioner yatt resurser i processorn ska bli lediga yatt få veta om instruktioner efter ett villkorligt hopp ska köras
Exempel zadd skriver ett värde i R1 zsub ska läsa värdet - måste vänta på add FIALUMEMWBFO FIALUMEMWBFO add r1 <- r2 + r3 sub r4 <- r1 + r5
Åtgärder zAnalys zStatisk optimering (i kompilatorn) zDynamisk optimering (i processorn)
Denna föreläsning zKodblock (basic blocks) zHoppgissning zDataberoenden zRegisterberoenden zResurskonflikter zPrecisa felavbrott
Analys zDela in koden i kodblock (basic blocks) zSamband mellan kodblock y- hoppgissning zInom kodblock yberoenden, resurskonflikter y- schemaläggning
Kodblock (basic blocks) zLäge börjar nytt block (det förra slutar precis innan) zHopp avslutar block (och nästa börjar precis efter)... instr LÄGE:instr instr BEQ R1,PLATS instr...
Kodsnutt zi1 L1:LOADR1 <- 8(R2) ; R1 <- hm(r2 + 8) zi2 LOADR4 <- 4(R1) ; R4 <- hm(r1 + 4) zi3 LOADR5 <- 8(R4) ; R5 <- hm(r4 + 8) zi4 ADDR1 <- R6 + R7 ; R1 <- r6 + r7 zi5 SUBIR8 <- R1 - #4 ; R8 <- r1 + 4 zi6 ADDR9 <- R4 + R1 ; R9 <- r4 + r1 zi7 BNEZR9,LABEL ; hopp till LABEL om r9 != 0 zi8 ADDIR4 <- R0 + #17 ; R4 <- 17 ty r0 == 0 zi9 ADDIR2 <- R1 + #4 ; R2 <- r1 + 4 zi10 JUMPL1
Indelning i kodblock zi1 L1:LOADR1 <- 8(R2) ; R1 <- hm(r2 + 8) zi2 LOADR4 <- 4(R1) ; R4 <- hm(r1 + 4) zi3 LOADR5 <- 8(R4) ; R5 <- hm(r4 + 8) zi4 ADDR1 <- R6 + R7 ; R1 <- r6 + r7 zi5 SUBIR8 <- R1 - #4 ; R8 <- r1 + 4 zi6 ADDR9 <- R4 + R1 ; R9 <- r4 + r1 zi7 BNEZR9,LABEL ; hopp till LABEL om r9 != 0 zi8 ADDIR4 <- R0 + #17 ; R4 <- 17 ty r0 == 0 zi9 ADDIR2 <- R1 + #4 ; R2 <- r1 + 4 zi10 JUMPL1 A B Indelning i kodblock
Kodblockets egenskap zKörs en instruktion i blocket, så körs alla zUndantag: felavbrott
Kontrollflödesgraf (CFG) B JUMP L1... X JUMP L1 LABEL: Y... L1: A BNEZ R9,LABEL
Kontrollberoende zInstruktioner efter ett hopp (block B) är kontrollberoende av hoppet zHoppinstruktionen måste köras först så att man vet om B ska köras
Hoppgissning zFöre körning - statisk yprovkörning + omkompilering ytumregler - enklare, mindre exakt zUnder körning - dynamisk yöverblick saknas men statistiken helt aktuell
Terminologi Fall-through = branch not taken = hoppet togs ej Branch taken = hoppet togs zi7 BNEZR9,LABEL ; hopp till LABEL om r9 != 0 zi8 ADDIR4 <- R0 + #17 ; R4 <- 17 ty r0 == 0 … zLABEL:
Statisk hoppgissning zProvkörning med indata (profiling) yhoppinstr på adress $47110: 0,1% taken yhoppinstr på adress $47124:91,2% taken... yomkompilering där statistiken utnyttjas zTumregler (heuristics) yKontrollflödesgrafen analyseras yBall & Larus: Branch Prediction For Free
Dynamisk hoppgissning Programräknare Adress till nästa instruktion De n minst signifikanta bitarna i adressen till nästa instruktion Giss- nings- tabell Instruktions- cacheminne
1-bits dynamisk hoppgissning z1 bit på varje plats i gissningstabellen zGissar att villkoret blir som förra gången for( i = 1; i < M; i++ ) for( j = 1; j < N; j++ ) loop_body(); zEfter N varv: felgissning + ändring zFörsta varvet därefter: felgissning igen
2-bits dynamisk hoppgissning zTvå felgissningar före ändring av gissning not taken taken not taken taken predict not taken (gissa att hopp inte tas) predict taken (gissa att hopp tas) z"Räknaralgoritmen" (saturating counter) 0123
Efter hoppgissning: spekulation zSpekulativ exekvering = En instruktion körs innan man vet att den ska köras z - statisk z - dynamisk
Statisk spekulativ exekvering zKompilatorn flyttar instruktioner förbi hopp BNEZR9,LABEL ADDIR4 <- R0 + #17 zÄr detta tillåtet? Krav: ysafeness ylegality
Safeness zInstruktionen får inte ge felavbrott BEQZR7,L3; hopp om r7 == 0 LOADR2 <- 0(R7) zFlyttningen är unsafe och alltså otillåten zÄndrar programmets exception behavior
Legality zInstruktionen får inte skriva över data som (kanske) behövs senare BEQZR1,L4 ADDR8 <- R5 + R6 L4:SUBIR9 <- R8 - #17 zFlyttningen illegal - ändrar dataflödet
En tillåten flyttning BNEZR9,LABEL ADDIR4 <- R0 + #17 zsafeness: OK, r ger ej overflow zlegality: OK, R4 skrivs ändå vid LABEL LABEL:ADDIR4 <- R0 + #43...
Dynamisk spekulativ exekvering zInstruktioner efter ett hopp utförs zWriteback stoppas om gissningen var fel zBehandling av felavbrott skjuts upp zÄven instruktioner där hoppet landar (branch target) kan hämtas och utföras
Analys inom ett kodblock zDataberoenden zRegisterberoenden zResurskonflikter
Databeroende FIALUMEMWBFO FIALUMEMWBFO add r1 <- r2 + r3 sub r4 <- r1 + r5 zadd producerar värde, sub konsumerar zavspeglar dataflödet genom programmet zflow dependence ztrue data dependence zRAW (Read After Write)
Dataflödesgraf (DFG) i1i2i3i4i5i6i7 RAW R4RAW R1 RAW R9 zEndast RAW-beroenden zEndast inom ett kodblock RAW R1RAW R4
Varning, fälla! zi1 L1:LOADR1 <- 8(R2) ; R1 <- hm(r2 + 8) zi2 LOADR4 <- 4(R1) ; R4 <- hm(r1 + 4) zi3 LOADR5 <- 8(R4) ; R5 <- hm(r4 + 8) zi4 ADDR1 <- R6 + R7 ; R1 <- r6 + r7 zi5 SUBIR8 <- R1 - #4 ; R8 <- r1 + 4 Detta är inget databeroende (inget RAW-beroende) ! Det inte är samma data som läses! x
Registerberoenden: WAR zadd skriver över r1 zsub måste köras först för att få rätt värde zantidependence zWAR (Write After Read) sub r4 <- r1 + r5 add r1 <- r2 + r3
Registerberoenden: WAW sub r1 <- r4 + r5 add r1 <- r2 + r3 zBåde sub och add skriver r1 zadd måste köras sist, så att det blir rätt värde efteråt zoutput dependence zWAW (Write After Write)
Beroendegraf i1i2i3i4i5i6i7 RAW R1RAW R4 RAW R1 RAW R9 zRAW, WAR, WAW zEndast inom ett kodblock WAR R1 WAW R1 Beroendegraf
Kompilatorn gör zRegisterallokering (register allocation) -avgör när en variabel ska finnas i register zRegistertilldelning (register assignment) -avgör vilket register en variabel ska finnas i vid ett visst tillfälle
Registerallokering och registertilldelning kan göras: zLokalt = inom ett kodblock zGlobalt = inom en procedur (men över flera kodblock) zInterprocedurellt = över flera procedurer
Renaming i processorn zRegisteromdöpning (renaming) zEtt antal extraregister utan nummer zKan ej styras av programmeraren zLagrar gamla värden som skrivits över tills instruktionen som behöver värdet körs
Resurser i processorn zFetch bandwidth = hämtade instr./cykel zLäsportar på registeruppsättningen zALU-enheter zSkrivportar till cacheminnet z...
Instruktionsschemaläggning zInstruktioner kan flyttas om, så att processorns resurser utnyttjas bättre zKan göras statiskt (av kompilatorn) eller dynamiskt (av processorn) zKan göras lokalt (inom kodblock) eller globalt (inom procedur)
Precisa felavbrott zDynamisk instruktionsschemaläggning ger problem: var var man vid felavbrottet? zPrecisa avbrott: det går att peka ut en instruktion, så att den och alla tidigare instruktioner är helt utförda, och alla senare instruktioner inte är utförda alls.
Hårdvara för precisa avbrott zHoppgissning i alla nya processorer zFelgissade hopp händer ofta, måste klaras zHårdvara för att ångra felspekulation finns zSamma kretsar används vid felavbrott
Sammanfattning (1) zKontrollberoenden yvar 5:e instruktion ett hopp yhoppgissning, spekulation zDataberoenden (RAW) yomöjliga att gå runt ysnabbare hårdvara enda chansen
Sammanfattning (2) zRegisterberoenden (WAR, WAW) yflera register ybättre registerallokering zResurskonflikter ymera resurser yinstruktionsschemaläggning yWAR, WAW specialfall av resurskonflikter