Kazeia-engine/dist/decoder_patches
Richard Loyer 9de6b76838 chantier BigVGAN HMX Phase 0+2a: audit + chaîne load HTP validée
PHASE 0 audit (PERF_ANALYSIS.md + cette commit):
  - BigVGAN = 95% du decoder (3.24s sur 3.36s), confirmé via KZTTS_DECODER_PROFILE=1
  - 26 conv1d (63.7 Gops) + 4 conv_transpose_1d (51.6 Gops) + 30 snake (0.4 Gops)
  - channels par block : 1024->1536->768->384->192->96->1
  - T_cur évolution : 124->992->4960->19840->59520
  - poids decoder TOUS en F16 déjà (110 MB F16 conv + 215 MB F32 snake α/β)
  - ggml_conv_1d = im2col + mul_mat en interne, le graphe expose déjà MUL_MAT
  - ggml-hexagon ql/ggml supporte : MUL_MAT (HMX fp16), UNARY (exp/silu/etc),
    SOFT_MAX, ROPE, ADD, MUL, NORM, PAD, etc.
    PAS supporté : IM2COL, CONV_1D, CONV_TRANSPOSE_1D, SIN
  - opt_hostbuf=1 default -> HTP buffer CPU-mappable via ION
  - budget RAM HTP session: 2 GB sur 3.5 GB plafond, ~1.5 GB marge

PHASE 2a (chaîne load HTP, sans gain HMX):
  - Refactor decoder.h + gguf_loader.cpp : load_with_backends(path, devs)
    crée le sched optionnellement (gated KZTTS_DECODER_SCHED).
  - tts_engine.cpp : KZTTS_DECODER_HTP=1 -> initialise backend HTP +
    backend CPU (sched), passe les deux à load_with_backends.
  - Mode KZTTS_DECODER_HTP=1 sans SCHED : poids 325 MB sur HTP, compute
    CPU pur lit via opt_hostbuf=1. WAV produit correct, ~baseline perf.
  - Mode SCHED=1 : sched créé mais sched_alloc_graph plante (buffer_id>=0)
    car les stages utilisent ggml_init(no_alloc=false) + memset, incompatible
    avec sched. Refactor stages requis pour activer.

Snapshots des modifs decoder dans dist/decoder_patches/ (le repo decoder
est externe /opt/Kazeia, fichiers untracked).

PHASE 2b à faire prochaine session (~1 session):
  - stage_bigvgan en pattern sched-friendly:
    * no_alloc=true + ggml_set_input/output
    * memset zeros -> ggml_pad_ext
    * precompute_snake host -> ggml_exp + ggml_div in-graph
    * sched_reset + alloc + tensor_set + compute + tensor_get
  - Cible: decoder 3.2s -> 0.5-0.8s (×4-6 sur MUL_MAT HMX)
  - Snake sin reste CPU (fallback sched), borné à 0.4 Gops/115 total

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-29 11:51:08 +02:00
..
README.md chantier BigVGAN HMX Phase 0+2a: audit + chaîne load HTP validée 2026-05-29 11:51:08 +02:00
decoder.cpp.snapshot chantier BigVGAN HMX Phase 0+2a: audit + chaîne load HTP validée 2026-05-29 11:51:08 +02:00
decoder.h.snapshot chantier BigVGAN HMX Phase 0+2a: audit + chaîne load HTP validée 2026-05-29 11:51:08 +02:00
gguf_loader.cpp.snapshot chantier BigVGAN HMX Phase 0+2a: audit + chaîne load HTP validée 2026-05-29 11:51:08 +02:00

README.md

Snapshots decoder /opt/Kazeia/kazeia-tts-decoder-ggml/src/

Le repo decoder est externe (mono-repo /opt/Kazeia, fichiers untracked en pratique). Ces snapshots gardent une trace des modifications apportées pour Phase 2 du chantier BigVGAN HMX.

Modifications par fichier

decoder.h

  • Ajout std::vector<ggml_backend_t> backends + ggml_backend_sched_t sched dans struct Decoder.
  • Ajout bool owns_backends pour la libération.
  • Nouvelle méthode load_with_backends(path, devs) : variante de load_with_buft qui prend une liste de backends et crée optionnellement un sched (gated par env KZTTS_DECODER_SCHED).
  • Nouvelle méthode compute_graph(ctx, gf, n_threads) qui dispatche vers sched_compute si sched actif, sinon ggml_graph_compute_with_ctx legacy.

gguf_loader.cpp

  • Impl de load_with_backends : alloue les poids sur le buft du backend[0] (HTP si présent) via load_with_buft. Sched créé seulement si KZTTS_DECODER_SCHED=1 (le sched complet nécessite refactor des stages).
  • Impl de compute_graph : sched path ou compute_with_ctx legacy.
  • unload() libère sched + backends si owns_backends.

decoder.cpp

  • Ajout du timing par stage dans Decoder::forward (gated par KZTTS_DECODER_PROFILE=1). Imprime quant/preconv/pretr/upsample/bigvgan.
  • (pas d'autres modifs structurelles : le refactor stage_bigvgan en pattern sched-friendly reste à faire dans la session suivante)

Modes de fonctionnement

Env Effet
(rien) path CPU pur historique, poids CPU buffer (default)
KZTTS_DECODER_HTP=1 poids alloués sur HTP buffer, compute CPU pur via opt_hostbuf=1 (HTP buffer CPU-mappable). Pas de gain HMX mais valide la chaîne.
KZTTS_DECODER_HTP=1 KZTTS_DECODER_SCHED=1 sched créé, mais stages encore en compute_with_ctx → assertion buffer_id >= 0 au premier compute. NE FONCTIONNE PAS sans refactor stages.

Reste à faire (Phase 2 session suivante)

Refactor de stage_bigvgan (et causal_conv1d_TC, apply_snake_TC, precompute_snake) pour le pattern sched :

  1. ggml_init(no_alloc=true) avec mem_size réduit (metadata only)
  2. ggml_set_input(input_tensor) sur l'input host
  3. ggml_set_output(output_tensor) sur l'output final
  4. Remplacer memset(zeros->data) + ggml_concat par ggml_pad_ext
  5. Remplacer precompute_snake host (exp, 1/x) par ops in-graph ggml_exp + ggml_div
  6. Wrapping sched_reset + sched_alloc_graph + ggml_backend_tensor_set(input) + sched_graph_compute + ggml_backend_tensor_get(output)

Snake sin n'est pas supporté HTP → sched fallback automatique vers CPU pour cette op. Le ping-pong est borné (snake = 0.4 Gops total sur 115).

Estimation : ~70 lignes propres, ~1 session focalisée. Cibles : decoder 3.2s → ~0.5-0.8s (gain ×4-6 réaliste avec HMX sur MUL_MAT).

Rebuild

cd /opt/Kazeia/kazeia-tts-decoder-ggml/build-android-engine && \
  make qwen3tts-decoder -j$(nproc)
# puis côté Kazeia-engine
cd /opt/Kazeia-engine/dist && ./build_tts_pipeline.sh