Número subnormal
En informática, números subnormales son el subconjunto de números desnormalizados (a veces llamados desnormales) que llenan el espacio de subdesbordamiento alrededor de cero en flotante -aritmética de puntos. Cualquier número distinto de cero con una magnitud menor que el número normal más pequeño es subnormal.
- Nota de uso: en algunos documentos antiguos (especialmente documentos de estándares como las versiones iniciales de IEEE 754 y el lenguaje C), "denormal" se utiliza para referirse exclusivamente a números subnormales. Este uso persiste en varios documentos de normas, especialmente cuando se discute hardware incapaz de representar cualquier otro número desnormalizado, pero la discusión aquí utiliza el término subnormal de acuerdo con la revisión 2008 de IEEE 754.
En un valor de coma flotante normal, no hay ceros a la izquierda en la mantisa; más bien, los ceros iniciales se eliminan ajustando el exponente (por ejemplo, el número 0,0123 se escribiría como 1,23 × 10−2). Por el contrario, un valor de punto flotante desnormalizado tiene un significado con un dígito inicial de cero. De estos, los números subnormales representan valores que, si se normalizaran, tendrían exponentes por debajo del exponente representable más pequeño (el exponente que tiene un rango limitado).
La mantisa (o mantisa) de un número de punto flotante IEEE es la parte de un número de punto flotante que representa los dígitos significativos. Para un número normalizado positivo, se puede representar como m0.m1m2m3...mp−2mp−1 (donde m representa un dígito significativo y p es la precisión) con distinto de cero m0. Observe que para una base binaria, el primer dígito binario siempre es 1. En un número subnormal, dado que el exponente es el menor que puede ser, cero es el primer dígito significativo (0.m1m2m3...mp−2mp−1), permitiendo la representación de números más cercanos a cero que el menor número normal. Un número de coma flotante puede reconocerse como subnormal siempre que su exponente tenga el menor valor posible.
Al llenar la brecha de subdesbordamiento de esta manera, los dígitos significativos se pierden, pero no tan abruptamente como cuando se usa el enfoque vaciar a cero en subdesbordamiento (descartando todos los dígitos significativos cuando se alcanza el subdesbordamiento). Por lo tanto, la producción de un número subnormal a veces se denomina subdesbordamiento gradual porque permite que un cálculo pierda precisión lentamente cuando el resultado es pequeño.
En IEEE 754-2008, los números anormales se renombran como números subnormales y se admiten en formato binario y decimal. En los formatos de intercambio binario, los números subnormales se codifican con un exponente sesgado de 0, pero se interpretan con el valor del exponente más pequeño permitido, que es uno mayor (es decir, como si estuviera codificado como 1). En los formatos de intercambio decimal, no requieren una codificación especial porque el formato admite directamente números no normalizados.
Matemáticamente hablando, los números de coma flotante normalizados de un signo determinado están espaciados logarítmicamente de forma aproximada y, como tal, cualquier flotante normal de tamaño finito no puede incluir el cero. Los valores flotantes subnormales son un conjunto de valores espaciados linealmente, que abarcan el espacio entre los valores flotantes normales negativos y positivos.
Antecedentes
Los números subnormales proporcionan la garantía de que la suma y resta de números de punto flotante nunca se desborda; dos números de coma flotante cercanos siempre tienen una diferencia representable distinta de cero. Sin subdesbordamiento gradual, la resta a − b puede subdesbordarse y producir cero aunque los valores no sean iguales. Esto, a su vez, puede conducir a errores de división por cero que no pueden ocurrir cuando se utiliza un subdesbordamiento gradual.
Los números subnormales se implementaron en Intel 8087 mientras se escribía el estándar IEEE 754. Fueron, con mucho, la característica más controvertida en la propuesta de formato K-C-S que finalmente se adoptó, pero esta implementación demostró que los números subnormales podrían admitirse en una implementación práctica. Algunas implementaciones de unidades de coma flotante no admiten directamente números subnormales en el hardware, sino que se conectan a algún tipo de soporte de software. Si bien esto puede ser transparente para el usuario, puede resultar en que los cálculos que producen o consumen números subnormales sean mucho más lentos que los cálculos similares en números normales.
Problemas de rendimiento
Algunos sistemas manejan valores subnormales en el hardware, de la misma manera que los valores normales. Otros dejan el manejo de valores subnormales al software del sistema ("asistencia"), solo manejando valores normales y cero en hardware. El manejo de valores por debajo de lo normal en el software siempre conduce a una disminución significativa en el rendimiento. Cuando los valores subnormales se calculan completamente en hardware, existen técnicas de implementación para permitir su procesamiento a velocidades comparables a los números normales. Sin embargo, la velocidad de cálculo sigue siendo significativamente reducida en muchos procesadores x86 modernos; en casos extremos, las instrucciones que involucran operandos subnormales pueden tomar hasta 100 ciclos de reloj adicionales, lo que hace que las instrucciones más rápidas se ejecuten hasta seis veces más lento.
Esta diferencia de velocidad puede ser un riesgo para la seguridad. Los investigadores demostraron que proporciona un canal lateral de tiempo que permite que un sitio web malicioso extraiga el contenido de la página de otro sitio dentro de un navegador web.
Algunas aplicaciones necesitan contener código para evitar números subnormales, ya sea para mantener la precisión o para evitar la penalización del rendimiento en algunos procesadores. Por ejemplo, en las aplicaciones de procesamiento de audio, los valores por debajo de lo normal generalmente representan una señal tan silenciosa que está fuera del rango auditivo humano. Debido a esto, una medida común para evitar subnormales en los procesadores donde habría una penalización de rendimiento es reducir la señal a cero una vez que alcanza niveles subnormales o mezclar una señal de ruido extremadamente silenciosa. Otros métodos para prevenir números subnormales incluyen agregar una compensación de CC, cuantificar números, agregar una señal de Nyquist, etc. Desde la extensión del procesador SSE2, Intel ha proporcionado dicha funcionalidad en el hardware de la CPU, que redondea los números subnormales a cero.
Deshabilitar flotadores subnormales a nivel de código
Intel SSE
Los compiladores C y Fortran de Intel habilitan el DAZ
(desnormales-son-cero) y FTZ
(flush-to-zero) indicadores para SSE de forma predeterminada para niveles de optimización superiores a -O0
. El efecto de DAZ
es tratar argumentos de entrada subnormales para operaciones de coma flotante como cero, y el efecto de FTZ
es devolver cero en lugar de un flotante subnormal para operaciones que darían como resultado un flotante subnormal, incluso si los argumentos de entrada no son en sí mismos subnormales. clang y gcc tienen diferentes estados predeterminados según la plataforma y el nivel de optimización.
Un método no compatible con C99 para habilitar el DAZ
y FTZ
en destinos que admiten SSE es a continuación, pero no es ampliamente compatible. Se sabe que funciona en Mac OS X desde al menos 2006.
#include - No.#pragma STDC FENV_ACCESS ON// Establece DAZ y FTZ, coagulando otros ajustes de RSC.// Véase https://opensource.apple.com/source/Libm/Libm-287.1/Source/Intel/, fenv.c y fenv.h.fesetenv()FE_DFL_DISABLE_SSE_DENORMS_ENV);// fesetenv(FE_DFL_ENV) // Desactivar ambos, obstruyendo otros ajustes de RSC.
Para otras plataformas x86-SSE donde la biblioteca C aún no ha implementado este indicador, lo siguiente puede funcionar:
#include ■xmmintrin.h_mm_setcsr()_mm_getcsr() Silencio 0x0040); // DAZ_mm_setcsr()_mm_getcsr() Silencio 0x8000); // FTZ_mm_setcsr()_mm_getcsr() Silencio 0x8040); // Ambos_mm_setcsr()_mm_getcsr() " ~0x8040); // Desactivar ambos
El _MM_SET_DENORMALS_ZERO_MODE
y _MM_SET_FLUSH_ZERO_MODE
envuelven una interfaz más legible para el código anterior.
// Para habilitar DAZ#include pmmintrin.h_MM_SET_DENORMALS_ZERO_MODE()_MM_DENORMALS_ZERO_ON);// Para habilitar FTZ#include ■xmmintrin.h_MM_SET_FLUSH_ZERO_MODE()_MM_FLUSH_ZERO_ON);
La mayoría de los compiladores ya proporcionarán la macro anterior de forma predeterminada; de lo contrario, se puede usar el siguiente fragmento de código (la definición de FTZ es análoga):
#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().#define _MM_GET_DENORMALS_ZERO_MODE() (_mm_getcsr() > _MM_DENORMALS_ZERO_MASK)
El comportamiento de desnormalización predeterminado es exigido por la ABI y, por lo tanto, el software que funciona correctamente debe guardar y restaurar el modo de desnormalización antes de volver a la persona que llama o al código de llamada en otras bibliotecas.
BRAZO
La FPU AArch32 NEON (SIMD) siempre usa un modo de descarga a cero, que es lo mismo que FTZ + DAZ
. Para la FPU escalar y en el SIMD AArch64, el comportamiento de descarga a cero es opcional y está controlado por FZ
bit del registro de control – FPSCR en Arm32 y FPCR en AArch64.
La manera de hacer esto puede ser:
#if defined(__arm64___) uint64_t fpcr; asm() "Mrs %0, fpcr" : "=r"() fpcr )); // Cargar el registro FPCR asm() "msr fpcr, %0" :: "r"() fpcr Silencio ()1 .. 24) )); // Colocar el bit 24 (FTZ) a 1#endif
Algunos procesadores ARM tienen manejo de hardware de subnormales.
Contenido relacionado
GTE
301 (movido permanentemente)
Linux con seguridad mejorada