dist: prefill HTP corrigé (SSM_CONV gate backend), JNI option C sans OPFILTER

Fix intégré dans libggml-hexagon.so (ql e872623): ggml_hexagon_supported_ssm_conv route le
conv1d multi-token (prefill) sur ggml-cpu (le kernel HTP est faux multi-token pour d_inner
1024/2048). Plus besoin de GGML_HEXAGON_OPFILTER -> retiré du JNI. Validé: oracle SSM_CONV 18/18,
cli -dev HTP0 cohérent, multi-tour cohérent+mémoire, prefill HTP 110-180 t/s. libggml-hexagon.so
rafraîchi. Rebuild requis avant ship: libggml-hexagon.so + libkazeia_engine.so. Docs MAJ.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Richard Loyer 2026-05-27 10:39:08 +02:00
parent 2c89ec01a2
commit 2699b631a3
6 changed files with 25 additions and 22 deletions

16
dist/HANDOFF.md vendored
View File

@ -28,13 +28,15 @@ Le JNI implémente **C** (prefill HTP / decode CPU), validé multi-tour (`jni/du
(40%, idem à d=512). Le déquant KV en flash-attn coûte plus que le BW épargné. `type_k/v`
repassé en `GGML_TYPE_F16`. → **rebuild `libkazeia_engine.so` avant de shipper** (le .so livré
contient encore l'ancien q8_0). q8_0 seulement si OOM KV en très long contexte.
2. **Prefill HTP : RÉCUPÉRABLE via `GGML_HEXAGON_OPFILTER=SSM_CONV`.** Cause du charabia localisée :
**une seule op, SSM_CONV (conv1d), est cassée sur HTP en multi-token (prefill) pour d_inner=1024/2048**
(oracle FAIL ERR~1.3 ; decode n=1 OK ; bug côté backend hexagon, pas le calcul — les 2 chemins HTP
échouent, ggml-cpu est correct). En forçant cette op sur CPU (`OPFILTER=SSM_CONV`), le reste du prefill
tourne sur HTP et la **sortie redevient cohérente** : « Je comprends que cette rumination nocturne… ».
Mesuré : **prefill HTP 181 t/s** (×13 vs CPU 14) avec sortie correcte. Trois options d'intégration :
- **A (livrée) CPU-only** : prefill 14, decode 10.9, 2.4 GB. Simple.
2. **Prefill HTP : CORRIGÉ (fix intégré au backend).** Cause du charabia localisée à **une seule op,
SSM_CONV (conv1d), cassée sur HTP en multi-token (prefill) pour certains d_inner (1024/2048 ; 1536 OK)**
— bug données/marshalling côté DSP (HVX ET scalaire HTP faux, ggml-cpu correct), non localisé à la ligne.
**Fix livré dans `libggml-hexagon.so`** (`ggml_hexagon_supported_ssm_conv` : `n_t>1 → CPU`) : le conv1d
prefill tourne sur ggml-cpu (correct, bon marché), le reste du prefill sur HTP, decode conv sur HTP (n_t=1).
Plus besoin de `OPFILTER`. Validé : oracle SSM_CONV 18/18, cli `-dev HTP0` cohérent, multi-tour cohérent+mémoire.
Mesuré : **prefill HTP 110-180 t/s** (×8-13 vs CPU 14), sortie correcte. → **rebuild `libggml-hexagon.so`
+ `libkazeia_engine.so` avant ship.** Trois options (le JNI implémente C) :
- **A CPU-only** : prefill 14, decode 10.9, 2.4 GB. Simple.
- **B mono-contexte HTP + OPFILTER** : prefill **181**, decode HTP **6.4**, 2.4 GB (+ION). Gros gain prefill,
decode + lent, aucune RAM en plus, peu de code (ngl99 + env). **Recommandé** pour prompts longs/multi-tour.
- **C dual-contexte (prefill HTP+OPFILTER → transfert KV → decode CPU)** : prefill 181, decode **10.9**,

14
dist/PERF.md vendored
View File

@ -9,13 +9,13 @@ Decode optimum = **t4 / fa1 / KV f16** (PAS t8 : contention ; PAS KV q8_0 : déq
| Qwen3.5-9B | — | — | ~4-5 | 5.0 |
Notes :
- **PREFILL HTP charabia = 1 op cassée, SSM_CONV (conv1d), RÉCUPÉRABLE.** Localisé 27/05 : SSM_CONV sur HTP
est faux en multi-token (prefill) pour d_inner=1024/2048 (oracle FAIL ERR~1.3 ; decode n=1 OK ; bug backend
hexagon, pas le calcul — HVX ET scalaire HTP échouent, ggml-cpu correct). Fix immédiat = `GGML_HEXAGON_OPFILTER=SSM_CONV`
(route conv sur CPU, reste sur HTP) → **prefill HTP 181 t/s + sortie cohérente** (« Je comprends que cette
rumination… »), ×13 vs CPU 14. 3 configs : A CPU-only (14/10.9, livrée), B mono-ctx HTP+OPFILTER (181/6.4),
C dual-ctx prefill-HTP/decode-CPU (181/10.9, +2.3GB). cf HANDOFF.md décision 2. Dense sur HTP crashe (0x2e).
TODO: corriger SSM_CONV HTP (gate test-backend-ops -o SSM_CONV = 45/45) → supprime l'OPFILTER.
- **PREFILL HTP charabia = 1 op cassée (SSM_CONV conv1d), CORRIGÉ.** Localisé 27/05 : SSM_CONV sur HTP faux
en multi-token (prefill) pour d_inner=1024/2048 (1536 OK ; bug données/marshalling DSP, HVX+scalaire HTP faux,
ggml-cpu correct, non localisé). **Fix intégré au backend** `ggml_hexagon_supported_ssm_conv` (n_t>1 → CPU) :
conv1d prefill sur ggml-cpu (correct, bon marché), reste sur HTP, decode conv HTP (n_t=1). Plus d'OPFILTER.
Validé : oracle SSM_CONV 18/18, cli -dev HTP0 cohérent, multi-tour cohérent+mémoire. **prefill HTP 110-180 t/s**
(×8-13 vs CPU 14). Le JNI = option C (prefill HTP→transfert KV→decode CPU). Dense sur HTP crashe (0x2e, distinct).
TODO bas-ROI : réparer le kernel SSM_CONV HTP multi-token (gate cas multi-token) pour mettre le conv aussi sur HTP.
- **KV f16 ≫ q8_0 au decode** : q35-lmq4 f16=10.9 vs q8_0=6.5 (40%, idem à d=512). → JNI `type_k/v=F16`.
- **GDN-compute n'est PAS le goulot prefill** (débit) : serial f32 / fp16 / WY = même pp512. Piste kernel GDN close.
- NPU≈CPU au decode (GEMV M=1 latency-bound). RAM = GGUF mmap + ~3.3 GB ION/session.

8
dist/STATUS.md vendored
View File

@ -5,10 +5,10 @@ thinking-off déterministe. Modèle tranché = `q35-lmq4` (éval qualité ../eva
Perf : prefill clos côté kernel GDN (pas le goulot), decode au plafond CPU.
LIMITES / OUVERT :
1. **Prefill HTP RÉCUPÉRABLE** (27/05) : charabia causé par 1 op, SSM_CONV (conv1d), cassée sur HTP en
prefill. Fix = `GGML_HEXAGON_OPFILTER=SSM_CONV` → prefill HTP 181 t/s cohérent (×13). Config livrée = CPU-only
(A) ; B = mono-ctx HTP+OPFILTER (181/decode 6.4) ; C = dual-ctx (181/decode 10.9, +2.3GB). cf HANDOFF.md déc.2.
TODO backend : corriger SSM_CONV HTP (oracle test-backend-ops -o SSM_CONV).
1. **Prefill HTP CORRIGÉ** (27/05) : charabia = 1 op (SSM_CONV conv1d) cassée sur HTP en multi-token. Fix
intégré au backend (`libggml-hexagon.so` : supported_ssm_conv n_t>1→CPU). Plus d'OPFILTER. Prefill HTP
110-180 t/s cohérent. JNI = option C (prefill HTP→transfert KV→decode CPU), validé multi-tour. **Rebuild
libggml-hexagon.so + libkazeia_engine.so avant ship.** Options A/B/C dans HANDOFF.md déc.2.
2. **KV = f16 (résolu, JNI corrigé)** : f16=10.9 vs q8_0=6.5 au decode. Rebuild .so requis (livré=q8_0).
3. `generate()` applique déjà ChatML + thinking-off. App fournit `sys`/`usr` (voir system_fr.txt).
4. TTS Talker GGUF chargeable mais **audio e2e non validé** (= intégration app).

View File

@ -28,9 +28,10 @@ static llama_context* make_ctx(llama_model* m, int nctx, int nthreads) {
extern "C" JNIEXPORT jlong JNICALL
Java_com_kazeia_llm_EngineJni_load(JNIEnv* e, jobject, jstring path, jint nctx) {
const char* p = e->GetStringUTFChars(path, 0);
// Doit être posé AVANT l'init du backend hexagon (lu au registre).
setenv("GGML_HEXAGON_GDN_PREFILL", "1", 1); // GDN prefill sur HTP
setenv("GGML_HEXAGON_OPFILTER", "SSM_CONV", 1); // conv1d HTP cassé en prefill -> sur CPU
// Posé AVANT l'init du backend hexagon (lu au registre). GDN prefill sur HTP.
// (Plus besoin de GGML_HEXAGON_OPFILTER=SSM_CONV : le fallback CPU multi-token du conv1d
// est désormais intégré dans le backend, ggml_hexagon_supported_ssm_conv n_t>1.)
setenv("GGML_HEXAGON_GDN_PREFILL", "1", 1);
llama_backend_init();
// device HTP0 explicite pour l'instance prefill

Binary file not shown.

2
ql

@ -1 +1 @@
Subproject commit 50e250d7bce09f3cf312c1f4eb97f62f17ce1acd
Subproject commit e87262370078f3d7213993773fdbc95945b32076