Diffusers documentation

BFL (fp8r / nvfp4)

Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

BFL (fp8r / nvfp4)

Black Forest Labs ofrece variantes cuantizadas de sus transformers Flux3 en dos esquemas, almacenadas como puntos de control de archivo único junto a los pesos bf16 originales:

  • fp8r: FP8 por fila. Cada lineal cuantizado almacena un weight E4M3 y una weight_scale fp32 por fila. Las activaciones se cuantizan a E4M3 por fila en tiempo de ejecución.
  • nvfp4: NVFP4 en el formato de ModelOpt. Cada lineal cuantizado almacena un weight E2M1 empaquetado (dos valores por byte), escalas de bloque E4M3 de 16 (weight_scale), una escala global fp32 weight_scale_2 y una escala de activación fp32 calibrada input_scale.

Diffusers carga ambos a través de ~FromSingleFileMixin.from_single_file con una BFLQuantizationConfig. El esquema se lee desde el checkpoint, por lo que la misma configuración funciona para cualquiera de los dos archivos. Solo se admite la carga de checkpoints precuantizados; no se admite la carga a nivel de pipeline.

El ejemplo siguiente carga el punto de control fp8r de FLUX 3 Image Klein Base, que se encuentra en variants/fp8r/model.safetensors del repositorio del modelo. Pasa config para que la configuración del modelo se lea desde la carpeta Diffusers de ese repositorio y luego carga los demás componentes por nombre (consulta Carga de un solo archivo).

import torch

from diffusers import BFLQuantizationConfig, Flux3Transformer2DModel, ModularPipeline

ckpt_path = "https://huggingface.co/black-forest-labs/flux-3-image-klein-base/blob/main/variants/fp8r/model.safetensors"
transformer = Flux3Transformer2DModel.from_single_file(
    ckpt_path,
    config="black-forest-labs/flux-3-image-klein-base",
    subfolder="transformer",
    quantization_config=BFLQuantizationConfig(compute_dtype=torch.bfloat16),
    dtype=torch.bfloat16,
)
pipe = ModularPipeline.from_pretrained("black-forest-labs/flux-3-image-klein-base")
pipe.load_components(dtype=torch.bfloat16)
pipe.update_components(transformer=transformer)
pipe.to("cuda")

prompt = "A wide-angle wildlife photograph of a red fox standing alert in a snow-covered forest clearing at golden hour."
image = pipe(prompt=prompt, generator=torch.Generator().manual_seed(0), output="images")[0]
image.save("flux3-klein-base-fp8r.png")

Reemplace variants/fp8r por variants/nvfp4 para cargar la variante nvfp4. El FLUX 3 Image Klein destilado por pasos incluye las mismas dos variantes; cárguelas usando su id de repositorio como config y pipeline.

Kernels

Los pesos cuantizados permanecen en su dtype de almacenamiento de baja precisión. El GEMM que se ejecuta depende del dispositivo:

EsquemaKernel fusionadoRequisitos
fp8rtorch._scaled_mm con escalas por filaGPU CUDA con capacidad de cálculo 8.9 o superior
nvfp4flashinfer.mm_fp4 (CUTLASS) con flashinfer.nvfp4_quantize para las activacionesGPU Blackwell (capacidad de cálculo 10.0 o superior), un kit de herramientas CUDA con nvcc y flashinfer-python con flashinfer-cubin en la misma versión

Instale los dos paquetes de FlashInfer en la misma versión, por ejemplo pip install flashinfer-python==0.6.13 flashinfer-cubin==0.6.13. La versión de flashinfer-cubin puede estar por detrás de flashinfer-python, y FlashInfer se niega a importarse si las versiones difieren.

FlashInfer compila sus kernels NVFP4 en el primer uso con el kit de herramientas CUDA del entorno y selecciona la arquitectura objetivo a partir de la GPU visible (o desde FLASHINFER_CUDA_ARCH_LIST cuando está definido). Las GPUs Blackwell de consumo y de estación de trabajo (capacidad de cómputo 12.0) requieren un kit de herramientas CUDA de la versión 12.9 o superior. Con un kit de herramientas más antiguo, FlashInfer no encuentra ninguna arquitectura elegible y la primera llamada NVFP4 falla con FlashInfer requires GPUs with sm75 or higher.

En cualquier otro dispositivo, los pesos se descuantizan a compute_dtype en cada pasada hacia adelante y la capa se ejecuta como una lineal regular. En ese caso, las activaciones no se cuantizan, por lo que las salidas difieren ligeramente de los núcleos fusionados.

Update on GitHub