Widget
Podziel się:

Streaming SIMD Extensions


Definicja intuicyjna:
SSE to dodatkowe rozkazy rozpoznawane przez mikroprocesory firmy Intel oraz kompatybilnych, które pozwalają znacznie szybciej wykonywać obliczenia matematyczne, szczególnie te wykorzystywane w dziedzinie multimediów, co przekłada się na zwiększenie efektywności działania m.in. gier komputerowych, programów graficznych, muzycznych, kodowania filmów i muzyki.

Nowe rejestry SSE

SSE (ang. "Streaming SIMD Extensions") jest nazwą zestawu instrukcji wprowadzonego w 1999 roku po raz pierwszy w procesorach Pentium III firmy Intel. SSE daje przede wszystkim możliwość wykonywania działań zmiennoprzecinkowych na 4-elementowych wektorach liczb pojedynczej precyzji (48 rozkazów). Ponadto wprowadzono jedenaście nowych rozkazów stałoprzecinkowych w zestawie MMX, a także dano możliwość wskazywania, które dane powinny znaleźć się w pamięci podręcznej.

SSE to również zmiany w architekturze procesora: dodano 8 rejestrów XMM o rozmiarze 128 bitów oraz 32-bitowy rejestr kontrolny MXCSR; w 64-bitowych wersjach procesorów (AMD64, EM64T) dostępne jest jeszcze 8 dodatkowych rejestrów XMM. Rejestry 128-bitowe, na zawartości których wykonywana jest większość rozkazów SSE (nazywane w asemblerze xmm0, xmm1, ..., xmm15), stanowią zupełnie odrębne komórki pamięci – w odróżnieniu od rejestrów MMX nie zostały zamapowane na inne rejestry.


Spis treści

[edytuj] Typy danych

SSE wprowadza nowy typ danych: 4-elementowy wektor liczb zmiennoprzecinkowych pojedynczej precyzji (ang. 128-bit packed sigle-precision floating-point); liczba zmiennoprzecinkowa ma rozmiar 32 bitów. Poza tym wykorzystuje typy wektorowe zdefiniowane w MMX.

Rozkazy SSE mogą wykonywać działania arytmetyczne na wektorach liczb zmiennoprzecinkowych na dwa sposoby:

  1. packed (równoległe) — wykonując równocześnie 4 niezależne działania zmiennoprzecinkowe na odpowiadających sobie elementach wektorów;
  2. scalar (skalarne) — wykonując działanie tylko na pierwszych elementach wektorów.

Przykład – mnożenie dwóch wektorów (rozkazem MULPS xmm0, xmm1):

+-------+-------+-------+-------+|   x3  |   x2  |   x1  |   x0  | xmm0+-------+-------+-------+-------+    *       *       *       *+-------+-------+-------+-------+|   y3  |   y2  |   y1  |   y0  | xmm1+-------+-------+-------+-------+    =       =       =       =+-------+-------+-------+-------+| x3*y3 | x2*y2 | x1*y1 | x0*y0 | xmm0+-------+-------+-------+-------+

Przykład – mnożenie pierwszych elementów wektorów (rozkazem MULSS xmm0, xmm1):

+-------+-------+-------+-------+|   x3  |   x2  |   x1  |   x0  | xmm0+-------+-------+-------+-------+                            *+-------+-------+-------+-------+|   y3  |   y2  |   y1  |   y0  | xmm1+-------+-------+-------+-------+    =       =       =       =+-------+-------+-------+-------+|   x3  |   x2  |   x1  | x0*y0 | xmm0+-------+-------+-------+-------+

[edytuj] Mnemoniki rozkazów

Mnemoniki instrukcji SSE działających na wektorach liczb całkowitych zostały wybrane zgodnie z konwencję wprowadzoną w MMX — nazwy zaczynają się najczęściej od litery P.

Dla nazw instrukcji działających na liczbach zmiennoprzecinkowych nie wprowadzono żadnego prefiksu; jednak podobnie jak w MMX sufiks nazwy określa typ:

  • PS (packed single) – działanie na wektorach,
  • SS (scalar single) – działanie na skalarach.

Ponadto jeśli rozkazy działają na połówkach rejestrów XMM (tj. albo odnoszą się do bitów 0..63, albo 64..127), w mnemonikach rozkazu występuje litera – odpowiednio – L albo H, od angielskich słów low ("niski") i high ("wysoki").

[edytuj] Działania zmiennoprzecinkowe

SSE jest zgodne ze standardem IEEE-754. Możliwe jest jednak włączenie pewnych niestandardowych cech, które w niektórych przypadkach przyspieszają obliczenia.

[edytuj] Działania arytmetyczne

  • dodawanie (ADDPS, ADDSS)
  • odejmowanie (SUBPS, SUBSS)
  • mnożenie (MULPS, MULSS)
  • dzielenie (DIVPS, DIVSS)
  • przybliżenie odwrotności (1/x) (RCPPS, RCPSS)
  • pierwiastek kwadratowy (SQRTPS, SQRTSS)
  • przybliżenie odwrotności pierwiastka kwadratowego (RSQRTPS, RSQRTSS)
  • wyznaczenie minimalnej wartości (MINPS, MINSS)
  • wyznaczenie maksymalnej wartości (MAXPS, MAXSS)

[edytuj] Działania logiczne

Działania logiczne są wykonywane na poziomie bitów, nie na liczbach zmiennoprzecinkowych:

  • suma (ORPS);
  • iloczyn (ANDPS);
  • iloczyn z negacją (ANDNPS) – jeden z operandów jest negowany przed obliczeniem iloczynu;
  • różnica symetryczna (XORPS).

[edytuj] Porównania

Porównania w SSE są dwojakiego rodzaju:

  1. Modyfikujące rejestr SSE w sposób analogiczny jak w MMX
  2. Modyfikujące rejestr flag

Ad. 1. Modyfikujące rejestr SSE w sposób analogiczny jak w MMX: dla tych elementów, dla których wynik porównania jest prawdziwy wszystkie bity w rejestrze docelowym są ustawiane, gdy nieprawdziwy – zerowane. Ten sposób porównania może być zastosowany zarówno dla wektorów (rozkaz CMPPS) jak i skalarów (rozkaz CMPSS).

Przykład testowania, czy liczby są różne (rozkaz CMPNEQPS xmm0, xmm1[1]):

 +---------+---------+---------+---------+ |   1.0   |  -5.3   |   16.5  |   17.2  | xmm0 +---------+---------+---------+---------+      ≠         ≠         ≠         ≠ +---------+---------+---------+---------+ |   7.0   |  -5.3   |   16.5  |   17.3  | xmm1 +---------+---------+---------+---------+      =         =         =         = +---------+---------+---------+---------+ |111..1111|000..0000|000..0000|111..1111| xmm0 +---------+---------+---------+---------+

Można testować 8 różnych relacji:

  • równy,
  • mniejszy,
  • mniejszy lub równy,
  • różny,
  • większy,
  • większy lub równy,
  • ang. unordered[2].
  • ang. orderded (odwrotność unordered).

Ad. 2. Modyfikujące rejestr flag, dzięki czemu można sterować przepływem sterowania za pomocą rozkazów skoku warunkowego; rozpoznawane są 4 różne relacje liczb: mniejszy, większy, równy oraz unordered. Ten sposób porównania może być stosowany tylko do skalarów, przy czym dostępne są dwa rozkazy: COMISS – sygnalizujący błąd gdy wystąpi nieprawidłowa liczba zmiennoprzecinkowa QNaN lub SNaN oraz UCOMISS – sygnalizująca błąd tylko w przypadku SNaN.

[edytuj] Konwersje pomiędzy liczbami całkowitymi i zmiennoprzecinkowymi

#typ źródłowytyp docelowyinstrukcja
1liczba całkowitaliczba zmiennoprzecinkowaCVTSI2SS
2para liczb całkowitychpara liczb zmiennoprzecinkowychCVTPI2PS
3liczba zmiennoprzecinkowaliczba całkowitaCVTSS2SI
4CVTTPS2PI
5para liczb zmiennoprzecinkowychpara liczb całkowitychCVTPS2PI
6CVTTPS2PI

Uwagi:

  • Liczby całkowita, tj. 32-bitowe liczby ze znakiem
  • Metoda zaokrąglania w większości rozkazów jest ustawiana w rejestrze kontrolnym MXCSR, wyjątkiem są rozkazy CVTTPS2PI i CVTTSS2SI dla których zawsze trybem zaokrąglanie jest ucinanie (ang. chop, truncate).
  • Wyniki zapisywane są do najmłodszego albo dwóch najmłodszych elementów wektora docelowego, zaś pozostałe elementy nie są zmieniane.

[edytuj] Rozmieszczenie elementów w wektorze

Rozkazy SHUFPS, UNPCKLPS, UNPCKHPS umożliwiają różnorakie rozmieszczenie ("wymieszanie") elementów, np. odwrócenie kolejności elementów w wektorze.

[edytuj] UNPCKLPS, UNPCKHPS

Rozkazy ustawia na przemian 2 elementy z obu wektorów. UNPCKLPS bierze dwa młodsze elementy (tj. o indeksach 0 i 1), natomiast UNPCKHPS dwa starsze (indeksy 2 i 3). Rozkaz UNPCKLPS xmm1, xmm2 wykonuje:

temp[0] := xmm1[0]temp[1] := xmm2[0]temp[2] := xmm1[1]temp[3] := xmm2[1]xmm1 := temp

zaś UNPCKHPS xmm1, xmm2

temp[0] := xmm1[2]temp[1] := xmm2[2]temp[2] := xmm1[3]temp[3] := xmm2[3]xmm1 := temp

Np.

           3     2     1     0        +-----+-----+-----+-----+ xmm1 = |  d  |  c  |  b  |  a  |        +-----+-----+-----+-----+                +-----+-----+-----+-----+ xmm2 = |  h  |  g  |  f  |  e  |        +-----+-----+-----+-----+

Wynik UNPCKLPS:

        +-----+-----+-----+-----+ xmm1 = |  f  |  b  |  e  |  a  |        +-----+-----+-----+-----+

Wynik UNPCKHPS:

        +-----+-----+-----+-----+ xmm1 = |  h  |  d  |  g  |  c  |        +-----+-----+-----+-----+

[edytuj] SHUFPS

Rozkaz bardziej ogólny niż UNPCKxPS, umożliwia wskazanie dowolnych indeksów z wektorów źródłowych za pomocą trzeciego argumentu (stałej natychmiastowej), w którym na każdych kolejnych dwóch bitach zapisane są 4 indeksy. Rozkazowi SHUFPS xmm1, xmm2, imm8 odpowiada:

{ pobranie indeksów }index1_0 := (imm8 AND 00000011b)index1_1 := (imm8 AND 00001100b) SHR 2index2_0 := (imm8 AND 00110000b) SHR 4index2_1 := (imm8 AND 11000000b) SHR 6{ rozmieszczenie elementów }temp[0] := xmm1[index1_0]temp[1] := xmm1[index1_1]temp[2] := xmm2[index2_0]temp[3] := xmm2[index2_1]xmm1 := temp

[edytuj] MXCSR - rejestr kontrolny/statusu

Rejestr MXCSR przechowuje:

  1. Ustawienia operacji zmiennoprzecinkowych:
    • sposób zaokrąglanie wyniku:
      • do najbliższej liczby całkowitej
      • zaokrąglanie w stronę plus nieskończoności
      • zaokrąglanie w stronę minus nieskończoności
      • ucinanie (zaokrąglanie w stronę zera)
    • flaga flush-to-zero – jeśli ustawiona w przypadku niedomiaru zamiast zgłaszania wyjątku, zapisywana jest liczba zero; działanie nie jest zgodne ze standardem, ale powoduje przyspieszenie programów
  2. Maski włączające zgłaszanie wyjątków przy błędach; wykrywane błędy:
    • niewłaściwe argumenty (np. pierwiastkowanie ujemnej liczby),
    • dzielenie przez zero,
    • nadmiar (wynik jest zbyt duży),
    • niedomiar (wynikiem jest liczba nie znormalizowana),
    • niedokładny wynik (wynik nie może być dokładnie reprezentowany).
  3. Flagi wskazujące rodzaj błędu – ustawiane automatycznie przez procesor, niezależnie od tego, czy dany błąd jest zgłaszany, czy nie; muszą zostać wyzerowane programowo (zwykle w procedurze obsługi wyjątków SSE).

[edytuj] Przesłania liczb zmiennoprzecinkowych między rejestrami i pamięcią

Rozkazy działają na wektorach liczb zmiennoprzecinkowych (4 elementy).

[edytuj] MOVAPS, MOVUPS

Przesłanie 4 liczb zmiennoprzecinkowych pomiędzy rejestrem XMM, a pamięcią lub innym rejestrem XMM:

  • MOVAPS — wymaga, by adres pamięci był wyrównany do granicy 16 bajtów, tj. jego 4 najmłodsze bity muszą być równe zero – w przeciwnym przypadku zgłaszany jest błąd.
  • MOVUPS — nie nakłada takich ograniczeń, ale odczyt danych niewyrównanych jest zwykle wolniejszy.

[edytuj] MOVSS

Przesłanie jednej liczby zmiennoprzecinkowej pomiędzy rejestrem XMM, a pamięcią lub innym rejestrem XMM. Rozkaz działa na elemencie 0 rejestrów XMM: przy przesłaniach z rejestru do rejestru tylko on jest zmieniany, przy przesłaniu z pamięci do rejestru zerowane są pozostałe elementy.

[edytuj] MOVLPS, MOVHPS

Przesłanie 2 liczb zmiennoprzecinkowych pomiędzy rejestrem XMM i pamięcią. Rozkaz MOVLPS działa na elementach 0 i 1 rejestru XMM, natomiast MOVHPS na elementach 2 i 3.

[edytuj] MOVLHPS, MOVHLPS

Przesłanie między rejestrami 64-bitów (2 liczb zmiennoprzecinkowych)

  • MOVLHPS – zapisanie elementów 0 i 1 rejestru źródłowego na pozycjach 2 i 3 rejestru docelowego;
  • MOVHLPS – zapisanie elementów 2 i 3 rejestru źródłowego na pozycjach 0 i 1 rejestru docelowego.

[edytuj] MOVMSKPS

Utworzenie 4-bitowej maski z najstarszych bitów każdej z liczb (tj. z bitów znaku) i zapisanie jej do rejestru ogólnego przeznaczenia x86 (EAX, EBX itd.).

[edytuj] Pamięć podręczna

W SSE dostępne są trzy grupy rozkazów odnoszące się do pamięci podręcznej.

[edytuj] Pobranie danych "bliżej" procesora

Rozkazy PREFETCH (PREFETCHT0, PREFETCHT1, PREFETCHT2, PREFETCHNTA) są rodzajami podpowiedzi (ang. hint) dla procesora, wskazującymi, że obszar pamięci powinien znaleźć się wyżej w hierarchii pamięci podręcznej: poziom 1 znajduje się najbliżej procesora, poziom 2 dalej itd. Im "bliżej" procesora znajdują się dane, tym mniejszy jest czas oczekiwania na nie; np. jeśli dane są już w pamięci podręcznej pierwszego poziomu, prawie w ogóle nie trzeba czekać, w przeciwnym razie czas oczekiwania może wynieść kilkanaście, a nawet kilkadziesiąt lub kilkaset cykli maszynowych[3].

Programista czy kompilator wie lepiej kiedy i które dane wykorzystuje – za pomocą rozkazów PREFETCH może odpowiednio wcześniej powiadomić procesor o zapotrzebowaniu i uniknąć tym samym oczekiwania, kiedy dane będą już potrzebne.

Należy zauważyć, że procesor może owych "podpowiedzi" w ogóle nie uwzględnić.

[edytuj] Trwały zapis (ang. non-temporal)

Pamięć podręczna służy m.in. do szybkiego sięgania po ostatnio zapisane informacje. Jednak zauważono, że pewnych przypadkach dane zapisywane z rejestrów do pamięci nie są więcej używane i dlatego nie ma potrzeby, aby zapisywać je w pamięci podręcznej (oraz marnować przy okazji jej ograniczone zasoby).

W SSE wprowadzono trzy rozkazy pozwalające przesłać dane do pamięci z pominięciem pamięci podręcznej:

  1. MOVNTQ – zapis zawartości rejestru MMX
  2. MOVNTPS – zapis zawartości rejestru SSE
  3. MASKMOVQ – zapis wybranych bajtów z rejestru MMX

W przypadku innych przesłań do pamięci, procesor może zakładać, że wszystkie zapisy do pamięci są tymczasowe (ang. temporal) i w ogóle nie uaktualniać zawartości pamięci głównej. Za pomocą rozkazu SFENCE wymusza się synchronizację - patrz bariera pamięci.

[edytuj] 64-bitowe rozkazy całkowitoliczbowe

Operandami dodatkowych rozkazów całkowitoliczbowych są tylko rejestry MMX; w SSE2 pojawiła się już możliwość wykorzystania również rejestrów SSE.

Rozkazy:

  • PAVGB, PAVGW – średnia bajtów/słów bez znaku (tutaj: słowo ma 16-bitów)
  • PMAXUB, PMINUB – wybranie bajtów bez znaku o maksymalnej/minimalnej wartości
  • PMAXSW, PMINSW – wybranie słów ze znakiem o maksymalnej/minimalnej wartości
  • PMOVMSKB – utworzenie maski bitowej z najstarszych bitów wszystkich bajtów
  • PMULHUW – starsze słowo z wyniku mnożenia słów bez znaku
  • PSADBW – suma modułów różnicy bajtów (tj. \sum_{i=0}^7 |a_i - b_i|, czyli odległość w metryce manhattan)
  • PEXTRW, PINSRW – pobranie/wstawienie dowolnego słowa wektora
  • PSHUFW – rozmieszczenie słów w wektorze

[edytuj] Rozszerzenia SSE

Kolejne rozszerzenia do zestawu instrukcji SSE:

  • SSE2 – 2000 rok (wprowadzone przez firmę Intel):
    • wprowadzenie działań wektorowych i skalarnych na liczbach zmiennoprzecinkowych podwójnej precyzji,
    • umożliwienie wykonywania działań całkowitoliczbowych na 128-bitowych rejestrach XMM,
    • większa kontrola nad pamięcią podręczną.
  • SSE3 – 2004 rok (Intel):
    • dodatkowe rozkazy wektorowe działające na liczbach zmiennoprzecinkowych pojedynczej i podwójnej precyzji,
    • sprzętowe wspomaganie synchronizacji wątków.
  • SSSE3 – 2006 rok (Intel):
    • dodatkowe rozkazy wektorowe działające na liczbach całkowitych,
    • rozkaz umożliwiający wyznaczenie zadanej permutacji bajtów w rejestrze XMM.
  • SSE4 – 2007 rok (Intel):
    • dodatkowe rozkazy wektorowe działające zarówno na liczbach całkowitych jak zmiennoprzecinkowych,
    • rozkazy wektorowe wspomagające kompresję wideo,
    • rozkazy wektorowe wykonujące działania na łańcuchach znaków,
    • rozkazy wyznaczający sumę CRC-32.
  • SSE5 – 2009 rok (AMD):
    • dodatkowe rozkazy wektorowe działające zarówno na liczbach całkowitych jak zmiennoprzecinkowych,
    • wprowadzenie rozkazów trój- i czteroargumentowych, w który jeden z argumentów jest docelowy (rozwiązanie z architektury RISC) – dotychczas rozkazy były 2-argumentowe, z czego jeden był równocześnie docelowy i jeśli jego wartość była potrzebna w dalszej części obliczeń, należało go zapamiętać – w rozkazach 3- i 4-arguementowych takiego problemu nie ma,
    • rozkazy 4-argumentowe pozwalają akumulować wyniki mnożenia wg schematu w = \pm z + (\pm x \cdot y).
  • Advanced Vector Extensions – 2010 rok (Intel):
    • dodanie nowych, 256-bitowych rejestrów: część istniejących rozkazów SSE, SSE2, SSE3 i SSSE3, głównie zmiennoprzecinkowych może wykonywać działania na tych rejestrach,
    • kilka rozkazów wektorowych działających wyłącznie na 256-bitowych rejestrach,
    • część istniejących rozkazów może być wykonywana wariantach 3-argumentowych (jak w SSE5),
    • rozkazy 4-argumentowe pozwalają akumulować wyniki mnożenia na liczbach zmiennoprzecinkowych wg schematu w = \pm z + (\pm x \cdot y),
    • zwiększono z 8 do 32 liczbę relacji, które można sprawdzić rozkazami porównania (CMPPS, CMPPD),
    • sprzętowe wsparcie szyfrowania AES.

Przypisy

  1. Rozkazy CMPPS/CMPSS są trójargumentowe: dwa pierwsze argumenty to porównywane wektory, trzeci argument to stała określająca testowaną relację. Jednak Intel proponuje, aby w asemblerze dostępne były dwurgumentowe pseduorozkazy, w których rodzaj relacji zapisany będzie w mnemoniku – np. CMPNEQPS xmm0, xmm1 odpowiada CMPPS xmm0, xmm1, 4 (4 – kod dla relacji "różny", ang. Not EQual).
  2. Relacja unordered jest prawdziwa, gdy argumentów nie można porównać, ponieważ przynajmniej jeden z nich jest nie-liczbą (NaN) lub nie reprezentuje prawidłowej liczby zmiennoprzecinkowej.
  3. Orientacyjne wartości: jeśli dane są w L1 – 2-3 cykle, w L2 – rzędu 10 cykli, w pamięci głównej – rzędu 100–200 cykli.

[edytuj] Zobacz też


Tekst udostępniany na licencji Creative Commons: uznanie autorstwa, na tych samych warunkach, z możliwością obowiązywania dodatkowych ograniczeń.

Zobacz szczegółowe informacje o warunkach korzystania.

Zasady ochrony prywatności O Wikipedii Informacje prawne