# Configuration multi-GPU

Exécutez de grands modèles d'IA sur plusieurs GPU sur CLORE.AI.

{% hint style="success" %}
Trouvez des serveurs multi-GPU sur [CLORE.AI Marketplace](https://clore.ai/marketplace).
{% endhint %}

## Quand avez-vous besoin de plusieurs GPU ?

| Taille du modèle | Option GPU unique | Option multi-GPU |
| ---------------- | ----------------- | ---------------- |
| ≤13B             | RTX 3090 (Q4)     | Non nécessaire   |
| 30B              | RTX 4090 (Q4)     | 2x RTX 3090      |
| 70B              | A100 40GB (Q4)    | 2x RTX 4090      |
| 70B FP16         | -                 | 2x A100 80Go     |
| 100B+            | -                 | 4x A100 80GB     |
| 405B             | -                 | 8x A100 80Go     |

***

## Concepts multi-GPU

### Parallélisme de tenseur (TP)

Répartir les couches du modèle sur plusieurs GPU. Idéal pour l'inférence.

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

**Avantages :** Latence plus faible, configuration simple **Inconvénients :** Nécessite une interconnexion à haut débit

### Parallélisme par pipeline (PP)

Traiter différents lots sur différents GPU.

```
GPU 0 : Lot 1 → GPU 1 : Lot 1
GPU 0 : Lot 2 → GPU 1 : Lot 2
```

**Avantages :** Débit plus élevé **Inconvénients :** Latence plus élevée, plus complexe

### Parallélisme de données (DP)

Même modèle sur plusieurs GPU, données différentes.

```
GPU 0 : Traiter le lot A
GPU 1 : Traiter le lot B
```

**Avantages :** Simple, mise à l'échelle linéaire **Inconvénients :** Chaque GPU nécessite le modèle complet

***

## Configuration multi-GPU pour LLM

### vLLM (Recommandé)

**2 GPU :**

```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 GPU :**

```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 GPU (pour 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 utilise automatiquement plusieurs GPU lorsqu'ils sont disponibles :

```bash
# Vérifier les GPU disponibles
nvidia-smi

# Ollama détectera et utilisera automatiquement tous les GPU
ollama run llama3.1:70b
```

**Limiter à des GPU spécifiques :**

```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
# Spécifier les couches GPU par appareil
./llama-server \
    -m llama-3.1-70b-q4.gguf \
    -ngl 999 \
    --split-mode layer \
    --tensor-split 0.5,0.5
```

***

## Génération d'images Multi-GPU

### ComfyUI

ComfyUI peut décharger différents modèles sur différents GPU :

```python
# Dans le flux de travail ComfyUI
# Utiliser "Load Checkpoint" avec le paramètre device
# device : "cuda:0" pour le premier GPU
# device : "cuda:1" pour le deuxième GPU
```

**Exécuter le VAE sur un GPU séparé :**

```python
# Modèle principal sur GPU 0
# VAE sur GPU 1
# Réduit la pression sur la VRAM
```

### Stable Diffusion WebUI

**Activer le multi-GPU dans webui-user.sh :**

```bash
export COMMANDLINE_ARGS="--device-id 0"
# Ou pour des modèles spécifiques :
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
)

# Distribuer sur plusieurs GPU
pipe.enable_model_cpu_offload()  # ou
pipe.to("cuda:0")  # Sélection explicite du GPU
```

***

## Entraînement Multi-GPU

### PyTorch Distribué

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

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

# Envelopper le modèle
model = YourModel().to(local_rank)
model = DDP(model, device_ids=[local_rank])

# Boucle d'entraînement comme d'habitude
```

**Lancer :**

```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}
    }
)
```

**Lancer :**

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

### Accelerate (HuggingFace)

```python
from accelerate import Accelerator

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

**Configurer :**

```bash
accelerate config  # Configuration interactive
accelerate launch train.py
```

### Entraînement Kohya (LoRA)

```bash
# Entraînement 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"
```

***

## Sélection du GPU

### Vérifier les GPU disponibles

```bash
# Lister tous les GPU
nvidia-smi

# Informations détaillées
nvidia-smi -L

# Utilisation de la mémoire
nvidia-smi --query-gpu=index,memory.used,memory.total --format=csv
```

### Sélectionner des GPU spécifiques

**Variable d'environnement :**

```bash
# Utiliser uniquement les GPU 0 et 1
export CUDA_VISIBLE_DEVICES=0,1
python your_script.py

# Utiliser uniquement le GPU 2
export CUDA_VISIBLE_DEVICES=2
python your_script.py
```

**En Python :**

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

# Ou avec torch
import torch
device = torch.device("cuda:0")  # Premier GPU visible
device = torch.device("cuda:1")  # Deuxième GPU visible
```

***

## Optimisation des performances

### NVLink vs PCIe

| Connexion | Bande passante | Idéal pour                |
| --------- | -------------- | ------------------------- |
| NVLink    | 600 GB/s       | Parallélisme tensoriel    |
| PCIe 4.0  | 32 GB/s        | Parallélisme de données   |
| PCIe 5.0  | 64 GB/s        | Charges de travail mixtes |

**Vérifier l'état de NVLink :**

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

### Configuration optimale

| GPUs | Taille TP | Taille PP | Remarques                       |
| ---- | --------- | --------- | ------------------------------- |
| 2    | 2         | 1         | Parallélisme de tenseur simple  |
| 4    | 4         | 1         | Nécessite NVLink                |
| 4    | 2         | 2         | Compatible PCIe                 |
| 8    | 8         | 1         | Parallélisme de tenseur complet |
| 8    | 4         | 2         | Parallélisme mixte              |

### Équilibrage de la mémoire

**Répartition uniforme (par défaut) :**

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

**Répartition personnalisée (GPU inégaux) :**

```bash
# vLLM ne prend pas en charge l'inégalité, utilisez llama.cpp :
./llama-server --tensor-split 0.6,0.4
```

***

## Dépannage

### "Erreur NCCL"

```bash
# Régler le debug NCCL
export NCCL_DEBUG=INFO

# Essayer différents algorithmes NCCL
export NCCL_ALGO=Ring
```

### "Mémoire insuffisante sur le GPU X"

```bash
# Vérifier la mémoire par GPU
nvidia-smi

# Réduire la taille du lot
--max-batch-size 1

# Activer le gradient checkpointing (entraînement)
--gradient-checkpointing
```

### "Performance multi-GPU lente"

1. Vérifier la connectivité NVLink
2. Réduire la taille du parallélisme de tenseur
3. Utiliser plutôt le parallélisme par pipeline
4. Vérifier le goulet d'étranglement CPU

### "GPU non détectés"

```bash
# Vérifier CUDA
nvidia-smi

# Vérifier que PyTorch voit les GPU
python -c "import torch; print(torch.cuda.device_count())"

# Réinstaller les pilotes CUDA si nécessaire
```

***

## Optimisation des coûts

### Quand le multi-GPU en vaut la peine

| Scénario              | GPU unique           | Multi-GPU               | Gagnant         |
| --------------------- | -------------------- | ----------------------- | --------------- |
| 70B usage occasionnel | A100 80GB (0,25 $/h) | 2x RTX 4090 (0,20 $/h)  | Multi           |
| 70B production        | A100 40GB (0,17 $/h) | 2x A100 40GB (0,34 $/h) | Unique (Q4)     |
| Entraînement 7B       | RTX 4090 (0,10 $/h)  | 2x RTX 4090 (0,20 $/h)  | Dépend du temps |

### Configurations rentables

| Cas d'utilisation    | Configuration | \~Coût/h |
| -------------------- | ------------- | -------- |
| Inférence 70B        | 2x RTX 3090   | $0.12    |
| Inférence rapide 70B | 2x A100 40Go  | $0.34    |
| 70B FP16             | 2x A100 80Go  | $0.50    |
| Entraînement 13B     | 2x RTX 4090   | $0.20    |

***

## Exemples de configurations

### Serveur de chat 70B

```bash
# Configuration 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
# 8x A100 80GB requis
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 Image + LLM

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

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

***

## Prochaines étapes

* [- Débit le plus élevé](https://docs.clore.ai/guides/guides_v2-fr/modeles-de-langage/vllm) - Service LLM en production
* [Comparaison GPU](https://docs.clore.ai/guides/guides_v2-fr/pour-commencer/gpu-comparison) - Choisissez vos GPU
* [ ](https://docs.clore.ai/guides/guides_v2-fr/avance/api-integration) - Construire des applications
* [Calculatrice de coûts](https://docs.clore.ai/guides/guides_v2-fr/pour-commencer/cost-calculator) - Estimer les coûts
