Wat is Sprongvoorspelling (branch prediction)?
Techniek die de uitkomst van een voorwaardelijke sprong voor de uitvoering voorspelt en vooruit instructies verwerkt zonder de pipeline stil te leggen. Bij een foute voorspelling wordt het werk opnieuw gedaan.
Japanse benaming: 分岐予測
“Sprongvoorspelling (branch prediction)” komt voor in 12 oefenvragen uit 6 onderwerpen, bijv. CPU en architectuur, Instructieset en assembly, Hardwarebeveiliging.
Vakgebied: CPU en architectuur
Waarom pipelines het nodig hebben
Een CPU met pipeline haalt elke cyclus nieuwe instructies op, maar of een voorwaardelijke sprong wordt genomen, en waarheen, is pas bekend wanneer die enkele trappen later wordt uitgevoerd. Wachten zou de pipeline stil laten staan, en ruwweg één op de vijf instructies is een sprong. Sprongvoorspelling raadt in plaats daarvan de uitkomst bij het ophalen en gaat speculatief verder langs het voorspelde pad. Is de gok juist, dan gaat er geen tijd verloren; is hij fout, dan worden de speculatieve instructies weggegooid zonder de architecturale toestand te beïnvloeden en begint het ophalen opnieuw op het juiste pad, wat in een diepe pipeline een tiental tot ongeveer twintig cycli kost.
Hoe voorspellers gokken
Statische schema's gebruiken vaste regels, zoals voorspellen dat sprongen terug (lussen) worden genomen en sprongen vooruit niet. Dynamische voorspellers leren van de geschiedenis: een tabel met verzadigende 2-bitstellers, geïndexeerd op sprongadres, heeft twee foute uitkomsten op rij nodig om de voorspelling om te draaien, zodat het verlaten van een lus maar één misser veroorzaakt. Betere voorspellers combineren het adres met een globale geschiedenis van recente uitkomsten om correlaties tussen sprongen te vangen. De richting voorspellen is maar het halve werk; een branch target buffer (BTB) levert het doeladres, en een return address stack voorspelt terugkeer uit functies.
Wat een misser kost
De impact kan worden geschat als extra cycli per instructie (CPI): sprongfrequentie × misvoorspellingspercentage × penalty. Met 20 procent sprongen, 95 procent nauwkeurigheid en een penalty van 20 cycli is dat 0,2 × 0,05 × 20 = 0,2 extra CPI, een groot deel van het budget van een moderne core. Daarom doen verbeteringen in nauwkeurigheid van een procent of twee ertoe. Voor sprongen die van willekeurige data afhangen en niet kunnen worden voorspeld, gebruiken compilers en programmeurs soms code zonder sprongen, zoals conditional moves, waarbij een beetje extra werk wordt ingeruild voor de garantie dat er geen flushes optreden.
Speculatie en beveiliging
Verkeerd voorspelde instructies worden architecturaal weggegooid, maar ze kunnen toch sporen achterlaten in de microarchitecturale toestand, zoals caches. Aanvallen van het Spectre-type trainen de voorspeller zodat een slachtoffer speculatief geheime data leest en die via cachetiming lekt. Verdedigingen zijn onder meer speculatiebarrières na gevoelige grenscontroles (zoals lfence in x86), het maskeren van array-indices, retpoline-reeksen voor indirecte sprongen en microcodeinstellingen voor de voorspellers. Elke beperking kost prestaties, dus worden ze selectief toegepast. Oudere ISA's zoals MIPS gebruikten branch delay slots in plaats van voorspelling, een regel die voor latere ontwerpen een last werd.
Veelgestelde vragen
Wat gebeurt er als een sprong verkeerd wordt voorspeld?
De CPU gooit de instructies weg die hij speculatief langs het verkeerde pad heeft opgehaald en uitgevoerd, en begint opnieuw vanaf het juiste doel, wat in een typische diepe pipeline ruwweg 10 tot 20 cycli kost.
Hoe nauwkeurig is sprongvoorspelling in moderne CPU's?
High-performance voorspellers halen bij gewone code doorgaans meer dan 95 procent nauwkeurigheid, al kunnen sprongen die van willekeurige data afhangen veel moeilijker te voorspellen zijn.
Wat is het verschil tussen sprongvoorspelling en speculatieve uitvoering?
Sprongvoorspelling is de gok welke kant een sprong op gaat; speculatieve uitvoering is het daadwerkelijk uitvoeren van instructies langs dat gegokte pad voordat de gok is bevestigd.