# bitsandbytes

[bitsandbytes](https://huggingface.co/docs/bitsandbytes/index) é a opção mais simples para quantizar um modelo para 8 e 4 bits. A quantização de 8 bits multiplica os valores extremos em fp16 pelos valores não extremos em int8, converte os valores não extremos de volta para fp16 e, em seguida, os soma para retornar os pesos em fp16. Isso reduz o efeito degradante que os valores extremos têm no desempenho de um modelo.

A quantização de 4 bits comprime ainda mais um modelo e é comumente usada com [QLoRA](https://hf.co/papers/2305.14314) para fazer o ajuste fino de LLMs quantizados.

Este guia demonstra como a quantização pode permitir a execução do [FLUX.1-dev](https://huggingface.co/black-forest-labs/FLUX.1-dev) com menos de 16GB de VRAM e até mesmo em uma instância gratuita do Google Colab.

![comparison image](https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/quant-bnb/comparison.png)

Para usar o bitsandbytes, verifique se as seguintes bibliotecas estão instaladas:

```bash
pip install diffusers transformers accelerate bitsandbytes -U
```

Agora você pode quantizar um modelo passando um [BitsAndBytesConfig](/docs/diffusers/main/pt/api/quantization#diffusers.BitsAndBytesConfig) para [from_pretrained()](/docs/diffusers/main/pt/api/models/overview#diffusers.ModelMixin.from_pretrained). Isso funciona para qualquer modelo em qualquer modalidade, desde que ele suporte carregamento com [Accelerate](https://hf.co/docs/accelerate/index) e contenha camadas `torch.nn.Linear`.

Quantizar um modelo em 8 bits reduz o uso de memória pela metade:

bitsandbytes é suportado tanto no Transformers quanto no Diffusers, permitindo quantizar tanto o [FluxTransformer2DModel](/docs/diffusers/main/pt/api/models/flux_transformer#diffusers.FluxTransformer2DModel) quanto o [T5EncoderModel](https://huggingface.co/docs/transformers/main/en/model_doc/t5#transformers.T5EncoderModel).

Para GPUs da série Ada e superiores, recomendamos alterar `dtype` para `torch.bfloat16`.

> [!TIP]
> O `CLIPTextModel` e o [AutoencoderKL](/docs/diffusers/main/pt/api/models/autoencoderkl#diffusers.AutoencoderKL) não são quantizados porque já são pequenos em tamanho e porque o [AutoencoderKL](/docs/diffusers/main/pt/api/models/autoencoderkl#diffusers.AutoencoderKL) possui apenas algumas camadas `torch.nn.Linear`.

```py
from diffusers import BitsAndBytesConfig as DiffusersBitsAndBytesConfig
from transformers import BitsAndBytesConfig as TransformersBitsAndBytesConfig
import torch
from diffusers import AutoModel
from transformers import T5EncoderModel

quant_config = TransformersBitsAndBytesConfig(load_in_8bit=True,)

text_encoder_2_8bit = T5EncoderModel.from_pretrained(
    "black-forest-labs/FLUX.1-dev",
    subfolder="text_encoder_2",
    quantization_config=quant_config,
    dtype=torch.float16,
)

quant_config = DiffusersBitsAndBytesConfig(load_in_8bit=True,)

transformer_8bit = AutoModel.from_pretrained(
    "black-forest-labs/FLUX.1-dev",
    subfolder="transformer",
    quantization_config=quant_config,
    dtype=torch.float16,
)
```

Por padrão, todos os outros módulos, como `torch.nn.LayerNorm`, são convertidos para `torch.float16`. Você pode alterar o tipo de dados desses módulos com o parâmetro `dtype`.

```diff
transformer_8bit = AutoModel.from_pretrained(
    "black-forest-labs/FLUX.1-dev",
    subfolder="transformer",
    quantization_config=quant_config,
+   dtype=torch.float32,
)
```

Vamos gerar uma imagem usando nossos modelos quantizados.

Definir `device_map="auto"` preenche automaticamente todo o espaço disponível primeiro nas GPUs, depois na CPU e, por fim, no disco rígido (a opção mais lenta possível), caso ainda não haja memória suficiente.

```py
from diffusers import FluxPipeline

pipe = FluxPipeline.from_pretrained(
    "black-forest-labs/FLUX.1-dev",
    transformer=transformer_8bit,
    text_encoder_2=text_encoder_2_8bit,
    dtype=torch.float16,
    device_map="auto",
)

pipe_kwargs = {
    "prompt": "A cat holding a sign that says hello world",
    "height": 1024,
    "width": 1024,
    "guidance_scale": 3.5,
    "num_inference_steps": 50,
    "max_sequence_length": 512,
}

image = pipe(**pipe_kwargs, generator=torch.manual_seed(0),).images[0]
```

   

Quando há memória suficiente, você também pode mover diretamente o pipeline para a GPU com `.to("cuda")` e aplicar [enable_model_cpu_offload()](/docs/diffusers/main/pt/api/pipelines/overview#diffusers.DiffusionPipeline.enable_model_cpu_offload) para otimizar o uso de memória da GPU.

Uma vez que um modelo é quantizado, você pode enviar o modelo para o Hub com o método [push_to_hub()](/docs/diffusers/main/pt/api/schedulers/overview#diffusers.utils.PushToHubMixin.push_to_hub). O arquivo de configuração de quantização `config.json` é enviado primeiro, seguido pelos pesos do modelo quantizado. Você também pode salvar os modelos 8-bit serializados localmente com [save_pretrained()](/docs/diffusers/main/pt/api/models/overview#diffusers.ModelMixin.save_pretrained).

Quantizar um modelo em 4 bits reduz o uso de memória em 4x:

bitsandbytes é suportado tanto no Transformers quanto no Diffusers, portanto, você pode quantizar tanto o [FluxTransformer2DModel](/docs/diffusers/main/pt/api/models/flux_transformer#diffusers.FluxTransformer2DModel) quanto o [T5EncoderModel](https://huggingface.co/docs/transformers/main/en/model_doc/t5#transformers.T5EncoderModel).

Para GPUs da série Ada e superiores, recomendamos alterar `dtype` para `torch.bfloat16`.

> [!TIP]
> O `CLIPTextModel` e o [AutoencoderKL](/docs/diffusers/main/pt/api/models/autoencoderkl#diffusers.AutoencoderKL) não são quantizados porque já são pequenos em tamanho e porque o [AutoencoderKL](/docs/diffusers/main/pt/api/models/autoencoderkl#diffusers.AutoencoderKL) possui apenas algumas camadas `torch.nn.Linear`.

```py
from diffusers import BitsAndBytesConfig as DiffusersBitsAndBytesConfig
from transformers import BitsAndBytesConfig as TransformersBitsAndBytesConfig
import torch
from diffusers import AutoModel
from transformers import T5EncoderModel

quant_config = TransformersBitsAndBytesConfig(load_in_4bit=True,)

text_encoder_2_4bit = T5EncoderModel.from_pretrained(
    "black-forest-labs/FLUX.1-dev",
    subfolder="text_encoder_2",
    quantization_config=quant_config,
    dtype=torch.float16,
)

quant_config = DiffusersBitsAndBytesConfig(load_in_4bit=True,)

transformer_4bit = AutoModel.from_pretrained(
    "black-forest-labs/FLUX.1-dev",
    subfolder="transformer",
    quantization_config=quant_config,
    dtype=torch.float16,
)
```

Por padrão, todos os outros módulos, como `torch.nn.LayerNorm`, são convertidos para `torch.float16`. Você pode alterar o tipo de dados desses módulos com o parâmetro `dtype`.

```diff
transformer_4bit = AutoModel.from_pretrained(
    "black-forest-labs/FLUX.1-dev",
    subfolder="transformer",
    quantization_config=quant_config,
+   dtype=torch.float32,
)
```

Vamos gerar uma imagem usando nossos modelos quantizados.

Definir `device_map="auto"` preenche automaticamente todo o espaço disponível primeiro nas GPUs, depois na CPU e, por fim, no disco rígido (a opção mais lenta possível), caso ainda não haja memória suficiente.

```py
from diffusers import FluxPipeline

pipe = FluxPipeline.from_pretrained(
    "black-forest-labs/FLUX.1-dev",
    transformer=transformer_4bit,
    text_encoder_2=text_encoder_2_4bit,
    dtype=torch.float16,
    device_map="auto",
)

pipe_kwargs = {
    "prompt": "A cat holding a sign that says hello world",
    "height": 1024,
    "width": 1024,
    "guidance_scale": 3.5,
    "num_inference_steps": 50,
    "max_sequence_length": 512,
}

image = pipe(**pipe_kwargs, generator=torch.manual_seed(0),).images[0]
```

   

Quando há memória suficiente, você também pode mover diretamente o pipeline para a GPU com `.to("cuda")` e aplicar [enable_model_cpu_offload()](/docs/diffusers/main/pt/api/pipelines/overview#diffusers.DiffusionPipeline.enable_model_cpu_offload) para otimizar o uso de memória da GPU.

Uma vez que um modelo é quantizado, você pode enviar o modelo para o Hub com o método [push_to_hub()](/docs/diffusers/main/pt/api/schedulers/overview#diffusers.utils.PushToHubMixin.push_to_hub). O arquivo de configuração de quantização `config.json` é enviado primeiro, seguido pelos pesos do modelo quantizado. Você também pode salvar os modelos 4-bit serializados localmente com [save_pretrained()](/docs/diffusers/main/pt/api/models/overview#diffusers.ModelMixin.save_pretrained).

> [!WARNING]
> O treinamento com pesos de 8 bits e 4 bits é suportado apenas para o treinamento de *parâmetros extras*.

Verifique a sua pegada de memória com o método `get_memory_footprint`:

```py
print(model.get_memory_footprint())
```

Observe que isso apenas informa a pegada de memória dos parâmetros do modelo e não _estima_ os requisitos de memória para inferência.

Modelos quantizados podem ser carregados a partir do método [from_pretrained()](/docs/diffusers/main/pt/api/models/overview#diffusers.ModelMixin.from_pretrained) sem a necessidade de especificar os parâmetros de `quantization_config`:

```py
from diffusers import AutoModel, BitsAndBytesConfig

quantization_config = BitsAndBytesConfig(load_in_4bit=True)

model_4bit = AutoModel.from_pretrained(
    "hf-internal-testing/flux.1-dev-nf4-pkg", subfolder="transformer"
)
```

## 8-bit (algoritmo LLM.int8())

> [!TIP]
> Saiba mais sobre os detalhes da quantização de 8 bits neste [post de blog](https://huggingface.co/blog/hf-bitsandbytes-integration)!

Esta seção explora alguns dos recursos específicos dos modelos de 8 bits, como limites de outliers e a conversão de módulos ignorada.

### Limiar de outlier

Um "outlier" é um valor de estado oculto maior que um determinado limiar, e esses valores são calculados em fp16. Embora os valores geralmente sigam uma distribuição normal ([-3.5, 3.5]), essa distribuição pode ser muito diferente para modelos grandes ([-60, 6] ou [6, 60]). A quantização de 8 bits funciona bem para valores ~5, mas, além disso, há uma penalidade significativa de desempenho. Um bom valor de limiar padrão é 6, mas um limiar menor pode ser necessário para modelos mais instáveis (modelos pequenos ou finetuning).

Para encontrar o melhor limiar para o seu modelo, recomendamos experimentar com o parâmetro `llm_int8_threshold` em [BitsAndBytesConfig](/docs/diffusers/main/pt/api/quantization#diffusers.BitsAndBytesConfig):

```py
from diffusers import AutoModel, BitsAndBytesConfig

quantization_config = BitsAndBytesConfig(
    load_in_8bit=True, llm_int8_threshold=10,
)

model_8bit = AutoModel.from_pretrained(
    "black-forest-labs/FLUX.1-dev",
    subfolder="transformer",
    quantization_config=quantization_config,
)
```

### Pular a conversão de módulos

Para alguns modelos, não é necessário quantizar todos os módulos para 8 bits, o que pode, na verdade, causar instabilidade. Por exemplo, para modelos de difusão como [Stable Diffusion 3](../api/pipelines/stable_diffusion/stable_diffusion_3), o módulo `proj_out` pode ser ignorado usando o parâmetro `llm_int8_skip_modules` em [BitsAndBytesConfig](/docs/diffusers/main/pt/api/quantization#diffusers.BitsAndBytesConfig):

```py
from diffusers import SD3Transformer2DModel, BitsAndBytesConfig

quantization_config = BitsAndBytesConfig(
    load_in_8bit=True, llm_int8_skip_modules=["proj_out"],
)

model_8bit = SD3Transformer2DModel.from_pretrained(
    "stabilityai/stable-diffusion-3-medium-diffusers",
    subfolder="transformer",
    quantization_config=quantization_config,
)
```

## 4-bit (algoritmo QLoRA)

> [!TIP]
> Saiba mais sobre os detalhes em [este post de blog](https://huggingface.co/blog/4bit-transformers-bitsandbytes).

Esta seção explora alguns dos recursos específicos dos modelos de 4 bits, como a alteração do tipo de dados de computação, o uso do tipo de dados Normal Float 4 (NF4) e o uso de quantização aninhada.

### Tipo de dados de computação

Para acelerar o cálculo, você pode alterar o tipo de dados de float32 (o valor padrão) para bf16 usando o parâmetro `bnb_4bit_compute_dtype` em [BitsAndBytesConfig](/docs/diffusers/main/pt/api/quantization#diffusers.BitsAndBytesConfig):

```py
import torch
from diffusers import BitsAndBytesConfig

quantization_config = BitsAndBytesConfig(load_in_4bit=True, bnb_4bit_compute_dtype=torch.bfloat16)
```

### Float 4 Normal (NF4)

NF4 é um tipo de dados de 4 bits do paper [QLoRA](https://hf.co/papers/2305.14314), adaptado para pesos inicializados a partir de uma distribuição normal. Você deve usar NF4 para treinar modelos base de 4 bits. Isso pode ser configurado com o parâmetro `bnb_4bit_quant_type` no [BitsAndBytesConfig](/docs/diffusers/main/pt/api/quantization#diffusers.BitsAndBytesConfig):

```py
from diffusers import BitsAndBytesConfig as DiffusersBitsAndBytesConfig
from transformers import BitsAndBytesConfig as TransformersBitsAndBytesConfig

from diffusers import AutoModel
from transformers import T5EncoderModel

quant_config = TransformersBitsAndBytesConfig(
    load_in_4bit=True,
    bnb_4bit_quant_type="nf4",
)

text_encoder_2_4bit = T5EncoderModel.from_pretrained(
    "black-forest-labs/FLUX.1-dev",
    subfolder="text_encoder_2",
    quantization_config=quant_config,
    dtype=torch.float16,
)

quant_config = DiffusersBitsAndBytesConfig(
    load_in_4bit=True,
    bnb_4bit_quant_type="nf4",
)

transformer_4bit = AutoModel.from_pretrained(
    "black-forest-labs/FLUX.1-dev",
    subfolder="transformer",
    quantization_config=quant_config,
    dtype=torch.float16,
)
```

Para inferência, o `bnb_4bit_quant_type` não tem um impacto enorme no desempenho. No entanto, para manter a consistência com os pesos do modelo, você deve usar os valores de `bnb_4bit_compute_dtype` e `dtype`.

### Quantização aninhada

A quantização aninhada é uma técnica que pode economizar memória adicional sem custo de desempenho extra. Este recurso executa uma segunda quantização dos pesos já quantizados para economizar mais 0,4 bits/parâmetro.

```py
from diffusers import BitsAndBytesConfig as DiffusersBitsAndBytesConfig
from transformers import BitsAndBytesConfig as TransformersBitsAndBytesConfig

from diffusers import AutoModel
from transformers import T5EncoderModel

quant_config = TransformersBitsAndBytesConfig(
    load_in_4bit=True,
    bnb_4bit_use_double_quant=True,
)

text_encoder_2_4bit = T5EncoderModel.from_pretrained(
    "black-forest-labs/FLUX.1-dev",
    subfolder="text_encoder_2",
    quantization_config=quant_config,
    dtype=torch.float16,
)

quant_config = DiffusersBitsAndBytesConfig(
    load_in_4bit=True,
    bnb_4bit_use_double_quant=True,
)

transformer_4bit = AutoModel.from_pretrained(
    "black-forest-labs/FLUX.1-dev",
    subfolder="transformer",
    quantization_config=quant_config,
    dtype=torch.float16,
)
```

## Desquantizando modelos `bitsandbytes`

Uma vez quantizado, você pode desquantizar um modelo para sua precisão original, mas isso pode resultar em uma pequena perda de qualidade. Certifique-se de ter RAM de GPU suficiente para acomodar o modelo desquantizado.

```python
from diffusers import BitsAndBytesConfig as DiffusersBitsAndBytesConfig
from transformers import BitsAndBytesConfig as TransformersBitsAndBytesConfig

from diffusers import AutoModel
from transformers import T5EncoderModel

quant_config = TransformersBitsAndBytesConfig(
    load_in_4bit=True,
    bnb_4bit_use_double_quant=True,
)

text_encoder_2_4bit = T5EncoderModel.from_pretrained(
    "black-forest-labs/FLUX.1-dev",
    subfolder="text_encoder_2",
    quantization_config=quant_config,
    dtype=torch.float16,
)

quant_config = DiffusersBitsAndBytesConfig(
    load_in_4bit=True,
    bnb_4bit_use_double_quant=True,
)

transformer_4bit = AutoModel.from_pretrained(
    "black-forest-labs/FLUX.1-dev",
    subfolder="transformer",
    quantization_config=quant_config,
    dtype=torch.float16,
)

text_encoder_2_4bit.dequantize()
transformer_4bit.dequantize()
```

## torch.compile

Acelere a inferência com `torch.compile`. Certifique-se de ter a versão mais recente do `bitsandbytes` instalada e também recomendamos instalar o [PyTorch nightly](https://pytorch.org/get-started/locally/).

```py
torch._dynamo.config.capture_dynamic_output_shape_ops = True

quant_config = DiffusersBitsAndBytesConfig(load_in_8bit=True)
transformer_4bit = AutoModel.from_pretrained(
    "black-forest-labs/FLUX.1-dev",
    subfolder="transformer",
    quantization_config=quant_config,
    dtype=torch.float16,
)
transformer_4bit.compile(fullgraph=True)
```

```py
quant_config = DiffusersBitsAndBytesConfig(load_in_4bit=True)
transformer_4bit = AutoModel.from_pretrained(
    "black-forest-labs/FLUX.1-dev",
    subfolder="transformer",
    quantization_config=quant_config,
    dtype=torch.float16,
)
transformer_4bit.compile(fullgraph=True)
```

Em uma RTX 4090 com compilação, a geração de Flux em 4 bits foi concluída em 25,809 segundos, em comparação com 32,570 segundos sem compilação.

Confira o [script de benchmarking](https://gist.github.com/sayakpaul/0db9d8eeeb3d2a0e5ed7cf0d9ca19b7d) para mais detalhes.

## Recursos

* [Nota de demonstração de ponta a ponta mostrando a inferência do Flux.1 Dev em um Colab de nível gratuito](https://gist.github.com/sayakpaul/c76bd845b48759e11687ac550b99d8b4)
* [Treinamento](https://github.com/huggingface/diffusers/blob/8c661ea586bf11cb2440da740dd3c4cf84679b85/examples/dreambooth/README_hidream.md#using-quantization)

