Liczba podnormalna - Subnormal number
W informatyce , numery niedorozwinięty są podzbiorem nieznormalizowana numerów (czasami nazywane denormals ), które wypełniają niedopełnienie szczelinę wokół zera w arytmetyki zmiennoprzecinkowej . Każda niezerowa liczba o wielkości mniejszej niż najmniejsza liczba normalna jest podnormalna .
- Uwaga dotycząca użycia: w niektórych starszych dokumentach (zwłaszcza w dokumentach standardów, takich jak pierwsze wydania IEEE 754 i języka C ), słowo „denormalne” jest używane wyłącznie w odniesieniu do liczb podnormalnych. To użycie występuje w różnych dokumentach normatywnych, zwłaszcza w przypadku omawiania sprzętu, który nie jest w stanie reprezentować żadnych innych zdenormalizowanych liczb, ale w niniejszym omówieniu użyto terminu podnormalne zgodnie z rewizją IEEE 754 z 2008 roku .
W normalnej wartości zmiennoprzecinkowej nie ma wiodących zer w znaczącej ( mantysa ); raczej początkowe zera są usuwane przez dostosowanie wykładnika (na przykład liczba 0,0123 zostanie zapisana jako 1,23 × 10 -2 ). Odwrotnie, zdenormalizowana wartość zmiennoprzecinkowa ma znaczący z cyfrą wiodącą wynoszącą zero. Spośród nich liczby subnormalne reprezentują wartości, które po znormalizowaniu miałyby wykładniki poniżej najmniejszego możliwego do przedstawienia wykładnika (wykładnik o ograniczonym zakresie).
Znacząca (lub mantysa) liczby zmiennoprzecinkowej IEEE jest częścią liczby zmiennoprzecinkowej, która reprezentuje cyfry znaczące . Dla dodatniej znormalizowanej liczby można ją przedstawić jako m 0 . m 1 m 2 m 3 ... m p -2 m p -1 (gdzie m oznacza cyfrę znaczącą, a p jest precyzją) z niezerowym m 0 . Zauważ, że dla podstawy dwójkowej , wiodąca cyfra dwójkowa to zawsze 1. W liczbie podnormalnej, ponieważ wykładnik jest najmniejszym możliwym, zero jest wiodącą cyfrą znaczącą (0. m 1 m 2 m 3 ... m p -2 m p -1 ), umożliwiając reprezentację liczb bliższych zeru niż najmniejsza liczba normalna. Liczbę zmiennoprzecinkową można uznać za podnormalną, gdy jej wykładnik jest najmniejszą możliwą wartością.
Wypełniając lukę niedomiaru w ten sposób, znaczące cyfry są tracone, ale nie tak nagle, jak w przypadku użycia spłukiwania do zera przy podejściu niedomiaru (odrzucanie wszystkich znaczących cyfr po osiągnięciu niedomiaru). Dlatego tworzenie liczby podnormalnej jest czasami nazywane stopniowym niedomiarem, ponieważ pozwala na powolną utratę precyzji obliczeń, gdy wynik jest mały.
W standardzie IEEE 754-2008 liczby nienormalne są przemianowane na liczby podnormalne i są obsługiwane zarówno w formacie binarnym, jak i dziesiętnym. W binarnych formatach wymiany liczby podnormalne są kodowane z wykładnikiem obciążonym równym 0, ale są interpretowane z wartością najmniejszego dozwolonego wykładnika, który jest o jeden większy (tj. tak, jakby był zakodowany jako 1). W formatach wymiany dziesiętnej nie wymagają one specjalnego kodowania, ponieważ format bezpośrednio obsługuje nieznormalizowane liczby.
Matematycznie rzecz biorąc, znormalizowane liczby zmiennoprzecinkowe danego znaku są z grubsza rozmieszczone logarytmicznie i jako takie nie mogą zawierać zero . Pływaki podnormalne są liniowo rozmieszczonymi zestawami wartości, które obejmują lukę między ujemnymi i dodatnimi pływakami normalnymi.
Formaty zmiennoprzecinkowe |
---|
IEEE 754 |
|
Inne |
Tło
Liczby podnormalne dają gwarancję, że dodawanie i odejmowanie liczb zmiennoprzecinkowych nigdy nie jest niedostateczne; dwie pobliskie liczby zmiennoprzecinkowe zawsze mają dającą się przedstawić niezerową różnicę. Bez stopniowego niedopełnienia odejmowanie a - b może spowodować niedopełnienie i dać zero, nawet jeśli wartości nie są równe. To z kolei może prowadzić do błędów dzielenia przez zero, które nie mogą wystąpić przy stosowaniu stopniowego niedopełnienia.
Liczby podnormalne zostały zaimplementowane w Intel 8087 podczas pisania standardu IEEE 754. Były one zdecydowanie najbardziej kontrowersyjną cechą propozycji formatu KCS, która została ostatecznie przyjęta, ale ta implementacja pokazała, że liczby podnormalne mogą być obsługiwane w praktycznej implementacji. Niektóre implementacje jednostek zmiennoprzecinkowych nie obsługują bezpośrednio liczb podnormalnych w sprzęcie, ale raczej pułapki na pewnego rodzaju wsparcie programowe. Chociaż może to być niewidoczne dla użytkownika, może to spowodować, że obliczenia generujące lub zużywające liczby podnormalne będą znacznie wolniejsze niż podobne obliczenia na liczbach normalnych.
Problemy z wydajnością
Niektóre systemy obsługują wartości subnormalne sprzętowo, w taki sam sposób jak wartości normalne. Inni pozostawiają obsługę wartości podnormalnych oprogramowaniu systemowemu („asystent”), obsługując tylko wartości normalne i zero w sprzęcie. Obsługa wartości podnormalnych w oprogramowaniu zawsze prowadzi do znacznego spadku wydajności. Gdy wartości podnormalne są całkowicie obliczane sprzętowo, istnieją techniki implementacji umożliwiające ich przetwarzanie z szybkością porównywalną do normalnych liczb. Jednak szybkość obliczeń pozostaje znacznie zmniejszona na wielu nowoczesnych procesorach x86; w skrajnych przypadkach instrukcje zawierające podnormalne operandy mogą zająć nawet 100 dodatkowych cykli zegara, powodując, że najszybsze instrukcje działają nawet sześć razy wolniej.
Ta różnica prędkości może stanowić zagrożenie dla bezpieczeństwa. Badacze wykazali, że zapewnia boczny kanał czasowy, który umożliwia złośliwej witrynie internetowej wyodrębnienie zawartości strony z innej witryny w przeglądarce internetowej.
Niektóre aplikacje muszą zawierać kod, aby uniknąć podnormalnych liczb, albo w celu zachowania dokładności, albo w celu uniknięcia spadku wydajności niektórych procesorów. Na przykład w zastosowaniach przetwarzania dźwięku wartości podnormalne zwykle reprezentują sygnał tak cichy, że znajduje się poza zasięgiem ludzkiego słuchu. Z tego powodu, powszechnym sposobem uniknięcia subnormalnych na procesorach, gdzie występuje spadek wydajności, jest obcięcie sygnału do zera, gdy osiągnie on poziomy subnormalne lub zmieszanie z wyjątkowo cichym sygnałem szumowym. Inne metody zapobiegania liczbom nienormalnym obejmują dodanie przesunięcia DC, kwantyzację liczb, dodanie sygnału Nyquist itp. Od rozszerzenia procesora SSE2 , Intel zapewnił taką funkcjonalność w sprzęcie CPU, która zaokrągla liczby nienormalne do zera.
Wyłączanie subnormalnych pływaków na poziomie kodu
Intel® SSE
Kompilatory C i Fortran firmy Intel domyślnie włączają flagi DAZ
(denormals-are-zero) i FTZ
(flush-to-zero) dla SSE dla poziomów optymalizacji wyższych niż -O0
. Efektem DAZ
jest traktowanie podnormalnych argumentów wejściowych dla operacji zmiennoprzecinkowych jako zero, a efektem FTZ
jest zwracanie zera zamiast wartości zmiennoprzecinkowej nienormalnej dla operacji, które skutkowałyby zmiennością nienormalną, nawet jeśli same argumenty wejściowe nie są nienormalne. clang i gcc mają różne stany domyślne w zależności od platformy i poziomu optymalizacji.
Poniżej podano niezgodną z C99 metodę włączania flag DAZ
i FTZ
na obiektach docelowych obsługujących SSE, ale nie jest powszechnie obsługiwana. Wiadomo, że działa na Mac OS X od co najmniej 2006 roku.
#include <fenv.h>
#pragma STDC FENV_ACCESS ON
// Sets DAZ and FTZ, clobbering other CSR settings.
// See https://opensource.apple.com/source/Libm/Libm-287.1/Source/Intel/, fenv.c and fenv.h.
fesetenv(FE_DFL_DISABLE_SSE_DENORMS_ENV);
// fesetenv(FE_DFL_ENV) // Disable both, clobbering other CSR settings.
W przypadku innych platform x86-SSE, w których biblioteka C nie zaimplementowała jeszcze tej flagi, może działać:
#include <xmmintrin.h>
_mm_setcsr(_mm_getcsr() | 0x0040); // DAZ
_mm_setcsr(_mm_getcsr() | 0x8000); // FTZ
_mm_setcsr(_mm_getcsr() | 0x8040); // Both
_mm_setcsr(_mm_getcsr() & ~0x8040); // Disable both
_MM_SET_DENORMALS_ZERO_MODE
I _MM_SET_FLUSH_ZERO_MODE
makra owinąć bardziej czytelny interfejs dla powyższego kodu.
// To enable DAZ
#include <pmmintrin.h>
_MM_SET_DENORMALS_ZERO_MODE(_MM_DENORMALS_ZERO_ON);
// To enable FTZ
#include <xmmintrin.h>
_MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON);
Większość kompilatorów domyślnie udostępnia poprzednie makro, w przeciwnym razie można użyć następującego fragmentu kodu (definicja dla FTZ jest analogiczna):
#define _MM_DENORMALS_ZERO_MASK 0x0040
#define _MM_DENORMALS_ZERO_ON 0x0040
#define _MM_DENORMALS_ZERO_OFF 0x0000
#define _MM_SET_DENORMALS_ZERO_MODE(mode) _mm_setcsr((_mm_getcsr() & ~_MM_DENORMALS_ZERO_MASK) | (mode))
#define _MM_GET_DENORMALS_ZERO_MODE() (_mm_getcsr() & _MM_DENORMALS_ZERO_MASK)
Domyślne zachowanie denormalizacji jest wymagane przez ABI i dlatego dobrze zachowujące się oprogramowanie powinno zapisać i przywrócić tryb denormalizacji przed powrotem do obiektu wywołującego lub wywołaniem kodu w innych bibliotekach.
RAMIĘ
AArch32 NEON (SIMD) FPU zawsze używa trybu wyrównania do zera, który jest taki sam jak FTZ + DAZ
. Dla skalarnego FPU i w AArch64 SIMD zachowanie wyrównania do zera jest opcjonalne i kontrolowane przez FZ
bit rejestru kontrolnego – FPSCR w Arm32 i FPCR w AArch64.
Niektóre procesory ARM obsługują sprzętową obsługę podnormalnych.
Zobacz też
Bibliografia
Dalsza lektura
- Eric Schwarz, Martin Schmookler i Son Dao Trong (czerwiec 2003). „Implementacje sprzętowe liczb zdenormalizowanych” (PDF) . Proceedings 16. IEEE Sympozjum Arytmetyki Komputerowej (Arith16) . 16. sympozjum IEEE na temat arytmetyki komputerowej . Stowarzyszenie Komputerowe IEEE . s. 104-111. Numer ISBN 0-7695-1894-X.
- Zobacz także różne artykuły na stronie internetowej Williama Kahana [1], aby zapoznać się z przykładami, w których liczby subnormalne pomagają poprawić wyniki obliczeń.