Kazeia-engine/dist/PERF_INFRA_TESTS.md

137 lines
5.6 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.

# Tests infra — où HTP/HMX échoue, et pourquoi (29/05)
Session de tests systématiques sur les hypothèses non-explorées du Phase 2b/F.
Verdict global : **le HTP n'est pas le bon outil pour notre TTS**, parce que
tous nos workloads sont des decodes batch=1 (talker, CP sub-forwards) ou des
matmul énormes (BigVGAN) au-delà de la limite backend `nrows > 1024`.
## A — Sched HMX vs HVX (USE_HMX=0)
Bench : CP + sched HTP, varier `GGML_HEXAGON_USE_HMX`.
| Config | CP/frame | N frames | RTF | WAV md5 |
|---|---:|---:|---:|---|
| Baseline CPU pur | 110 ms | 33 | 2.92 | unique |
| Sched HMX=1 | 226 ms | 64 | 4.48 | A2=A3 |
| Sched HMX=0 (HVX) | 180 ms | 64 | 3.81 | A2=A3 |
- HVX 20% plus rapide que HMX sur CP (tile 32×32 sous-utilisé à batch=1).
- HMX et HVX **produisent bit-exact le même WAV**.
- Les deux divergent du CPU baseline : N passe de 33 à 64 (le talker prend
une trajectoire différente parce que les codes CP ne sont plus bit-exact à NEON).
- Coût × 2 frames + overhead par-step = régression nette.
**Conclusion A** : HVX > HMX sur batch=1, mais aucun ne bat NEON.
## B — op_offload=false vs true
| Config | CP/frame |
|---|---:|
| HMX + op_offload=true | 216 ms |
| HMX + op_offload=false | 181 ms |
- Placement strict (false) = -16% sur CP. Moins de "magic" de placement adaptatif.
- Toujours plus lent que baseline CPU.
**Conclusion B** : `op_offload=false` est meilleur défaut. Quick win mais
ne sauve pas la régression.
## C — Profile fin par sub-step (KZTTS_CP_PROFILE)
Breakdown moyen d'un sub-forward (HVX) :
| Étape | Temps |
|---|---:|
| `sched_reset + sched_alloc_graph` | 0.1 ms |
| `ggml_backend_tensor_set` ×3 (x, pos_ids, mask) | 0.0 ms (< µs) |
| **`sched_graph_compute`** | **6-11 ms (croît avec pos_off)** |
| `ggml_backend_tensor_get` | 0.0 ms |
- **L'overhead sched est négligeable** : ~0.1 ms/step × 15 = 1.5 ms/frame.
Les copies CPUHTP sont gratuites (opt_hostbuf=1 = ION partagé).
- **Le compute lui-même domine** : 95% du temps.
- CPU NEON équivalent : ~7 ms/step, HVX 10 ms/step. HVX est intrinsèquement
**plus lent que NEON sur ces matmul batch=1**.
**Conclusion C MAJEURE** : ma hypothèse #1 (`sched_reserve` + ctx persistant)
est invalidée. L'overhead qu'on espérait éliminer n'existe pas le compute
HTP est juste plus lent que CPU pour notre workload.
## D — Talker en HTP option C
Pour vérifier si le pattern HTP-prefill / CPU-decode (validé pour Qwen3.5-4B)
marche sur Qwen3-TTS-Talker (0.6B).
| Métrique | CPU pur | HTP option C |
|---|---:|---:|
| Prefill | 87 ms | 185 ms (**+112%**) |
| Talker per-frame | 32 ms | 81 ms (**+154%**) |
| N frames | 33 | 18 |
- Le talker TTS (0.6B) **REGRESSE sévèrement** en HTP option C.
- Pour un petit modèle, l'overhead routing HTP par token (DMA, sync, sched
inter-backend) dépasse le gain compute.
- Le pattern option C ne marche bien que pour des modèles assez gros pour
amortir le routing (Qwen3.5-4B = OK ; Qwen3-TTS 0.6B = perte).
**Conclusion D** : le HTP n'apporte rien sur ce talker non plus.
## Verdict cumulé
Le HTP est non-rentable sur **tous** nos workloads TTS :
| Composant | Workload | HTP gain réel | Raison |
|---|---|---|---|
| BigVGAN | conv1d batch 60k | rejeté | limite backend `nrows > 1024` |
| CP sub-forwards | matmul batch=1 ou 2 | régresse | compute HVX < NEON à batch=1 |
| Talker decode | batch=1 | régresse | overhead routing > gain compute (0.6B) |
| Talker prefill | batch ~10-20 | ❌ régresse | trop petit pour amortir |
Le projet l'avait noté en partie dans CLAUDE.md :
> « CPU NEON bat le HVX 3.4× sur Q6_K M=1 »
> « decode CPU verrouillé (~16.5 tok/s), HTP perdant decode (~3.6 tok/s) »
Mais on n'avait pas tiré la conséquence globale : **notre TTS n'a pas de
workload "prefill HTP-friendly"**. Les phrases courtes (10-20 tokens) sont
juste assez courtes que le routing coûte plus que le gain.
## Vrais leviers restants (sans HTP)
Avec le HTP exclu, les optims réelles sont :
1. **Streaming pipeline** (1 session) — chevaucher talker / CP / decoder
par chunks. Le RTF total ne baisse pas mais le TTFB perçu passe de ~5 s
à ~500 ms. **Le seul gain UX significatif réaliste.**
2. **Réduction overhead CP CPU** (½ session) — réutiliser le ctx ggml entre
les 15 sub-forwards par frame. L'overhead par-step est petit (~5 ms
d'init/free × 15 = ~75 ms) mais réel. Estimé -10 à -15% sur CP CPU.
3. **Decoder : optim NEON conv1d** (R&D) — actuellement compute-bound à 95%
du plafond NEON. Pour gagner faut vectoriser plus agressivement ou
restructurer les conv1d en blocked matmul. Sujet R&D.
4. **Quantization plus agressive du CP** (½ session) — Q8 ou Q4 sur les
poids matmul. Note CLAUDE.md : « Q8_0 CP perdu (76% codes vs 100% f16) »
= qualité dégrade. Donc compromis qualité/perf à explorer.
## Ce qui est DÉJÀ committé qui marche
- `KZTTS_CP_HTP=1` (sans SCHED) : poids CP sur HTP buffer, compute CPU pur.
Neutre en perf, prouve que la chaîne marche.
- `KZTTS_DECODER_HTP=1` (sans SCHED) : idem decoder. Neutre.
- Phase 2b refactor stage_bigvgan_sched : code propre, désactivé par défaut.
- Phase F refactor cp_forward_cached_step sched-friendly : idem.
Tout ça est opt-in et n'affecte pas le path par défaut (RTF 3.0).
## Recommandation finale
Le ROI / risque dit clairement : **streaming pipeline (#1) est le seul vrai
gain accessible**. RTF<1 sur HTP demande de modifier le backend hexagon
(semaines), ce qui sort du scope.
Si Richard accepte RTF=3 mais TTFB=500 ms comme livrable acceptable, le
chemin est clair en 1-2 sessions. Sinon, le frontier kernel HVX BigVGAN
reste sur la table mais c'est un autre projet.