SSE3

Z Wikipedii, wolnej encyklopedii

Streaming SIMD Extensions 3 (SSE3, oznaczany również przez firmę Intel jako Prescott New Instructions lub PNI) – zestaw instrukcji SIMD wykorzystywany w architekturze IA-32. Wcześniejsze zestawy SIMD stosowane na platformie x86, od najstarszej to: MMX, 3DNow! (używany tylko przez AMD), SSE i SSE2.

SSE3 wprowadza 13 nowych rozkazów w stosunku do swojego poprzednika SSE2, są to:

  • FISTTP – do konwersji liczb zmiennoprzecinkowych do całkowitych
  • ADDSUBPS, ADDSUBPD, MOVSLDUP, MOVSHDUP, MOVDDUP – do arytmetyki zespolonej
  • LDDQU – do kodowania wideo
  • HADDPS, HSUBPS, HADDPD, HSUBPD – do grafiki (SIMD FP/AOS)
  • MONITOR, MWAIT – do synchronizacji wątków

Intel wprowadził SSE3 2 lutego 2004 roku wraz z procesorem Pentium 4 Prescott, natomiast firma AMD w procesorach Athlon 64 od wersji E.

Nowe rozkazy[edytuj | edytuj kod]

Nowe rozkazy:

  • rozkazy wektorowe działające albo na wektorach liczb zmiennoprzecinkowych pojedynczej albo podwójnej precyzji (tj. wektory 4 × 32 bity lub 2 × 64 bity):
    • ADDSUBPS
    • ADDSUBPD
    • HADDPS, HSUBPS
    • HADDPD, HSUBPD
    • MOVSLDUP, MOVSHDUP
    • MOVDDUP
  • FISTTP – nowy rozkaz FPU
  • LDDQU
  • MONITOR i MWAIT

Przed wprowadzaniem SSE3 prawie wszystkie rozkazy arytmetyczne występujące w MMX, SSE, SSE2 działały, jak to określa Intel, „pionowo” (ang. vertical), tj. argumentami działań zawsze są elementy z dwóch wektorów. Natomiast w SSE3 pojawiły się rozkazy działające „poziomo” (ang. horizontal) — argumentami operacji arytmetycznych są elementy tego samego wektora; te instrukcje to: HADDPS, HADDPD, HSUBPS, HSUBPD.

FISTTP[edytuj | edytuj kod]

Rozkaz koprocesora arytmetycznego zamieniający liczbę zmiennoprzecinkową zapisaną w wierzchołku stosu na liczbę całkowitą ze znakiem; trybem zaokrąglania zawsze jest ucinanie (ang. chop), niezależnie od ustawień zapisanych w rejestrze kontrolnym FPU. Liczba całkowita może być 16-, 32- lub 64-bitowa, zależnie od argumentu.

Zgłaszany jest wyjątek w przypadku, gdy konwersja jest niemożliwa (wartość przekracza zakres liczby całkowitej, albo jest klasy plus/minus nieskończoność lub NaN).

Rozkaz FISTTP to uproszczona wersja istniejącej instrukcji FISTP, w której tryb zaokrąglania sterowany jest poprzez słowo kontrolne koprocesora – jego ewentualna zmiana jest kosztowna (trzeba wykonać kilka lub kilkanaście dodatkowych instrukcji: zachować bieżące ustawienia, włączyć inny tryb zaokrąglania, wykonać FISTP, przywrócić poprzedni tryb).

ADDSUBPS[edytuj | edytuj kod]

Rozkaz działa na dwóch wektorach liczb zmiennoprzecinkowych pojedynczej precyzji. Wykonywane jest dodawanie elementów o nieparzystych indeksach, odejmowanie – parzystych. Działania realizowane przez ADDSUBPS xmm1, xmm2:

xmm1[0] := xmm1[0] - xmm2[0]
xmm1[1] := xmm1[1] + xmm2[1]
xmm1[2] := xmm1[2] - xmm2[2]
xmm1[3] := xmm1[3] + xmm2[3]

ADDSUBPD[edytuj | edytuj kod]

Rozkaz analogiczny do ADDSUBPS, działa na dwóch wektorach liczb zmiennoprzecinkowych podwójnej precyzji. Działania realizowane przez ADDSUBPD xmm1, xmm2:

xmm1[0] := xmm1[0] - xmm2[0]
xmm1[1] := xmm1[1] + xmm2[1]

HADDPS, HSUBPS[edytuj | edytuj kod]

Rozkazy działają na wektorach liczb zmiennoprzecinkowych pojedynczej precyzji. HADDPS dodaje, zaś HSUBPS odejmuje sąsiednie elementy wektorów, tzn. HADDPS xmm1, xmm2 wykonuje:

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

natomiast HSUBPS xmm1, xmm2:

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

Np.:

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

Wynik HADDPS:

        +-----+-----+-----+-----+
 xmm1 = | h+g | f+e | c+d | a+b |
        +-----+-----+-----+-----+

Wynik HSUBPS:

        +-----+-----+-----+-----+
 xmm1 = | h-g | f-e | c-d | a-b |
        +-----+-----+-----+-----+

HADDPD, HSUBPD[edytuj | edytuj kod]

Rozkazy działają na wektorach liczb zmiennoprzecinkowych podwójnej precyzji. Rozkaz HADDPD dodaje do siebie sąsiednie elementy wektorów, natomiast HSUBPD odejmuje. Instrukcja HADDPD xmm1, xmm2 wykonuje:

temp[0] := xmm1[0] + xmm1[1]
temp[1] := xmm2[0] + xmm2[1]
xmm1 := temp

natomiast HSUBPD xmm1, xmm2:

temp[0] := xmm1[0] - xmm1[1]
temp[1] := xmm2[0] - xmm2[1]
xmm1 := temp

MOVSLDUP, MOVSHDUP[edytuj | edytuj kod]

Rozkazy działają na wektorze liczb zmiennoprzecinkowych pojedynczej precyzji; rozkaz MOVSLDUP powiela elementy o parzystych indeksach, MOVHLDUP – o nieparzystych. Instrukcja MOVSLDUP xmm1, xmm2 wykonuje:

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

natomiast MOVSHDUP xmm1, xmm2:

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

Np.

           3     2     1     0
        +-----+-----+-----+-----+
 xmm2 = |  d  |  c  |  b  |  a  |
        +-----+-----+-----+-----+

Wynik MOVSLDUP:

        +-----+-----+-----+-----+
 xmm1 = |  c  |  c  |  a  |  a  |
        +-----+-----+-----+-----+

Wynik MOVSHDUP:

        +-----+-----+-----+-----+
 xmm1 = |  d  |  d  |  b  |  b  |
        +-----+-----+-----+-----+

MOVDDUP[edytuj | edytuj kod]

Argumentem rozkazu jest liczba zmiennoprzecinkowa podwójnej precyzji, która w rejestrze XMM jest powielana, tj. MOVDDUP xmm1, arg wykonuje:

xmm1[0] := arg
xmm1[1] := arg

Argumentem może być albo lokacja pamięci (wówczas czytane są 64 bity), albo rejestr XMM, wówczas brane są jego 64 najmłodsze bity.

LDDQU[edytuj | edytuj kod]

Rozkaz ładuje 128 bitów spod adresów niewyrównanych do granicy 16 bajtów (tj. adresy mający niezerowe 4 najmłodsze bity). Rozkaz realizuje działanie analogiczne do istniejącego w SSE MOVDQU, jednak został specjalnie zoptymalizowany do kodu o następującej charakterystyce:

  • występuje spadek wydajności spowodowany częstymi odczytami obszarów znajdujących się na granicy linijek cache,
  • dane są tylko odczytywane i nie mają zostać (po ewentualnej modyfikacji) z powrotem zapisane pod tym samym adresem.

W przeciwnym razie producent poleca, by nadal używać rozkazów SSE MOVDQU lub MOVDQA.

MONITOR i MWAIT[edytuj | edytuj kod]

Para rozkazów służy do efektywnego synchronizowania wątków.

Rozkaz MONITOR ustala początkowy adres zakresu pamięci (rozmiar tego obszaru jest stały, zależny od modelu procesora), który następnie jest automatycznie monitorowany przez procesor: w przypadku wystąpienia zapisu gdziekolwiek w obserwowanym zakresie ustawiana jest wewnętrzna flaga, którą odczytuje MWAIT.

Wykonanie rozkazu MWAIT powoduje wejście w zoptymalizowaną sprzętową pętlę, która jest przerywana, dopiero gdy wspomniana flaga zostanie ustawiona, a więc gdy nastąpi zapis pod obserwowany adres.

Producenci procesorów mogą rozszerzać funkcjonalność tych rozkazów, dlatego m.in. możliwe jest przejście w tryb oszczędzanie energii na czas wykonywania MWAIT.

Bibliografia[edytuj | edytuj kod]

  • Intel 64 and IA-32 Architectures Software Developer's Manual: Volume 2A: Instruction Set Reference, A-M (253666), maj 2007

Zobacz też[edytuj | edytuj kod]