Visualizzatore dei bit di FP16 e bfloat16

Strumento gratuito che mostra la configurazione dei bit dei numeri in virgola mobile a mezza precisione, cioè FP16 secondo la norma IEEE 754 binary16, e di bfloat16. Converte in entrambi i sensi, dal decimale ai bit e viceversa, distinguendo con colori diversi segno, esponente e mantissa. Utile per studiare la quantizzazione e l'accelerazione dell'inferenza nell'apprendimento automatico.

Confronto fra la struttura di FP16 e quella di bfloat16

Entrambi occupano sedici bit in tutto, ma li ripartiscono in modo diverso fra esponente e mantissa: l'intervallo dei valori rappresentabili e la precisione risultano quindi completamente diversi.

Voce FP16 (IEEE 754 mezza precisione) bfloat16
Bit complessivi 16 16
Bit dell'esponente 5 8
Bit della mantissa 10 7
Intervallo dei valori rappresentabili Da circa ±6,1×10⁻⁵ a ±65504 (intervallo ristretto, ma mantissa ampia e quindi precisione elevata) Da circa ±1,2×10⁻³⁸ a ±3,4×10³⁸ (stesso ampio intervallo di float32, ma precisione inferiore)
Impieghi principali Elaborazione delle immagini e grafica; risparmio di memoria nell'inferenza, cioè apprendimento a mezza precisione Addestramento nell'apprendimento profondo, su TPU e schede grafiche recenti. Nella conversione da float32 non occorre preoccuparsi del traboccamento dell'esponente

Poiché bfloat16 ha lo stesso esponente di float32, cioè a precisione singola — otto bit e polarizzazione 127 — presenta il vantaggio pratico di poter essere ottenuto dal float32 con il semplice troncamento della mantissa.

Consigli per l'uso

  • Anche per uno stesso valore come 0,1, l'errore di arrotondamento si manifesta in modo del tutto diverso in FP16 e in bfloat16. Provate a cambiare formato e a confrontare le sequenze di bit della mantissa.
  • Poiché bfloat16 ha l'esponente della stessa ampiezza e polarizzazione di float32, difficilmente trabocca anche con valori grandi, superiori a 65504. FP16, al contrario, diventa infinito non appena si supera quella soglia.
  • Convertendo 70000 in FP16 si ottiene un traboccamento e quindi l'infinito, mentre in bfloat16 il valore è ancora rappresentabile, seppure con precisione ridotta.
  • Quando si quantizza un modello con le principali librerie per l'apprendimento automatico, bfloat16 si ottiene facilmente da float32, mentre FP16, per il suo intervallo ristretto, può richiedere una scalatura preventiva.
  • Nella conversione inversa a partire dai bit occorre indicare quattro cifre esadecimali con il prefisso `0x` oppure sedici cifre binarie, con il prefisso `0b` facoltativo.

Domande frequenti

Entrambi occupano sedici bit, ma li ripartiscono diversamente: FP16, la mezza precisione IEEE 754, ha cinque bit di esponente e dieci di mantissa, bfloat16 otto di esponente e sette di mantissa. FP16, avendo la mantissa più ampia, è più preciso ma copre un intervallo più ristretto; bfloat16 copre lo stesso ampio intervallo di float32 al prezzo di una precisione inferiore.

Nell'apprendimento profondo gradienti e parametri possono assumere valori tanto grandissimi quanto piccolissimi: si preferisce quindi bfloat16, che conserva lo stesso ampio intervallo di float32, rendendo improbabili traboccamenti in eccesso e in difetto, e insieme dimezza memoria e carico di calcolo. FP16, con il suo intervallo ristretto, trabocca facilmente e in fase di addestramento può richiedere una scalatura aggiuntiva della funzione di perdita.

Circa 65504. Tentando di convertire in FP16 un valore superiore si ottiene un traboccamento e quindi l'infinito. bfloat16, avendo l'esponente della stessa ampiezza di float32, arriva invece a circa 3,4×10³⁸.

Sono le configurazioni con esponente tutto a zero e mantissa diversa da zero. Ai numeri in virgola mobile normalizzati si antepone alla mantissa un uno implicito; i denormalizzati vi rinunciano e riescono così a rappresentare valori ancora più vicini allo zero del più piccolo normalmente esprimibile, sacrificando però le cifre significative.

Perché bfloat16 ha esattamente la stessa ampiezza dell'esponente, otto bit, e la stessa polarizzazione, 127, di float32: basta troncare, cioè arrotondare, la mantissa della configurazione float32 conservandone i sette bit più significativi. Non servendo né ricalcolare l'esponente né verificare l'intervallo, la realizzazione risulta molto semplice.
Tool-kun

A proposito — perché l'apprendimento automatico ha voluto rappresentazioni numeriche «meno precise»

Intorno al 2018 Google ideò per le proprie unità di elaborazione tensoriale un nuovo formato in virgola mobile a sedici bit, bfloat16. FP16, la mezza precisione della norma IEEE 754, esisteva già da tempo ed era in uso nell'elaborazione delle immagini e nella grafica, ma con soli cinque bit di esponente copriva un intervallo troppo ristretto e non reggeva i fenomeni tipici dell'addestramento profondo, in cui i gradienti diventano ora minuscoli ora enormi: la loro scomparsa e la loro esplosione.

Il principio ispiratore di bfloat16 è limpido: sacrificare la precisione della mantissa e conservare invece per l'esponente esattamente la stessa ampiezza di float32, cioè otto bit, in modo da trattare senza rischi i valori estremamente grandi o piccoli che ricorrono durante l'addestramento. Il nome «Brain Floating Point» deriva da Google Brain, la divisione di ricerca sull'apprendimento automatico dell'azienda.

Nell'informatica tradizionale ridurre la precisione dei numeri in virgola mobile è sempre stato considerato un invito agli errori. I modelli di apprendimento profondo, però, hanno la singolare proprietà di conservare quasi intatta l'accuratezza finale delle previsioni pur in presenza di qualche imprecisione numerica. Aver rovesciato a proprio favore questa caratteristica — «funziona nel complesso anche se non è esatto» — e aver diffuso rappresentazioni a sedici bit che dimezzano memoria e costo di calcolo è un'ottimizzazione tipica del solo apprendimento automatico, distante dal senso comune dell'informatica.