Kazeia-engine/dist/PERF_INFRA_TESTS.md

5.6 KiB
Raw Blame History

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 CPU↔HTP 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.