# Configuración multi-GPU

Ejecute grandes modelos de IA en múltiples GPU en CLORE.AI.

{% hint style="success" %}
Encuentre servidores multi-GPU en [CLORE.AI Marketplace](https://clore.ai/marketplace).
{% endhint %}

## ¿Cuándo necesita Multi-GPU?

| Tamaño del modelo | Opción de GPU única | Opción Multi-GPU |
| ----------------- | ------------------- | ---------------- |
| ≤13B              | RTX 3090 (Q4)       | No requerido     |
| 30B               | RTX 4090 (Q4)       | 2x RTX 3090      |
| 70B               | A100 40GB (Q4)      | 2x RTX 4090      |
| 70B FP16          | -                   | 2x A100 80GB     |
| 100B+             | -                   | 4x A100 80GB     |
| 405B              | -                   | 8x A100 80GB     |

***

## Conceptos Multi-GPU

### Paralelismo de Tensor (TP)

Divida las capas del modelo entre GPUs. Mejor para inferencia.

```
GPU 0: Capas 1-20
GPU 1: Capas 21-40
```

**Pros:** Menor latencia, configuración simple **Contras:** Requiere interconexión de alta velocidad

### Paralelismo de Pipelining (PP)

Procese diferentes lotes en diferentes GPUs.

```
GPU 0: Lote 1 → GPU 1: Lote 1
GPU 0: Lote 2 → GPU 1: Lote 2
```

**Pros:** Mayor rendimiento **Contras:** Mayor latencia, más complejo

### Paralelismo de Datos (DP)

Mismo modelo en múltiples GPUs, datos diferentes.

```
GPU 0: Procesar lote A
GPU 1: Procesar lote B
```

**Pros:** Escalado simple y lineal **Contras:** Cada GPU necesita el modelo completo

***

## Configuración Multi-GPU para LLM

### vLLM (Recomendado)

**2 GPUs:**

```bash
python -m vllm.entrypoints.openai.api_server \
    --model meta-llama/Llama-3.1-70B-Instruct \
    --tensor-parallel-size 2 \
    --host 0.0.0.0
```

**4 GPUs:**

```bash
python -m vllm.entrypoints.openai.api_server \
    --model meta-llama/Llama-3.1-70B-Instruct \
    --tensor-parallel-size 4 \
    --host 0.0.0.0
```

**8 GPUs (para 405B):**

```bash
python -m vllm.entrypoints.openai.api_server \
    --model meta-llama/Llama-3.1-405B-Instruct \
    --tensor-parallel-size 8 \
    --host 0.0.0.0
```

### Ollama Multi-GPU

Ollama usa automáticamente múltiples GPUs cuando están disponibles:

```bash
# Comprobar GPUs disponibles
nvidia-smi

# Ollama detectará y usará todas las GPUs
ollama run llama3.1:70b
```

**Limitar a GPUs específicas:**

```bash
CUDA_VISIBLE_DEVICES=0,1 ollama run llama3.1:70b
```

### Text Generation Inference (TGI)

```bash
docker run --gpus all -p 8080:80 \
    ghcr.io/huggingface/text-generation-inference:latest \
    --model-id meta-llama/Llama-3.1-70B-Instruct \
    --num-shard 2
```

### llama.cpp

```bash
# Especificar capas de GPU por dispositivo
./llama-server \
    -m llama-3.1-70b-q4.gguf \
    -ngl 999 \
    --split-mode layer \
    --tensor-split 0.5,0.5
```

***

## Generación de Imágenes Multi-GPU

### ComfyUI

ComfyUI puede descargar diferentes modelos en distintas GPUs:

```python
# En el flujo de trabajo de ComfyUI
# Use "Load Checkpoint" con el parámetro device
# device: "cuda:0" para la primera GPU
# device: "cuda:1" para la segunda GPU
```

**Ejecutar VAE en una GPU separada:**

```python
# Modelo principal en GPU 0
# VAE en GPU 1
# Reduce la presión de VRAM
```

### Stable Diffusion WebUI

**Habilitar multi-GPU en webui-user.sh:**

```bash
export COMMANDLINE_ARGS="--device-id 0"
# O para modelos específicos:
export COMMANDLINE_ARGS="--lowvram --device-id 0,1"
```

### FLUX Multi-GPU

```python
from diffusers import FluxPipeline
import torch

pipe = FluxPipeline.from_pretrained(
    "black-forest-labs/FLUX.1-dev",
    torch_dtype=torch.bfloat16
)

# Distribuir entre GPUs
pipe.enable_model_cpu_offload()  # o
pipe.to("cuda:0")  # Selección explícita de GPU
```

***

## Entrenamiento Multi-GPU

### PyTorch Distribuido

```python
import torch
import torch.distributed as dist
from torch.nn.parallel import DistributedDataParallel as DDP

# Inicializar
dist.init_process_group("nccl")
local_rank = int(os.environ["LOCAL_RANK"])
torch.cuda.set_device(local_rank)

# Envolver modelo
model = YourModel().to(local_rank)
model = DDP(model, device_ids=[local_rank])

# Bucle de entrenamiento como de costumbre
```

**Lanzamiento:**

```bash
torchrun --nproc_per_node=2 train.py
```

### DeepSpeed

```python
import deepspeed

model, optimizer, _, _ = deepspeed.initialize(
    model=model,
    config={
        "train_batch_size": 32,
        "fp16": {"enabled": True},
        "zero_optimization": {"stage": 2}
    }
)
```

**Lanzamiento:**

```bash
deepspeed --num_gpus=2 train.py
```

### Accelerate (HuggingFace)

```python
from accelerate import Accelerator

accelerator = Accelerator()
model, optimizer, dataloader = accelerator.prepare(
    model, optimizer, dataloader
)
```

**Configurar:**

```bash
accelerate config  # Configuración interactiva
accelerate launch train.py
```

### Kohya Training (LoRA)

```bash
# Entrenamiento LoRA Multi-GPU
accelerate launch --num_processes=2 train_network.py \
    --pretrained_model_name_or_path="model.safetensors" \
    --train_data_dir="./images" \
    --output_dir="./output"
```

***

## Selección de GPU

### Comprobar GPUs disponibles

```bash
# Listar todas las GPUs
nvidia-smi

# Información detallada
nvidia-smi -L

# Uso de memoria
nvidia-smi --query-gpu=index,memory.used,memory.total --format=csv
```

### Seleccionar GPUs específicas

**Variable de entorno:**

```bash
# Usar solo GPU 0 y 1
export CUDA_VISIBLE_DEVICES=0,1
python your_script.py

# Usar solo GPU 2
export CUDA_VISIBLE_DEVICES=2
python your_script.py
```

**En Python:**

```python
import os
os.environ["CUDA_VISIBLE_DEVICES"] = "0,1"

# O con torch
import torch
device = torch.device("cuda:0")  # Primera GPU visible
device = torch.device("cuda:1")  # Segunda GPU visible
```

***

## Optimización del rendimiento

### NVLink vs PCIe

| Conexión | Ancho de banda | Mejor para               |
| -------- | -------------- | ------------------------ |
| NVLink   | 600 GB/s       | Paralelismo tensorial    |
| PCIe 4.0 | 32 GB/s        | Paralelismo de datos     |
| PCIe 5.0 | 64 GB/s        | Cargas de trabajo mixtas |

**Comprobar estado de NVLink:**

```bash
nvidia-smi nvlink --status
```

### Configuración óptima

| GPUs | Tamaño TP | Tamaño PP | Notas                          |
| ---- | --------- | --------- | ------------------------------ |
| 2    | 2         | 1         | Paralelismo de tensor simple   |
| 4    | 4         | 1         | Requiere NVLink                |
| 4    | 2         | 2         | Amigable con PCIe              |
| 8    | 8         | 1         | Paralelismo de tensor completo |
| 8    | 4         | 2         | Paralelismo mixto              |

### Equilibrio de memoria

**División uniforme (por defecto):**

```bash
--tensor-parallel-size 2
```

**División personalizada (GPUs desiguales):**

```bash
# vLLM no admite desiguales, use llama.cpp:
./llama-server --tensor-split 0.6,0.4
```

***

## Solución de problemas

### "Error NCCL"

```bash
# Establecer depuración de NCCL
export NCCL_DEBUG=INFO

# Probar diferentes algoritmos de NCCL
export NCCL_ALGO=Ring
```

### "Memoria insuficiente en la GPU X"

```bash
# Comprobar memoria por GPU
nvidia-smi

# Reducir tamaño de lote
--max-batch-size 1

# Habilitar gradient checkpointing (entrenamiento)
--gradient-checkpointing
```

### "Rendimiento Multi-GPU lento"

1. Comprobar conectividad NVLink
2. Reducir tamaño de paralelismo de tensor
3. Usar paralelismo de pipeline en su lugar
4. Comprobar el cuello de botella de la CPU

### "GPUs no detectadas"

```bash
# Verificar CUDA
nvidia-smi

# Comprobar que PyTorch detecta las GPUs
python -c "import torch; print(torch.cuda.device_count())"

# Reinstalar controladores CUDA si es necesario
```

***

## Optimización de costos

### Cuándo vale la pena Multi-GPU

| Escenario            | GPU única            | Multi-GPU               | Ganador            |
| -------------------- | -------------------- | ----------------------- | ------------------ |
| Uso ocasional de 70B | A100 80GB ($0.25/hr) | 2x RTX 4090 ($0.20/hr)  | Multi              |
| 70B en producción    | A100 40GB ($0.17/hr) | 2x A100 40GB ($0.34/hr) | Única (Q4)         |
| Entrenamiento 7B     | RTX 4090 ($0.10/hr)  | 2x RTX 4090 ($0.20/hr)  | Depende del tiempo |

### Configuraciones rentables

| Caso de uso           | Configuración | \~Costo/hr |
| --------------------- | ------------- | ---------- |
| Inferencia 70B        | 2x RTX 3090   | $0.12      |
| Inferencia rápida 70B | 2x A100 40GB  | $0.34      |
| 70B FP16              | 2x A100 80GB  | $0.50      |
| Entrenamiento 13B     | 2x RTX 4090   | $0.20      |

***

## Configuraciones de ejemplo

### Servidor de Chat 70B

```bash
# Configuración 2x A100 40GB
python -m vllm.entrypoints.openai.api_server \
    --model meta-llama/Llama-3.1-70B-Instruct \
    --tensor-parallel-size 2 \
    --max-model-len 8192 \
    --host 0.0.0.0 \
    --port 8000
```

### DeepSeek-V3 (671B)

```bash
# Se requieren 8x A100 80GB
python -m vllm.entrypoints.openai.api_server \
    --model deepseek-ai/DeepSeek-V3 \
    --tensor-parallel-size 8 \
    --trust-remote-code \
    --host 0.0.0.0
```

### Pipeline de Imagen + LLM

```bash
# GPU 0: Stable Diffusion
CUDA_VISIBLE_DEVICES=0 python comfyui/main.py --port 8188 &

# GPU 1: LLM para prompts
CUDA_VISIBLE_DEVICES=1 python -m vllm.entrypoints.openai.api_server \
    --model meta-llama/Llama-3.1-8B-Instruct --port 8000
```

***

## Próximos pasos

* [Guía de vLLM](https://docs.clore.ai/guides/guides_v2-es/modelos-de-lenguaje/vllm) - Serving LLM en producción
* [Comparación de GPU](https://docs.clore.ai/guides/guides_v2-es/primeros-pasos/gpu-comparison) - Elija sus GPUs
* [Integración de API](https://docs.clore.ai/guides/guides_v2-es/avanzado/api-integration) - Construir aplicaciones
* [Calculadora de costos](https://docs.clore.ai/guides/guides_v2-es/primeros-pasos/cost-calculator) - Estime los costos
