Streaming av SIMD-utvidelser

SSE ( S treaming S IMD Extensions ) er et SIMD - instruksjonssett designet av Intel i 1999 og brukt i Pentium III-prosessoren som et svar på 3DNow! laget av AMD , som hadde vært på markedet i omtrent ett år. Det ble opprinnelig kjent under forkortelsen KNI , fra K atmai N ew I nstructions ( Katmaivar kodenavnet til den første Pentium III). Under Katmai-prosjektet prøvde Intel å skille den fra sin forrige produktlinje, spesielt Pentium II . AMD la senere til støtte for SSE-instruksjoner i sin Athlon XP-prosessor .

Intels første forsøk på SIMD, MMX -teknologi , var en skuffelse. MMX har hovedsakelig to problemer: den gjenbruker flyttallsregistre, noe som gjør det umulig for CPU'en å jobbe med flyttalldata og SIMD -data samtidig, men den kan bare operere på heltall.

SSE legger til åtte nye 128 - biters registre med navn som spenner fra XMM0 til XMM7. Hvert register grupperer fire 32-biters (enkelt presisjon) flyttallstall.

Siden disse 128-bits registrene representerer tilleggstilstander som operativsystemet må bevare under bytte av oppgavekontekst , er de deaktivert inntil operativsystemet eksplisitt aktiverer dem. Dette betyr at operativsystemet må programmeres til å bruke FXSAVE- og FXRSTOR-instruksjonene, som er instruksjonene introdusert av SSE for å lagre x86 , MMX, 3DNow! og SSE. Støtte for disse instruksjonene ble raskt lagt til alle større 32-biters operativsystemer.

Siden SSE legger til flytende punktstøtte, ble det mye mer brukt enn MMX ettersom alle skjermkort håndterer heltallsberegninger internt. Hele settet besto av 70 instruksjoner. Med introduksjonen av SSE2 kan jevne heltall brukes med de nye XMM-registrene, så MMX -instruksjonssettet er nå overflødig.

Pentium III er imidlertid SSE implementert ved å bruke de samme kretsene som FPU , noe som betyr at CPU ikke kan sende SSE- og flytepunktinstruksjoner inn i rørledningen samtidig. Separate registre gjør det mulig å blande SIMD- og flyttalloperasjoner, men uten ytelsen som oppnås ved eksplisitt å bytte fra flyttall- til MMX-modus.

Pentium 4 implementerer SSE2 , en utvidelse av SSE-instruksjonssettet . Hovedtrekkene til SSE2 er støtte for dobbelpresisjon (64-bits) flyttall og støtte for heltall i 128-biters registervektoren introdusert med SSE, som lar programmereren bruke MMX-registre. SSE2 i seg selv har blitt utvidet med SSE3 introdusert med Prescott -kjerne fra de siste Pentium 4-generasjonene.

Registrerer

SSE har lagt til åtte nye 128-bits registre identifisert med kodene XMM0 til XMM7. AMD64 -utvidelsene (senere duplisert av Intel) la til åtte flere registre fra XMM8 til XMM15. Det er også et nytt 32-bits statusregister, MXCSR. Registrene XMM8 til XMM15 er kun tilgjengelige i 64-bits modus.

Hvert register kan inneholde sammen:

Operasjoner på heltall har varianter for signerte og usignerte tall. Full SIMD -operasjoner kan utføres med de åtte 64-bits MMX-registrene.

Siden disse 128-bits registrene er tilleggsprogramtilstander som må vedlikeholdes av operativsystemet under oppgavebytte, er de deaktivert som standard inntil operativsystemet eksplisitt aktiverer dem. Dette krever at operativsystemet selv kjenner til og bruker paret med FXSAVE- og FXRSTOR-instruksjoner, som lagrer alle x86- og SSE-statusregistre på én gang. Denne muligheten ble raskt lagt til alle 32-biters operativsystemer.

Siden SSE-instruksjoner også fungerer med flyttall, er de mye mer nyttige enn MMX-utvidelser, og tillegget av SSE2-instruksjoner har gjort dem enda mer attraktive. Selv om MMX-instruksjoner er overflødige, kan de kjøre parallelt med SSE-instruksjoner, noe som øker ytelsen under noen omstendigheter.

SSE-instruksjoner

SSE introduserer både operasjoner på enkeltskalarer og på grupper av flyttall (pakket).

Flytende kommasetninger

Instruksjoner om heltall

Andre instruksjoner

Eksempler

Følgende eksempler viser fordelen med å bruke SSE-instruksjoner. Tenk på en operasjon som summen av vektorer, som veldig ofte brukes i datagrafikk; Å legge til to enkeltpresisjonsvektorer med 4 komponenter hver krever fire flyttallssuminstruksjoner i en normal x86-prosessor:

vec_res.x = v1.x + v2.x ; vec_res.y = v1.y + v2.y ; vec_res.z = v1.z + v2.z ; vec_res.w = v1.w + v2.w ;

Disse fire linjene blir like mange FADD-setninger i den kompilerte objektkoden. Med SSE-instruksjoner derimot, som du kan se av følgende kode, er en enkelt 128-bits 'packed-add'-instruksjon nok til å utføre beregningen.

movaps xmm0, adresse-av-v1  ; xmm0 = v1.w | v1.z | v1.y | v1.x addps xmm0, address-of-v2  ; xmm0 = v1.w + v2.w | v1.z + v2.z | v1.y + v2.y | v1.x + v2.x

Forskjeller mellom x87 FPU og SSE

FPU (x87)-instruksjoner lagrer vanligvis resultater med 80 bits presisjon. Når gamle algoritmer skrevet for x87 FPU-er tilpasses de nye SSE-utvidelsene, som kun støtter 64 bits presisjon, kan noen kombinasjoner av aritmetiske operasjoner og datasett resultere i betydelige numeriske forskjeller: dette er veldig viktig i vitenskapelige beregninger, hvis beregningen må sammenlignes med resultater oppnådd på andre maskinvarearkitekturer.

Avhengig av hvilken tolk eller kompilator som brukes og hvilke optimaliseringer som er valgt, kan det være nødvendig å midlertidig lagre visse data og laste dem på nytt senere; vanligvis er resultatene av x87 FPU også avrundet til 64 eller 32 biter, men det nøyaktige stedet og tidspunktet dette skjer kan forårsake forskjeller i det endelige resultatet av beregningene. Følgende kodeeksempel i Fortran 95 gir bevis: den riktige verdien av det tredje og siste tallet som skal skrives ut er null.

program hei ekte a, b, c, d ekte x, y, z a = 0,013 b = 0,027 c = 0,0937 d = 0,79 y = -a / b + (a / b + c) * EXP (d) skriv ut *, y z = (- a) / b + (a / b + c) * EXP (d) skriv ut *, z x = yz skriv ut *, x slutt

Ved å kompilere med x87 FPU-instruksjoner og utføre får vi:

# g95 -o hi -mfpmath = 387 -fzero -ftrace = full -fsloppy-char hi.for # ./hei 0,78587145 0,7858714 5.9604645E-8

Ved å kompilere med SSE-utvidelser og utføre får du:

# g95 -o hi -mfpmath = sse -msse2 -fzero -ftrace = full -fsloppy-char hi.for # ./hei 0,78587145 0,78587145 0.

Relaterte elementer