Vooruitblik op Intel’s nieuwe IA-64 processorarchitectuur

0 reacties
Inhoudsopgave
  1. 1. Vooruitblik op Intel’s nieuwe IA-64 processor architectuur
  2. 0 reacties

Vooruitblik op Intel’s nieuwe IA-64 processor architectuur

Wat is IA-64 / Merced?

Van buitenaf lijkt de evolutie van de Intel processoren ontzettend hard te gaan, maar toch valt dit tot nu toe wel mee. Al sinds de 386 processor heeft Intel een 32-bits processor voor de PC op de markt. Ten tijde van de Pentium (en ook van de Pentium II en III) is deze 32-bit processor "geüpgrade" met een 64-bits databus, maar de processorkern zelf is nog steeds 32-bits gebleven: tot op de dag vandaag. Ook is zelfs onze allerlaatste Pentium III 550 MHz processor nog steeds gebaseerd op het oude x86 principe. Het de hele tijd sneller maken van bestaande processor architecturen kan natuurlijk niet eeuwig door gaan: tijd voor wat nieuws dus. Zo dacht Intel ook en samen met HP is er een geheel nieuwe processor architectuur bedacht onder de naam IA-64 (Intel Architecture - 64). In tegenstelling tot de IA-32 processoren (386 t/m Pentium III) zijn de IA-64 processoren compleet 64-bits: niet alleen de databus, maar vooral ook de processorkern. De IA-64 processoren hebben een aantal zeer interessante verbeteringen in de processor architectuur: de voornaamste zullen we zodadelijk bekijken. De eerste IA-64 processor die op de markt zal komen heeft nu nog steeds de codenaam Merced. Merced zal halverwege 2000 productieklaar zijn en is alleen bedoeld voor zware server-systemen. Een jaar later, in 2001, kunnen we al weer de tweede IA-64 processor verwachten, de McKinley. Volgens Intel’s roadmap heeft de McKinley twee maal zoveel performance als de Merced. Met de komst van een geheel nieuw type processoren is natuurlijk ook nieuwe software nodig. Voordat de Merced op de markt komt zal alle software al herschreven en/of opnieuw gecompileerd moeten worden naar 64-bits IA-64 versies. Alleen met de nieuwe software kan de Merced, of een andere IA-64 processor, echt het onderste uit de kan halen. Aangezien Intel al een IA-64 emulator heeft gemaakt voor IA-32 processoren kunnen software leveranciers nu al beginnen met de nieuwe versies.

De nieuwe zaken in IA-64

De nieuwe IA-64 architectuur is op zeer veel plaatsen superieur aan de IA-32 architectuur. We zullen een aantal voorbeelden bekijken om te zien wat nu de interessante zaken uit de IA-64 specificaties zijn. Een aantal van deze innovatieve technieken zijn Explicit Parallelism en Predication / Speculation. Alles zorgt ervoor dat twee belangrijke zaken in de processorwereld zo hoog mogelijk worden: de ILP (Instruction Level Parallelism), een maat voor het parallel uitvoeren van instructies en de IPC (Instructions Per Cycle) die aangeeft hoeveel instructies de processor gemiddeld per klokslag kan uitvoeren.

De probleemstelling: branches en memory latencies

De twee grootste performance tegenwerkers in de huidige processor architecturen zijn de zogenaamde branches en memory latencies. Een branch is vrij vertaald een "tak" en met die semafoor is het fenomeen branch ook goed te begrijpen. Indien binnen een programma op een gegeven moment een (conditionele) keuze moet worden gemaakt (bijvoorbeeld met een if of een compare statement) kan het programma verder gaan met meerdere programmatakken, ofwel branches. Als voorbeeld nemen we een programma dat twee getallen inleest en daarna met de eerste set instructies verder gaat als getal 1 groter is dan getal 2 en met de tweede set instructies verder gaat als getal 2 groter (of gelijk) is dan getal 1. De kracht van hedendaagse processoren is door parallel werken alvast vooruit te kunnen werken in programma's. Dit systeem heet out-of-order execution, oftewel de processor bepaalt de meest ideale volgorde waarin alle instructies worden uitgevoerd. Bij branches vormt er zich dus een probleem: op welk van de twee paden moet de processor alvast verder doorwerken? Hiervoor zijn in het verleden systemen als branch prediction uitgevonden: de processor voorspelt welke tak er het meest waarschijnlijk genomen gaat worden en die tak wordt alvast verder uitgevoerd. Als later in het programma blijkt dat deze voorspelling niet klopte is al het werk voor niets geweest en moet er opnieuw begonnen worden met de andere branch. Hoewel in de huidige architecturen misvoorspellingen slechts tussen de 5% en 10% van de gevallen voorkomen zijn de gevolgen toch fataal: een performance terugval tussen de 30% en 40% is meestal het gevolg. De oplossingen die de IA-64 architectuur hier voor heeft zien we verderop. Het tweede grote probleem zijn de memory latencies. Als de processor een aanvraag bij het geheugen doet voor het inlezen van een stuk data gaat er een tijd (een aantal nanoseconden) overheen eer deze data bij de processor aankomt. Deze "verknoeide" tijd noemen we de memory latency. Om de performance terugval als gevolg van deze latencies zo laag mogelijk te houden proberen huidige processor architecturen data al in te lezen voordat deze nodig is. Dit klinkt natuurlijk prachtig maar bij deze methode is er een groot probleem: indien ertussen het inlezen van de data en het gebruiken van de data een ander stuk data wordt weggeschreven naar het gebruikte stuk geheugen klopt de data die de processor al heeft ingelezen niet meer. Zo kunnen er grove fouten ontstaan. Ook voor dit probleem heeft de IA-64 architectuur een nieuw systeem bedacht.

Predication als oplossing voor branch-problemen

Zoals al vermeld zijn branches een groot struikelblok voor hoge processor performance. De IA-64 processoren pakken dit probleem op een nieuwe (een beetje lompe) wijze aan. Door de vele execution units die de processor heeft worden alle branches parallel verder uitgewerkt. Indien er dus een keuze uit twee is gaat de processor beide parallel verder verwerken. Nieuw bij de IA-64 zijn de 64 1-bit predication registers. Aan iedere nieuwe branch wordt een predication register toegewezen die het mogelijk maakt het verder berekenen van die branch stop te zetten. Zodra het predication register van een branch gelijk aan 1 wordt stoppen direct alle taken voor deze branch. De werkwijze is dus nu als volgt: de processor begint al met het verder doorwerken van alle branches. Zodra het blijkt dat een branch absoluut zeker niet gebruikt wordt zet de processor het predication register van deze branch op een. Het verder uitwerken hiervan stopt dan en alleen de branches waarvan wel nog gedacht wordt dat ze gebruikt kunnen gaan worden blijven door verwerkt worden. Doordat de juiste branch ook altijd vanaf het begin verwerkt wordt zal een performance terugval zich niet meer voordoen.

Bovenstaand plaatje illustreert dit alles nogmaals. We zien een mooie if-then-else constructie. Huidige processor architecturen zetten dit om naar 4 blokken: voor na de if wordt er gespeculeerd over then en else. Een van de twee blokken zal de processor alvast van tevoren doorwerken. Indien blijkt dat het de verkeerde was moet weer helemaal terug gegaan worden naar het einde van blok 1: een onzettende performance terugval dus. In de rechterkant van het plaatje zien we de aanpak van de IA-64. Beide mogelijkheden worden parallel uitgerekend. Ook zijn de predication bits te zien (p1 en p2). Een van beide processen zal d.m.v. predication bits worden uitgeschakeld zodra het bovenste gedeelte geheel is berekend. Een performance terugval door een speculatiefout is in deze architectuur niet mogelijk.

Speculation als oplossing voor memory latencies

Het tweede grote probleem waren de memory latencies. De laatste jaren is dit probleem steeds groter geworden: de toename in snelheid van processoren gaat namelijk veel harder dan de toename in snelheid van geheugen. Hoewel nieuwe RISC architecturen al een systeem hebben om data al in te lezen voordat deze gebruikt wordt is toch al gebleken dat deze methode enkele nadelen met zich meebrengt. Voor twee memory problemen heeft de IA-64 architectuur nieuwe oplossingen in petto: De van tevoren ingelezen data is later in het programma niet altijd noodzakelijk. Zeker bij branches is het goed mogelijk dat data die achteraf nooit gebruikt wordt alvast wordt ingelezen. Bij traditionele structuren wordt, indien er al een vooruit lees mogelijkheden zijn, de data niet alleen al van tevoren ingelezen (om de memory latency zo laag mogelijk te houden), maar wordt ook al meteen een groot brok error-correctie op de data los gelaten om non-valid informatie te vermijden. Deze error-correctie codes kosten (redelijk veel) processor tijd en zijn dus helaas in veel gevallen niet nodig. De IA-64 architectuur maakt gebruik van zogenaamde error-bits ("Nat" bits geheten) die aan stukken data worden gekoppeld. Deze bits geven aan of er errors zijn opgetreden bij het inlezen van de data. De Nat bit volgt de data bij alle operaties totdat de data wordt gecontroleerd met een nieuwe speciale check instructie. Zodra een check instructie wordt aangeroepen op de data wordt de error-correctie code pas gestart. De check instructie is zo geïmplementeerd dat deze geen extra klokslag nodig heeft. Volgens Intel is het zo dat data die errors oplevert bij het inlezen in 99% van de gevallen later toch niet gebruikt wordt. De processorintensieve error correctie wordt zo uitgespaard. Bij de IA-64 kan een compiler er dus voor zorgen dat zeer veel data al voor gebruik wordt ingelezen. Doordat er geen performance nadelen aan dit nieuwe systeem vast hangen kan vooruit lezen bij de nieuwe IA-64 veel intensiever gebruikt worden.

Een tweede vorm van speculation is Data Speculation. Dit maakt het zelfs mogelijk om data al in te lezen voordat er mogelijk nog iets weggeschreven gaat worden op hetzelfde geheugenadres. Indien dit met traditionele architecturen zou gebeuren gaat er onherroepelijk is verkeerd: stel je voor dat in regel 50 van een programma de variabele X nodig is. Bij regel 20 haalt de processor deze variabele alvast uit het geheugen om geen last te hebben van memory latencies. Als in regel 35 nu echter iets wordt weggeschreven naar variabele X is er voor de instructie van regel 50 de verkeerde waarde beschikbaar, omdat de alvast eerder ingelezen waarde niet mee is veranderd bij de schrijf actie. De IA-64 architectuur heeft voor dit probleem een Advanced Load Address Table (ALAT) ingesteld. In deze tabel wordt bijgehouden welke data al van tevoren is ingelezen uit het geheugen. Indien de processor een schrijfactie tegenkomt voor een geheugenadres dat in de ALAT staat wordt de van tevoren ingelezen data ongeldig verklaard en vervangen door de nieuwe waarde(s). Dit systeem is geheel nieuw en maakt het mogelijk om data al ver voordat deze nodig is in te lezen zonder gevaar voor ongeldige waardes.

Loops worden geoptimaliseerd door register rotation

Speciaal voor de veel gebruikte loops in programmatuur heeft de IA-64 architectuur enkele nieuwe functies. Traditionele processoren zien loops als standaard branches: iedere iteratie van een loop wordt gezien als nieuwe tak. (Een iteratie is een enkele doorloop van een loop. Indien we een loopje tweemaal doorlopen zijn er dus twee iteraties.) Iets wat nieuwere RISC architecturen al kunnen is het systeem van loop unrolling. Met dit systeem worden loops ook echt als loops herkend en wordt de code van een loop gewoonweg enkele keren gedupliceerd. Dit vervaagt het branches idee en maakt parallel verwerken een stuk makkelijker. Een nieuw systeem van de IA-64 architectuur is Register Rotation. Dit maakt het mogelijk dat loops gepipelined worden uitgevoerd. Pipelining is een systeem waarbij een proces wordt opgedeeld in een aantal stages. Als object a al in stage 2 van een proces is dat object b dan al aan stage 1 kan beginnen. Daarna schuift object a door naar stage 2, object b door naar stage 2 en kan object c beginnen aan stage 1, en zo verder. Bij de loops zijn de verschillende instructies in de loop de stages en zijn de verschillende iteraties de objecten die door deze stages heen moeten. De instructies binnen een loop hebben altijd een aantal registers nodig. Als we bij traditionele architecturen de loops parallel willen uitvoeren moeten we iedere iteratie een nieuw set registers toekennen. Bij Register Rotation is dit niet nodig. Het is mogelijk de inhoud van verschillende registers met een enkele instructie door te schuiven: de inhoud van register 40 komt zo in 41 terecht, de inhoud van 41 in 42, etc. We laten als voorbeeld instructie 1 van een loop gebruik laten maken van register 40, instructie 2 van register 41 en instructie 3 van register 42. De eerste iteratie van de loop begint met instructie 1 in register 40. Hierna wordt een register rotation uitgevoerd en komt de data van de eerste iteratie terecht in register 41, klaar voor instructie 2. Register 40 is nu weer beschikbaar voor de instructie 1 van de tweede iteratie. Hierna wordt weer een register rotatie doorgevoerd: 41 gaat naar 42 en 40 naar 41. Zo kan de gepipelinede loop perfect parallel doorgewerkt worden. Aangezien de afzonderlijke instructies binnen een loop altijd gebruik maken van hetzelfde register hoeft de loop-code nooit omgeschreven te worden. Dit brengt natuurlijk veel performance winst met zich mee. Nog meer performance winst wordt bereikt door het parallel verwerken van de loops: op deze manier kan aan veel meer iteraties tegelijkertijd gewerkt worden. In onderstaande afbeelding is het voordeel van gepipelinede loops t.o.v. gebranchte loops nog eens duidelijk afgebeeld:

In de afbeelding is prachtig te zien wat pipelining precies inhoudt. Dat het niet meer nodig is om code voor iedere iteratie te bewerken om verschillende registers te kunnen gebruiken wordt uitgebeeld in de volgende afbeelding.

Duidelijk is te zien dat een bepaalde instructie in de oude situatie voor iedere iteratie moet worden herschreven met een nieuw register als parameter. Door rotation in de IA-64 architectuur blijft de instructie echter gelijk voor alle iteraties.

Veel resources

De oplettende lezer zal er wel achter zijn gekomen dat alle vermelde trucjes van de IA-64 een belangrijk iets vereisen, namelijk de aanwezigheid van zeer veel resources. Indien data al ver voordat deze nodig is wordt ingelezen moet hij ergens in de processor in een register kunnen worden opgeslagen. Indien de processor bij branches meerdere takken parallel wil berekenen zijn er vele zogenaamde execution units nodig. Over registers hebben de eerste IA-64 processoren niet te klagen. De Merced heeft 128 general purpose integer registers, 128 floating point registers en 64 predicate registers. Verder zijn er in de processor een groot aantal execution units ingebracht. Dit alles maakt de Merced een veel krachtigere processor dan de huidige (Intel) processoren.

Compatibiliteit

Om volledig compatible te blijven met de oude IA-32 processor stopt Intel er bij de Merced een extra IA-32 gedeelte bij. Zo is de Merced hardwarematig 100% compatible aan de IA-32 (en oudere) processoren. Mooi zou je in eerste instantie denken, zo blijft de processor compatible met de oudere Intel processoren. Toch is dit, als je er wat langer over nadenkt, niet zo positief als het lijkt. Intel heeft namelijk in haar hele geschiedenis zo gedacht en dit is in veel gevallen niet echt positief uitgelopen. Een klein stukje geschiedenis: lang geleden bedacht Intel een 4-bit microprocessor, namelijk de 4004. (tot een tijdje geleden nog terug te vinden in bijv. horloges met rekenmachine, e.d.). Hierna kwam de 8008 en de 8080, beide 8-bit. Deze 8-bit processoren werden zo opgebouwd dat ze 100% compatible bleven met de 4004. Na de 8080 kregen we de 8086: Intel’s eerste 16-bit processor. De instructieset en de architectuur van deze processor werd zeer verwant aan die van de 8080, om het porten van programmatuur zeer gemakkelijk te maken. Voor de IBM XT werd als tussen stap de 8088 gemaakt: een 16 bit processor met een 8 bit databus die IBM’s 8-bit I/O chips kon gebruiken. Na de 8088 kwamen de 16-bits 80186 (nooit succesvol gebruikt voor een IBM-compatible PC) en de 80286. Bij deze laatste werden zaken als protected mode uitgevonden, wat nieuwe mogelijkheden (zoals multi-tasking) aan de processor toevoegde. Toch moest ook de 80286 weer compatible blijven aan zijn voorgangers en vandaar dat alle vreemd zaken in het verleden waren verzonnen nog steeds terugkeerden in deze processor. Na de 80286 kwam de 80386DX (Intel’s eerste volledige 32-bits processor) en iets later de 80386SX (dezelfde 32-bit processor, maar wel met 16-bit databus, om de hardware van de 80286 te kunnen gebruiken). Nog steeds moest alle compatible blijven. Na de 80386 kwam de 80486, wederom een 32-bits processor, maar wel met nieuwe zaken als een cache-manager en pipelining mogelijkheden. De originele 80486 (later 80486DX genaamd) had zelfs nog standaard een coprocessor aan boord. Bij een product dat iets later op de markt kwam, de 80486SX, werd deze coprocessor weer uitgeschakeld. Het verhaal wordt vervolgd met de Pentium, een 32-bit processor met een 64-bit databus. De Pentium MMX voerde hier nog een instructie set toevoeging aan toe. Als laatste krijgen we de Pentium II en Pentium III, beide nog steeds 32-bits met 64-bits databus, maar nu wel met een RISC kern. Wat nu de strekking van dit verhaal is: de geschiedenis van Intel heeft zich zo voortgeplant dat onze laatste nieuwe Pentium III processor nog steeds compatible is met de oude 4004 en alle chips hiertussen: alle software die in je digitale horloge functioneert werk, na een hercompilering, ook perfect op een Pentium III. Dit heeft in het verleden voor veel "problemen" gezorgd. Intel verblijdde de wereld altijd met een nieuw type processor met nieuwe mogelijkheden. Zouden we van deze mogelijkheden gebruik maken dan is er zeker bij alle nieuwe processoren een grote vooruitgang te vinden. Maar juist door het de hele tijd compatible houden van nieuwe processoren worden de software leveranciers "lui" gehouden. Waarom zou men een nieuwe versie van een pakket maken indien de oude versie ook nog steeds perfect werkt. Dit is dus de reden waarom in het 486/Pentium-tijdperk geen volledige 32-bits Windows 95 kregen, maar een programma met nog zeer veel 16-bits code: het werkt, dus waarom zou je het veranderen naar optimalere code? Zo ook bij de overstap van 32-bit naar 64-bit: zolang de oude 32-bits OS-en en programma's blijven draaien zal geen enkele software leverancier eraan beginnen om de programma's opnieuw te compileren, al brengt dit performance toename met zich mee. Hier ben ik dus ook bang voor met de Merced: Intel’s idee is om in deze eerste IA-64 processor nog een volledige IA-32 compatibiliteit te plaatsen. Voor de verkoop is dit natuurlijk perfect: mensen kunnen met de huidige software al makkelijk overstappen. Maar software fabrikanten worden zo niet gedwongen om hun programmatuur meteen (geheel) om te zetten naar IA-64 versies. Veel software zal dus nog geen gebruik gaan maken van de mooie nieuwe IA-64 features zolang de oude IA-32 versies ook nog werken. Het omzetten van de programmatuur is gewoon te veel en te duur werk voor software leveranciers en dit proberen ze natuurlijk zo lang mogelijk te voorkomen. Voor Intel is dit gewoon uitstel van executie: indien de eerste IA-64 processor nog IA-32 compatible is zal er nog steeds IA-32 code door de programmatuur blijven dwalen. Bij de tweede IA-64 processor kan Intel het dan ook niet maken om de IA-32 compatibiliteit weg te halen: en dan is de cirkel rond. Compatibiliteit kost veel chipoppervlak en dus ook veel performance en voor ook veel prijs. (Bedenk dit maar eens: meer transistoren, dus meer uitval, dus hogere prijs!) Met de IA-64 heeft Intel eindelijk iets compleet vernieuwends bedacht. Mij lijkt het dan ook het beste om de software leveranciers meteen te dwingen zich aan te passen aan de nieuwe IA-64 architectuur en de gehele geschiedenis van de 4004 tot de Pentium III eindelijk achter zich te laten.

Met dank aan Martijn van Buul voor de informatie over de geschiedenis van Intel

0
*