> 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/mlops-and-bereitstellung/triton-inference-server.md).

# Triton Inference Server

**NVIDIA Triton Inference Server** ist eine produktionsreife, quelloffene Inferenz-Serving-Plattform, die praktisch jedes wichtige ML-Framework unterstützt. Für hochdurchsatzfähiges Serving mit niedriger Latenz entwickelt, verarbeitet Triton PyTorch, TensorFlow, ONNX, TensorRT, OpenVINO und mehr – alles aus einem einzigen Serverprozess. Setzen Sie ihn auf Clore.ais GPU-Cloud ein für skalierbare, kosteneffiziente Inferenz-Infrastruktur.

***

## Was ist der Triton Inference Server?

Triton ist NVIDIAs Antwort auf die Herausforderung, ML-Modelle im großen Maßstab bereitzustellen:

* **Mehrere Frameworks:** PyTorch, TensorFlow, TensorRT, ONNX, OpenVINO, Python-Custom-Backends
* **Gleichzeitige Ausführung:** Mehrere Modelle, mehrere Instanzen pro GPU
* **Dynamisches Batching:** Anfragen automatisch batchen für höheren Durchsatz
* **gRPC + HTTP:** Branchenübliche Protokolle sofort einsatzbereit
* **Metriken:** Prometheus-kompatibler Metrik-Endpunkt
* **Model-Repository:** Dateisystembasierte Modellverwaltung

**Verwendete Ports:**

| Port | Protokoll | Zweck               |
| ---- | --------- | ------------------- |
| 8000 | HTTP      | REST-Inferenz-API   |
| 8001 | gRPC      | gRPC-Inferenz-API   |
| 8002 | HTTP      | Prometheus-Metriken |

***

## Voraussetzungen

| Anforderung | Minimum                  | Empfohlen       |
| ----------- | ------------------------ | --------------- |
| GPU-VRAM    | 8 GB                     | 16–24 GB        |
| GPU         | Jede NVIDIA mit CUDA 11+ | RTX 4090 / A100 |
| RAM         | 16 GB                    | 32 GB           |
| Speicher    | 20 GB                    | 50 GB           |

{% hint style="info" %}
Triton unterstützt auch CPU-only Inferenz für Nicht-CUDA-Workloads. Verwenden Sie das `cpu-only` Variant des Docker-Images, um bei Batch-Jobs ohne GPU Kosten zu sparen.
{% endhint %}

***

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

1. Melden Sie sich an bei [clore.ai](https://clore.ai).
2. Klicken Sie **Marktplatz** und filtern Sie nach VRAM ≥ 16 GB.
3. Wählen Sie einen Server und klicken Sie auf **Konfigurieren**.
4. Docker-Image festlegen: **`nvcr.io/nvidia/tritonserver:24.01-py3`**
   * (Ersetzen Sie `24.01` durch die neueste Version — prüfen Sie [NGC-Katalog](https://catalog.ngc.nvidia.com/orgs/nvidia/containers/tritonserver))
5. Offene Ports festlegen: `22` (SSH), `8000` (HTTP), `8001` (gRPC), `8002` (Metriken).
6. Klicken Sie **Mieten**.

{% hint style="warning" %}
Triton Docker-Images sind groß (\~15–20 GB). Geben Sie beim ersten Start 3–5 Minuten für den anfänglichen Pull ein. Nachfolgende Starts sind schnell.
{% endhint %}

***

## Schritt 2 — Custom Dockerfile (mit SSH)

Das offizielle Triton-Image enthält keinen SSH-Server. Verwenden Sie dieses Dockerfile:

```dockerfile
FROM nvcr.io/nvidia/tritonserver:24.01-py3

RUN apt-get update && apt-get install -y \
    openssh-server \
    wget curl \
    && rm -rf /var/lib/apt/lists/*

# Konfiguriere SSH
RUN mkdir /var/run/sshd && \
    echo 'root:clore123' | chpasswd && \
    sed -i 's/#PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config

# Installieren der Python-Clientbibliothek
RUN pip install tritonclient[all] numpy Pillow

RUN mkdir -p /models

EXPOSE 22 8000 8001 8002

CMD service ssh start && \
    tritonserver \
        --model-repository=/models \
        --log-verbose=0 \
        --http-port=8000 \
        --grpc-port=8001 \
        --metrics-port=8002
```

***

## Schritt 3 — Verstehen des Model-Repository

Triton lädt Modelle aus einem **Model-Repository** — einem Verzeichnis mit einer spezifischen Struktur:

```
/models/
├── model_name_1/
│   ├── config.pbtxt          # Modellkonfiguration
│   ├── 1/                    # Version 1
│   │   └── model.pt          # Modell-Datei
│   └── 2/                    # Version 2 (optional)
│       └── model.pt
├── model_name_2/
│   ├── config.pbtxt
│   └── 1/
│       └── model.onnx
```

Jedes Modell benötigt:

1. Ein Verzeichnis mit dem Modellnamen
2. Eine `config.pbtxt` Konfigurationsdatei
3. Mindestens ein Versions-Unterverzeichnis (z. B., `1/`) mit der Modelldatei

***

## Schritt 4 — Ein PyTorch-Modell bereitstellen

### Modell zu TorchScript exportieren

```python
import torch
import torchvision

# Ein vortrainiertes ResNet50 laden
model = torchvision.models.resnet50(pretrained=True)
model.eval()

# Zu TorchScript exportieren
example_input = torch.randn(1, 3, 224, 224)
traced_model = torch.jit.trace(model, example_input)

# Speichern
traced_model.save("/tmp/resnet50.pt")
print("Modell erfolgreich exportiert")
```

### Model-Repository einrichten

```bash
# SSH in Ihre Clore.ai-Instanz
ssh root@<clore-host> -p <port>

# Verzeichnisstruktur erstellen
mkdir -p /models/resnet50/1

# Modell hochladen
# (von Ihrem lokalen Rechner)
scp -P <port> /tmp/resnet50.pt root@<clore-host>:/models/resnet50/1/model.pt
```

### config.pbtxt erstellen

```bash
cat > /models/resnet50/config.pbtxt << 'EOF'
name: "resnet50"
platform: "pytorch_libtorch"
max_batch_size: 32

input [
  {
    name: "input__0"
    data_type: TYPE_FP32
    dims: [3, 224, 224]
  }
]

output [
  {
    name: "output__0"
    data_type: TYPE_FP32
    dims: [1000]
  }
]

dynamic_batching {
  preferred_batch_size: [8, 16, 32]
  max_queue_delay_microseconds: 100
}

instance_group [
  {
    count: 2
    kind: KIND_GPU
    gpus: [0]
  }
]
EOF
```

***

## Schritt 5 — Ein ONNX-Modell bereitstellen

### In ONNX exportieren

```python
import torch
import torchvision
import torch.onnx

model = torchvision.models.resnet50(pretrained=True)
model.eval()

dummy_input = torch.randn(1, 3, 224, 224)

torch.onnx.export(
    model,
    dummy_input,
    "/tmp/resnet50.onnx",
    opset_version=13,
    input_names=["images"],
    output_names=["logits"],
    dynamic_axes={
        "images": {0: "batch_size"},
        "logits": {0: "batch_size"}
    }
)
```

### ONNX-Konfiguration

```bash
mkdir -p /models/resnet50_onnx/1
scp -P <port> /tmp/resnet50.onnx root@<clore-host>:/models/resnet50_onnx/1/model.onnx

cat > /models/resnet50_onnx/config.pbtxt << 'EOF'
name: "resnet50_onnx"
platform: "onnxruntime_onnx"
max_batch_size: 32

input [
  {
    name: "images"
    data_type: TYPE_FP32
    dims: [3, 224, 224]
  }
]

output [
  {
    name: "logits"
    data_type: TYPE_FP32
    dims: [1000]
  }
]

dynamic_batching {
  preferred_batch_size: [8, 16, 32]
  max_queue_delay_microseconds: 100
}
EOF
```

***

## Schritt 6 — Ein Python-Custom-Backend bereitstellen

Für Modelle, die nicht in Standard-Backends passen (benutzerdefinierte Vorverarbeitung, Ensemble-Logik):

```bash
mkdir -p /models/custom_model/1

cat > /models/custom_model/1/model.py << 'EOF'
import triton_python_backend_utils as pb_utils
import numpy as np
import torch

class TritonPythonModel:
    def initialize(self, args):
        self.model = torch.nn.Linear(10, 5).cuda()
        self.model.eval()
    
    def execute(self, requests):
        responses = []
        for request in requests:
            input_tensor = pb_utils.get_input_tensor_by_name(request, "INPUT")
            input_np = input_tensor.as_numpy()
            
            with torch.no_grad():
                inp = torch.from_numpy(input_np).float().cuda()
                out = self.model(inp).cpu().numpy()
            
            output_tensor = pb_utils.Tensor("OUTPUT", out.astype(np.float32))
            responses.append(pb_utils.InferenceResponse(output_tensors=[output_tensor]))
        
        return responses
    
    def finalize(self):
        pass
EOF

cat > /models/custom_model/config.pbtxt << 'EOF'
name: "custom_model"
backend: "python"
max_batch_size: 64

input [
  {
    name: "INPUT"
    data_type: TYPE_FP32
    dims: [10]
  }
]

output [
  {
    name: "OUTPUT"
    data_type: TYPE_FP32
    dims: [5]
  }
]
EOF
```

***

## Schritt 7 — Triton starten und testen

### Triton Server starten

```bash
# Starten (wenn das Dockerfile-CMD verwendet wird, startet es automatisch)
tritonserver \
    --model-repository=/models \
    --http-port=8000 \
    --grpc-port=8001 \
    --metrics-port=8002 \
    --log-verbose=0 &

# Warten, bis der Server bereit ist
sleep 5
curl -s http://localhost:8000/v2/health/ready
# Erwartet: {"live": true}
```

### Verfügbare Modelle prüfen

```bash
curl http://<clore-host>:<public-8000>/v2/models
```

### Inferenz per HTTP ausführen

```python
import tritonclient.http as httpclient
import numpy as np

client = httpclient.InferenceServerClient(
    url="<clore-host>:<public-port-8000>",
    ssl=False
)

# Server-Gesundheit prüfen
print("Server bereit:", client.is_server_ready())
print("Modell bereit:", client.is_model_ready("resnet50_onnx"))

# Eingabe erstellen
image = np.random.rand(1, 3, 224, 224).astype(np.float32)
input_tensor = httpclient.InferInput("images", image.shape, "FP32")
input_tensor.set_data_from_numpy(image)

# Inferenz ausführen
outputs = [httpclient.InferRequestedOutput("logits")]
response = client.infer("resnet50_onnx", [input_tensor], outputs=outputs)

logits = response.as_numpy("logits")
predicted_class = np.argmax(logits[0])
print(f"Vorhergesagte Klasse: {predicted_class}")
```

### Inferenz per gRPC ausführen

```python
import tritonclient.grpc as grpcclient
import numpy as np

client = grpcclient.InferenceServerClient(
    url="<clore-host>:<public-port-8001>"
)

image = np.random.rand(1, 3, 224, 224).astype(np.float32)
input_tensor = grpcclient.InferInput("images", image.shape, "FP32")
input_tensor.set_data_from_numpy(image)

outputs = [grpcclient.InferRequestedOutput("logits")]
response = client.infer("resnet50_onnx", [input_tensor], outputs=outputs)

logits = response.as_numpy("logits")
print(f"Ausgabe-Shape: {logits.shape}")
```

***

## Überwachung mit Prometheus

Triton stellt Metriken auf Port 8002 bereit:

```bash
curl http://<clore-host>:<public-port-8002>/metrics
```

Wichtige Metriken:

```
# Inferenz-Durchsatz
nv_inference_request_success{model="resnet50_onnx", version="1"}
# Durchschnittliche Inferenzzeit
nv_inference_compute_infer_duration_us{model="resnet50_onnx", version="1"}
# GPU-Auslastung
nv_gpu_utilization{gpu_uuid="..."}
# GPU-Speicher
nv_gpu_memory_used_bytes{gpu_uuid="..."}
```

***

## Konfiguration des dynamischen Batchings

```protobuf
dynamic_batching {
  preferred_batch_size: [4, 8, 16, 32]
  max_queue_delay_microseconds: 5000
  preserve_ordering: true
  
  priority_levels: 3
  default_priority_level: 2
  default_queue_policy {
    timeout_action: REJECT
    default_timeout_microseconds: 10000
    allow_timeout_override: true
    max_queue_size: 100
  }
}
```

***

## Fehlerbehebung

### Modell-Ladefehler

```
Laden des Modells fehlgeschlagen: Modelldatei konnte nicht gefunden werden
```

**Lösung:** Prüfen Sie Verzeichnisstruktur und Berechtigungen:

```bash
ls -la /models/resnet50/1/
# Muss model.pt (PyTorch) oder model.onnx (ONNX) enthalten
chmod -R 755 /models/
```

### CUDA-Inkompatibilität

**Lösung:** Passen Sie die Triton-Image-Version an Ihren CUDA-Treiber an:

```bash
nvidia-smi  # CUDA-Version notieren
# Verwenden Sie passenden tritonserver-Tag, z. B. 23.10 für CUDA 12.2
```

### Port nicht erreichbar

**Lösung:** Vergewissern Sie sich, dass alle drei Ports (8000, 8001, 8002) in Clore.ai weitergeleitet werden. Testen Sie jeden:

```bash
curl http://<host>:<port>/v2/health/live
```

### OOM während des Modell-Ladens

**Lösung:** Reduzieren Sie die Instanzanzahl oder verwenden Sie CPU-Instanzen für einige Modelle:

```protobuf
instance_group [
  {
    count: 1       # Von Standardwert reduzieren
    kind: KIND_GPU
  }
]
```

***

## Kostenabschätzung

| GPU       | VRAM  | Geschätzter Preis | Durchsatz (ResNet50) |
| --------- | ----- | ----------------- | -------------------- |
| RTX 3080  | 10 GB | \~$0.10/Stunde    | \~500 Anfragen/Sek   |
| RTX 4090  | 24 GB | \~$0.35/Stunde    | \~1500 Anfragen/Sek  |
| A100 40GB | 40 GB | \~$0.80/Stunde    | \~3000 Anfragen/Sek  |
| H100      | 80 GB | \~$2.50/Stunde    | \~8000 Anfragen/Sek  |

***

## Nützliche Ressourcen

* [Triton GitHub](https://github.com/triton-inference-server/server)
* [NGC Container Registry](https://catalog.ngc.nvidia.com/orgs/nvidia/containers/tritonserver)
* [Triton-Client-Bibliotheken](https://github.com/triton-inference-server/client)
* [Triton Modellkonfigurations-Referenz](https://docs.nvidia.com/deeplearning/triton-inference-server/user-guide/docs/user_guide/model_configuration.html)
* [Triton Python Backend](https://github.com/triton-inference-server/python_backend)
* [Triton Performance Analyzer](https://github.com/triton-inference-server/client/blob/main/src/c%2B%2B/perf_analyzer/README.md)

***

## 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ße Modelle (70B+) | 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/mlops-and-bereitstellung/triton-inference-server.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.
