> 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, Open-Source-Inferenzbereitstellungsplattform, die praktisch jedes große ML-Framework unterstützt. Triton wurde für Bereitstellung mit hohem Durchsatz und geringer Latenz entwickelt und unterstützt PyTorch, TensorFlow, ONNX, TensorRT, OpenVINO und mehr — alles aus einem einzigen Serverprozess. Setzen Sie es in der GPU-Cloud von Clore.ai für eine skalierbare, kosteneffiziente Inferenzinfrastruktur ein.

***

## Was ist der Triton Inference Server?

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

* **Mehrere Frameworks:** PyTorch, TensorFlow, TensorRT, ONNX, OpenVINO, benutzerdefinierte Python-Backends
* **Parallele Ausführung:** Mehrere Modelle, mehrere Instanzen pro GPU
* **Dynamisches Batching:** Anfragen automatisch zu Batches zusammenfassen für höheren Durchsatz
* **gRPC + HTTP:** Industrie-Standardprotokolle von Haus aus
* **Metriken:** Prometheus-kompatibler Metrik-Endpunkt
* **Modell-Repository:** Dateisystembasiertes Modellmanagement

**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-GPU 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 Workloads ohne CUDA. Verwenden Sie die `nur-CPU` Variante des Docker-Images, um bei Batch-Jobs ohne GPU-Bedarf Kosten zu sparen.
{% endhint %}

***

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

1. Melde dich an bei [clore.ai](https://clore.ai).
2. Klicken Sie auf **Marktplatz** und filtern Sie nach VRAM ≥ 16 GB.
3. Wählen Sie einen Server aus 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 den [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 auf **Mieten**.

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

***

## Schritt 2 — Benutzerdefinierte 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/*

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

# Python-Clientbibliothek installieren
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 — Das Modell-Repository verstehen

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

```
/models/
├── model_name_1/
│   ├── config.pbtxt          # Modellkonfiguration
│   ├── 1/                    # Version 1
│   │   └── model.pt          # Modelldatei
│   └── 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 in TorchScript exportieren

```python
import torch
import torchvision

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

# In 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")
```

### Modell-Repository einrichten

```bash
# Per SSH auf Ihre Clore.ai-Instanz zugreifen
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 benutzerdefiniertes Python-Backend bereitstellen

Für Modelle, die nicht zu standardmäßigen 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
# Start (wenn Sie das Dockerfile-CMD verwenden, 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 über HTTP ausführen

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

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

# Serverzustand 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)

# Führe Inferenz aus
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 über 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"Ausgabeform: {logits.shape}")
```

***

## Monitoring mit Prometheus

Triton stellt Metriken an Port 8002 bereit:

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

Wichtige Metriken:

```
# Inferenzdurchsatz
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 für dynamisches Batching

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

### Fehler beim Laden des Modells

```
Modell konnte nicht geladen werden: Modelldatei nicht gefunden
```

**Lösung:** Verzeichnisstruktur und Berechtigungen prüfen:

```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 ein passendes tritonserver-Tag, z. B. 23.10 für CUDA 12.2
```

### Port nicht erreichbar

**Lösung:** Überprüfen Sie, ob alle drei Ports (8000, 8001, 8002) in Clore.ai weitergeleitet sind. Testen Sie jeden:

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

### OOM während des Modellladens

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

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

***

## Kostenschätzung

| GPU       | VRAM  | Geschätzter Preis                         | Durchsatz (ResNet50) |
| --------- | ----- | ----------------------------------------- | -------------------- |
| RTX 3080  | 10 GB | $0,05–0,19/Std.                           | \~500 Anfragen/Sek.  |
| RTX 4090  | 24 GB | ca. 0,14–0,42 $/h                         | \~1500 Anfragen/Sek. |
| A100 40GB | 40 GB | [Bare Metal](https://clore.ai/bare-metal) | \~3000 Anfragen/Sek. |
| H100      | 80 GB | \~1,04 $/Std.                             | \~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-Referenz zur Modellkonfiguration](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-Leistungsanalysator](https://github.com/triton-inference-server/client/blob/main/src/c%2B%2B/perf_analyzer/README.md)

***

## GPU-Empfehlungen für Clore.ai

| Anwendungsfall       | Empfohlene GPU   | Geschätzte Kosten bei Clore.ai            |
| -------------------- | ---------------- | ----------------------------------------- |
| Entwicklung/Testen   | RTX 3090 (24 GB) | 0,07–0,21 $/GPU/Stunde                    |
| Produktionsinferenz  | RTX 4090 (24 GB) | 0,14–0,42 $/GPU/Stunde                    |
| Große Modelle (70B+) | A100 80GB        | [Bare Metal](https://clore.ai/bare-metal) |

> 💡 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, and the optional `goal` query parameter:

```
GET https://docs.clore.ai/guides/guides_v2-de/mlops-and-bereitstellung/triton-inference-server.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

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.
