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łowy typ docelowy instrukcja
1 liczba całkowita liczba zmiennoprzecinkowa CVTSI2SS
2 para liczb całkowitych para liczb zmiennoprzecinkowych CVTPI2PS
3 liczba zmiennoprzecinkowa liczba całkowita CVTSS2SI
4 CVTTPS2PI
5 para liczb zmiennoprzecinkowych para liczb całkowitych CVTPS2PI
6 CVTTPS2PI

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Å› UNPCKLPS 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 2
index2_0 := (imm8 AND 00110000b) SHR 4
index2_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] MOVLSP, MOVHSP

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ę.

[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, PMAXSW - 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Ä™ CRC32
  • SSE5 - zapowiadane na 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 - zapowiadane na 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ż