SSE3
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