Kazeia-engine/RAPPORT_RD.md

44 lines
4.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Kazeia-Engine — Rapport R&D complet (24-25/05/2026)
Synthèse de toute la session. Matériel : OnePlus Pad3, SM8750 (Snapdragon 8 Elite, Hexagon V79), 16 GB, sans root. Mémoire LPDDR5x ~77 GB/s, CPU ~25. NDK r27d, Hexagon SDK 6.5.0.0.
## 1. Objectif
Faire tourner Qwen3.5-4B (et 9B) en GGUF, sans conversion `.pte`, en exploitant le NPU pour le prefill et le CPU pour le decode. Cible : égaler/battre ExecuTorch (4B `.pte` = 15 tok/s, 2.2 GB), empreinte mémoire mini.
## 2. Le fait dur (mesuré, reproductible)
Decode M=1 = **memory-bandwidth bound**, pas compute. Le NPU n'aide pas le decode (bus DDR saturé), il aide le prefill (batché, compute-bound). Donc : **prefill NPU / decode CPU**, verrouillé pour 4B et 9B.
## 3. Performances stables — MAJ 26/05, fork ql (qualcomm/llama.cpp), t4+fa decode
| Modèle | prefill (t8/b512) | decode (t4+fa) | RAM |
|---|---:|---:|---:|
| Qwen3.5-4B-Q4_0 | 93 | 8.5 | 2.4 GB |
| Qwen3.5-9B-Q4_0 | 70 | 5.7 | 5.0 GB |
| Qwen3-4B dense | 285 | 14 | 2.2 GB |
| 4B ExecuTorch .pte | ~451 | 15 | 3.3 GB |
Decode dense 4B = parité pte à RAM 30%. NPU 9.82=CPU 9.8 → 77GB/s injoignable (GEMV M=1 latency-bound, ~32 réel). t4=optimum, t8=contention (3.5 chute 2.3). Fork qualcomm DOUBLE le prefill (50→93, 103→285) + sortie FR cohérente. Anciens 9.8/50/t8 obsolètes. Leviers decode morts (mesurés): spec-decode négatif, IQ4_NL=même octets, fusion GDN compute-bound. >9 decode = kernel GDN-HMX frontière.
## 4. Cascade Thinker+Guard : RAM OK
9B+Guard-4B = 7.5 GB ; 9B+Guard-8B = 9.5 GB ; +TTS/STT → 11.5. Tient sur 16 GB. 9B>4B en qualité FR.
## 5. Engine vs briques
briques (stack NPU+lm_head CPU) : 2B 13, 4B 7, 9B 2.1 tok/s. **2B briques 13/2.5GB = sweet spot**, > engine 4B 9.8. Repo `/opt/Kazeia/to_delete/briques_qwen35`. Pour le 4B, `.pte` reste devant (15, 2.2GB). GGUF utile = 9B/modèles sans pte.
## 6. Intégration #277 (dev) — débloquée, 2 fixes
hang in-app = thinking non bridé + 1 thread. FIX : signature `generate(sys,usr,maxTok)`, ChatML+`<think></think>`, ngl0 + n_threads=8 → 14 tok/s. Bridge STATIC (0 NEEDED libllama, coexiste TTS). dist `/opt/Kazeia-engine/dist/` : libkazeia_engine.so + htp-v79.so + EngineLlmEngine.kt + docs.
## 7. R&D pousser prefill GDN — PISTE FERMÉE (26/05, mesuré)
Conclusion dure : **le calcul GDN n'est pas le goulot du prefill sur le fork ql**. A/B sur la même commande llama-bench (Qwen3.5-4B-Q4_0, pp512, ngl99/t8/b512, gate scalaire S_v=128) :
| Schéma GDN (HTP) | flops GDN | pp512 |
|---|---:|---:|
| serial f32 (vrai baseline) | 1× | **89.5** |
| serial fp16 (HVX 64-lane) | ~0.5× ALU | 89.65 |
| WY chunkwise | ~2.5× | 89.6 |
Trois schémas de calcul (0,5× / 1× / 2,5× flops) → pp512 **plat**. Si l'arithmétique GDN limitait, le 2,5× s'effondrerait et le 0,5× grimperait. Donc le mur prefill (~89,5) est **ailleurs** : matmuls denses / FFN MoE / attention / conv / overhead op-batch. Ça corrige la vieille prémisse « GDN = l'ancre » (vraie sur l'ancien tree GDN-CPU série, **fausse** sur le fork GDN-HTP). Le « 98 » d'avant était un fantôme de mesure ; vrai baseline = 89,5.
Corollaire : **aucune optim du kernel GDN** (chunkwise, HMX, fp16) ne peut bouger le prefill. HMX-per-tête en plus = NO-GO (matmuls 32×128 latency-bound ~12 µs, 28 têtes × 24 couches sérialisées sur le moteur HMX unique). Pour réellement pousser pp512 il faut profiler/attaquer les ops **non-GDN** sur HTP — autre chantier, et prefill = « utile pas vital ».
Artefacts (branche `ql` gdn-chunkwise-wy) : kernel fp16 serial validé (oracle 28/28, `hvx_vec_mpyacc_f32_f16`, état fp16 paddé-64, aucune dérive à 256 tok — le gate exp(g<0) borne), gardé derrière env `KZ_F16` (défaut OFF = baseline f32 inchangé) ; kernel WY chunkwise conservé inutilisé comme base d'un éventuel batch-têtes. `GGML_HEXAGON_OPFILTER` existe sur ce fork ; profiler `GGML_HEXAGON_PROFILE` masqué par llama-bench (sortie DEBUG).
## 8. À FAIRE : quantize 4B IQ4_NL on-device + bench, brancher JNI, valider qualité FR. STT reste ORT-QAIRT. Détail commits : `git log`.