Referat Evolutia Microprocesoarelor
Mai jos puteti citi fragmente din
Referat Evolutia Microprocesoarelor si de asemenea puteti face
Download Referat Evolutia microprocesoarelorCiteste fragmente din Referat Evolutia Microprocesoarelor
Evolutia procesoarelor
Perioada 1993-1998 a fost foarte zbuciumata, marcata de o lupta foarte
dura pe piata microprocesoarelor, in care Intel a inceput sa simta din
ce in ce mai mult prezenta competitiei formate din AMD, Cyrix sau
NexGen. Tot in aceasta perioada s-a lansat si standardul MMX care mai
este folosit si in prezent.
Era Pentium (1993-1998)
Intel Pentium (22 martie 1993)
PRIVATE "TYPE=PICT;ALT=Intel Pentium"
Intel Pentium a fost primul procesor superscalar de la Intel (putea
executa pana la doua instructiuni simultan). Multi s-au intrebat de ce
Intel nu a denumit acest procesor 80586. Motivul a fost ca numele format
numai din cifre nu putea fi protejat de copyright, asa ca Intel s-a
vazut nevoit sa foloseasca si litere pentru a-si diferentia produsele de
cele ale concurentei. Procesorul lucra cu o magistrala de date de 64 de
biti (cu toate ca a fost un procesor pe 32 de biti) si a fost lansat
initial la viteze de 60 si 66 de MHz. Au urmat insa foarte rapid
versiuni de 75, 90, 100, 120, 133, 150, 166, 200, 233 MHZ. De fapt au
existat trei versiuni de Pentium: prima versiune care nu cuprindea decat
doua modele: Pentium la 60 si la 66MHz, a doua versiune care a adaugat
instructiunile MMX si o ultima versiune care a micsorat distanta dintre
tranzistoare permitand astfel viteze mai mari care au ajuns pana la
233MHz. Intel Pentium a fost primul microprocesor pentru PC-uri care
putea sa calculeze mai mult de 100MIPS (milioane de instructiuni pe
secunda). Tot pentru prima oara era posibila construirea unor sisteme
care sa lucreze cu 2 procesoare in paralel (sisteme multiprocesor).
Microprocesorul de la Intel venea cu 16Kb de cache incorporati in
pastila de siliciu.
AMD K5 / Nexgen Nx586 (1995)
AMD a reactionat destul de tarziu in a lansa un procesor comparabil ca
viteza cu Intel Pentium. In 1995 a produs totusi primul sau procesor
care era conceput integral de catre ei, nemaifiind o simpla clona a
procesoarelor Intel. Acest procesor s-a numit K5 si avea viteze de la 75
la 166MHz. Cu toate acestea nu era un procesor mai rapid decat cele de
la Intel, in plus avand o unitate de calcul in virgula mobila destul de
slaba (ca si Cyrix de altfel). Una din inovatiile aduse de K5 era faptul
ca instructiunile x86 erau transformate intern in ROP (Risc OPerations).
Aceste operatii RISC se puteau executa in nucleul RISC al procesorului
care era mult mai rapud. In acelasi timp o companie de care putina lume
auzise pana atunci, Nexgen, lansa primul sau procesor: Nx586.
Complexitatea procesorului K5 a dus la frecvente destul de mici, ceea ce
i-a facut pe cei de la AMD sa cumpere compania Nexgen care tocmai
terminase design-ul noului lor procesor, NX686. Acest design a fost
ulterior folosit de AMD in urmatoarea sa familie de procesoare pe care
avea sa o lanseze in 1997.
Cyrix 6x86 (Octombrie 1995)
6x86 a fost replica lui Cyrix la procesorul Pentium al lui Intel. Acest
chip era produs initial de catre IBM dat fiind ca Cyrix nu avea unitati
de asamblare de procesoare, insa ulterior, odata cu achizitionarea Cyrix
de catre National Semiconductor a fost produs chiar de catre acestia.
Procesorul a avut un succes destul de mare dat fiind ca era mai rapid
decat un Intel Pentium la aceeasi frecventa. De altfel pentru a-l putea
compara cu procesoarele de la Intel, cei de la Cyrix au inventat ceea ce
s-a numit ulterior P-Rating. De exemplu procesorul Cyrix 6x86 care
functiona la 150 de MHz a fost denumit 6x86PR200, ceea ce insemna ca era
comparabil ca viteza cu un Pentium la 200. Unul din marile dezavantaje
ale acestui procesor a fost insa viteza foarte mica a calculelor in
virgula mobila. Cu toate acestea in aplicatiile de tip office s-a
dovedit cel putin la fel de rapid ca si un Pentium.
Intel Pentium Pro (1 noiembrie 1995)
Acest procesor a fost una dintre cele mai mari inovatii tehnice produse
de Intel pana acum. Procesorul ingloba pentru prima oara in istorie pe
langa cache-ul Level1 de 8k pentru date si 8k pentru instructiuni, si un
cache Level2 de 256Kb sau 512Kb. Folosea un sistem complex de predictie
a ramurii de executie (branch prediction) si executie speculativa
(speculative execution) - in momentul in care executia programului
ajungea la o bifurcatie ramura corecta nu era stiuta pana in momentul in
care se executa instructiunea conditionala; pentru ca procesorul sa nu
astepte pana in acea clipa, se alegea una din cele doua ramuri si se
incepea executia instructiunilor respective; daca se dovedea ca ramura
aleasa a fost cea corecta aceasta insemna un castig important de viteza.
Acest microprocesor transforma instructiunile x86 in microoperatii care
erau mult mai mici si mai rapide. Acest lucru, cu toate ca avea ca
rezultat o viteza mult mai mare a instructiunilor de 32 de biti, a dus
la performante mult mai slabe in sistemele de operare care mai contineau
cod pe 16 biti. Acesta a fost unul din motivele performantei mai mici
comparabil cu Intel Pentium in Windows 95 de exemplu.
Intel Pentium MMX (Ianuarie 1997)
MMX s-a crezut initial ca inseamna MultiMedia eXtension, dar Intel a
declarat ca inseamna Matrix Math eXtension. Acesta reprezinta un
standard introdus de Intel care aduce cateva noi instructiuni care
usurau in principal calculele matematice cu vectori.
AMD K6 (Aprilie 1997)
PRIVATE "TYPE=PICT;ALT=AMD K6"
Ca urmare a cumpararii firmei Nexgen, AMD a reusit sa lanseze un nou
procesor, K6 care avea viteze de la 166 la 266MHz. Bineinteles ca
politica AMD a fost ca procesoarele sale sa se vanda la aproape jumatate
din pretul la care se vindeau procesoarele Intel. K6 incorpora
instructiuni MMX (a caror licenta a cumparat-o de la Intel) devenind
astfel un rival de temut pentru procesoarele Intel Pentium MMX.
Cyrix 6x86MX (30 Mai 1997)
6x86MX a adus nou extensiile MMX precum si viteze de ceas mai mari decat
precedentele chip-uri de la Cyrix. Astfel cel mai performant model era
6x86MX PR266 care rula la 233MHz. De asemenea, marimea memoriei cache
Level2 s-a marit de patru ori fata de 6x86, ajungand la 64Kb.
Cyrix MII (14 Aprilie 1998)
Aceasta versiune a chip-ului 6x86 a imbunatatit putin performanta FPU si
a atins viteze mai mari ajungand la 300MHz (PR433). De asemenea viteza
bus-ului a ajuns la 100MHz.
Cyrix MediaGX (1998)
PRIVATE "TYPE=PICT;ALT=Cyrix MediaGX"
MediaGX a reprezentat incercarea lui Cyrix de a produce un chip care sa
integreze atat functiile de sunet si video, cat si controller-ul de
memorie si CPU-ul in sine. Scopul acestui chip a fost acela de a putea
produce computere foarte ieftine si la vremea aceea deja se vorbea de
calculatoare sub 500$ (ceea ce era foarte putin la acea data) construite
in jurul lui MediaGX. Cu toate acestea, nici unul din marii producatori
de computere nu a adoptat aceasta solutie, astfel incat procesorul
acesta, desi revolutionar, nu a avut deloc succesul scontat.
Procesoarele Cyrix
Arhitectura x86
orporaţia Cyrix este unul dintre furnizorii de bază ai soluţiilor
bazate pe microprocesoare, care a introdus noi standarde pe piaţa
calculatoarelor personale. ÃŽn ultimii zece ani Cyrix a dezvoltat
aproape o duzină de procesoare originale folosite în milioane de
calculatoare din întreaga lume.
În luna noiembrie a anului 1997, Cyrix a fost cumpărată de National
Semiconductor. Această fuziune a adus două componente importante
pentru Cyrix: capacitatea de producţie la nivel mondial a National
Semiconductor şi infrastructura necesară acestei producţii.
Primul produs Cyrix a fost un coprocesor matematic destinat creÅŸterii
vitezei de realizare a calculelor matematice. Succesul acestui
coprocesor matematic a permis celor de la Cyrix să distribuie
începând cu 1992, primul procesor din familia x86. Compania a
dezvoltat rapid o linie de producţie pentru procesoarele 486, şi apoi
pentru procesoarele din generaţia a cincea 5x86, un CPU pentru
sistemele PC (mobile ÅŸi desktop). ÃŽn 1995, Cyrix a introdus procesorul
din generaţia a şasea, 6x86, un procesor superscalar, bazat pe o
superbandă de asamblare; în iunie 1997, a introdus procesorul MMX
6x86MX, iar în 1998 a apărut procesorul MII.
Procesorul Cyrix 5x86
Familia de procesoare 5x86 reprezintă o nouă generaţie pe 64 de biţi
compatibilă x86. Unitatea centrală se bazează pe o bandă de
asamblare cu şase nivele, putând executa o instrucţiune într-un
impuls de tact.
Unitatea centrală 5x86 este divizată în următoarele blocuri
funcţionale (Fig. 1): -unitatea pentru numere întregi (Integer Unit -
IU), -unitatea în virgulă flotantă (Floating Point Unit - FPU) ,
-unitatea cache (Write-Back Cache) , -unitatea pentru gestiunea memoriei
(Memory Management Unit - MMU) , -unitatea de interfaţă cu magistrala
(Bus Interface Unit - BIU).
Unitatea pentru numere întregi conţine: -tamponul pentru instrucţiuni
(Instruction Buffer - IB) , -unitatea de aducere a instrucţiunii
(Instruction Fetch Unit - IF) , -unitatea de decodificare a
instrucţiunii (Instruction Decoder Unit - ID).
Instrucţiunile sunt executate în unitatea pentru numere întregi sau
în unitatea de calcul în virgulă flotantă. Cache-ul conţine cele
mai recent utilizate date şi instrucţiuni şi asigură accesul rapid
la aceste date din partea IU ÅŸi FPU.
Când apare o cerere de acces la o locaţie din memoria externă, MMU
calculează adresa fizică pe care o trimite unitaţii de interfaţă cu
magistrala, care asigură interfaţarea unitaţii centrale cu memoria
externă şi celelalte circuite de pe placa de bază.
Unitatea pentru numere întregi
Această unitate citeşte, decodifică şi execută intrucţiunile
într-o bandă de asamblare cu şase nivele (Fig. 2): -nivelul de
aducere al codului instrucţiunii (Instrucţion Fetch - IF) - citeşte
din cache codul instrucţiunii următoare şi îl trimite spre
decodificare nivelului următor din banda de asamblare. Se pot citi
până la 128 de octeţi într-un impuls de tact, -nivelul de
decodificare a instrucţiunii (Instruction Decode - ID) - evaluează
şirul de octeţi primit de la nivelul IF, determinând numărul de
octeţi pentru fiecare instrucţiune şi tipul acesteia, pe care apoi le
decodifică la viteza de o instrucţiune într-un impuls de tact,
-primul nivel de caclul al adresei (Address Calculation 1 - AC1) - dacă
instrucţiunea are un operand în memorie, acest nivel calculează
adresa de memorie liniară pentru instrucţiune, -al doilea nivel de
caclul al adresei (Address Calculation 2 - AC2) - realizează toate
funcţiile de gestionare a memoriei, accesarea cache-ului şi a
registrelor. Dacă detectează o instrucţiune în virgulă flotantă,
aceasta este trimisă pentru execuţie unităţii în virgulă
flotantă, -nivelul de execuţie (Execution - EX) - execută
instrucţiunea folosind operanzii furnizaţi de nivelele pentru calculul
adresei, -nivelul write-back (WB) - ultimul nivel din IU, actualizează
setul de registre sau trimite rezultatul unităţii de interfaţă cu
memoria (Load/Store Unit) din MMU.
Unitatea cache
Procesorul Cyrix 5x86 conţine un cache unificat pentru date şi
instrucţiuni de 16Ko, set-asociativ pe patru căi, organizat pe 1024 de
linii. Scrierile în cache se fac prin metoda write-back. Memoria cache
este organizată în patru bancuri a câte 256 linii fiecare, cu 16
octeţi pe linie. Fiecare linie cache are asociat câte un tag pe 21 de
biţi şi un bit de valid (arată dacă linia conţine informaţii
valide sau nu). Pe lângă aceşti biţi, fiecare linie mai conţine
încă patru biţi care indică dacă conţinutul liniei a fost
modificat (dirty bits), câte unul pentru fiecare dublu-cuvânt din
linie. Aceşti ultimi patru biţi permit marcarea independentă a
fiecărui dublu-cuvânt ca fiind modificat, în loc de a marca întreaga
linie ca fiind modificată.
Unitatea de gestionare a memoriei
MMU translatează adresele liniare furnizate de IU în adrese fizice,
pentru a putea fi folosite de unitatea cache şi unitatea de interfaţă
cu magistrala. Mecanismul de paginare este cel standard x86.
Unitatea pentru gestionarea memoriei mai conţine un bloc (Load/Store
Unit) care planifică accesele la memoria cache şi memoria externă şi
implementează următoarele concepte: -reordonarea citirilor şi
scrierilor - conferă o prioritate mai mare citirilor din memorie faţă
de scrierile în memorie, -evitarea citirilor din memorie - elimină
citirile inutile din memorie prin folosirea datelor existente deja în
unitatea centrală (în cazul dependenţelor de tipul citire după
scriere).
Controlul ramificaţiilor, prezicerea ramificaţiilor, dependenţele
între date, unitatea în virgulă flotantă, unitatea de interfaţă cu
magistrala vor fi prezentate la procesorul 6x86.
Procesorul Cyrix 6x86
Procesorul Cyrix 6x86 este cel mai performant dintre procesoarele de
generaţia a şasea compatibile x86. Îmbunătăţirea performanţelor
este realizată prin utilizarea unei arhitecturi superscalare, bazate pe
o superbandă de asamblare.
Cyrix 6x86 este un procesor superscalar, deoarece conţine două benzi
de asamblare separate ce permit procesarea mai multor instrucţiuni în
acelaÅŸi timp. Folosirea unei tehnologii de procesare avansate ÅŸi
creşterea numărului de nivele în benzile de asamblare
(superpipelining) permit procesorului 6x86 să atingă frecvenţe de
lucru mai mari de 100MHz.
Prin folosirea caracteristicilor arhitecturale unice, procesorul 6x86
elimină multe dintre dependenţele între date şi conflictele la
accesarea resurselor, rezultând o performanţă optimă atât pentru
programele pe 16 biţi cât şi pentru cele pe 32 de biţi.
Procesorul Cyrix 6x86 conţine două cache-uri: -un cache unificat
(pentru date şi pentru instrucţiuni) de 16Ko dual port, şi -un cache
de instrucţiuni de 256 octeţi.
Deoarece cache-ul unificat poate conţine instrucţiuni şi date în
orice raport, acesta oferă o rată a hit-urilor (numărul de accese în
cache, raportat la numărul total de accese) mai mare comparativ cu
două cache-uri separate pentru date şi pentru instrucţiuni, având
dimensiuni egale. O creştere a lăţimii de bandă a transferurilor
cache-unitatea întreagă este realizată prin suplimentarea cache-ului
unificat cu un mic cache de instrucţiuni foarte rapid, complet
asociativ. Prin includerea acestui cache de instrucţiuni, se evită
conflictele excesive între accesele pentru date şi pentru cod în
cache-ul unificat.
Unitatea în virgulă flotantă din procesor permite executarea
instrucţiunilor în virgulă flotantă în paralel cu instrucţiunile
întregi. Aceasta conţine o coadă de instrucţiuni pe patru nivele şi
o coadă pentru datele scrise tot pe patru nivele, pentru a facilita
execuţia paralelă.
Procesorul 6x86 este alimentat la 3.3V ducând la un consum redus pentru
toate frecvenţele de lucru. În plus, 6x86 mai posedă un mod de
suspendare pe nivel scăzut, posibilitatea de a întrerupe tactul şi
modul de management al sistemului (SMM) pentru aplicaţiile sensibile la
alimentare.
Principalele blocuri funţionale
Procesorul Cyrix 6x86 conţine cinci mari blocuri funcţionale (Fig. 3):
-Unitatea întreagă (Integer Unit - IU) , -Unitatea cache (Cache Unit)
, -Unitatea de gestionare a memoriei (Memory Management Unit - MMU) ,
-Unitatea în virgulă flotantă (Floating Point Unit - FPU) , -Unitatea
de interfaţă cu magistrala (Bus Interface Unit - BIU).
Instrucţiunile sunt executate în cele două benzi de asamblare
întregi (X şi Y) şi în unitatea în virgulă flotantă. Cache-ul
conţine cele mai recent utilizate date şi instrucţiuni pentru a
permite accese rapide la informaţii din partea IU şi FPU.
Adresele fizice sunt calculate de MMU şi sunt trimise unitaţii cache
şi unităţii de interfaţă cu magistrala. BIU oferă o interfaţă
între placa sistem externă şi unitaţile interne ale procesorului.
Unitatea întreagă
Unitatea de calcul cu numere întregi oferă o execuţie paralelă a
instrucţiunilor în două benzi de asamblare pentru numere întregi cu
şapte nivele (Fig. 4). Fiecare din cele două benzi de asamblare (X şi
Y) poate procesa simultan câteva instrucţiuni.
Benzile de asamblare întregi conţin următoarele nivele de prelucrare:
-aducerea codului instrucţiunii (Instruction Fetch –IF) , -primul
decodificator pentru instrucţiuni (Instruction Decode 1 – ID1) , -al
doilea decodificator pentru instrucţiuni (Instruction Decode 2 – ID2)
, -primul bloc de calculare a adresei (Address Calculation 1 – AC1) ,
-al doilea bloc de calculare a adresei (Address Calculation 2 – AC2) ,
-execuţie (Execute – EX) , -writeback (WB) (Fig. 4).
Nivelul de aducere al codului instrucţiunii (IF) este împărţit de
cele două benzi de asamblare, aduce câte 16 octeţi de cod din
unitatea cache într-un singur ciclu de tact. În acest nivel se caută
orice instrucţiune de salt ce poate apare în fluxul de cod şi poate
afecta secvenţierea normală a programului. Dacă este detectată o
instrucţiune de salt necondiţionat sau una de salt condiţionat,
logica de prezicere a salturilor din acest nivel generează o posibilă
adresă destinaţie pentru instrucţiunea de salt. Apoi IF aduce codul
instrucţiunilor începând cu această adresă.
Funcţia de decodificare a codului instrucţiunii este realizată de
nivelele ID1 ÅŸi ID2. Nivelul ID1, folosit de ambele benzi de asamblare,
evaluează şirul de octeţi de cod transmis de nivelul IF şi
determină numărul de octeţi pentru fiecare instrucţiune. Acest nivel
poate trimite cel mult două instrucţiuni într-un impuls de tact
nivelului ID2, câte una pentru fiecare bandă de asamblare.
Cele două nivele ID2 decodifică instrucţiunile şi le trimite uneia
din cele două benzi de asamblare X sau Y spre execuţie. Banda de
asamblare este aleasă bazată pe tipul instrucţiunilor aflate deja în
fiecare bandă şi cât de repede se presupune că se vor termina.
Funcţia de calculare a adreselor este realizată tot în două nivele:
AC1 şi AC2. Dacă instrucţiunea are o referinţă la un operand în
memorie, AC1 calculează o adresă de memorie liniară pentru
instrucţiune.
Nivelul AC2 realizează toate funcţiile de gestiunea memoriei cerute,
accesele la cache şi accesele la setul de registre. Dacă AC2
detectează o instrucţiune în virgulă flotantă, aceasta este
trimisă spre prelucrare unităţii FPU.
În nivelul de execuţie (EX), se execută instrucţiunile folosind
operanzii primiţi din nivelul AC2.
Nivelul writeback (WB) este ultimul din unitatea de lucru cu numere
întregi. În acest nivel sunt stocate rezultatele execuţiei sau în
registre sau în tamponul de scriere din unitatea cache.
Procesarea în inordine
Dacă o instrucţiune este executată mai repede decât instrucţiunea
precedentă din cealaltă bandă de asamblare, instrucţiunile sunt
completate în inordine. Toate instrucţiunile sunt prelucrate în
ordine până la nivelul EX. În timp ce în nivelele EX şi WB
instrucţiunile pot fi executate în inordine.
Dacă există dependenţe de date între cele două instrucţiuni, este
necesară intervenţia unui bloc care să asigure execuţia corectă a
programului. Astfel, chiar dacă instrucţiunile sunt executate în
inordine, excepţiile şi scrierile din cadrul instrucţiunilor sunt
întotdeauna efectuate în ordinea cerută de program.
Selectarea benzii de execuţie
În majoritatea cazurilor, instrucţiunile sunt prelucrate în oricare
din cele două benzi de asamblare şi nu există constrângeri cu
privire la tipul instrucţiunilor executabile în paralel în cele două
benzi de asamblare. Însă, unele instrucţiuni pot fi prelucrate doar
de banda de asamblare X: -instrucţiunile de salt, -instrucţiunile în
virgulă flotantă, -instrucţiunile exclusive.
Instrucţiunile de salt şi cele în virgulă flotantă pot fi executate
în paralel cu o altă instrucţiune ce poate fi executată în banda Y.
Instrucţiunile exclusive nu pot fi executate în paralel cu nici o
altă instrucţiune. Aceste instrucţiuni necesită accese multiple la
memorie. Chiar dacă aceste instrucţiuni sunt executate exclusiv, este
folosit hardware-ul din cele două benzi de asamblare pentru a se
accelera completarea instrucţiunii. În continuare sunt înşirate
tipurile de instrucţiuni exclusive ale procesorului 6x86: -încărcarea
segmentelor în modul protejat, -accesele la registrele speciale
(registrele de control, debug şi test) , -instrucţiunile pe şiruri,
-înmulţirea şi împărţirea, -accesele la porturile I/O, -PUSHA şi
POPA, -salturile intersegment, apelurile de proceduri ÅŸi ieÅŸirea din
proceduri intersegment.
Soluţionarea dependenţelor de date
Când două instrucţiuni care sunt executate în paralel accesează
aceeaşi dată sau acelaşi registru, poate apare una din următoarele
tipuri de dependenţe de date: -citire după scriere (Read-After-Write -
RAW) , -scriere după citire (Write-After-Read - WAR) , -scriere după
scriere (Write-After-Write - WAW).
Dependenţele între date în mod normal necesită serializarea
execuţiei instrucţiunilor implicate. Însă, 6x86 implementează
următoarele trei mecanisme ce permit execuţia paralelă a
instrucţiunilor ce conţin dependenţe între date: -redenumirea
registrelor (Register Renaming) , -înaintarea datelor (Data Forwarding)
, -evitarea datelor (Data Bypassing). ÃŽn continuare, se vor descrie pe
scurt aceste meacnisme.
Redenumirea registrelor
Procesorul Cyrix 6x86 conţine 32 registre fizice de uz general. Fiecare
din cele 32 de registre din fiÅŸierul de registre poate fi desemnat a fi
unul din registrele de uz general din arhitectura x86 (EAX, EBX, ECX,
EDX, ESI, EDI, EBP şi ESP). Pentru fiecare operaţie de scriere
într-un registru este selectat un nou registru fizic, pentru a se
reţine temporar şi data precedentă. Redenumirea registrelor elimină
efectiv toate dependinţele WAW şi WAR. Pentru programator este
transparent acest mod de redenumire a registrelor; este transparent
atât pentru sistemul de operare, cât şi pentru programele aplicaţie.
Exemplul 1. Redenumirea registrelor elimină dependenţele de tipul
scriere după citire (WAR). O dependenţă de tip WAR apare atunci când
prima dintr-o pereche de instrucţiuni citeşte un registru logic şi a
doua instrucţiune scrie în acelaşi registru. Acest tip de
dependenţă este ilustrat de perechea de instrucţiuni de mai jos:
banda X banda Y
(1) MOV BX, AX (2) ADD AX, CX
(BX <- AX) (AX <- AX + CX)
(Ordinea iniţială din program a instrucţiunilor este arătată de
numerele din paranteze.)
În absenţa redenumirii registrelor, instrucţiunea ADD din banda de
asamblare Y ar trebui să aştepte până când instrucţiunea MOV din
banda de asamblare X ar citi registrul AX.
Însă, procesorul 6x86 evită blocarea benzii de asamblare într-o
astfel de situaţie. Pe măsură ce este executată fiecare
instrucţiune, rezultatele sunt plasate într-un nou registru fizic,
pentru a evita posibilitatea suprascrierii unei valori a unui registru
logic şi pentru a permite execuţia în paralel a două instrucţiuni
fără blocare (fără a fi necesară nici o secvenţiere la accesarea
aceleiaÅŸi resurse) (Tab.1).
Exemplul 2. Redenumirea registrelor elimină dependenţele de tipul
scriere după scriere (WAW)
O dependenţă WAW apare când două instrucţiuni consecutive
realizează scrierea în acelaşi registru logic. Acest tip de
dependenţă este ilustrat de:
banda X banda Y
(1) ADD AX, BX (2) MOV AX, [mem]
(AX <- AX + BX) (AX <- [mem])
Fără denumirea registrelor instrucţiunea MOV din banda de asamblare Y
ar trebui să fie întreruptă pentru a garanta că instrucţiunea ADD
din banda X şi-a depus rezultatul în AX (Tab.2).
ÃŽnaintarea datelor (Data Forwarding)
Doar redenumirea registrelor, nu poate elimina dependenţele de tipul
citire după scriere (RAW). 6x86 foloseşte două tipuri de data
forwarding împreună cu redenumirea registrelor pentru a elimina acest
tip de dependenţe: -înaintarea operandului (operand forwarding), -
apare când prima dintr-o pereche de instrucţiuni efectuează o citire
din registru sau memorie iar această dată este necesară celei de-a
doua instrucţiuni. CPU execută operaţia de citire şi furnizează
data citită ambelor instrucţiuni; -înaintarea rezultatului (result
forwarding) - apare atunci când prima dintr-o pereche de instrucţiuni
execută o operaţie (cum ar fi ADD) iar rezultatul ei este citit de o a
doua instrucţiune. CPU-ul execută operaţia primei instrucţiuni şi
depune rezultatul operaţiei în destinaţiile ambelor instrucţiuni
simultan.
Exemplul 3. Înaintarea operandului elimină dependenţa de tipul RAW
O dependenţă de tipul RAW apare când prima dintr-o pereche de
instrucţiuni realizează o scriere iar a doua instrucţiune citeşte
acelaÅŸi registru.
banda X banda Y
(1) MOV AX, [mem] (2) ADD BX, AX
(AX <- [mem]) (BX <- AX + BX)
Înaintarea operandului poate apare doar dacă prima instrucţiune nu
modifică valoarea iniţială a datei (Tab. 3).
Exemplul 4. Înaintarea rezultatului elimină dependenţa de tipul RAW
O dependenţă de tipul RAW apare când prima dintr-o pereche de
instrucţiuni realizează o scriere iar a doua instrucţiune citeşte
acelaÅŸi registru.
banda X banda Y
(1) ADD AX, BX (2) MOV [mem], AX
(AX <- AX + BX) ([mem] <- AX)
A doua instrucţiune trebuie să fie o instrucţiune de transfer iar
destinaţia ei poate fi sau un registru sau o locaţie de memorie (Tab.
4).
Evitarea datelor (Data Bypassing)
Pe lângă redenumirea registrelor şi înaintarea datelor, 6x86
conţine o a treia tehnică de eliminare a dependenţelor de date,
denumită evitarea datelor. Aceasta reduce scăderilor în performanţă
ale acelor dependenţe de tipul RAW din memorie ce nu pot fi eliminate
cu ajutorul înaintării datelor.
Evitarea datelor apare când prima dintr-o pereche de instrucţiuni
scrie în memorie şi următoarea citeşte aceeaşi dată din memorie.
6x86 reţine data din prima instrucţiune şi o pasează celeilalte
instrucţiuni, astfel eliminându-se un ciclu de citire din memorie.
Exemplul 5. Evitarea datei în dependenţa de tipul RAW
În acest exemplu, dependenţa de tipul RAW apare când prima
instrucţiune efectuează o scriere în memorie iar instrucţiunea
următoare citeşte aceeaşi locaţie de memorie (Tab. 5).
banda X banda Y
(1) ADD [mem], AX (2) SUB BX, [mem]
([mem] <- [mem] + AX) (BX <- BX - [mem])
Controlul ramificaţiilor
În programe instrucţiunile de salt apar în proporţie de 20-25%.
Când fluxul de secvenţiere normală al programului se schimbă
datorită unei instrucţiuni de salt, nivelele benzilor de asamblare
trebuie blocate până când CPU-ul calculează adresa, aduce şi
decodifică noul flux de instrucţiuni. Procesorul Cyrix 6x86
minimizează degradarea în performanţă şi latenţa introduse de
instrucţiunile de salt prin folosirea conceptelor de prezicere a
salturilor şi execuţie speculativă.
Prezicerea salturilor
Procesorul 6x86 foloseşte un tabel al adreselor destinaţie (Branch
Target Buffer - BTB) cu 256 de intrări, set asociativ pe 4 căi, pentru
menţinerea adreselor destinaţie ale instrucţiunile de salt şi a
altor informaţii necesare prezicerii acestor salturi. În timpul
aducerii codului instrucţiunii sunt căutate instrucţiunile de salt
în fluxul de instrucţiuni. Dacă este descoperită o instrucţiune de
salt necondiţionat, CPU-ul accesează BTB pentru a afla adresa
destinaţie a instrucţiunii de salt. Dacă această adresă există în
BTB, CPU-ul începe să aducă instrucţiunile de la noua adresă.
În cazul salturilor condiţionate, BTB mai menţine o serie de
informaţii cu privire la istoricul efectuării saltului respectiv
(pentru a se putea lua decizia de efectuare sau nu a saltului). Dacă
instrucţiunea de salt condiţionat este găsită în BTB, 6x86 începe
aducerea instrucţiunilor de la adresa prezisă. Dacă instrucţiunea nu
este găsită în BTB, 6x86 prezice neexecutarea saltului şi aducerea
instrucţiunilor va continua cu adresa următoare. Decizia de efectuare
sau nu a saltului este luată pe baza unui algoritm de prezicere a
salturilor.
Odată ce a fost adus codul unei instrucţiuni de salt condiţionat,
aceasta este decodificată şi distribuită spre execuţie benzii de
asamblare X. Instrucţiunea trece prin nivelele benzii de asamblare X
şi este terminată sau în nivelul EX sau în WB, în funcţie de
instrucţiunea care a setat indicatorii de condiţii: -dacă
instrucţiunea care a setat indicatorii de condiţii este executată în
paralel cu instrucţiunea de salt condiţionat, atunci aceasta este
terminată în nivelul WB, -dacă instrucţiunea care a setat
indicatorii de condiţii a fost executată înaintea instrucţiunii de
salt, atunci aceasta se va termina în EX.
Instrucţiunile de salt condiţionat corect prezise se vor executa
într-un singur impuls de tact. Dacă după terminarea execuţiei
instrucţiunii de salt condiţionat s-a detectat o prezicere eronată a
saltului, CPU-ul goleşte benzile de asamblare şi începe execuţia de
la adresa corectă. Procesorul 6x86 în cazul unei instrucţiuni de salt
condiţionat aduce în avans atât instrucţiunea prezisă cât şi
cealaltă, dar o trimite benzii de asamblare spre execuţie doar pe cea
prezisă. Astfel că, în cazul unei preziceri eronate, instrucţiunea
de la adresa neprezisă nu va mai fi citită din cache, deoarece a fost
adusă deja. Dacă instrucţiunea de salt condiţionat a fost rezolvată
în nivelul EX, atunci întârzierea în cazul unei preziceri eronate
este de patru impulsuri de tact, iar dacă instrucţiunea de salt a fost
rezolvată doar în WB, atunci întârzierea este de cinci impulsuri de
tact.
Deoarece instrucţiunea de revenire dintr-o subrutină (RET) este
dinamică, procesorul 6x86 menţine adresele pentru aceste instrucţiuni
într-o stivă cu opt intrări. Adresa de revenire este introdusă în
stiva adreselor de revenire de către instrucţiunea CALL, şi este
scoasă de către instrucţiunea RET corespunzătoare.
Execuţia speculativă
Procesorul 6x86 are posibilitatea de a executa speculativ
instrucţiunile următoare unei instrucţiuni în virgulă flotantă sau
a unei instrucţiuni de salt. Execuţia speculativă permite benzilor de
asamblare să execute continu instrucţiuni după un salt, fără a fi
necesară blocarea benzii de asamblare până la obţinerea rezultatului
execuţiei instrucţiunii de salt condiţionat. Acelaşi mecanism este
folosit pentru a se executa instrucţiuni în virgulă flotantă în
paralel cu instrucţiunile de numere întregi.
Procesorul are posibilitatea de execuţie în patru nivele de
speculaţie. După generarea unei noi adrese prin mecanismul de
predicţie, CPU-ul salvează starea curentă (registrele, indicatorii de
condiţii, etc.), incrementează numărătorul nivelului de speculaţie
şi începe execuţia fluxului de instrucţiuni prezis.
Odată ce instrucţiunea de salt a fost rezolvată, CPU-ul
decrementează nivelul de speculaţie. Pentru un salt corect prezis este
ştearsă starea resurselor salvate la intrarea în nivelul de
speculaţie curent. Pentru un salt prezis eronat, procesorul 6x86
generează adresa corectă pentru următoarea instrucţiune şi
foloseşte valorile de stare salvate pentru a restaura starea curentă,
într-un singur impuls de tact.
Pentru a se menţine compatibilitatea, nu sunt permise scrierile în
memorie sau cache, până când nu este rezolvată instrucţiunea de
salt. Execuţia speculativă continuă până când apare una din
următoarele condiţii: -este decodificată o nouă instrucţiune de
salt sau de calcul în virgulă flotantă şi nivelul de speculaţie
este patru (maximul) , -apare o excepţie sau o eroare, -tamponul de
scriere este plin, -se încearcă modificarea unei resurse a cărei
stare nu a fost salvată (registrele segment, indicatorii sistem).
Cache-ul unificat de date şi instrucţiuni
Procesorul Cyrix 6x86 conţine un cache unificat şi un cache de
instrucţiuni (Fig. 5). Cache-ul unificat cu dimensiunea de 16Ko
funcţionează ca un cache primar (L1) de date şi ca un cache secundar
(L2) de instrucţiuni. Configurat ca un cache set-asociativ pe patru
căi, conţine până la 16Ko de cod şi date în 512 linii. Cache-ul
este dual-port şi permite executarea a două din operaţiile următoare
în paralel: -citirea unui cod de instrucţiune, -citirea unei date (de
către banda X, banda Y sau FPU) , -scrierea unei date (de către banda
X, banda Y sau FPU).
Acest cache foloseÅŸte un algoritm de replasare pseudo-LRU (Last
Recently Used) şi poate fi configurat să aloce o nouă linie de cache
doar la un miss de citire, sau ÅŸi la citire ÅŸi la scriere.
Cache-ul de instrucţiuni de 256 octeţi complet asociativ serveşte
drept cache de instrucţiuni primar (L1). Cache-ul de instrucţiuni este
încărcat din cache-ul unificat prin magistrala de date internă.
Citirile codurilor de instrucţiuni din unitatea pentru numere întregi
care se găsesc în cache-ul de instrucţiuni nu mai accesează cache-ul
unificat. Dacă instrucţiunea nu este găsită în cache-ul de
instrucţiuni, linia din cache-ul unificat care conţine instrucţiunea
respectivă, este transferată atât cache-ului de instrucţiuni cât
şi unităţii pentru numere întregi.
Acest cache foloseÅŸte tot algorimtul de replasare pseudo-LRU. Pentru a
se asigura operarea corectă în cazul codului automodificabil, orice
scriere în cache-ul unificat este verificată cu conţinutul cache-ului
de instrucţiuni. Dacă a fost modificată o locaţie care este
prezentă şi în cache-ul de instrucţiuni, atunci linia ce conţine
respectiva locaţie este dezactivată.
Unitatea de gestionare a memoriei
Unitatea de gestionare a memoriei (Memory Management Unit - MMU) a
procesorului Cyrix 6x86, prezentată în Fig. 6, translatează adresele
liniare furnizate de IU într-o adresă fizică, pentru a putea fi
utilizată în continuare de cache şi interfaţa cu magistrala. MMU
include două mecanisme de paginare, un mecanism tradiţional şi un
mecanism specific lui 6x86 cu pagini de dimensiuni variabile (Fig. 6).
Mecanismul de paginare cu dimensiunea paginilor variabilă
Acest mecanism de paginare permite programelor să mapeze pagini cu
dimensiunea între 4Ko şi 4Go. Folosirea paginilor de dimensiuni mari
poate duce la sporirea performanţei unor anumite aplicaţii.
Mecanismul tradiţional de paginare
Mecanismul tradiţional de paginare a fost îmbunătăţit la 6x86 prin
adăugarea unui cache pentru tabelul directorilor (Directory Table Entry
-DTE) şi un TLB victimă. TLB-ul principal este cu mapare directă şi
conţine 128 de intrări pentru tabelul paginilor. Cache-ul DTE cu patru
intrări complet asociative conţine accesele cele mai recente la DTE.
TLB-ul victimă conţine liniile din TLB principal care au fost
înlocuite datorită unui miss în TLB. Dacă se face referirea la o
pagină ce are PTE-ul în TLB-ul victimă, linia aceasta este schimbată
cu o linie din TLB-ul primar.
Unitatea în virgulă flotantă
Interfaţa dintre unitatea în virgulă flotantă (FPU) a procesorului
6x86 şi unitatea pentru numere întregi este realizată printr-o
magistrală internă pe 64 de biţi. Setul de instrucţiuni FPU al
procesorului 6x86 este compatibil x87 şi aderă standardului IEEE-754.
Procesorul Cyrix 6x86 execută instrucţiunile întregi în paralel cu
instrucţiunile în virgulă flotantă. Instrucţiunile întregi pot fi
executate în inordine cu respectarea instrucţiunilor FPU.
Aşa cum s-a mai spus, instrucţiunile FPU sunt întotdeauna executate
în banda de asamblare X. Nivelul pentru calculul adresei din banda X
verifică apariţia excepţiilor de gestionare a memoriei şi accesează
operanzii din memorie folosiţi de FPU. Dacă nu apare nici o excepţie,
se salvează starea curentă a procesorului în AC2 şi trimite
instrucţiunea în virgulă flotantă spre execuţie FPU-ului. Apoi
unitatea centrală poate executa orice instrucţiune întreagă
următoare, speculativ şi în inordine.
Unitatea centrală 6x86 poate trimite până la patru instrucţiuni FPU
în coada de aşteptare a FPU. CPU-ul continuă cu execuţia
speculativă şi în inordine până când apare una dintre condiţiile
ce cauzează oprirea execuţiei speculative. Pe măsură ce FPU termină
de executat o instrucţiune în virgulă flotantă, este decrementat
nivelul speculativ ÅŸi sunt ÅŸterse valorile de stare salvate la
începutul acestei instrucţiuni. Unitatea în virgulă flotantă mai
conţine şi un set de patru tampoane de scriere pentru a preveni
întreruperile datorate scrierilor speculative.
Procesoarele Cyrix 6x86MX ÅŸi MII
Aceste procesoare au la bază nucleul procesorului 6x86, îmbunătăţit
cu cele 57 instrucţiuni multimedia noi, compatibile cu tehnologia MMX.
În plus, 6x86MX şi MII lucrează la frecvenţe mai mari, conţin un
cache de dimensiune mai mare, un tampon destinat translatării adreselor
liniare în adrese fizice (TLB) pe două nivele şi un cache destinat
adreselor de salt îmbunătăţit (Fig. 7).
Pentru a oferi suportul pentru operaţiile multimedia, cache-ul poate fi
transformat într-o memorie RAM scratchpad. Această memorie
funcţionează ca o memorie privată pentru CPUşi nu participă în
operaţiile cache.
Evoluţia procesoarelor
Până unde se poate merge în direcţia miniaturizării şi creşterii
performanţelor?
O privire asupra dezvoltării procesoarelor de la origini până în
prezent ne poate permite să caracterizăm arhitecturile
microprocesoarelor contemporane şi chiar să încercăm să prevedem
cum vor arată cele de mâine.
Am întâlnit de mai multe ori un banc pe Internet, care spunea că,
dacă maşinile ar fi evoluat în aceeaşi măsură cu calculatoarele,
acum ar fi mers 120 de kilometri cu benzina dintr-o brichetă şi ar fi
costat cât o pâine. Pe de altă parte, un contra-banc, din partea
industriei automobilistice, ofensate, zicea apoi că, dacă ar fi
evoluat la fel, maşina ar fi refuzat să mai meargă de câteva ori pe
zi, şi ar fi trebuit să o duci înapoi în garaj ca să repornească.
è
ê
ì
oarelor sunt absolut uluitoare; ajunge să îţi cumperi un calculator
nou după doi ani ca să fii impresionat de câştigul de performanţă
înregistrat. Sporul de performanţă se datorează unor procesoare din
ce în ce mai sofisticate şi mai rapide, şi unor memorii de
capacităţi din ce în ce mai mari.
Răspunzătoare pentru creşterea exponenţială a performanţei sunt
însă în cea mai mare măsură microprocesoarele. În acest articol
vom arunca o privire asupra evoluţiei microprocesoarelor de la origini
până în prezent. Vom încerca apoi să caracterizăm arhitecturile
procesoarelor contemporane şi să extrapolăm din datele la
dispoziţie, speculând despre unele din posibilele evoluţii viitoare.
Trebuie să atrag de la început atenţia că nu am însuşiri
paranormale ÅŸi, ca atare, nu sunt profet. Domeniul tehnologiilor de
calcul este extraordinar de volatil şi se mişcă cu o viteză
fantastică; orice previziune este cel puţin hazardată. De altfel
caseta "Performanţe - estimări" ilustrează acest fapt, contrapunând
previziunile din urmă cu câţiva ani ale unei organizaţii extrem de
prestigioase, Semiconductor Industry Association (SIA,
http://www.semichips.org/), cu realitatea. Deci nu vă aşteptaţi de la
mine la mai mult.
Am mai publicat în PC Report o serie întreagă de articole despre
arhitectura procesoarelor moderne, pe care le voie cita ocazional; toate
acestea sunt disponibile din pagina mea de web. Articolul de faţă va
fi însă mai superficial. Există o cantitate enormă de informaţie pe
web. În acest articol am folosit în mod repetat informaţii de la
http://bwrc.eecs.berkeley. edu/CIC/, CPU Info Center.
Aspecte economice
Un istoric interesant al diferitelor idei arhitecturale din
microprocesoare puteţi găsi pe web la
http://bwrc.eecs.berkeley.edu/CIC/archive/ cpu_history.html.
Primul microprocesor a fost creat de firma Intel în 1971. Numele său
era Intel 4004, şi era un procesor pe 4 biţi. Apariţia primului
microprocesor a fost un pas cu uriaşe consecinţe în evoluţia
ulterioară a sistemelor de calcul. Diferenţa între microprocesor şi
metodele îndeobşte folosite era că procesorul strânge pe o singură
pilulă de siliciu toate unităţile funcţionale importante necesare
executării programelor; fiind toate strâns integrate, comunicaţia
între ele este rapidă şi eficace, permiţând dintr-o dată un salt
calitativ.
Nu mai puţin importantă este reducerea de cost care urmează unei
astfel de integrări. Cu siguranţă că principalul motiv al evoluţiei
explozive a tehnologiei circuitelor integrate nu este de natură
tehnologică, ci economică: spirala preţurilor din ce în ce mai
scăzute face echipamentele de calcul din ce în ce mai accesibile,
cererea creşte, ducând la venituri mai ridicate pentru fabricanţi,
care investesc mai mult în cercetare/dezvoltare şi linii tehnologice,
obţinând densităţi mai mari, permiţând integrarea mai multor
circuite precum şi costuri şi mai scăzute. Cu toată scăderea de
preţ, veniturile globale ale industriei semiconductoarelor au crescut
în mod galopant: numai anul trecut vânzările globale au fost de 149
de miliarde de dolari!
Esenţial pentru a menţine această spirală este faptul că
echipamentele de calcul măresc enorm productivitatea muncii, direct sau
indirect: de aici cererea crescândă. Iar experţii afirmă că acesta
este doar începutul şi că în viitor fiecare individ va depinde de
zeci de dispozitive de calcul în fiecare clipă. Nu suntem prea departe
de acest punct: chiar în ziua de azi, o maşină modernă are în medie
15 microprocesoare, care controlează, reglează şi diagnostichează
tot felul de parametri, de la injecţie până la frâne.
Nu pot să mă abţin să remarc că Statele Unite ale Americii atribuie
o treime din creşterea venitului naţional brut în anul trecut doar
tehnologiilor informaţionale, care însă ocupă doar 8% din forţa de
muncă. În foarte mare măsură, tehnologia informaţiei este
responsabilă pentru fenomenala dezvoltare economică pe care Statele
Unite o traversează în aceşti ani.
Aspecte cantitative
Să lăsăm acum deoparte economia, şi să aruncăm o privire asupra
evoluţiei unor parametri ai procesoarelor de-a lungul timpului. Tabela
"Cronologia Intel" prezintă evoluţia generaţiilor succesive ale celei
mai proeminente familii de procesoare, ale firmei Intel.
Ultima coloană din tabel şi figura "Performanţe - estimări" arată
care este impactul miniaturizării: această coloană indică
dimensiunea de bază (feature size), care poate fi văzută ca fiind
dimensiunea unui tranzistor. Orice reducere a acestei valori are un
impact cvadratic, pentru că suprafaţa creşte cu pătratul laturii. O
reducere de la 2 microni la 1,5 (50%) măreşte deci suprafaţa
efectivă cu 77% (4/2,25 = 1,77).
Din fericire, reducerea dimensiunilor mai are încă o consecinţă
foarte importantă: traseele pe care trebuie să le parcurgă curentul
electric între dispozitive devin mai scurte, deci se pot parcurge mai
rapid. Proiectanţii pot face deci procesorul să funcţioneze cu un
ceas mai rapid.
Observaţie: Majoritatea covârşitoare a procesoarelor contemporane
funcţionează în mod sincron: întreaga lor funcţionare este
orchestrată de un tact de ceas, care garantează că feluritele părţi
sunt sincronizate. Din ce în ce mai mult însă se tinde spre scheme cu
multiple semnale de ceas, sau chiar scheme asincrone. Nu ne vom ocupa
însă de aceste evoluţii în textul acestui articol.
Faptul că avem siliciu la dispoziţie pentru a implementa mai mulţi
tranzistori înseamnă că:
1). Putem muta mai multe circuite auxiliare pe acelaşi cip. Evoluţia
procesoarelor cunoaşte câteva salturi calitative: când miniaturizarea
făcea posibilă integrarea unui nou dispozitiv pe acelaşi circuit
integrat, se realiza un salt de performanţă. Astfel, au fost integrate
succesiv: unităţi din ce în ce mai mari de procesare (8, 16, 32, acum
64 de biţi), coprocesoare aritmetice, unităţi de management al
memoriei, cache-uri de nivel 1 ÅŸi chiar 2;
2). Designerii folosesc tranzistorii suplimentari pentru a construi
circuite mai sofisticate, care pot executa mai repede ÅŸi mai eficient
programele. Metoda fundamentală folosită este de a face mai multe
lucruri în paralel.
Împreună aceste trei fenomene (viteza ceasului, integrarea pe o
singură pastilă şi exploatarea paralelismului) contribuie la
creşterea performanţei totale a procesoarelor. Aşa cum am povestit
şi cu alte ocazii, măsurarea performanţei unui calculator se face
evaluând sistemul pe mai multe programe (deci performanţa depinde
foarte mult ÅŸi de compilatorul folosit), care de obicei fac parte din
suite de teste standardizate (benchmark suites). Cele mai folosite
pentru a evalua procesoare sunt cele din seria SPEC (Standard
Performance Evaluation Corporation, http:// www.specbench.org). Nu ne va
interesa acum prea tare ce reprezintă numerele acestea; cert este că
cu cât sunt mai mari, cu atât e mai bine. Graficul din figura
"Performanţe - SPEC" arată evoluţia performanţei procesoarelor în
ultimii 10 ani, în termeni SPEC.
Evoluţia urmăreşte aproximativ o curbă exponenţială: în fiecare
an performanţa creşte cu 60%.
Tehnologii arhitecturale
Aşa cum am ilustrat în seria mea de articole intitulate "Arhitectura
avansată a procesoarelor", o mulţime de inovaţii tehnologice au fost
introduse una după alta în arhitecturi; de fapt intenţionez să
continui această serie şi în viitor, pentru că mai sunt de prezentat
ÅŸi alte mecanisme importante.
Îmi permit să prezint în continuare viziunea profesorului John
Hennessy, de la universitatea Stanford, aşa cum a expus-o în
prelegerea pe care a ţinut-o ca invitat la Federated Computer Research
Conferences, în mai 1999.
Hennessy vede două tehnologii arhitecturale ca fiind esenţiale:
exploatarea paralelismului la nivel de instrucţiune (Instruction Level
Parallelism, ILP) şi ierarhii sofisticate de memorie (cache-uri). Să
spunem câteva cuvinte despre fiecare:
ILP
Paralelismul la nivel de instrucţiune constă în independenţa
instrucţiunilor din programe una de alta, ceea ce ne permite să
executăm mai multe instrucţiuni simultan. Am vorbit altădată pe larg
despre paralelismul la nivel de instrucţiune; să observăm că toate
procesoarele contemporane îl exploatează prin două forme:
Execuţia pe bandă de asamblare (pipeline) a instrucţiunilor
succesive;
Execuţia în paralel a instrucţiunilor independente: procesoarele de
tip VLIW (very long instruction word) aleg la compilare care
instrucţiuni merg în paralel, iar procesoarele superscalare fac
această alegere în timpul execuţiei.
Astfel, în 1985 au apărut primele procesoare cu banda de asamblare,
în 1990 primele procesoare de tip VLIW, iar în 1995 procesoare foarte
sofisticate superscalare, care pot executa instrucţiunile în ordini
foarte diferite de cea din program (out-of-order execution).
Cache-uri
Am scris în repetate rânduri despre cache-uri în PC Report (de pildă
martie 1997 ÅŸi noiembrie 1998). Aici vom arunca doar o privire
superficială asupra lor; scopul nostru este de a înţelege de ce
cache-urile joacă un rol fundamental în creşterea performanţei.
Figura "Performanţe - memorii şi procesoare" ne oferă cheia: deşi
atât procesoarele cât şi memoriile cresc constant în viteză,
creşterea procesoarelor este cu 50% mai rapidă decât a memoriilor. Ca
atare există o disparitate crescândă între nevoile de date (şi
instrucţiuni) ale procesorului şi ceea ce memoriile pot oferi. Durata
unui acces la memorie ajunge la zeci de cicli de ceas pentru
procesoarele contemporane. Întârzierea accesului este şi mai
exacerbată în cazul sistemelor care au mai multe procesoare, în care
caz timpii de acces la date pot ajunge la mii de cicli.
Din această cauză se construiesc cache-uri, care sunt memorii mai mici
şi mai rapide, care se plasează între procesor şi memoria
principală, şi în care sunt aduse datele pentru prelucrare.
Proiectanţii au reuşit să sporească eficacitatea cache-urilor
folosind două metode:
(a) Prin folosirea unor cache-uri din ce în ce mai mari, plasate din ce
în ce mai aproape de procesor. Această evoluţie este clar vizibilă:
Primele procesoare nu aveau nici un fel de cache, pentru că memoriile
erau suficient de rapide pentru a le servi cu date. În 1980 au apărut
cache-uri (L1) sub forma unor circuite speciale, care în 1984 au fost
integrate pe aceeaşi pilulă de siliciu cu procesorul central, după
care (1986) a apărut un al doilea nivel de cache (L2), mai mare şi
ceva mai lent, care în procesoarele moderne (1995) este la rândul lui
adesea integrat cu circuitul microprocesorului, pentru a permite un
acces rapid. Au apărut nivele terţiare de cache (1999).
(b) Pe de altă parte metodele de management ale cache-urilor sunt din
ce în ce mai sofisticate:
Au apărut cache-uri care servesc procesorul de îndată ce primul
cuvânt a sosit, chiar dacă restul sunt pe drum (early restart, 1992),
cache-uri care nu blochează procesorul când datele lipsesc, ci îi
permit să continue execuţia (non-blocking, 1994) şi tot felul de alte
tehnologii sofisticate, pe care le-am expus în alte părţi (cache-uri
victimă, buffere de scriere, instrucţiuni speciale (prefetching) de
management al cache-ului etc.). Tot aici se cuvine să menţionăm
multiprocesoarele simetrice şi protocoalele de coerenţă ale
cache-urilor pentru astfel de sisteme; toate procesoarele moderne sunt
construite pentru a fi folosite în sisteme multi-procesor, şi includ
astfel de dispozitive.
Arhitecturile contemporane
Astfel, urmărind evoluţia arhitecturilor, am ajuns până în ziua de
azi. Vom încerca să caracterizăm sumar starea arhitecturilor, după
care vom arunca o privire asupra unora din direcţiile viitoare.
Hardware şi software. Istoria modernă a procesoarelor contrapune două
paradigme pentru creşterea performanţei, bazate pe software şi
respectiv pe hardware. Aparent, un articol despre arhitectura
procesoarelor nu are nimic de-a face cu softul. Nimic mai greÅŸit: la
ora aceasta există o simbioză totală între hardware şi software.
Procesoarele se proiectează odată cu compilatoarele care le folosesc
iar relaţia dintre ele este foarte strânsă: compilatorul trebuie să
genereze cod care să exploateze caracteristicile arhitecturale, altfel
codul generat va fi foarte ineficace.
Metodele de creştere a performanţei cu ajutorul compilatoarelor se
numesc şi statice, pentru că programul este analizat şi optimizat o
singură dată, înainte de a fi pornit în execuţie. Metodele bazate
pe hardware se numesc dinamice, pentru că sunt aplicate în timp ce
programul se execută.
Istoria arhitecturilor contrapune mereu cele două paradigme: de exemplu
dezbaterea iniţială RISC/CISC era de aceeaşi natură, ca şi
dezbaterea între superscalar şi VLIW, pe care am menţionat-o deja în
acest text.
Notă: În anii 80 a apărut ideea de a face procesoarele mult mai
simple pentru a le permite să meargă mai repede. Astfel de arhitecturi
au fost n