> 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-de/gpu-devops/onnx-runtime.md).

# ONNX Runtime GPU

> **Plattformübergreifende, hardwarebeschleunigte ML-Inferenz — beliebiges Modell aus jedem Framework bereitstellen**

ONNX Runtime (ORT) ist Microsofts quelloffene Inferenz-Engine für ONNX (Open Neural Network Exchange)-Modelle. Sie bietet hardwarebeschleunigte Inferenz über CPUs, GPUs und spezialisierte Beschleuniger durch eine einheitliche API. Unabhängig davon, ob Ihr Modell in PyTorch, TensorFlow, Scikit-learn oder XGBoost trainiert wurde — wenn Sie es in das ONNX-Format exportieren können, kann ORT es schneller ausführen.

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

***

## Warum ONNX Runtime?

| Funktion                   | ONNX Runtime      | TorchScript   | TensorFlow Serving |
| -------------------------- | ----------------- | ------------- | ------------------ |
| Framework-unabhängig       | ✅                 | ❌ Nur PyTorch | ❌ Nur TF           |
| GPU-Beschleunigung         | ✅ CUDA/TensorRT   | ✅             | ✅                  |
| INT8/FP16-Quantisierung    | ✅                 | Teilweise     | Teilweise          |
| Mobile/Edge-Bereitstellung | ✅                 | Begrenzt      | Begrenzt           |
| Operator-Fusion            | ✅                 | Teilweise     | ✅                  |
| Einfache Integration       | ✅ Python/C++/Java | Python        | Python/gRPC        |

{% hint style="success" %}
**Hauptvorteil:** ONNX Runtime mit dem CUDA-Ausführungsanbieter liefert typischerweise **1,5–3x Beschleunigung** gegenüber nativer PyTorch-Inferenz für Modelle der Computer Vision und NLP.
{% endhint %}

***

## Unterstützte Ausführungsanbieter

ONNX Runtime unterstützt mehrere Hardware-Backends (Execution Providers):

| Anbieter                    | Hardware      | Anwendungsfall          |
| --------------------------- | ------------- | ----------------------- |
| `CUDAExecutionProvider`     | NVIDIA-GPUs   | Allgemeine GPU-Inferenz |
| `TensorrtExecutionProvider` | NVIDIA-GPUs   | Maximaler Durchsatz     |
| `CPUExecutionProvider`      | CPU           | Fallback / Edge         |
| `ROCMExecutionProvider`     | AMD-GPUs      | AMD-Hardware            |
| `CoreMLExecutionProvider`   | Apple Silicon | macOS/iOS               |
| `OpenVINOExecutionProvider` | Intel         | Intel-CPUs/GPUs         |

***

## Voraussetzungen

* Clore.ai-Konto mit GPU-Vermietung
* Grundkenntnisse in Python
* Ein trainiertes Modell (PyTorch, TensorFlow oder bereits nach ONNX exportiert)

***

## Schritt 1 — Mieten Sie eine GPU auf Clore.ai

1. Gehe zu [clore.ai](https://clore.ai) → **Marktplatz**
2. Jede NVIDIA-GPU funktioniert — von RTX 3070 für kleine Modelle bis A100 für große Transformer
3. **Für Transformermodelle:** RTX 4090 oder A100 empfohlen
4. **Für Computer Vision:** RTX 3090 oder RTX 4090 ist ausreichend

***

## Schritt 2 — Bereitstellen Ihres Containers

ONNX Runtime hat keinen offiziellen vorgefertigten Container, aber die NVIDIA CUDA-Basis ist ideal:

**Docker-Image:**

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

**Ports:**

```
22
```

**Umgebungsvariablen:**

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

{% hint style="info" %}
Alternativ verwenden Sie `pytorch/pytorch:2.1.0-cuda12.1-cudnn8-runtime` welches CUDA und eine Python-Umgebung enthält, die für die ORT-Installation bereit ist.
{% endhint %}

***

## Schritt 3 — ONNX Runtime mit GPU-Unterstützung installieren

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

# Pakete aktualisieren
apt-get update && apt-get install -y \
    python3-pip \
    python3-dev \
    wget \
    git \
    libgomp1

# ONNX Runtime mit CUDA-Unterstützung installieren
pip install onnxruntime-gpu

# Unterstützende Pakete installieren
pip install \
    onnx \
    numpy \
    Pillow \
    transformers \
    torch \
    torchvision \
    fastapi \
    uvicorn

# Installation überprüfen
python3 << 'EOF'
import onnxruntime as ort
print(f"ORT Version: {ort.__version__}")
print(f"Verfügbare Anbieter: {ort.get_available_providers()}")
# Sollte enthalten: CUDAExecutionProvider, TensorrtExecutionProvider, CPUExecutionProvider
EOF
```

***

## Schritt 4 — Exportieren Sie Ihr Modell nach ONNX

### PyTorch-Modell-Export

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

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

# Dummy-Eingabe erstellen (Batch=1, RGB-Bild 224x224)
dummy_input = torch.randn(1, 3, 224, 224)

# Nach ONNX exportieren
torch.onnx.export(
    model,
    dummy_input,
    "resnet50.onnx",
    export_params=True,
    opset_version=17,              # Verwenden Sie das neueste stabile Opset
    do_constant_folding=True,      # Konstante Operationen optimieren
    input_names=["input"],
    output_names=["output"],
    dynamic_axes={
        "input": {0: "batch_size"},    # Dynamische Batch-Größe
        "output": {0: "batch_size"}
    }
)
print("Modell erfolgreich exportiert!")

# Überprüfen Sie das exportierte Modell
onnx_model = onnx.load("resnet50.onnx")
onnx.checker.check_model(onnx_model)
print("ONNX-Modell ist gültig!")
```

### HuggingFace Transformers Export

```bash
# Installieren Sie optimum für HuggingFace ONNX-Export
pip install optimum[exporters]

# BERT für Textklassifikation exportieren
optimum-cli export onnx \
    --model bert-base-uncased \
    --task text-classification \
    ./bert_onnx/

# Export mit Optimierung
optimum-cli export onnx \
    --model microsoft/phi-2 \
    --task text-generation \
    --optimize O2 \
    ./phi2_onnx/
```

### Export mit ORT-Optimierung

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

# Laden und optimieren
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
)
```

***

## Schritt 5 — Inferenz mit ONNX Runtime ausführen

### Basis-GPU-Inferenz

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

# Sitzung mit GPU-Ausführungsanbietern konfigurieren
# Anbieter werden der Reihenfolge nach versucht — zuerst CUDA, dann CPU-Fallback
providers = [
    ("CUDAExecutionProvider", {
        "device_id": 0,
        "arena_extend_strategy": "kNextPowerOfTwo",
        "gpu_mem_limit": 4 * 1024 * 1024 * 1024,  # 4GB-Limit
        "cudnn_conv_algo_search": "EXHAUSTIVE",
        "do_copy_in_default_stream": True,
    }),
    "CPUExecutionProvider"
]

# Sitzungsoptionen für Leistung
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

# Modell laden
session = ort.InferenceSession(
    "resnet50.onnx",
    sess_options=opts,
    providers=providers
)

print(f"Läuft auf: {session.get_providers()}")

# Eingabe vorbereiten
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()

# Inferenz ausführen
outputs = session.run(None, {"input": img_tensor})
probabilities = outputs[0][0]
top5_idx = probabilities.argsort()[-5:][::-1]
print("Top 5 Vorhersagen:", top5_idx, probabilities[top5_idx])
```

### Batch-Inferenz für Durchsatz

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

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

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

# Batch-Größen benchmarken
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")
```

***

## Schritt 6 — TensorRT-Ausführungsanbieter (Maximale Leistung)

Für NVIDIA-GPUs bietet der TensorRT-EP noch bessere Leistung:

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

# TensorRT-Ausführungsanbieter-Konfiguration
tensorrt_provider_options = {
    "trt_max_workspace_size": 4 * 1024 * 1024 * 1024,  # 4GB
    "trt_fp16_enable": True,          # FP16 für schnellere Inferenz aktivieren
    "trt_int8_enable": False,
    "trt_engine_cache_enable": True,   # Kompilierte Engines zwischenspeichern
    "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("Aktiver Anbieter:", session.get_providers()[0])

# Der erste Lauf kompiliert die TensorRT-Engine (kann 1–3 Minuten dauern)
# Nachfolgende Läufe verwenden den zwischengespeicherten Engine und sind sehr schnell
```

{% hint style="warning" %}
**TensorRT-Engine-Kompilierung** erfolgt bei der ersten Inferenz und kann 1–5 Minuten dauern. Aktivieren Sie das Caching (`trt_engine_cache_enable: True`) damit die kompilierte Engine über Sitzungen hinweg wiederverwendet wird.
{% endhint %}

***

## Schritt 7 — INT8-Quantisierung für maximale Geschwindigkeit

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

# Dynamische INT8-Quantisierung (Keine Kalibrierdaten erforderlich)
quantize_dynamic(
    model_input="resnet50.onnx",
    model_output="resnet50_int8_dynamic.onnx",
    weight_type=QuantType.QInt8
)

# Statische INT8-Quantisierung (erfordert Kalibrierdaten)
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):
        # 100 Kalibrierungsbilder laden
        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
)
```

***

## Schritt 8 — Erstellen einer Inferenz-API

```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="ONNX Runtime Inference API")

# Lade Modell beim Start
session = ort.InferenceSession(
    "resnet50.onnx",
    providers=["CUDAExecutionProvider", "CPUExecutionProvider"]
)

# ImageNet-Klassenlabels laden
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 &

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

***

## Schritt 9 — GPU-Auslastung überwachen

```bash
# Echtzeit-GPU-Überwachung während der Inferenz
watch -n 0.5 nvidia-smi

# Oder verwenden Sie nvitop für eine bessere UI
pip install nvitop
nvitop
```

***

## Leistungs-Benchmarks

| Modell    | GPU      | Anbieter      | Durchsatz (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               |

***

## Fehlerbehebung

### CUDA-Anbieter nicht verfügbar

```bash
# Prüfen Sie, ob CUDA-ORT installiert ist (nicht nur die CPU-Version)
pip uninstall onnxruntime
pip install onnxruntime-gpu

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

### TensorRT-Kompilierungsfehler

```bash
# Prüfen Sie die Kompatibilität der TensorRT-Version
python3 -c "import tensorrt; print(tensorrt.__version__)"

# Stattdessen den CUDA-EP verwenden
providers = ["CUDAExecutionProvider"]  # TensorRT-EP überspringen
```

### Shape-Mismatch-Fehler

```python
# Prüfen Sie Modell-Eingabe-/Ausgabeformen
for input in session.get_inputs():
    print(f"Eingabe: {input.name}, shape: {input.shape}, type: {input.type}")

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

***

## Fortgeschritten: Multi-Model-Pipeline

```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:
        # Stufe 1: Objekterkennung
        boxes = self.detector.run(None, {"image": image})[0]
        
        results = []
        for box in boxes:
            # Erkannten Bereich zuschneiden
            crop = self._crop(image, box)
            
            # Stufe 2: Jeden Bereich klassifizieren
            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()
```

***

## Weitere Ressourcen

* [ONNX Runtime GitHub](https://github.com/microsoft/onnxruntime)
* [ONNX Runtime Dokumentation](https://onnxruntime.ai/docs/)
* [Hugging Face Optimum](https://huggingface.co/docs/optimum/)
* [ONNX Model Zoo](https://github.com/onnx/models) — Vorexportierte Modelle
* [Netron](https://netron.app/) — ONNX-Modell-Visualizer
* [ONNX Runtime Python API](https://onnxruntime.ai/docs/api/python/)

***

*ONNX Runtime auf Clore.ai ist die ideale Wahl für produktive Inferenzdienste, die Modelle aus verschiedenen Frameworks mit maximaler GPU-Effizienz bereitstellen müssen.*

***

## Clore.ai GPU-Empfehlungen

| Anwendungsfall              | Empfohlene GPU  | Geschätzte Kosten auf Clore.ai |
| --------------------------- | --------------- | ------------------------------ |
| Entwicklung/Tests           | RTX 3090 (24GB) | \~$0.12/gpu/hr                 |
| Produktions-Inferenz        | RTX 4090 (24GB) | \~$0.70/gpu/hr                 |
| Großflächige Bereitstellung | A100 80GB       | \~$1.20/gpu/hr                 |

> 💡 Alle Beispiele in diesem Leitfaden können bereitgestellt werden auf [Clore.ai](https://clore.ai/marketplace) GPU-Servern. Durchsuchen Sie verfügbare GPUs und mieten Sie stundenweise — keine Verpflichtungen, voller Root-Zugriff.


---

# 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-de/gpu-devops/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.
