# CPU

CPUs executam modelos do Transformers com a string de dispositivo `cpu`, sem um acelerador. Elas funcionam para inferência e treinamento quando GPUs não estão disponíveis, ou quando você deseja uma configuração economicamente viável.

## Executar inferência

Os modelos são carregados na CPU por padrão quando você não passa `device_map`, e [pipeline()](/docs/transformers/main/pt/main_classes/pipelines#transformers.pipeline) usa a CPU quando nenhum acelerador está disponível. Passe `device_map="cpu"` ou `device="cpu"` para usar a CPU em uma máquina que também possui um acelerador.

```py
from transformers import pipeline

generator = pipeline("text-generation", model="Qwen/Qwen3-0.6B", device="cpu")
print(generator("CPUs are", max_new_tokens=50, do_sample=False)[0]["generated_text"])
```

## Treinar com o Trainer

CPUs com suporte a bf16, como os processadores recentes da Intel e da AMD, podem usar o treinamento de precisão mista bf16 com [AMP do PyTorch](https://docs.pytorch.org/docs/stable/amp), o que reduz o uso de memória e acelera o treinamento.

Os exemplos abaixo cobrem três configurações, de uma única CPU a vários computadores, quando uma única CPU é muito lenta:

- uma única CPU
- vários processos em uma única máquina (um por soquete de CPU)
- vários processos em várias máquinas

Os exemplos de nó único e multi-nó iniciam processos com `mpirun` do [Intel MPI](https://www.intel.com/content/www/us/en/developer/tools/oneapi/mpi-library.html), parte do [Intel oneAPI HPC Toolkit](https://www.intel.com/content/www/us/en/developer/tools/oneapi/hpc-toolkit.html), e o [Trainer](/docs/transformers/main/pt/main_classes/trainer#transformers.Trainer) executa DDP sobre o backend `gloo`.

Defina `bf16=True` e `use_cpu=True` em [TrainingArguments](/docs/transformers/main/pt/main_classes/trainer#transformers.TrainingArguments), ou passe `--bf16` e `--use_cpu` para um script de treinamento. Prefira bf16 em vez de fp16 em CPU, pois é mais numericamente estável.

```py
from transformers import TrainingArguments

training_args = TrainingArguments(
    output_dir="./outputs",
    bf16=True,
    use_cpu=True,
)
```

Em uma CPU de dois soquetes, execute um processo por soquete. Manter os acessos à memória locais a cada soquete melhora o throughput. O exemplo abaixo inicia dois processos em uma única máquina, com um processo por soquete, onde `train.py` é o seu script de treinamento `Trainer`.

> [!TIP]
> Defina `OMP_NUM_THREADS` para o número de núcleos físicos em um soquete, menos um núcleo reservado para o sistema operacional. Por exemplo, em um soquete de 24 núcleos, defina `OMP_NUM_THREADS=23`.

```bash
export MASTER_ADDR=127.0.0.1
mpirun -n 2 -genv OMP_NUM_THREADS=23 \
python3 train.py \
 --output_dir ./outputs \
 --use_cpu \
 --bf16
```

Escale o treinamento para quatro processos em duas máquinas (`node0` e `node1`) usando um `hostfile` que lista o endereço IP de cada nó. A flag `-n 4` define o número total de processos. `-ppn 2` define dois processos por nó (um por soquete).

Execute este script a partir de `node0`, que atua como o processo principal.

> [!TIP]
> Defina `OMP_NUM_THREADS` para o número de núcleos físicos em um soquete, menos um núcleo reservado para o sistema operacional. Por exemplo, em um soquete de 24 núcleos, defina `OMP_NUM_THREADS=23`.

Crie um hostfile com o endereço IP de cada nó.

```bash
cat hostfile
xxx.xxx.xxx.xxx #node0 ip
xxx.xxx.xxx.xxx #node1 ip
```

Em seguida, execute o script de treinamento.

```bash
export MASTER_ADDR=xxx.xxx.xxx.xxx #node0 ip
mpirun -f hostfile -n 4 -ppn 2 \
 -genv OMP_NUM_THREADS=23 \
python3 train.py \
 --output_dir ./outputs \
 --use_cpu \
 --bf16
```

## Ajustar o desempenho da CPU

Pré-carregue um alocador de memória mais rápido e o runtime OpenMP da Intel para reduzir o overhead no treinamento em CPU. Instale o `google-perftools` (para o `libtcmalloc`) e o pacote Python `intel-openmp` (para o `libiomp5`), e em seguida adicione ambas as bibliotecas à variável de ambiente `LD_PRELOAD` antes de iniciar o treinamento.

Defina `OMP_NUM_THREADS` para o número de núcleos que cada processo pode usar. Em um contêiner ou em um trabalho de cluster com limites de CPU, esse é o número de unidades de CPU alocadas, portanto, deixe alguns núcleos não alocados para os processos do sistema.

## Próximas etapas

- Leia o post no blog [Acelerando Transformers do PyTorch com Intel Sapphire Rapids](https://huggingface.co/blog/intel-sapphire-rapids) para uma análise mais aprofundada do desempenho BF16 em hardware Intel moderno.
- Leia [DDP](./ddp) para saber mais sobre a estratégia distribuída usada nos exemplos multiprocessos.
- Leia as notas de [threading de CPU](https://docs.pytorch.org/docs/stable/notes/cpu_threading_torchscript_inference.html) do PyTorch para entender como `OMP_NUM_THREADS` afeta o desempenho.
- Leia o guia [PyTorchJob](https://www.kubeflow.org/docs/components/training/user-guides/pytorch/) do Kubeflow para executar treinamento distribuído de CPU no Kubernetes.

