Субнормальное число - Subnormal number

Система с плавающей запятой без дополнений будет содержать только нормализованные числа (обозначенные красным). Разрешение денормализованных чисел (синий) расширяет диапазон системы.

В информатике , субнормальные числа являются подмножеством денормализованных чисел (иногда называемыми денормализованными числа ) , которые заполняют сгущенный зазор вокруг нуля в арифметиках с плавающей точкой . Любое ненулевое число с величиной меньше наименьшего нормального числа является субнормальным .

Примечание по использованию: в некоторых старых документах (особенно в документах стандартов, таких как начальные версии IEEE 754 и язык C ) термин «денормальный» используется исключительно для обозначения субнормальных чисел. Это использование сохраняется в различных документах стандартов, особенно при обсуждении оборудования, которое не может представлять какие-либо другие денормализованные числа, но здесь обсуждается термин субнормальный в соответствии с редакцией IEEE 754 от 2008 года .

В обычном значении с плавающей запятой в мантиссе нет ведущих нулей ; скорее, начальные нули удаляются путем корректировки экспоненты (например, число 0,0123 будет записано как 1,23 × 10 -2 ). И наоборот, денормализованное значение с плавающей запятой имеет мантиссу с нулевой ведущей цифрой. Из них субнормальные числа представляют значения, которые при нормализации имели бы показатели ниже наименьшего представимого показателя (показатель, имеющий ограниченный диапазон).

Мантисса (или мантисса) числа с плавающей запятой IEEE - это часть числа с плавающей запятой, которая представляет значащие цифры . Для положительного нормализованного числа оно может быть представлено как m 0 . m 1 m 2 m 3 ... m p −2 m p −1 (где m представляет собой значащую цифру, а p - точность) с ненулевым m 0 . Обратите внимание, что для двоичной системы счисления ведущая двоичная цифра всегда равна 1. В субнормальном числе, поскольку показатель степени является наименьшим из возможных, ноль является ведущей значащей цифрой (0. m 1 m 2 m 3 ... m p −2 m p −1 ), позволяя представление чисел ближе к нулю, чем наименьшее нормальное число. Число с плавающей запятой может быть признано субнормальным, если его показатель степени является наименьшим возможным значением.

При заполнении промежутка потери значимости таким образом значимые цифры теряются, но не так резко, как при использовании сброса до нуля при подходе потери значимости (отбрасывание всех значащих цифр при достижении потери значимости). Следовательно, получение субнормального числа иногда называют постепенным истощением, потому что это позволяет вычислениям медленно терять точность, когда результат мал.

В IEEE 754-2008 денормальные числа переименовываются в субнормальные числа и поддерживаются как в двоичном, так и в десятичном форматах. В двоичных форматах обмена субнормальные числа кодируются смещенным показателем 0, но интерпретируются значением наименьшего допустимого показателя степени, который на единицу больше (т. Е. Как если бы он был закодирован как 1). В десятичных форматах обмена они не требуют специального кодирования, потому что формат напрямую поддерживает ненормализованные числа.

С математической точки зрения, нормализованные числа с плавающей запятой данного знака примерно логарифмически разнесены, и как таковые любые нормальные числа с плавающей запятой конечного размера не могут включать ноль . Субнормальные числа с плавающей запятой представляют собой линейно разнесенный набор значений, который охватывает промежуток между отрицательными и положительными нормальными числами с плавающей запятой.

Фон

Субнормальные числа обеспечивают гарантию того, что сложение и вычитание чисел с плавающей запятой никогда не приведет к потере значимости; два соседних числа с плавающей запятой всегда имеют представимую ненулевую разницу. Без постепенного истощения, вычитание a  -  b может привести к потере значимости и привести к нулю, даже если значения не равны. Это, в свою очередь, может привести к ошибкам деления на ноль, которые не могут возникнуть при использовании постепенного опустошения.

Субнормальные числа были реализованы в Intel 8087 во время написания стандарта IEEE 754. Они были, безусловно, самой спорной особенностью в предложении формата KCS, которое в конечном итоге было принято, но эта реализация продемонстрировала, что субнормальные числа могут поддерживаться в практической реализации. Некоторые реализации модулей с плавающей запятой напрямую не поддерживают субнормальные числа в оборудовании, а скорее ограничиваются какой-то программной поддержкой. Хотя это может быть прозрачным для пользователя, это может привести к тому, что вычисления, производящие или потребляющие субнормальные числа, будут намного медленнее, чем аналогичные вычисления для нормальных чисел.

Проблемы с производительностью

Некоторые системы аппаратно обрабатывают субнормальные значения так же, как и нормальные значения. Другие оставляют обработку субнормальных значений системному программному обеспечению («помощь»), обрабатывая только нормальные значения и ноль на оборудовании. Обработка субнормальных значений в программном обеспечении всегда приводит к значительному снижению производительности. Когда субнормальные значения полностью вычисляются аппаратно, существуют методы реализации, позволяющие обрабатывать их со скоростью, сравнимой с нормальными числами. Однако скорость вычислений остается значительно сниженной на многих современных процессорах x86; в крайних случаях инструкции, включающие субнормальные операнды, могут занять до 100 дополнительных тактовых циклов, в результате чего самые быстрые инструкции будут выполняться в шесть раз медленнее.

Эта разница в скорости может представлять угрозу безопасности. Исследователи показали, что он предоставляет боковой канал синхронизации, который позволяет вредоносному веб-сайту извлекать содержимое страницы с другого сайта в веб-браузере.

Некоторые приложения должны содержать код, чтобы избежать субнормальных чисел, либо для поддержания точности, либо для того, чтобы избежать потери производительности в некоторых процессорах. Например, в приложениях для обработки звука субнормальные значения обычно представляют сигнал настолько тихий, что он выходит за пределы диапазона человеческого слуха. Из-за этого распространенной мерой, позволяющей избежать субнормальных явлений на процессорах, которые могут снизить производительность, является обнуление сигнала, когда он достигает субнормальных уровней, или смешивание с очень тихим шумовым сигналом. Другие методы предотвращения субнормальных чисел включают добавление смещения постоянного тока, квантование чисел, добавление сигнала Найквиста и т. Д. Начиная с расширения процессора SSE2 , Intel предоставила такую ​​функциональность в аппаратном обеспечении ЦП, которая округляет субнормальные числа до нуля.

Отключение субнормальных поплавков на уровне кода

Intel SSE

Компиляторы Intel C и Fortran по умолчанию DAZвключают FTZфлаги (denormals-are-zero) и (flush-to-zero) для SSE для уровней оптимизации выше -O0. Эффект DAZзаключается в том, чтобы обрабатывать субнормальные входные аргументы для операций с плавающей запятой как ноль, а эффект FTZзаключается в том, чтобы возвращать ноль вместо субнормального числа с плавающей запятой для операций, которые могут привести к субнормальному числу с плавающей запятой, даже если входные аргументы сами не являются субнормальными. clang и gcc имеют разные состояния по умолчанию в зависимости от платформы и уровня оптимизации.

Не- C99 -совместимый метод позволяет DAZи FTZфлаги целей , поддерживающих SSE приведен ниже, но не так широко поддерживается. Известно, что он работает на Mac OS X по крайней мере с 2006 года.

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

Для других платформ x86-SSE, где библиотека C еще не реализовала этот флаг, может работать следующее:

#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И _MM_SET_FLUSH_ZERO_MODEмакросы завернуть более читаемый интерфейс для приведенного выше кода.

// 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);

Большинство компиляторов уже предоставляют предыдущий макрос по умолчанию, в противном случае можно использовать следующий фрагмент кода (определение для FTZ аналогично):

#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)

Поведение денормализации по умолчанию предписано ABI , и поэтому хорошо работающее программное обеспечение должно сохранять и восстанавливать режим денормализации перед возвратом к вызывающему или вызывающему коду в других библиотеках.

РУКА

AArch32 NEON (SIMD) FPU всегда использует режим сброса до нуля, который аналогичен режиму FTZ + DAZ. Для скалярного FPU и в AArch64 SIMD поведение сброса в ноль является необязательным и управляется FZбитом регистра управления - FPSCR в Arm32 и FPCR в AArch64.

Некоторые процессоры ARM имеют аппаратную обработку отклонений от нормы.

Смотрите также

использованная литература

дальнейшее чтение

  • См. Также различные статьи на веб-сайте Уильяма Кахана [1], где приведены примеры того, как субнормальные числа помогают улучшить результаты вычислений.