Self-Hosting

Debugging einer Performance-Regression bei einem selbst gehosteten LLM auf Legacy-Hardware

Ein Entwickler diagnostizierte eine schwere Verlangsamung eines Modells mit 125 Milliarden Parametern, das auf zwei Tesla P40 GPUs lief, und führte das Problem auf eine einzelne Codeänderung in der Inferenz-Engine zurück.

Illustration, die alte und neue Hardware vergleicht, mit Fokus auf Debugging
Für diesen Artikel erstellte Illustration

Automatisch aus dem englischen Original übersetzt.

Ein Entwickler, der ein großes Sprachmodell auf älterer Consumer-Hardware betreibt, erlebte einen plötzlichen Einbruch der Inferenzgeschwindigkeit, der eine Woche andauerte. Durch systematisches Ausschlussverfahren von Konfigurations- und Hardwareproblemen konnte er die Ursache auf eine spezifische Version der Open-Source-Engine Strata eingrenzen. Die Lösung ergab sich aus einem Community-Bug-Report, der eine einzelne Codezeile als Verantwortliche für die Regression identifizierte.

Was passiert ist

Das Setup umfasste einen EPYC 7302 Server mit 128 GB RAM und zwei für 403 $ gekaufte Tesla P40 Grafikkarten. Diese Karten basieren auf der Pascal-Architektur von 2016 und verfügen nicht über moderne Funktionen wie Tensor Cores. Trotz des Alters des Siliziums lief auf dem System Qwen3.8-Flash-Next, ein Mixture-of-Experts-Modell mit 125 Milliarden Parametern. Die Strata-Inferenz-Engine bewältigte dies, indem sie den Großteil der Expertengewichte im Videospeicher hielt und so eine Cache-Trefferquote von 99,9 % erreichte.

Eine Woche lang im Oktober dekodierten das System Text nur mit 17 bis 18 Tokens pro Sekunde. Dies war deutlich langsamer als die 23 Tokens pro Sekunde, die ein kleineres, dichtes Modell auf derselben Hardware erreichte. Es war auch langsamer als die Upstream-llama.cpp-Engine, die dieselben Gewichte nutzte. Der Entwickler verbrachte Tage damit, verschiedene Hypothesen zu testen, darunter die Änderung der Parallelisierungsstrategie, die Entfernung von Container-Overhead und die Anpassung der Batch-Größen. Keine dieser Änderungen verbesserte die Single-Stream-Dekodiergeschwindigkeit.

Der Durchbruch kam, als der Entwickler einen Bug-Report fand, der von einem anderen Nutzer im Strata-Projekttracker eingereicht worden war. Der Bericht stellte fest, dass Version 0.1.40.2 auf ähnlicher Pascal-Hardware mit halber Geschwindigkeit im Vergleich zu Version 0.1.40.0 lief. Der Maintainer hatte identifiziert, dass ein kürzlich durchgeführter Commit das __restrict__-Schlüsselwort von Aktivierungszeigern entfernt und eine Prefetch-Anweisung hinzugefügt hatte, die Pascal-Architekturen nicht mit Berechnungen überlappen können. Das Zurücksetzen auf Version 0.1.40.4, die den Fix enthielt, verdoppelte die Dekodiergeschwindigkeit auf über 35 Tokens pro Sekunde.

Wichtige Details

  • Die Hardware bestand aus zwei Tesla P40 GPUs mit Compute Capability 6.1 und ohne NVLink-Unterstützung.
  • Die Performance-Regression betraf die Strata-Versionen 0.1.40.2 und 0.1.40.3 und reduzierte die Geschwindigkeit von ~36 auf ~17 Tokens pro Sekunde.
  • Die Ursache war eine Codeänderung, die eine Prefetch-Anweisung einführte, die mit der Ausführungspipeline der Pascal-Architektur inkompatibel ist.
  • Das Community-Mitglied paulhothersall reichte Issue #1469 ein und stellte Benchmark-Daten bereit, die den problematischen Versionsbereich isolierten.
  • Der Maintainer Niko1221 pushte etwa 75 Minuten nach Meldung des Issues einen Fix, der das __restrict__-Schlüsselwort wiederherstellte.
  • Das Upgrade auf Version 0.1.44.1 bot einen zusätzlichen Geschwindigkeitszuwachs von 8 %, erforderte jedoch das Deaktivieren bestimmter Defaults, um konsistente Ausgaben sicherzustellen.

Hintergrund

Mixture-of-Experts-Modelle teilen ihre Parameter in mehrere Gruppen auf und aktivieren nur eine kleine Teilmenge für jedes generierte Token. Dies ermöglicht es Modellen mit hunderten Milliarden Parametern, auf Hardware mit begrenztem Speicher zu laufen, da nur die aktiven Experten schnell geladen werden müssen. Die Strata-Engine optimiert dies, indem sie einen großen Bereich von Experten im Host-RAM pinnt und häufig genutzte im GPU-Videospeicher cacht. Dies minimiert Datentransfers über den PCIe-Bus, der in Multi-GPU-Setups oft ein Engpass ist.

Das __restrict__-Schlüsselwort in C++ teilt dem Compiler mit, dass zwei Zeiger nicht auf überlappende Speicherbereiche zeigen. Dies ermöglicht es dem Compiler, effizienteren Maschinencode zu generieren, indem unnötige Speicherneuladungen vermieden werden. Wenn dieser Hinweis entfernt wird oder wenn unangemessene Prefetch-Anweisungen hinzugefügt werden, kann die CPU oder GPU während des Wartens auf Daten blockieren, insbesondere auf älteren Architekturen, denen fortgeschrittene Out-of-Order-Execution-Fähigkeiten fehlen. Deshalb betraf der Bug nur ältere Pascal-Karten und nicht neuere Hardware.

Warum es wichtig ist

Für Teams, die selbst gehostete KI-Infrastruktur betreiben, unterstreicht dieser Fall die Bedeutung des engen Monitorings von Softwareversionen. Performance-Regressionen können auftreten, ohne dass lokale Konfigurationen oder Hardware geändert wurden. In diesem Fall wurde die Verlangsamung durch ein Upstream-Update verursacht, das versehentlich die Kompatibilität mit älterer, aber noch weit verbreiteter Hardware brach. Ohne sorgfältige Versionsnachverfolgung können solche Probleme zu verschwendeter Ingenieurszeit führen, die für das Debuggen nicht existierender lokaler Probleme aufgewendet wird.

Es demonstriert auch den Wert community-getriebener Open-Source-Projekte. Der Bug wurde schnell gefunden und behoben, weil Nutzer detaillierte Benchmark-Daten teilten. Für Organisationen, die auf Nischen- oder Legacy-Hardware angewiesen sind, kann die Interaktion mit Projekt-Issue-Trackern schnellere Lösungen bieten als interne Fehlerbehebungsversuche. Die Transparenz des Strata-Projekts ermöglichte es dem Entwickler, genau zu sehen, welcher Commit das Problem verursachte, was ein schnelles Rollback und eine Überprüfung ermöglichte.

Schließlich unterstreicht die Geschichte, dass die reine Token-Generierungsgeschwindigkeit nicht die einzige relevante Metrik ist. Selbst nach Verdopplung der Geschwindigkeit können lange "Thinking"-Phasen in komplexen Modellen zu erheblicher Latenz führen, bevor Text erscheint. Teams müssen die Engine-Optimierung mit dem Modellverhalten abwägen, um die Erwartungen an die Benutzererfahrung zu erfüllen.

Was Sie tun können

  • Prüfen Sie die Issue-Tracker Ihrer Kernabhängigkeiten bei unerklärlichen Leistungseinbrüchen, auch wenn Ihre Konfiguration unverändert geblieben ist.
  • Pinnten Sie in Produktionsumgebungen spezifische Versionen von Inferenz-Engines, um unerwartete Regressionen durch automatische Updates zu verhindern.
  • Vergleichen Sie Ihre Benchmark-Ergebnisse mit öffentlichen Berichten anderer Nutzer mit ähnlicher Hardware, um festzustellen, ob ein Problem weit verbreitet ist.
  • Testen Sie neue Engine-Versionen mit konstant gehaltenen Standardeinstellungen, um Leistungsänderungen von Verhaltensänderungen im Modell zu isolieren.
  • Verwenden Sie Overrides pro Anfrage für Tuning-Parameter wie Draft-Token-Gates, um Verbesserungen zu testen, ohne den gesamten Dienst neu starten zu müssen.
  • Halten Sie einen Rollback-Plan bereit, z. B. durch Aufbewahrung vorheriger Docker-Images, um schnell zu einem bekannten guten Zustand zurückkehren zu können, falls ein Update fehlschlägt.

Weitere News

Alle News