BFloat16 (BF16)
BFloat16 (BF16) é um número de vírgula flutuante de 16 bits com o expoente de 8 bits do FP32 e uma fração de 7 bits, mantendo o intervalo do FP32 com metade da memória. Como se distingue do FP16.
BFloat16 (ponto flutuante cerebral, BF16) é um formato de ponto flutuante de 16 bits com 1 bit de sinal, 8 bits de expoente e 7 bits de fração. Ele mantém a mesma largura de expoente do ponto flutuante padrão de 32 bits (FP32), cobrindo assim o mesmo intervalo de valores, de cerca de 1,2 × 10⁻³⁸ a 3,4 × 10³⁸, enquanto armazena cada número usando metade da memória. O custo é a precisão: 7 bits de fração oferecem apenas dois ou três dígitos decimais significativos. O deep learning tolera bem esse arredondamento, e o formato, concebido no Google Brain para as TPUs do Google, tornou-se o formato padrão de 16 bits para treinar modelos grandes em GPUs modernas e aceleradores.
Como o BF16 representa números#
Um valor BF16 corresponde exatamente à metade superior de um valor FP32: mesmo sinal e expoente, com a fração reduzida de 23 para 7 bits. Portanto, converter FP32 em BF16 apenas arredonda os 16 bits inferiores, e a conversão de volta acrescenta zeros, o que torna o formato barato de implementar em hardware. O outro formato comum de 16 bits, IEEE FP16 ou meia precisão, divide seus bits de outra forma, com 5 bits de expoente e 10 de fração, o que oferece mais precisão em detrimento do intervalo. Comparar os três formatos com os mesmos valores mostra a diferença:
import torch
# Largest value, smallest normal value, and spacing just above 1.0 for each format
for dtype in [torch.float32, torch.float16, torch.bfloat16]:
info = torch.finfo(dtype)
print(f"{dtype!s:15} max={info.max:.3g} tiny={info.tiny:.3g} eps={info.eps:.3g}")
# A large activation, a tiny gradient, and a value that needs fine precision
x = torch.tensor([70000.0, 1e-8, 1.001953125])
print("FP16:", x.half().tolist())
print("BF16:", x.bfloat16().tolist())O BF16 chega ao máximo de 3.39e38, contra 65,504 do FP16, e seu menor valor normal, 1.18e-38, corresponde ao do FP32. O FP16 transforma 70,000 em infinito e 1e-8 em zero, enquanto o BF16 mantém ambos como 70,144 e cerca de 1.0e-8. O espaçamento mais fino do FP16 (eps 0.000977, contra 0.00781 do BF16) preserva 1.001953125 exatamente, enquanto o BF16 arredonda esse valor para 1.0.
BF16 vs. FP16 no treinamento#
Durante o treinamento, o intervalo importa mais que a precisão. Os gradientes muitas vezes ficam abaixo dos menores valores representáveis pelo FP16 e desaparecem; por isso, o treinamento com precisão mista FP16 multiplica a perda por um fator de escala antes da retropropagação e reduz esse fator sempre que os gradientes transbordam, uma técnica chamada escalonamento da perda. O BF16 não precisa de escalonamento da perda, pois seu intervalo é igual ao do FP32, e o treinamento com BF16 iguala os resultados do FP32 em modelos de visão, fala, linguagem e recomendação após o mesmo número de iterações, sem alterar os hiperparâmetros. O treinamento com precisão mista mantém uma cópia principal dos pesos em FP32 e executa multiplicações de matrizes em BF16 com acumulação FP32, já que somar muitos produtos com fração de 7 bits em BF16 causaria perda excessiva. A escolha entre os dois formatos de 16 bits depende principalmente do hardware:
O PyTorch aplica BF16 por meio da precisão mista automática com torch.autocast(device_type="cuda", dtype=torch.bfloat16). O Ultralytics YOLO oferece a mesma opção para o treinamento com amp="bf16", que executa a passagem direta sob autocast BF16 e desativa o escalonador de gradientes usado pelo modo FP16 padrão, em GPUs CUDA com suporte nativo a BF16.
Suporte de hardware#
As TPUs Cloud de segunda e terceira geração do Google multiplicam em BF16 dentro de suas unidades matriciais e acumulam em FP32, e as gerações posteriores de TPU mantiveram o formato. As GPUs NVIDIA executam BF16 em Tensor Cores a partir da geração Ampere, incluindo as GPUs A100, H100 e Blackwell, e os processadores Intel Xeon com Advanced Matrix Extensions (AMX) aceleram esse formato na CPU. Em uma NVIDIA A100, as operações BF16 e FP16 nos Tensor Cores atingem um pico de 312 teraFLOPS, 16 vezes os 19,5 teraFLOPS das operações FP32 padrão da GPU.
BF16 vs. formatos relacionados#
- Meia precisão (FP16): O formato IEEE de 16 bits, com mais precisão e um intervalo muito menor. Continua comum na inferência, em que as ativações permanecem dentro do intervalo e a precisão adicional é útil.
- TF32: Um modo de operações matemáticas dos Tensor Cores da NVIDIA com expoente de 8 bits do BF16 e fração de 10 bits do FP16, que as bibliotecas podem usar para multiplicações de matrizes FP32 em GPUs Ampere e mais recentes, mantendo os tensores armazenados em 32 bits.
- FP8: Formatos de ponto flutuante de 8 bits, como E4M3 e E5M2, compatíveis com GPUs Hopper e Blackwell, que reduzem novamente pela metade o uso de memória no treinamento e na inferência dos maiores modelos.
- Quantização de modelos: Converte os pesos treinados em formatos inteiros, como INT8 ou INT4, para implantação.
BF16 em modelos de linguagem grandes#
A maioria dos modelos de linguagem grandes (LLMs) de pesos abertos é treinada com precisão mista BF16 e publicada com pesos BF16, que servem de referência para avaliar versões quantizadas em FP8 e INT4. Com 2 bytes por parâmetro, os pesos de um modelo com 70 bilhões de parâmetros ocupam 140 GB em BF16, mais que os 80 GB de uma única NVIDIA H100; por isso, servir esse modelo em BF16 exige dividi-lo entre pelo menos duas GPUs.










