Strix Halo AI Benchmarks
gfx1151closed-sourceOpenAI-kompatible API

Halogen auf Strix Halo

Halogen ist eine proprietäre Inferenz-Engine von peonist-ai, gebaut für gfx1151. Auf dem Ryzen AI Max+ 395 liegt sie beim Prefill klar vor llama.cpp — beim Decode nur knapp. Und sie unterstützt genau ein Sprachmodell. Seit 0.12.3 hat sie bei gleichen Messbedingungen um rund 50 % zugelegt: 2145 t/s Prefill und 66,3 t/s Decode bei 16k Prompt unter 0.18.19. Diese Seite sortiert, was davon für den eigenen Betrieb zählt: gemessene Zahlen, die Entwicklung über die Versionen, die Cache-Fixes, die Fallstricke und der Update-Ablauf.

Einordnung

Lohnt sich, wenn …

  • ✓Langer Kontext, viele Turns, Agenten-Fan-out
  • ✓Prefill-dominierte Workloads (große System-Prompts, Repo-Kontext)
  • ✓Lizenz muss kostenlos und kommerziell nutzbar sein

Lohnt sich nicht, wenn …

  • ✕Mehr als ein Modell nötig
  • ✕Offene Engine, selbst patchbar, nachvollziehbar
  • ✕Kurze Einzel-Chats mit kleinem Kontext

Steckbrief

Engine
Halogen (proprietär, closed-source)
Anbieter
peonist-ai
Image
ghcr.io/peonist-ai/halogen-flash-server
API
OpenAI-kompatible HTTP-API, läuft als Container
Checkpoint-Format
.hgn (eigenes Format); seit 0.11.6 zusätzlich K-Quant GGUF; seit 0.15 Checkpoint v2 (62,1 GiB) plus n-gram-Lookup-Table
Gemessen auf
Ryzen AI Max+ 395 · gfx1151 · 128 GB Unified Memory
Lizenz
  • ✓Perpetual-Lizenz, kostenlos
  • ✓kommerzielle Nutzung erlaubt
  • ✓keine Telemetrie
Unterstützte Modelle
  • ·Qwen3.8-Flash-Next

Mehr ist es nicht. Wer ein zweites Modell braucht, bleibt bei llama.cpp oder Ollama.

1

Leistung: Halogen gegen llama.cpp

Identische Prompts, identische Hardware, beide Engines direkt nacheinander gemessen. Absolute Zahlen hängen am Prompt — belastbar ist die Relation zwischen den Engines.
KennzahlKontextHalogenllama.cppFaktor
Prefill12k Tokens Prompt, Halogen 0.11.31.340 t/s413 t/s3,2×
DecodeToken-Ausgabe, Halogen 0.11.333,5 t/s26,1 t/s1,28×
Prefill · 12k Tokens Prompt, Halogen 0.11.3
Halogen
1.340 t/s
llama.cpp
413 t/s

Der eigentliche Gewinn. Agenten hängen am ersten Token — hier entscheidet sich, ob ein Turn mit langem System-Prompt Minuten oder Sekunden kostet.

Decode · Token-Ausgabe, Halogen 0.11.3
Halogen
33,5 t/s
llama.cpp
26,1 t/s

Spürbar, aber nicht dramatisch. Wer nur chattet, merkt davon wenig; der Unterschied summiert sich erst bei langen Antworten.

Qualität: 8 Testfragen, direkter Vergleich Halogen vs. llama.cpp — Ergebnis: Zeile für Zeile identisch. Die Schwächen, die auffallen, kommen vom Modell — nicht von der Quantisierung und nicht von der Engine. Halogen macht dasselbe Modell schneller, nicht besser.
2

Entwicklung: dieselbe Maschine, neuere Versionen

Gemessen nach PROFIL-v1 mit derselben UMA-Aufteilung (117 GiB), derselben TDP (120 W) und derselben kalibrierten Promptlänge (16 477 bzw. 16 478 Tokens). Kalter Prompt-Cache, 256 Ausgabe-Tokens, Median aus drei Läufen. Nur so sind Versionen gegeneinander haltbar.
Qwen3.8-Flash-Next unter Halogen, 16k Prompt
Version · Checkpoint · Messdatum

Quellen: halogen-0.12.3-maxtok16384.json (2026-09-21) · halogen-0.14.0-maxtok16384.json (2026-09-26) · halogen-0.17.3-v2.json (2026-10-09) · halogen-0.18.5-v2.json (2026-10-16) · halogen-0.18.7-v2.json (2026-10-17) · halogen-0.18.19-v2.json (2026-10-30)

Alle Protokolle mit Stufen 512 und 4096 stehen auf /benchmarks unter den Messläufen.
3

Prompt-Cache: der eigentliche Grund für die Updates

Die 0.11.x-Reihe war im Kern eine Cache-Serie, 0.13.3 und 0.16.1 haben nachgelegt. Wer Halogen nur für einzelne Prompts nutzt, braucht davon wenig. Wer Agenten mit mehreren langen, parallel laufenden Konversationen betreibt, für den war der Stand vor diesen Fixes nicht benutzbar.
0.11.3

Determinismus-Bug im Cache

Ein kalter Request lieferte nicht dasselbe Ergebnis wie derselbe Request mit deaktiviertem Cache.

Vorher

Bei temperature > 0 führte das zu plausibel klingenden Falschantworten. Nichts crasht, nichts loggt — die Antwort ist einfach still falsch.

Nachher

Cache-Pfad und Nicht-Cache-Pfad verhalten sich identisch.

0.11.5 + 0.11.7

Cache-Verdrängung bei parallelen Konversationen

Zwei lange parallele Konversationen und Fan-out-Muster (ein Eltern-Agent mit mehreren Kind-Agenten) passten nicht nebeneinander in den Cache.

Vorher

Bei jedem Turn wurde komplett neu geprefillt: 100 bis 160 Sekunden pro Turn. Eltern und Kinder warfen sich gegenseitig aus dem Cache.

Nachher

99 Prozent Cache-Treffer in denselben Szenarien.

0.13.3

Cache-Diebstahl bei gleichem System-Prompt

Mehrere Konversationen mit identischem System-Prompt griffen auf denselben Cache-Eintrag zu.

Vorher

Eine Konversation konnte den Cache-Eintrag einer anderen an sich ziehen, die dann wieder von vorn prefillen musste — typisch bei Agenten, die alle mit demselben Prompt starten.

Nachher

Jede Konversation behält ihren eigenen Eintrag.

0.16.1

Gemeinsamer System-Prompt bleibt warm

Bei vielen kurzen Konversationen wurde auch der gemeinsame System-Prompt immer wieder verdrängt.

Vorher

Jede neue Konversation zahlte den Prefill des System-Prompts erneut.

Nachher

Der Cache hält den gemeinsamen System-Prompt plus den letzten Stand je Konversation. HALOGEN_CACHE_EVICT=0 stellt das alte Verhalten her.

Versionshistorie. Kompakt, nach Bereichen sortiert — die vollständigen Changelog-Details liefert das Projekt selbst.
VersionBereichWas passierte
0.11.0Token-BudgetEngine reserviert selbst Antwortraum (thinking_answer_room) — entschärft das Problem mit den Denk-Tokens gegen max_tokens.
0.11.3CacheDeterminismus-Bug behoben (kalter Request ≠ Ergebnis mit deaktiviertem Cache).
0.11.5 + 0.11.7CacheCache-Verdrängung bei parallelen Konversationen und Fan-out behoben: von 100–160 s pro Turn auf 99 % Treffer.
0.11.6ModellformateLiest zusätzlich K-Quant GGUF, nicht nur das eigene .hgn-Format.
0.11.9SpeicherGTT-Leak behoben: 35 GiB blieben nach unsauberem Abbruch im Kernel hängen.
0.12.xSpeicherReserviert rund 20 GiB Host-RAM für eine n-gram-Lookup-Tabelle. Die alte Konfiguration mit HALOGEN_MAX_TOK=32768 geht damit nicht mehr auf (Fallstrick „refusing to pin“).
0.13.4AgentenLeere Agent-Turns behoben (HALOGEN_EOS_GUARD=0 = altes Verhalten); 0.13.5/0.13.6: Sessions brachen nach angekündigtem Tool-Call ohne Tool-Call ab.
0.14.0DecodeNeuer MTP-Draft-Head (Tiefe 2, HALOGEN_MTP_DEPTH). Gemessen: Decode 51,0 statt 43,5 t/s bei 16k Prompt gegen 0.12.3.
0.15.xCheckpointCheckpoint v2: 62,1 GiB gepinnt statt 68, dazu eine eigene n-gram-Lookup-Datei. Dazu Anthropic-Messages-API (/v1/messages).
0.16.xPrefill / NPUSchnellerer Prefill, Abbruch bei langem Prefill in ~1 s, erste NPU-Kleinmodelle (Embedding, Reranker, Moderation, Qwen3.5-2B) — opt-in über HALOGEN_NPU_MODELS.
0.17.0NPU / DecodeBildgenerierung auf der NPU (flux2-klein-4b, 256 oder 512 px, ~8 GB Host-RAM) neben dem Sprachmodell auf der GPU. Zwei parallele Konversationen spekulieren gemeinsam.
0.17.1–0.17.3Tools / DecodeTool-Call-Fixes (Schleife bei JSON-Schema mit Thinking, nullable Strings), schnellerer Decode, HALOGEN_MTP_DEPTH ist ungesetzt automatisch. Gemessen 0.17.3: 1908 t/s Prefill, 58,6 t/s Decode bei 16k.
0.18.3–0.18.5Decode / PrefillAntworten stoppen am zweiten End-of-Text-Token statt bis max_tokens weiterzulaufen, schnellerer Prefill, MTP-Kette bricht ab, sobald der Draft-Head unsicher ist, schnellere Strict-Tool-Calls (HALOGEN_GRAMMAR_DRAFT). Gemessen 0.18.5: 2024 t/s Prefill, 62,8 t/s Decode bei 16k.
0.18.6–0.18.7DecodeGesampelter Decode schneller (Draft-Head schlägt bis zu sieben statt drei Tokens vor, HALOGEN_SAMPLED_DEPTH/HALOGEN_SAMPLED_GATE = alt), Fix: kurze Antworten seit 0.18.5 langsamer (#186), HALOGEN_CHAT_TEMPLATE tauscht das Chat-Template. Gemessen 0.18.7: 1990 t/s Prefill, 63,9 t/s Decode bei 16k — gleichauf mit 0.18.5.
0.18.8–0.18.11Cache / DecodeLanger Verlauf behält seinen Prompt-Cache (HALOGEN_CACHE_EVICT=1 = alt), opt-in 8-bit-KV-Cache (HALOGEN_KV8), schnellerer Prefill, drei bis vier parallele Requests dekodieren gemeinsam (HALOGEN_SPEC_GROUP=0 = aus). Fixes: Endlosschleife im KV-Pool (#190), Zweit-GPU (#188), Grammar-Crash bei rekursivem Schema (#192).
0.18.12–0.18.19Prefill / Tools / StabilitätSchnellerer Prefill und Decode, kurze Requests starten während eines langen Prompts, ein NPU-Fehler reißt den Server nicht mehr mit, Answer-Guard gegen Abbruch in Codeblöcken, Tool-Call-Argumente mit Markup kommen vollständig an (#209, #216, #221), Claude-Code-Sessions behalten den Prompt-Cache beim Nachladen von Tools, ggml-orgs offizielles GGUF lädt (#217). 0.18.15 (Auto-Keep) hier übersprungen. Gemessen 0.18.19: 2145 t/s Prefill, 66,3 t/s Decode bei 16k.
4

Fallstricke im Alltag

Die ersten fünf kosten beim Aufsetzen Zeit, die letzten vier im Dauerbetrieb und beim Update. Alle sind reproduzierbar, keiner ist ein Hardware-Problem der APU.
blockierend

KV-Pool kleiner als Kontext

Der Container beendet sich beim Start mit Exit 1. Ohne Meldung, was genau fehlt.

Damit umgehen

HALOGEN_KV_POOL_POSITIONS muss größer oder gleich HALOGEN_CTX sein. Beide Werte gehören zusammen geprüft, bevor der Start überhaupt Sinn ergibt.

tückisch

Denk-Tokens fressen das Antwortbudget

Standard-reasoning_effort ist xhigh. Die Denk-Tokens zählen gegen max_tokens — ohne chat_template_kwargs kommt leerer Content zurück.

Damit umgehen

Entweder reasoning_effort explizit setzen und max_tokens großzügig bemessen, oder ab 0.11.0 auf thinking_answer_room verlassen: die Engine reserviert den Antwortraum selbst.

tückisch

localhost löst auf IPv6 auf

Clients bekommen Connection error. Auf vielen Distributionen löst localhost nur auf ::1 auf, die Engine lauscht aber auf IPv4.

Damit umgehen

In Client-Konfigurationen 127.0.0.1 statt localhost schreiben. Kostet eine Zeile Konfiguration und spart die halbe Stunde Fehlersuche.

wissenswert

Das model-Feld wird ignoriert

Beliebige Werte im model-Feld des Requests funktionieren kommentarlos. Der Client glaubt, mit einem anderen Modell zu reden.

Damit umgehen

Nicht als Modell-Weiche missbrauchen wollen. Was geliefert wird, steht in der Server-Konfiguration, nicht im Request.

blockierend

Kein Parallelbetrieb mit llama.cpp

Halogen und llama.cpp schließen sich gegenseitig aus, wenn beide denselben Port und den Grafikspeicher beanspruchen.

Damit umgehen

Umsteigen heißt abschalten. Ein Side-by-Side-A/B über beide Engines hinweg erfordert getrennte Ports und genug Speicher für beide — oder zwei Startvorgänge nacheinander.

blockierend

podman stop tötet zu früh

Nach einem Update startet der neue Container nicht: „Address already in use“. Der Rollback scheitert anschließend an „container state improper“.

Damit umgehen

podman stop wartet standardmäßig nur 10 s, Halogen braucht zum Freigeben der gepinnten Gewichte länger. Mit stop -t 120 stoppen und vor dem Neustart aktiv prüfen, dass der Port wirklich frei ist (ss), nicht nur der Containerstatus.

blockierend

„checkpoint: refusing to pin“ nach Update

Ab 0.12 startet Halogen mit der bisherigen Konfiguration nicht mehr oder läuft knapp an der Speichergrenze.

Damit umgehen

Die n-gram-Lookup-Tabelle braucht eigenen Host-RAM. HALOGEN_MAX_TOK von 32768 auf 16384 senken — gemessen ohne Verlust (Prefill 1404 t/s bei 16k). Dauerkonfiguration ins Startskript, nicht in eine Update-Variable, sonst geht sie beim nächsten Update verloren.

tückisch

Lange Prompts kriechen, Platte ist busy

Prefill bei langen Prompts bricht ein, die NVMe zeigt Dauerlast, obwohl das Modell geladen ist.

Damit umgehen

Die Lookup-Tabelle liegt im Page-Cache und konkurriert mit dem BIOS-Carve-out der iGPU. Laut Halogen-README das Carve-out im BIOS auf das explizite Minimum stellen, nicht auf Auto.

tückisch

Benchmark misst den Cache statt des Prefills

Der zweite und dritte Lauf desselben Prompts sind um Größenordnungen schneller als der erste.

Damit umgehen

Halogens Prompt-Cache holt den gespeicherten Zustand zurück. Für Prefill-Messungen jedem Lauf eine eindeutige Kennung voranstellen (strix-bench macht das selbst), sonst misst man das Zurückholen eines Zustands.

5

Betrieb: Update im laufenden Betrieb

Der Update-Weg ist konventionell: Image ziehen, den alten Container behalten statt löschen, den neuen davorsetzen, prüfen, notfalls zurück. Gemessene Downtime: 12 bis 26 Sekunden. Der Image-Pull von 4,5 Minuten läuft vorher durch und unterbricht den laufenden Dienst dabei nicht.
  1. 1
    Neues Image ziehen

    Läuft 4,5 Minuten, ohne den laufenden Container zu stören.

  2. 2
    Alten Container parken statt löschen

    Hält den Rollback verfügbar, bis der neue bewiesen ist.

  3. 3
    Neuen Container starten

    /health antwortet — Version, Slots, Pool-Größe und Kontext abgleichen.

  4. 4
    Echten Completion-Request absetzen

    Health allein reicht nicht. Es muss ein echter Prompt durch, der Content muss stimmen.

  5. 5
    Bei Fehlern zurückrollen

    Den geparkten Container wieder starten, Problem am neuen Image suchen.

KennzahlWertKontext
Downtime beim Rolling-Update12–26 sGemessen von altem Container weg bis neuer Container bedienbar, inklusive Smoke-Test. 26 s bei den ersten Updates, 12 s beim Update auf 0.17.3.
Image-Pull4,5 minLäuft parallel zum laufenden Betrieb, unterbricht nichts.
Health-Endpunkt/healthLiefert Version, Slots, Pool-Größe und Kontext.
Alle Werte gemessen auf Ryzen AI Max+ 395 · gfx1151 · 128 GB Unified Memory · Vergleich gegen llama.cpp mit identischen Prompts