"Si un trabajador quiere hacer bien su trabajo, primero debe afilar sus herramientas." - Confucio, "Las Analectas de Confucio. Lu Linggong"
Página delantera > Programación > ¿Cuál es la diferencia entre FP y BF? Aquí una buena explicación para ti.

¿Cuál es la diferencia entre FP y BF? Aquí una buena explicación para ti.

Publicado el 2024-08-17
Navegar:306

What is the difference between FPand BF Here a good explanation for you

Representación de punto flotante:

FP16 (media precisión): en FP16, un número de punto flotante se representa utilizando 16 bits. Consta de 1 bit de signo, 5 bits para el exponente y 10 bits para la fracción (mantisa). Este formato proporciona mayor precisión para representar valores fraccionarios dentro de su rango.

BF16 (BFloat16): BF16 también usa 16 bits, pero con una distribución diferente. Tiene 1 bit de signo, 8 bits para el exponente y 7 bits para la mantisa. Este formato sacrifica algo de precisión en la parte fraccionaria para dar cabida a una gama más amplia de exponentes.

Rango numérico:

FP16 tiene un rango más pequeño pero mayor precisión dentro de ese rango debido a su mantisa de 10 bits.
BF16 tiene un rango más amplio pero menor precisión para valores fraccionarios debido a su exponente de 8 bits y mantisa de 7 bits.

Ejemplos:

Usemos ejemplos para ilustrar las diferencias entre FP16 y BF16 con 3 casos de ejemplo. TensorFlow se utiliza para realizar las pruebas y el código compartido en la parte inferior:

Valor original: 0,0001 — Ambos métodos pueden representar
FP16: 0,00010001659393 (Binario: 0|00001|1010001110, Hex: 068E) — 10 mantisa y 5 exponentes
BF16: 0.00010013580322 (Binario: 0|01110001|1010010, Hex: 38D2) — 7 mantisa y 8 exponente

Como puedes ver, tienen diferentes exponentes y mantisas y, por lo tanto, pueden representar de manera diferente. Pero podemos ver que el FP16 lo representó con mayor precisión y con un valor más cercano.

Valor original: 1e-08 (0.00000001)
FP16: 0.00000000000000 (Binario: 0|00000|0000000000, hexadecimal: 0000)
BF16: 0.00000001001172 (Binario: 0|01100100| 0101100, hexadecimal: 322C)

Este es un caso muy interesante. FP16 falla y hace que el resultado sea 0, pero BF16 puede representarlo con un formato especial.

Valor original: 100000.00001
FP16: inf (Binario: 0|11111|0000000000, Hex: 7C00)
BF16: 99840.00000000000000 (Binario: 0|10001111 |1000011, Hexadecimal: 47C3 )

En el caso anterior, FP16 falla ya que todos los bits del exponente se llenan y no son suficientes para representar el valor. Sin embargo, BF16 funciona

Casos de uso:

FP16 se usa comúnmente en inferencia y entrenamiento de aprendizaje profundo, especialmente para tareas que requieren alta precisión en la representación de pequeños valores fraccionarios dentro de un rango limitado.

BF16 se está volviendo popular en arquitecturas de hardware diseñadas para tareas de aprendizaje automático que se benefician de una gama más amplia de valores representables, incluso a costa de cierta precisión en la parte fraccionaria. Es particularmente útil cuando se trata de gradientes grandes o cuando la estabilidad numérica en un rango amplio es más importante que la precisión de valores pequeños.

En resumen

FP16 ofrece mayor precisión para valores fraccionarios dentro de un rango más pequeño, lo que lo hace adecuado para tareas que requieren una representación precisa de números pequeños. BF16, por otro lado, proporciona un rango más amplio a costa de cierta precisión, lo que lo hace ventajoso para tareas que involucran un espectro más amplio de valores o donde la estabilidad numérica en un amplio rango es crucial. La elección entre FP16 y BF16 depende de los requisitos específicos de la tarea de aprendizaje automático en cuestión.

Conclusión final

Debido a todas las razones anteriores, al realizar el entrenamiento de Difusión Estable XL (SDXL), FP16 y BF16 requieren tasas de aprendizaje ligeramente diferentes y encuentro que BF16 funciona mejor.

El código utilizado para generar los ejemplos anteriores

import tensorflow as tf
import struct

def float_to_binary(f):
    return ''.join(f'{b:08b}' for b in struct.pack('>f', f))

def display_fp16(value):
    fp16 = tf.cast(tf.constant(value, dtype=tf.float32), tf.float16)
    fp32 = tf.cast(fp16, tf.float32)
    binary = format(int.from_bytes(fp16.numpy().tobytes(), 'big'), '016b')
    sign = binary[0]
    exponent = binary[1:6]
    fraction = binary[6:]
    return f"FP16: {fp32.numpy():14.14f} (Binary: {sign}|{exponent}|{fraction}, Hex: {fp16.numpy().view('uint16'):04X})"

def display_bf16(value):
    bf16 = tf.cast(tf.constant(value, dtype=tf.float32), tf.bfloat16)
    bf32 = tf.cast(bf16, tf.float32)
    binary = format(int.from_bytes(bf16.numpy().tobytes(), 'big'), '016b')
    sign = binary[0]
    exponent = binary[1:9]
    fraction = binary[9:]
    return f"BF16: {bf32.numpy():14.14f} (Binary: {sign}|{exponent}|{fraction}, Hex: {bf16.numpy().view('uint16'):04X})"

values = [0.0001, 0.00000001, 100000.00001]

for value in values:
    print(f"\nOriginal value: {value}")
    print(display_fp16(value))
    print(display_bf16(value))
Declaración de liberación Este artículo se reproduce en: https://dev.to/furkangozukara/what-is-the-difference-between-fp16-and-bf16-here-a-good-explanation-for-you-gag?1Si hay alguna infracción, comuníquese con [email protected] para eliminar
Último tutorial Más>

Descargo de responsabilidad: Todos los recursos proporcionados provienen en parte de Internet. Si existe alguna infracción de sus derechos de autor u otros derechos e intereses, explique los motivos detallados y proporcione pruebas de los derechos de autor o derechos e intereses y luego envíelos al correo electrónico: [email protected]. Lo manejaremos por usted lo antes posible.

Copyright© 2022 湘ICP备2022001581号-3