Documente noi - cercetari, esee, comentariu, compunere, document
Documente categorii

Stall-uri in calculul cu virgula mobila

STALL-URI IN CALCULUL CU VIRGULA MOBILA


La un CPU actual, una din conditiile pentru o functionare eficienta este eliminarea pe cat posibil a stall-urilor, adica a situatiilor in care trebuie sa se astepte ca o anumita data sa fie disponibila pentru a continua prelucrarea. Un stall costa de la cativa la multe sute de cicli de tact, in functie de timpul necesar pentru a obtine acea data. Astfel o mare parte din instuctiunile in virgula mobila au o latenta mai mare de un ciclu masina, de aceea la familia de procesoare Pentium instructiunile urmatoare in virgula mobila nu pot accesa rezultatul inainte ca prima operatie sa ia sfarsit. Pentru a ascunde aceasta latenta, este indicat ca instructiunile sa fie inserate intre perechea ce cauzeaza stagiul pipeline-ului. Aceste instructiuni pot fi instructiuni destinate operatiilor cu numere intregi sau instructiuni in virgula mobila ce nu vor cauza ele insele un nou stall. Numarul instructiunilor ce ar trebui inserate depinde de marimea latentei. Datorita naturii "out-of-order" a executiei procesoarelor Pentium Pro si Pentium II, stall-urile nu vor aparea in mod necesar pe baza unei instructiuni sau a unei μop. Totusi, daca o instructiune are o latenta foarte mare, precum FDIV, atunci planificarea poate imbunatati rezultatul intregii aplicatii. In continuare vor fi prezentate consideratii legate de tehnica prelucrarii in conducta a instructiunilor in virgula mobila la familia de procesoare Pentium.




Utilizarea instructiunilor destinate operatiilor cu numere intregi pentru a ascunde latenta instuctiunilor in virgula mobila


Atunci cand o instructiune in virgula mobila depinde de rezultatul instructiunii imediat anterioare, fiind la randul acesteia tot o instructiune in virgula mobila, este avantajoasa mutarea instructiunilor pe numere intregi intre cele doua instructiuni in virgula mobila, chiar daca instructiunile cu intregi executa o bucla. Urmatorul exemplu restructureaza o bucla astfel:


for (i=0; i<Size; i++)

array1 [i] += array2 [i];


; assume eax=Size-1, esi=array1, edi=array2


Pentium Processor

CLOCKS

LoopEntryPoint:

fld real4 ptr [esi+eax*4]           ; 2 - AGI

fadd real4 ptr [edi+eax*4]       ; 1

fstp real4 ptr [esi+eax*4]         ; 5 - asteapta fadd

dec eax ; 1

jnz LoopEntryPoint

; assume eax=Size-1, esi=array1, edi=array2

jmp LoopEntryPoint

Align 16

TopOfLoop:

fstp real4 ptr [esi+eax*4+4]    ; 4 - asteapta fadd + AGI

LoopEntryPoint:

fld real4 ptr [esi+eax*4]           ;1

fadd real4 ptr [edi+eax*4]       ;1

dec eax                  ;1

jnz TopOfLoop


fstp real4 ptr [esi+eax*4+4]


Prin mutarea instructiunilor intre fadds si fstps, instructiunile cu intregi pot fi executate in timpul in care fadds isi finalizeaza executia in unitatea de virgula mobila, si inainte ca fstps sa-si inceapa excutia. A se nota faptul ca aceasta noua structura repetitiva necesita un punct de intrare separate pentru prima iteratie deoarece bucla trebuie sa inceapa cu flds. Totodata, este necesar sa existe o instructiune fstps suplimentara dupa saltul conditional pentru a finaliza ultima iteratie a buclei.



Mascarea latentei de un ciclu a operatiei de stocare in virgula mobila




Instructiunea de stocare in virgula mobila trebuie sa astepte un ciclu pentru operandul sau in virgula mobila. Dupa o instructiiune fld, instructiunea fst este nevoita sa astepte un ciclu masina. Dupa operatiile aritmetice obisnuite, fmul si fadd, care in mod normal au o latenta de 3, fst asteapta un ciclu suplimentar pentru un total de patru.


fld meml ; 1 fld necesita 1 ciclu

; 2 fst asteapta, programeaza ceva aici

fst mem2 ; 3,4 fst necesita 2 cicluri

fadd meml ; 1 add necesita 3 cicluri

; 2 add, programeaza ceva aici

; 3 add, programeaza ceva aici

; 4 fst asteapta, programeaza ceva aici

fst mem2 ; 5,2 fst necesita 2 cicluri


In exemplul urmator, stocarea nu este dependenta de incarcarea anterioara:


fld meml ; 1

fld mem2 ; 2

fxch st(l) ; 2

fst mem3 ; 3 salveaza valori descarcate din mem1


Un registru ar putea fi folosit imediat dup ace a fost incarcat (cu fld):


fld mem1 ; l

fadd mem2 ; 2,3,4


Utilizarea unui registru de o operatie in virgula mobila, imediat dupa ce a fost scris de o alta operatie fadd, fsub sau fmul produce o intarziere de 2 cicluri. Daca se insereaza instructiuni intre aceste doua operatii ce stau la baza intarzierii, atunci latenta si un potential stall pot fi ascunse.

De asemenea, exista instructiuni in virgula mobila cu o latenta de mai multe cicluri (fdiv si fsqrt) care opereaza in unitatea "pipe" (conducta) in virgula mobila. In timpul executarii acestor instructiuni in unitatea "pipe" in virgula mobila, se pot executa in paralel instructiuni pe numere intregi. Pipeline-ul a fost gandit tocmai pentru a oferi posibilitatea executiei simultane a mai multor instructiuni si, in cazul ideal, performanta este multiplicata de un numar de ori dat de lungimea pipeline-ului. Astfel, daca procesorul are de executat 100 de operatii, fiecare necesitand cate patru stagii, vor fi necesare doar 100 de cicluri de tact in locul a 400, pe fiecare ciclu fiind executate cate patru operatii. Din pacate, situatia ideala nu este intalnita niciodata pentru ca instructiunile depind unele de altele mai mult decat pare la prima vedere.



Instructiunile destinate operatiilor cu numere intregi se intretaie in general cu cele in virgula mobila, cu exceptia cazului in care ultima operatie in virgula mobila a fost fxch. In acest cay latenta este de un singur ciclu

U-pipe:                           V-pipe:

fadd                                  fxch ; 1

; 2 fxch delay

mov eax, 1                       inc edx ;


Multiplicarea valorilor intregi si in virgula mobila


Operatiile de inmultire a doua numere intregi, mul and imul, se executa in unitatea in virgula mobila, astfel ca aceste instructiuni nu pot fi executate in paralel cu o operatie in virgula mobila. O operatie de inmultire in virgula mobila (fmul) intarzie cu un ciclu daca ciclul imediat urmator executa o instructiune fmul sau o pereche fmul / fxch. Instructiunea poate accepta o noua pereche de operanzi doar la fiecare alt ciclu.


Operatii in virgula mobila cu operanzi intregi


Operatiile in virgula mobila care accepta operanzi de tipul intreg (fiadd sau fisub) trebuiesc evitate.

Aceste instructiuni ar trebui splitate in cate doua instructiuni: fild si o operatie in virgula mobila. Numarul de cicluri care trebuie sa treaca in cazul instructiunii fiadd pina la a executarea unei noi instructiuni este 4, in timp ce in cazul instructiunilor fild si cea in virgula mobila simpla numarul este de un singur ciclu, dupa cum se vede in exemplul de mai jos:


Instructiuni complexe:                           Exemplul mai bun:

fiadd [ebp] ; 4           fild [ebp] ; 1

faddp st(l) ; 2


Prin utlizarea instructiunilor fild - faddp aduce un beneficiu de doua cicluri libere pentru executarea altor instructiuni.


Instructiunile FSTSW


Instructiunile fstsw, utilizate in general dupa o comparatie in virgula mobila (fcom, fcomp, fcompp), au o latenta de 3 cicluri. In scopul de a ascunde aceasta latenta, dupa operatia de comparatie pot fi inserate alte instructiuni. In cazul procesoarelor Pentium Pro si Pentium II se poat utiliza in schimb instructiunea fcmov.





Utilizarea instructiunilor cvttps2pi / cvttss2si


Instructiunile cvttps2pi si cvttss2si seteaza in mod implicit regula de rotunjire prin trunchiere, avand astfel prioritate fata de regula de rotunjire specificata in registrul MXCSR. Acest lucru poate elimina necesitatea schimbarii regulii de rotunjire de la rotunjirea la cel mai apropiat numar in virgula mobila (rotunjirea la par) la rotunjirea prin trunchiere, si apoi inapoi la rotunjirea la par pentru reluarea calcului. Schimbarile frecvente in registrul MXCSR trebuie evitate intrucat exista o penalitate asociata scrierii acestui registru. Prin utilizarea instreuctiunilor cvttps2pi si cvttss2si, regula de rotunjire poate fi oricand setata in MXCSR drept rotunjire la par.


Codul scalar in virgula mobila


Exista instructiuni SIMD in virgula mobila care opereaza doar la nivelul celui mai putin semnificativ operand in registrul SIMD. Aceste instructiuni sunt cunoscute drept instructiuni scalare si permit registrilor XMM sa fie folositi in calcule generale in virgula mobila. In termeni de performanta, codul scalar in virgula mobila poate fi echivalent sau poate hiar depasi codul x87 in virgula mobila si are urmatoarele avantaje:

codul in virgula mobila SIMD utilizeaza un model "flat" de registrii, pe cand codul x87 in virgula mobila utilizeaza modelul stivei. Folosirea codului scalar in virgula mobila elimina necesitatea utilizarii instructiunii fxch, care are unele limitari in ceea ce priveste performanta procesorului Intel Pentium 4 processor.

.imbinarea cu tehnologia MMX fara penalizari..

.latente mai scurte decat codul x87 in virgula mobila.

La folosirea instructiunilor scalare in virgula mobila, nu este necesara asigurarea aparitiei datei sub forma de vectoriala.



BIBLIOGRAFIE



Lucian Vintan, Adrian Florea, Microarhitecturi de procesare a informatiei, Editura Tehnica, Bucuresti, 2000

Intel Architecture Optimization Manual, 1997