Diffusers documentation

BFL (fp8r / nvfp4)

You are viewing main version, which requires installation from source. If you'd like regular pip install, checkout the latest stable version (v0.42.1).
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 выпускает квантованные варианты своих трансформеров Flux3 в двух схемах, сохраняя их в виде однофайловых чекпоинтов рядом с исходными весами bf16:

  • fp8r: rowwise FP8. Каждый квантованный линейный слой хранит weight в формате E4M3 и weight_scale в формате fp32 для каждой строки. Активации квантуются в E4M3 построчно во время выполнения.
  • nvfp4: NVFP4 в раскладке ModelOpt. Каждый квантованный линейный слой хранит упакованные веса E2M1 weight (два значения на байт), блочные масштабы E4M3 для 16 элементов (weight_scale), глобальный масштаб weight_scale_2 в fp32 и откалиброванный масштаб активаций input_scale в fp32.

Diffusers загружает оба через ~FromSingleFileMixin.from_single_file с BFLQuantizationConfig. Схема считывается из контрольной точки, поэтому одна и та же конфигурация работает для обоих файлов. Поддерживается только загрузка предварительно квантованных контрольных точек; загрузка на уровне пайплайна не поддерживается.

Пример ниже загружает чекпоинт fp8r модели FLUX 3 Image Klein Base, который находится в репозитории модели по пути variants/fp8r/model.safetensors. Передайте параметр config, чтобы конфигурация модели была прочитана из папки Diffusers в этом репозитории, а затем загрузите остальные компоненты по имени (см. Загрузка из одного файла).

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")

Замените variants/fp8r на variants/nvfp4, чтобы загрузить вариант nvfp4. Step-distilled FLUX 3 Image Klein поставляется с теми же двумя вариантами; загрузите их, указав идентификатор репозитория в качестве config и pipeline.

Ядра

Квантованные веса сохраняются в своём типе данных с низкой точностью. Какой GEMM выполняется, зависит от устройства:

СхемаСлиянное ядроТребования
fp8rtorch._scaled_mm с rowwise-масштабамиCUDA GPU с вычислительной мощностью 8.9 или выше
nvfp4flashinfer.mm_fp4 (CUTLASS) с flashinfer.nvfp4_quantize для активацийGPU Blackwell (вычислительная способность 10.0 или выше), набор CUDA с nvcc, а также flashinfer-python и flashinfer-cubin той же версии

Установите оба пакета FlashInfer одной и той же версии, например pip install flashinfer-python==0.6.13 flashinfer-cubin==0.6.13. Релиз flashinfer-cubin может отставать от flashinfer-python, и FlashInfer отказывается импортироваться, если версии различаются.

FlashInfer компилирует свои ядра NVFP4 при первом использовании с помощью CUDA toolkit окружения и определяет целевую архитектуру по видимому GPU (или из переменной FLASHINFER_CUDA_ARCH_LIST, если она задана). Потребительские и рабочие станции Blackwell (compute capability 12.0) требуют CUDA toolkit версии 12.9 или новее. При использовании более старой версии toolkit FlashInfer не находит подходящую архитектуру, и первый вызов NVFP4 завершается ошибкой FlashInfer requires GPUs with sm75 or higher.

На любом другом устройстве веса деквантуются до compute_dtype на каждом проходе вперёд, и слой работает как обычный линейный. В этом случае активации не квантуются, поэтому выходные значения немного отличаются от результатов слиянных ядер.

Update on GitHub