# 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](/guides/guides_v2-es/modelos-de-lenguaje/vllm.md) - Serving LLM en producción
* [Comparación de GPU](/guides/guides_v2-es/primeros-pasos/gpu-comparison.md) - Elija sus GPUs
* [Integración de API](/guides/guides_v2-es/avanzado/api-integration.md) - Construir aplicaciones
* [Calculadora de costos](/guides/guides_v2-es/primeros-pasos/cost-calculator.md) - Estime los costos


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.clore.ai/guides/guides_v2-es/avanzado/multi-gpu-setup.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
