🧰Ökosystem: Compiler, Bibliotheken, Werkzeuge
Selbst geschriebene Kernels sind nur ein kleiner Teil der GPU-Welt. Meist ruft man hochoptimierte Bibliotheken auf – oder schreibt in Python. Und im Browser gibt es mit WebGPU sogar eine GPU-Schnittstelle zum Ausprobieren.
🏭Vom Quelltext zum GPU-Maschinencode
1nvcc -O3 -arch=sm_86 app.cu -o app
📚Bibliotheken
Lineare Algebra (BLAS), vor allem Matrixmultiplikation (GEMM) – nutzt Tensor Cores.
Bausteine für neuronale Netze: Faltungen, Attention, Normalisierung. Basis von PyTorch & Co.
Fourier-Transformation, Zufallszahlen, dünnbesetzte Matrizen.
C++-Algorithmen wie in der STL (sort, reduce, scan) bzw. Bausteine auf Block-/Warp-Ebene. Heute Teil der CUDA Core Compute Libraries (CCCL).
C++-Templates für eigene GEMM- und Faltungs-Kernels bis hinunter zu Tensor-Core-Befehlen.
Kollektive Kommunikation zwischen mehreren GPUs (All-Reduce …) über NVLink/InfiniBand.
Optimiert trainierte Modelle für schnelle Inferenz (Fusion, geringere Genauigkeit).
Python-basierte Sprache (von OpenAI) für eigene GPU-Kernels auf Block-Ebene; von PyTorch 2 (torch.compile) genutzt.
🐍GPU aus Python
PyTorch
Tensoren auf die GPU legen – Operationen rufen intern optimierte Kernels (cuBLAS, cuDNN) auf.
1import torch23dev = "cuda" if torch.cuda.is_available() else "cpu"4a = torch.randn(4096, 4096, device=dev)5b = torch.randn(4096, 4096, device=dev)6c = a @ b # Matrixmultiplikation über cuBLAS (ggf. Tensor Cores)7torch.cuda.synchronize() # Kernel-Starts sind asynchron – vor Zeitmessung warten8print(torch.cuda.get_device_name(0), torch.cuda.get_device_capability(0))
🔬Profiling und Fehlersuche
1nvidia-smi # GPUs, Treiber, Auslastung, Speicher, Prozesse2nvidia-smi --query-gpu=name,utilization.gpu,memory.used --format=csv -l 13nsys profile -o bericht ./app # Nsight Systems: Zeitleiste CPU/GPU, Kopien, Streams4ncu --set full -o kernel ./app # Nsight Compute: Detailanalyse je Kernel (Occupancy, Speicher, Warps)5compute-sanitizer ./app # Speicherfehler und Race Conditions finden
🐳Treiber, Toolkit, Container
nvidia-smi zeigt oben rechts „CUDA Version“ – das ist die höchste CUDA-Version, die der installierte Treiber unterstützt, nicht das installierte Toolkit. Das Toolkit (Compiler nvcc, Bibliotheken) zeigt nvcc --version. Ist die Laufzeit neuer als der Treiber, meldet CUDA „driver version is insufficient for CUDA runtime version“.nvidia/cuda:…-runtime oder -devel mit nvcc).1# Host: nur NVIDIA-Treiber + NVIDIA Container Toolkit (kein CUDA Toolkit nötig)2sudo nvidia-ctk runtime configure --runtime=docker3sudo systemctl restart docker45# Test: nvidia-smi im Container6docker run --rm --gpus all nvidia/cuda:12.4.1-base-ubuntu22.04 nvidia-smi7docker run --rm --gpus '"device=0"' mein-image # nur GPU 089# docker-compose.yml10# services:11# train:12# image: mein-image13# deploy:14# resources:15# reservations:16# devices:17# - driver: nvidia18# count: all19# capabilities: [gpu]
🌍CUDA im Vergleich
| CUDA | HIP / ROCm | OpenCL | SYCL | Metal | WebGPU (WGSL) | |
|---|---|---|---|---|---|---|
| Hersteller | NVIDIA | AMD (HIP auch auf NVIDIA) | herstellerübergreifend (Khronos) | herstellerübergreifend (Khronos) | Apple | Browser (W3C) |
| Thread | Thread | Thread | Work-Item | Work-Item | Thread | Invocation |
| Block | Block | Block | Work-Group | Work-Group | Threadgroup | Workgroup |
| Gleichschritt-Gruppe | Warp (32) | Wavefront (32 oder 64) | Sub-Group | Sub-Group | SIMD-Group | Subgroup (Erweiterung) |
| gemeinsamer Speicher | __shared__ | __shared__ (LDS) | __local | local_accessor | threadgroup | var<workgroup> |
| Barriere | __syncthreads() | __syncthreads() | barrier(…) | group_barrier(…) | threadgroup_barrier(…) | workgroupBarrier() |
Wavefront-Breite bei AMD: 64 bei GCN/CDNA, bei RDNA wahlweise 32 oder 64. HIP-Code lässt sich mit hipify weitgehend aus CUDA-Code erzeugen.
⚡Live: Compute-Shader im Browser (WebGPU)
1@group(0) @binding(0) var<storage, read_write> data: array<f32>;2@group(0) @binding(1) var<uniform> params: vec4<u32>; // x = n, y = Iterationen34@compute @workgroup_size(256) // 256 Invocations je Workgroup (≈ Block)5fn main(@builtin(global_invocation_id) gid: vec3<u32>) {6 let i = gid.x; // ≈ blockIdx.x * blockDim.x + threadIdx.x7 if (i >= params.x) { return; } // Wächter wie in CUDA8 var x = data[i];9 for (var k = 0u; k < params.y; k = k + 1u) {10 x = x * 0.999 + 0.001; // rechenlastige Schleife11 }12 data[i] = x;13}
WebGPU-Begriffe entsprechen CUDA: Invocation ≈ Thread, Workgroup ≈ Block, dispatchWorkgroups(x) ≈ Grid,var<workgroup> ≈ __shared__, workgroupBarrier() ≈ __syncthreads().