Número subnormal - Subnormal number

Um sistema de ponto flutuante não aumentado conteria apenas números normalizados (indicados em vermelho). Permitir números desnormalizados (azul) estende o alcance do sistema.

Na ciência da computação , os números subnormais são o subconjunto dos números desnormalizados (às vezes chamados de desnormais ) que preenchem a lacuna de underflow em torno de zero na aritmética de ponto flutuante . Qualquer número diferente de zero com magnitude menor que o menor número normal é subnormal .

Nota de uso: em alguns documentos mais antigos (especialmente documentos padrão, como as versões iniciais do IEEE 754 e a linguagem da linguagem C ), "denormal" é usado para se referir exclusivamente a números subnormais. Esse uso persiste em vários documentos de padrões, especialmente ao discutir hardware que é incapaz de representar qualquer outro número desnormalizado, mas a discussão aqui usa o termo subnormal de acordo com a revisão de 2008 do IEEE 754 .

Em um valor de ponto flutuante normal, não há zeros à esquerda no significando ( mantissa ); em vez disso, os zeros à esquerda são removidos ajustando o expoente (por exemplo, o número 0,0123 seria escrito como 1,23 × 10 −2 ). Por outro lado, um valor de ponto flutuante desnormalizado tem um significando com um dígito inicial igual a zero. Destes, os números subnormais representam valores que, se normalizados, teriam expoentes abaixo do menor expoente representável (o expoente tendo uma faixa limitada).

O significando (ou mantissa) de um número de ponto flutuante IEEE é a parte de um número de ponto flutuante que representa os dígitos significativos . Para um número normalizado positivo, ele pode ser representado como m 0 . m 1 m 2 m 3 ... m p −2 m p −1 (em que m representa um dígito significativo e p é a precisão) com m 0 diferente de zero . Observe que, para uma raiz binária , o dígito binário principal é sempre 1. Em um número subnormal, uma vez que o expoente é o mínimo que pode ser, zero é o dígito principal significativo (0. m 1 m 2 m 3 ... m p −2 m p −1 ), permitindo a representação de números mais próximos de zero do que o menor número normal. Um número de ponto flutuante pode ser reconhecido como subnormal sempre que seu expoente for o menor valor possível.

Ao preencher a lacuna de underflow como este, dígitos significativos são perdidos, mas não tão abruptamente como ao usar a descarga para zero na abordagem de underflow (descartando todos os dígitos significativos quando o underflow é atingido). Conseqüentemente, a produção de um número subnormal é algumas vezes chamada de underflow gradual porque permite que um cálculo perca a precisão lentamente quando o resultado é pequeno.

No IEEE 754-2008 , os números desnormalizados são renomeados como números subnormais e são suportados nos formatos binário e decimal. Em formatos de intercâmbio binário, os números subnormais são codificados com um expoente tendencioso de 0, mas são interpretados com o valor do menor expoente permitido, que é um maior (ou seja, como se fosse codificado como 1). Em formatos de intercâmbio decimal, eles não requerem codificação especial porque o formato suporta números não normalizados diretamente.

Matematicamente falando, os números de ponto flutuante normalizados de um determinado sinal são aproximadamente logaritmicamente espaçados e, como tal, qualquer flutuante normal de tamanho finito não pode incluir zero . As flutuações subnormais são um conjunto de valores espaçados linearmente, que abrangem a lacuna entre as flutuações normais negativas e positivas.

Fundo

Os números subnormais fornecem a garantia de que a adição e subtração de números de ponto flutuante nunca aumentam; dois números de ponto flutuante próximos sempre têm uma diferença representável diferente de zero. Sem underflow gradual, a subtração a  -  b pode underflow e produzir zero, embora os valores não sejam iguais. Isso pode, por sua vez, levar a erros de divisão por zero que não podem ocorrer quando o underflow gradual é usado.

Números subnormais foram implementados no Intel 8087 enquanto o padrão IEEE 754 estava sendo escrito. Eles foram, de longe, o recurso mais controverso na proposta de formato KCS que acabou sendo adotada, mas esta implementação demonstrou que números subnormais poderiam ser suportados em uma implementação prática. Algumas implementações de unidades de ponto flutuante não suportam diretamente números subnormais no hardware, mas sim prendem-se a algum tipo de suporte de software. Embora isso possa ser transparente para o usuário, pode resultar em cálculos que produzem ou consomem números subnormais sendo muito mais lentos do que cálculos semelhantes em números normais.

Problemas de desempenho

Alguns sistemas lidam com valores subnormais no hardware, da mesma forma que os valores normais. Outros deixam o tratamento de valores subnormais para o software do sistema ("assist"), tratando apenas de valores normais e zero no hardware. O tratamento de valores subnormais no software sempre leva a uma diminuição significativa no desempenho. Quando os valores subnormais são inteiramente calculados em hardware, existem técnicas de implementação para permitir seu processamento em velocidades comparáveis ​​aos números normais. No entanto, a velocidade de computação permanece significativamente reduzida em muitos processadores x86 modernos; em casos extremos, as instruções envolvendo operandos subnormais podem levar até 100 ciclos de clock adicionais, fazendo com que as instruções mais rápidas sejam executadas até seis vezes mais lentas.

Essa diferença de velocidade pode ser um risco à segurança. Os pesquisadores mostraram que ele fornece um canal lateral de tempo que permite a um site malicioso extrair o conteúdo da página de outro site dentro de um navegador.

Alguns aplicativos precisam conter código para evitar números subnormais, seja para manter a precisão ou para evitar a penalidade de desempenho em alguns processadores. Por exemplo, em aplicações de processamento de áudio, os valores subnormais geralmente representam um sinal tão baixo que está fora do alcance da audição humana. Por causa disso, uma medida comum para evitar subnormais em processadores onde haveria uma penalidade de desempenho é cortar o sinal para zero quando ele atinge níveis subnormais ou mixar em um sinal de ruído extremamente silencioso. Outros métodos de prevenção de números subnormais incluem adicionar um deslocamento DC, quantizar números, adicionar um sinal de Nyquist, etc. Desde a extensão do processador SSE2 , a Intel forneceu tal funcionalidade no hardware da CPU, que arredonda os números subnormais para zero.

Desativando flutuações subnormais no nível do código

Intel SSE

Os compiladores C e Fortran da Intel habilitam os DAZsinalizadores (denormals-are-zero) e FTZ(flush-to-zero) para SSE por padrão para níveis de otimização maiores que -O0. O efeito de DAZé tratar os argumentos de entrada subnormal para operações de ponto flutuante como zero, e o efeito de FTZé retornar zero em vez de um float subnormal para operações que resultariam em um float subnormal, mesmo se os argumentos de entrada não forem subnormais. clang e gcc têm estados padrão variados, dependendo da plataforma e do nível de otimização.

Um método não compatível com C99 de habilitar os sinalizadores DAZe FTZem destinos que suportam SSE é fornecido abaixo, mas não é amplamente suportado. É conhecido por funcionar no Mac OS X desde pelo menos 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.

Para outras plataformas x86-SSE em que a biblioteca C ainda não implementou esse sinalizador, o seguinte pode funcionar:

#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

As macros _MM_SET_DENORMALS_ZERO_MODEe _MM_SET_FLUSH_ZERO_MODEenvolvem uma interface mais legível para o código acima.

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

A maioria dos compiladores já fornece a macro anterior por padrão, caso contrário, o seguinte snippet de código pode ser usado (a definição de FTZ é 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() & ~_MM_DENORMALS_ZERO_MASK) | (mode))
#define _MM_GET_DENORMALS_ZERO_MODE()                (_mm_getcsr() &  _MM_DENORMALS_ZERO_MASK)

O comportamento de desnormalização padrão é exigido pela ABI e, portanto, o software bem comportado deve salvar e restaurar o modo de desnormalização antes de retornar ao chamador ou chamar o código em outras bibliotecas.

BRAÇO

A FPU AArch32 NEON (SIMD) sempre usa um modo nivelado para zero, que é o mesmo que FTZ + DAZ. Para o FPU escalar e no SIMD AArch64, o comportamento flush-to-zero é opcional e controlado pelo FZbit do registro de controle - FPSCR em Arm32 e FPCR em AArch64.

Alguns processadores ARM têm manipulação de hardware de subnormais.

Veja também

Referências

Leitura adicional

  • Veja também vários artigos sobre William Kahan web site 's [1] para exemplos de onde os números subnormais ajudar a melhorar os resultados dos cálculos.