> For the complete documentation index, see [llms.txt](https://docs.clore.ai/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.clore.ai/guides/guides_v2-fr/devops-gpu/onnx-runtime.md).

# ONNX Runtime GPU

> **Inférence ML multiplateforme accélérée par le matériel — déployez n'importe quel modèle depuis n'importe quel framework**

ONNX Runtime (ORT) est le moteur d'inférence open source de Microsoft pour les modèles ONNX (Open Neural Network Exchange). Il fournit une inférence accélérée par le matériel sur les CPU, GPU et accélérateurs spécialisés via une API unifiée. Que votre modèle ait été entraîné avec PyTorch, TensorFlow, Scikit-learn ou XGBoost — si vous pouvez l'exporter au format ONNX, ORT peut l'exécuter plus rapidement.

**GitHub :** [microsoft/onnxruntime](https://github.com/microsoft/onnxruntime) — 14K+ ⭐

***

## Pourquoi ONNX Runtime ?

| Fonctionnalité                | ONNX Runtime      | TorchScript          | TensorFlow Serving |
| ----------------------------- | ----------------- | -------------------- | ------------------ |
| Agnostique au framework       | ✅                 | ❌ uniquement PyTorch | ❌ uniquement TF    |
| Accélération GPU              | ✅ CUDA/TensorRT   | ✅                    | ✅                  |
| Quantification INT8/FP16      | ✅                 | Partiel              | Partiel            |
| Déploiement mobile/périphérie | ✅                 | Limité               | Limité             |
| Fusion d'opérateurs           | ✅                 | Partiel              | ✅                  |
| Intégration facile            | ✅ Python/C++/Java | Python               | Python/gRPC        |

{% hint style="success" %}
**Avantage clé :** ONNX Runtime avec le fournisseur d'exécution CUDA offre généralement **1,5–3x d'accélération** par rapport à l'inférence native PyTorch pour les modèles de vision par ordinateur et de NLP.
{% endhint %}

***

## Fournisseurs d'exécution pris en charge

ONNX Runtime prend en charge plusieurs backends matériels (Fournisseurs d'exécution) :

| Fournisseur                 | Matériel      | Cas d’utilisation      |
| --------------------------- | ------------- | ---------------------- |
| `CUDAExecutionProvider`     | GPU NVIDIA    | Inférence GPU générale |
| `TensorrtExecutionProvider` | GPU NVIDIA    | Débit maximal          |
| `CPUExecutionProvider`      | CPU           | Repli / périphérie     |
| `ROCMExecutionProvider`     | GPU AMD       | Matériel AMD           |
| `CoreMLExecutionProvider`   | Apple Silicon | macOS/iOS              |
| `OpenVINOExecutionProvider` | Intel         | CPU/GPU Intel          |

***

## Prérequis

* Compte Clore.ai avec location de GPU
* Connaissances Python de base
* Un modèle entraîné (PyTorch, TensorFlow ou ONNX pré-exporté)

***

## Étape 1 — Louez un GPU sur Clore.ai

1. Aller à [clore.ai](https://clore.ai) → **Place de marché**
2. N'importe quel GPU NVIDIA convient — de la RTX 3070 pour les petits modèles à l'A100 pour les grands transformeurs
3. **Pour les modèles de type transformer :** RTX 4090 ou A100 recommandés
4. **Pour la vision par ordinateur :** RTX 3090 ou RTX 4090 suffisent

***

## Étape 2 — Déployez votre conteneur

ONNX Runtime n'a pas de conteneur pré-construit officiel, mais la base NVIDIA CUDA est idéale :

**Image Docker :**

```
nvcr.io/nvidia/cuda:12.2.0-cudnn8-devel-ubuntu22.04
```

**Ports :**

```
22
```

**Variables d’environnement :**

```
NVIDIA_VISIBLE_DEVICES=all
NVIDIA_DRIVER_CAPABILITIES=compute,utility
```

{% hint style="info" %}
Alternativement, utilisez `pytorch/pytorch:2.1.0-cuda12.1-cudnn8-runtime` qui inclut CUDA et un environnement Python prêt pour l'installation d'ORT.
{% endhint %}

***

## Étape 3 — Installez ONNX Runtime avec le support GPU

```bash
ssh root@<server-ip> -p <ssh-port>

# Mettre à jour les paquets
apt-get update && apt-get install -y \
    python3-pip \
    python3-dev \
    wget \
    git \
    libgomp1

# Installer ONNX Runtime avec le support CUDA
pip install onnxruntime-gpu

# Installer les paquets de support
pip install \
    onnx \
    numpy \
    Pillow \
    transformers \
    torch \
    torchvision \
    fastapi \
    uvicorn

# Vérifier l'installation
python3 << 'EOF'
import onnxruntime as ort
print(f"ORT Version: {ort.__version__}")
print(f"Fournisseurs disponibles : {ort.get_available_providers()}")
# Devrait inclure : CUDAExecutionProvider, TensorrtExecutionProvider, CPUExecutionProvider
EOF
```

***

## Étape 4 — Exportez votre modèle en ONNX

### Exportation de modèle PyTorch

```python
import torch
import torch.nn as nn
import onnx

# Exemple : Exporter ResNet50
model = torch.hub.load('pytorch/vision:v0.10.0', 'resnet50', pretrained=True)
model.eval()

# Créer une entrée factice (batch=1, image RGB 224x224)
dummy_input = torch.randn(1, 3, 224, 224)

# Exporter en ONNX
torch.onnx.export(
    model,
    dummy_input,
    "resnet50.onnx",
    export_params=True,
    opset_version=17,              # Utiliser la dernière version stable de l'opset
    do_constant_folding=True,      # Optimiser les constantes
    input_names=["input"],
    output_names=["output"],
    dynamic_axes={
        "input": {0: "batch_size"},    # Batch dynamique
        "output": {0: "batch_size"}
    }
)
print("Modèle exporté avec succès !")

# Vérifier le modèle exporté
onnx_model = onnx.load("resnet50.onnx")
onnx.checker.check_model(onnx_model)
print("Le modèle ONNX est valide !")
```

### Exportation HuggingFace Transformers

```bash
# Installer optimum pour l'export ONNX HuggingFace
pip install optimum[exporters]

# Exporter BERT pour la classification de texte
optimum-cli export onnx \
    --model bert-base-uncased \
    --task text-classification \
    ./bert_onnx/

# Exporter avec optimisation
optimum-cli export onnx \
    --model microsoft/phi-2 \
    --task text-generation \
    --optimize O2 \
    ./phi2_onnx/
```

### Exporter avec l'optimisation ORT

```python
from optimum.onnxruntime import ORTModelForSequenceClassification
from optimum.onnxruntime.configuration import OptimizationConfig, ORTConfig
from optimum.onnxruntime import ORTOptimizer

# Charger et optimiser
model = ORTModelForSequenceClassification.from_pretrained(
    "distilbert-base-uncased-finetuned-sst-2-english",
    export=True
)

optimizer = ORTOptimizer.from_pretrained(model)
optimization_config = OptimizationConfig(
    optimization_level=2,
    optimize_for_gpu=True,
    fp16=True
)

optimizer.optimize(
    save_dir="./distilbert_optimized",
    optimization_config=optimization_config
)
```

***

## Étape 5 — Exécuter l'inférence avec ONNX Runtime

### Inférence GPU basique

```python
import onnxruntime as ort
import numpy as np
from PIL import Image
import torchvision.transforms as transforms

# Configurer la session avec les fournisseurs d'exécution GPU
# Les fournisseurs sont essayés dans l'ordre — CUDA d'abord, puis repli sur CPU
providers = [
    ("CUDAExecutionProvider", {
        "device_id": 0,
        "arena_extend_strategy": "kNextPowerOfTwo",
        "gpu_mem_limit": 4 * 1024 * 1024 * 1024,  # limite 4GB
        "cudnn_conv_algo_search": "EXHAUSTIVE",
        "do_copy_in_default_stream": True,
    }),
    "CPUExecutionProvider"
]

# Options de session pour la performance
opts = ort.SessionOptions()
opts.graph_optimization_level = ort.GraphOptimizationLevel.ORT_ENABLE_ALL
opts.intra_op_num_threads = 8
opts.execution_mode = ort.ExecutionMode.ORT_PARALLEL

# Charger le modèle
session = ort.InferenceSession(
    "resnet50.onnx",
    sess_options=opts,
    providers=providers
)

print(f"Exécution sur : {session.get_providers()}")

# Préparer l'entrée
transform = transforms.Compose([
    transforms.Resize(256),
    transforms.CenterCrop(224),
    transforms.ToTensor(),
    transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),
])

img = Image.open("test_image.jpg").convert("RGB")
img_tensor = transform(img).unsqueeze(0).numpy()

# Exécuter l'inférence
outputs = session.run(None, {"input": img_tensor})
probabilities = outputs[0][0]
top5_idx = probabilities.argsort()[-5:][::-1]
print("Top 5 prédictions :", top5_idx, probabilities[top5_idx])
```

### Inférence par lots pour le débit

```python
import onnxruntime as ort
import numpy as np
import time

session = ort.InferenceSession(
    "resnet50.onnx",
    providers=["CUDAExecutionProvider"]
)

# Chauffer le GPU
dummy = np.random.randn(1, 3, 224, 224).astype(np.float32)
for _ in range(10):
    session.run(None, {"input": dummy})

# Mesurer des tailles de batch
for batch_size in [1, 4, 8, 16, 32, 64]:
    inputs = np.random.randn(batch_size, 3, 224, 224).astype(np.float32)
    
    start = time.time()
    n_iter = 100
    for _ in range(n_iter):
        session.run(None, {"input": inputs})
    elapsed = time.time() - start
    
    throughput = (batch_size * n_iter) / elapsed
    latency = (elapsed / n_iter) * 1000  # ms
    
    print(f"Batch {batch_size:3d}: {throughput:7.1f} img/sec, {latency:.1f}ms/batch")
```

***

## Étape 6 — Fournisseur d'exécution TensorRT (performance maximale)

Pour les GPU NVIDIA, le fournisseur TensorRT offre des performances encore meilleures :

```python
import onnxruntime as ort
import numpy as np

# Configuration du fournisseur d'exécution TensorRT
tensorrt_provider_options = {
    "trt_max_workspace_size": 4 * 1024 * 1024 * 1024,  # 4GB
    "trt_fp16_enable": True,          # Activer FP16 pour une inférence plus rapide
    "trt_int8_enable": False,
    "trt_engine_cache_enable": True,   # Mettre en cache les moteurs compilés
    "trt_engine_cache_path": "/tmp/trt_cache",
    "trt_max_partition_iterations": 1000,
    "trt_min_subgraph_size": 1,
    "trt_timing_cache_enable": True,
}

providers = [
    ("TensorrtExecutionProvider", tensorrt_provider_options),
    ("CUDAExecutionProvider", {"device_id": 0}),
    "CPUExecutionProvider"
]

session = ort.InferenceSession("resnet50.onnx", providers=providers)
print("Fournisseur actif :", session.get_providers()[0])

# La première exécution compile le moteur TensorRT (peut prendre 1-3 minutes)
# Les exécutions suivantes utilisent le moteur en cache et sont très rapides
```

{% hint style="warning" %}
**La compilation du moteur TensorRT** se produit lors de la première inférence et peut prendre 1–5 minutes. Activez la mise en cache (`trt_engine_cache_enable: True`) afin que le moteur compilé soit réutilisé entre les sessions.
{% endhint %}

***

## Étape 7 — Quantification INT8 pour une vitesse maximale

```python
from onnxruntime.quantization import quantize_dynamic, quantize_static, QuantType
import onnxruntime as ort
import numpy as np

# Quantification INT8 dynamique (aucune donnée d'étalonnage requise)
quantize_dynamic(
    model_input="resnet50.onnx",
    model_output="resnet50_int8_dynamic.onnx",
    weight_type=QuantType.QInt8
)

# Quantification INT8 statique (nécessite des données d'étalonnage)
from onnxruntime.quantization import CalibrationDataReader

class ImageCalibrationReader(CalibrationDataReader):
    def __init__(self, data_dir, input_name="input"):
        self.data_dir = data_dir
        self.input_name = input_name
        self.images = self._load_images()
        self.idx = 0
    
    def _load_images(self):
        # Charger 100 images d'étalonnage
        import glob, torchvision.transforms as T
        from PIL import Image
        transform = T.Compose([T.Resize(256), T.CenterCrop(224), T.ToTensor()])
        images = []
        for path in glob.glob(f"{self.data_dir}/*.jpg")[:100]:
            img = Image.open(path).convert("RGB")
            images.append(transform(img).numpy())
        return images
    
    def get_next(self):
        if self.idx >= len(self.images):
            return None
        data = {self.input_name: self.images[self.idx:self.idx+1]}
        self.idx += 1
        return data

from onnxruntime.quantization import quantize_static, QuantFormat
quantize_static(
    model_input="resnet50.onnx",
    model_output="resnet50_int8_static.onnx",
    calibration_data_reader=ImageCalibrationReader("/data/calibration_images"),
    quant_format=QuantFormat.QDQ,
    weight_type=QuantType.QInt8
)
```

***

## Étape 8 — Construire une API d'inférence

```bash
cat > /workspace/onnx_api.py << 'EOF'
from fastapi import FastAPI, File, UploadFile
from fastapi.responses import JSONResponse
import onnxruntime as ort
import numpy as np
from PIL import Image
import io
import torchvision.transforms as transforms
import json

app = FastAPI(title="API d'inférence ONNX Runtime")

# Charger le modèle au démarrage
session = ort.InferenceSession(
    "resnet50.onnx",
    providers=["CUDAExecutionProvider", "CPUExecutionProvider"]
)

# Charger les labels ImageNet
with open("imagenet_classes.json") as f:
    classes = json.load(f)

transform = transforms.Compose([
    transforms.Resize(256),
    transforms.CenterCrop(224),
    transforms.ToTensor(),
    transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),
])

@app.get("/health")
async def health():
    return {"status": "ok", "providers": session.get_providers()}

@app.post("/predict")
async def predict(file: UploadFile = File(...), topk: int = 5):
    image_data = await file.read()
    img = Image.open(io.BytesIO(image_data)).convert("RGB")
    tensor = transform(img).unsqueeze(0).numpy()
    
    outputs = session.run(None, {"input": tensor})[0][0]
    top_indices = outputs.argsort()[-topk:][::-1]
    
    results = [
        {"label": classes[str(i)], "score": float(outputs[i])}
        for i in top_indices
    ]
    return JSONResponse({"predictions": results})

if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app, host="0.0.0.0", port=8080)
EOF

python3 /workspace/onnx_api.py &

# Tester l'API
curl -X POST "http://localhost:8080/predict" \
    -H "accept: application/json" \
    -F "file=@test_image.jpg"
```

***

## Étape 9 — Surveiller l'utilisation GPU

```bash
# Surveillance GPU en temps réel pendant l'inférence
watch -n 0.5 nvidia-smi

# Ou utilisez nvitop pour une meilleure interface
pip install nvitop
nvitop
```

***

## Benchmarks de performance

| Modèle    | GPU      | Fournisseur   | Débit (inf/sec) |
| --------- | -------- | ------------- | --------------- |
| ResNet50  | RTX 4090 | CUDA          | \~4,200         |
| ResNet50  | RTX 4090 | TensorRT FP16 | \~8,500         |
| BERT Base | RTX 4090 | CUDA          | \~380           |
| BERT Base | RTX 4090 | TensorRT FP16 | \~720           |
| YOLOv8n   | RTX 3090 | CUDA          | \~1,800         |
| YOLOv8x   | A100     | TensorRT FP16 | \~920           |

***

## Dépannage

### Fournisseur CUDA non disponible

```bash
# Vérifier que CUDA ORT est installé (pas la version CPU uniquement)
pip uninstall onnxruntime
pip install onnxruntime-gpu

python3 -c "import onnxruntime as ort; print(ort.get_available_providers())"
```

### Erreurs de compilation TensorRT

```bash
# Vérifier la compatibilité de la version TensorRT
python3 -c "import tensorrt; print(tensorrt.__version__)"

# Utiliser plutôt le fournisseur CUDA
providers = ["CUDAExecutionProvider"]  # Ignorer le fournisseur TensorRT
```

### Erreurs de mismatch de shape

```python
# Vérifier les shapes d'entrée/sortie du modèle
for input in session.get_inputs():
    print(f"Entrée : {input.name}, shape : {input.shape}, type : {input.type}")

for output in session.get_outputs():
    print(f"Sortie : {output.name}, shape : {output.shape}, type : {output.type}")
```

***

## Avancé : Pipeline multi-modèles

```python
import onnxruntime as ort
import numpy as np

class MultiModelPipeline:
    def __init__(self):
        providers = ["CUDAExecutionProvider"]
        self.detector = ort.InferenceSession("detector.onnx", providers=providers)
        self.classifier = ort.InferenceSession("classifier.onnx", providers=providers)
    
    def run(self, image: np.ndarray) -> list:
        # Étape 1 : Détection d'objets
        boxes = self.detector.run(None, {"image": image})[0]
        
        results = []
        for box in boxes:
            # Recadrer la région détectée
            crop = self._crop(image, box)
            
            # Étape 2 : Classer chaque région
            label = self.classifier.run(None, {"input": crop})[0]
            results.append({"box": box.tolist(), "label": int(label.argmax())})
        
        return results
    
    def _crop(self, image, box):
        x1, y1, x2, y2 = box.astype(int)
        return image[:, :, y1:y2, x1:x2]

pipeline = MultiModelPipeline()
```

***

## Ressources supplémentaires

* [ONNX Runtime GitHub](https://github.com/microsoft/onnxruntime)
* [Documentation ONNX Runtime](https://onnxruntime.ai/docs/)
* [Hugging Face Optimum](https://huggingface.co/docs/optimum/)
* [ONNX Model Zoo](https://github.com/onnx/models) — Modèles pré-exportés
* [Netron](https://netron.app/) — Visualiseur de modèles ONNX
* [API Python ONNX Runtime](https://onnxruntime.ai/docs/api/python/)

***

*ONNX Runtime sur Clore.ai est le choix idéal pour les services d'inférence en production qui doivent servir des modèles provenant de différents frameworks avec une efficacité GPU maximale.*

***

## Recommandations GPU Clore.ai

| Cas d’utilisation            | GPU recommandé  | Coût estimé sur Clore.ai |
| ---------------------------- | --------------- | ------------------------ |
| Développement/Test           | RTX 3090 (24GB) | \~$0.12/gpu/hr           |
| Inférence en production      | RTX 4090 (24GB) | \~$0.70/gpu/hr           |
| Déploiement à grande échelle | A100 80GB       | \~$1.20/gpu/hr           |

> 💡 Tous les exemples de ce guide peuvent être déployés sur [Clore.ai](https://clore.ai/marketplace) serveurs GPU. Parcourez les GPU disponibles et louez à l’heure — sans engagement, avec accès root complet.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## 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-fr/devops-gpu/onnx-runtime.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.
