Instruction-level parallellism (ILP) maakt gebruik van het feit dat meerdere instructies in een programma gelijktijdig kunnen worden uitgevoerd, zelfs als ze niet expliciet als parallel zijn gespecificeerd. Het wordt geïmplementeerd via een combinatie van hardware en compilertechnieken. Hier is een overzicht:
Hardwaretechnieken:
* Pipelining: Dit is de meest fundamentele techniek. Instructies worden opgesplitst in fasen (ophalen, decoderen, uitvoeren, geheugentoegang, terugschrijven), en meerdere instructies kunnen zich tegelijkertijd in verschillende fasen van de pijplijn bevinden. Dit verhoogt de instructiedoorvoer, zelfs als dit de latentie van individuele instructies niet vermindert. Gevaren (gegevensafhankelijkheden, controleafhankelijkheden) kunnen de effectiviteit van pipelining beperken, waardoor technieken als doorsturen en vertakkingsvoorspellingen nodig zijn.
* Superscalaire architectuur: Er zijn meerdere uitvoeringseenheden aanwezig, waardoor meerdere instructies tegelijkertijd in één klokcyclus kunnen worden uitgevoerd. De processor plant op dynamische wijze instructies naar verschillende uitvoeringseenheden op basis van hun afhankelijkheden en beschikbaarheid. Dit vereist geavanceerde hardware voor instructieplanning.
* Zeer lang instructiewoord (VLIW): De compiler voert uitgebreide statische planning uit, waarbij meerdere onafhankelijke instructies in één enkel, zeer lang instructiewoord worden verpakt. Dit vereenvoudigt de hardware in vergelijking met superscalair, omdat de instructieplanning volledig tijdens het compileren plaatsvindt. Het vermindert echter de flexibiliteit en kan leiden tot een opgeblazen code als er niet voldoende onafhankelijke instructies beschikbaar zijn.
* Uitvoering buiten bestelling: Instructies worden uitgevoerd in een volgorde die verschilt van hun programmavolgorde, zolang de gegevensafhankelijkheden worden gerespecteerd. Dit vereist complexe hardware om afhankelijkheden bij te houden en het hernoemen van registers te beheren (om conflicten te voorkomen wanneer instructies opnieuw worden geordend).
* Vertakkingsvoorspelling: Voorspelt de uitkomst van vertakkingen (voorwaardelijke sprongen) om te voorkomen dat de pijpleiding vastloopt wanneer een vertakking wordt aangetroffen. Onjuiste voorspellingen kunnen leiden tot het doorspoelen van pijpleidingen en verspilling van cycli. Geavanceerde vertakkingsvoorspellingstechnieken maken gebruik van geavanceerde algoritmen en vertakkingsgeschiedenistabellen.
* Speculatieve uitvoering: Voert instructies uit voordat hun afhankelijkheden volledig zijn opgelost (bijvoorbeeld voordat een vertakking is opgelost). Als de speculatie onjuist is, worden de resultaten weggegooid. Deze techniek verbetert de prestaties aanzienlijk, maar voegt complexiteit toe en het risico op onjuiste resultaten als deze niet zorgvuldig wordt beheerd.
* Gegevensstroomanalyse: Hardware houdt gegevensafhankelijkheden tussen instructies bij om de juiste uitvoeringsvolgorde te garanderen, zelfs als de uitvoering buiten de juiste volgorde valt.
Compilertechnieken:
* Instructieplanning: De compiler herschikt de instructies om ILP te maximaliseren, rekening houdend met gegevensafhankelijkheden en resourcebeperkingen. Dit is cruciaal voor zowel superscalaire als VLIW-architecturen.
* Lus afrollen: Repliceert de hoofdtekst van een lus meerdere keren, waardoor het aantal beschikbare instructies voor parallelle uitvoering toeneemt. Dit kan de ILP verbeteren, maar kan ook de codegrootte vergroten.
* Softwarepipelining: Overlapt de uitvoering van iteraties van een lus, vergelijkbaar met pipelining op instructieniveau. Dit is met name effectief voor lussen met aanzienlijke afhankelijkheden tussen iteraties.
* Registreertoewijzing: Wijst registers efficiënt toe aan variabelen om registerverspilling te minimaliseren (variabelen in het geheugen opslaan) en de instructieplanning te verbeteren.
* Predikaatuitvoering: Hiermee kunnen instructies voorwaardelijk worden uitgevoerd op basis van een Booleaans predikaat. Dit kan ILP verbeteren door in sommige gevallen vertakkingen te vermijden.
Uitdagingen:
* Gegevensafhankelijkheden: Instructies die afhankelijk zijn van de resultaten van eerdere instructies kunnen niet gelijktijdig worden uitgevoerd. Dit beperkt de hoeveelheid ILP die kan worden bereikt.
* Beheer afhankelijkheden: Instructies die voorwaardelijk worden uitgevoerd (op basis van vertakkingen) kunnen niet worden uitgevoerd totdat de vertakkingsvoorwaarde is opgelost. Branch-voorspelling helpt dit te verzachten.
* Resourcebeperkingen: Beperkte uitvoeringseenheden en andere hardwarebronnen kunnen het niveau van parallelliteit dat kan worden bereikt beperken.
* Complexiteit: Het implementeren van ILP-technieken vereist een aanzienlijke hardware- en softwarecomplexiteit, waardoor de ontwerpkosten en het energieverbruik stijgen.
Samenvattend impliceert de implementatie van ILP een synergetisch samenspel tussen geavanceerde hardwareontwerpen en geavanceerde compileroptimalisaties. De specifieke technieken die worden gebruikt, zijn afhankelijk van de doelarchitectuur en de kenmerken van het programma dat wordt uitgevoerd. Moderne processors gebruiken een combinatie van deze technieken om een hoog niveau van parallellisme op instructieniveau te bereiken. |