Multithreading (computerarchitectuur)
Interleaved/Temporal multithreadingEdit
Coarse-grained multithreadingEdit
De eenvoudigste vorm van multithreading doet zich voor wanneer een thread wordt uitgevoerd totdat deze wordt geblokkeerd door een gebeurtenis die normaal gesproken een lange-termijn-stagnatie zou veroorzaken. Zo’n blokkade kan een cache miss zijn die buiten de chip geheugen moet benaderen, wat honderden CPU cycli kan duren voordat de gegevens terugkomen. In plaats van te wachten tot de vertraging is opgelost, zou een processor met threads de uitvoering overschakelen naar een andere thread die klaar is om te draaien. Pas als de gegevens voor de vorige thread waren aangekomen, zou de vorige thread weer op de lijst van startklare threads worden geplaatst.
Voorbeeld:
- Cyclus i: instructie j van thread A wordt gegeven.
- Cyclus i + 1: instructie j + 1 van thread A wordt gegeven.
- Cyclus i + 2: instructie j + 2 van thread A wordt gegeven, wat een laadinstructie is die in alle caches mist.
- Cyclus i + 3: thread scheduler aangeroepen, schakelt over naar thread B.
- Cyclus i + 4: instructie k van thread B wordt gegeven.
- Cyclus i + 5: instructie k + 1 van thread B wordt gegeven.
Conceptueel is het vergelijkbaar met coöperatieve multi-tasking die in real-time besturingssystemen wordt gebruikt, waarbij taken vrijwillig uitvoeringstijd opgeven als ze op een of andere gebeurtenis moeten wachten. Dit type multithreading staat bekend als block, cooperative of coarse-grained multithreading.
Het doel van multithreading hardware-ondersteuning is om snel te kunnen schakelen tussen een geblokkeerde thread en een andere thread die klaar is om te draaien. Om dit doel te bereiken moet de hardware de zichtbare registers van het programma repliceren, evenals sommige controleregisters van de processor (zoals de programmateller). Schakelen van de ene thread naar de andere betekent dat de hardware overschakelt van de ene registerset naar de andere; om efficiënt tussen actieve threads te schakelen, moet elke actieve thread zijn eigen registerset hebben. Om bijvoorbeeld snel tussen twee threads te schakelen, moet de register-hardware twee keer worden geïnstantieerd.
Door extra hardware-ondersteuning voor multithreading kan in één CPU-cyclus van thread worden gewisseld, wat de prestaties ten goede komt. Bovendien zorgt extra hardware ervoor dat elke thread zich gedraagt alsof hij alleen werkt en geen hardware resources deelt met andere threads.
Vele families van microcontrollers en embedded processors hebben meerdere registerbanken om snel van context te kunnen wisselen voor interrupts. Dergelijke schema’s kunnen worden beschouwd als een soort blok multithreading tussen de gebruiker programma thread en de interrupt threads.
Interleaved multithreadingEdit
Het doel van interleaved multithreading is om alle data dependency stalls uit de uitvoeringspijplijn te verwijderen. Omdat een thread relatief onafhankelijk is van andere threads, is er minder kans dat een instructie in een fase van pipelining een output nodig heeft van een oudere instructie in de pijplijn. Conceptueel is het vergelijkbaar met preemptive multitasking, dat in besturingssystemen wordt gebruikt; een analogie zou zijn dat het tijdsinterval dat aan elke actieve thread wordt gegeven één CPU-cyclus is.
Voorbeeld:
- Cyclus i + 1: een instructie van thread B wordt gegeven.
- Cyclus i + 2: een instructie van thread C wordt gegeven.
Dit type multithreading werd eerst barrel processing genoemd, waarbij de duigen van een vat de pijplijnstadia en hun uitvoerende threads voorstellen. Interleaved, preemptive, fine-grained of time-sliced multithreading zijn modernere termen.
Naast de hardwarekosten die bij het bloktype multithreading worden besproken, heeft interleaved multithreading als extra kosten dat elke pijplijnstap de thread-ID bijhoudt van de instructie die hij aan het verwerken is. Omdat er meer threads tegelijk in de pijplijn worden uitgevoerd, moeten gedeelde bronnen zoals caches en TLB’s ook groter zijn om thrashing tussen de verschillende threads te voorkomen.
Gelijktijdige multithreadingEdit
De meest geavanceerde vorm van multithreading is van toepassing op superscalaire processoren. Terwijl een normale superscalaire processor elke CPU-cyclus meerdere instructies van een enkele thread uitvoert, kan een superscalaire processor bij simultaneous multithreading (SMT) elke CPU-cyclus instructies van meerdere threads uitvoeren. Aangezien een enkele thread een beperkte hoeveelheid parallellisme op instructieniveau heeft, probeert dit type multithreading het parallellisme over meerdere threads te benutten om de verspilling van ongebruikte uitgifteslots te verminderen.
Voorbeeld:
- Cyclus i: instructies j en j + 1 van thread A en instructie k van thread B worden gelijktijdig uitgegeven.
- Cyclus i + 1: instructie j + 2 van thread A, instructie k + 1 van thread B, en instructie m van thread C worden allemaal gelijktijdig uitgegeven.
- Cyclus i + 2: instructie j + 3 van thread A en instructies m + 1 en m + 2 van thread C worden gelijktijdig gegeven.
Om de andere soorten multithreading van SMT te onderscheiden, wordt de term “temporal multithreading” gebruikt om aan te geven wanneer instructies van slechts één thread tegelijk kunnen worden gegeven.
Naast de hardwarekosten die voor interleaved multithreading zijn besproken, brengt SMT de extra kosten met zich mee dat elke pijplijnfase de thread-ID van elke instructie die wordt verwerkt, moet bijhouden. Ook hier moeten gedeelde bronnen, zoals caches en TLB’s, worden afgestemd op het grote aantal actieve threads dat wordt verwerkt.
Implementaties zijn onder meer DEC (later Compaq) EV8 (niet voltooid), Intel Hyper-Threading Technology, IBM POWER5, Sun Microsystems UltraSPARC T2, Cray XMT, en AMD Bulldozer en Zen microarchitecturen.