Commit Graph

3 Commits

Author SHA1 Message Date
Richard Loyer 48c66c03e1 chantier F (CP HMX) : path sched livré, gain absent (overhead per-call)
cp_inference.h/.cpp : nouveau cp_load_with_backends + sched path dans
cp_forward_cached_step. KV cache aussi alloué sur backend buffer en mode sched
(no_alloc=true + ggml_backend_alloc_ctx_tensors_from_buft). Inputs (x, pos_ids,
mask) marqués ggml_set_input ; output ggml_set_output. Compute via sched_reset
+ alloc + tensor_set + sched_compute + tensor_get. Path legacy CPU pur (sans
sched) reste intact via détection s.sched.

tts_engine.cpp : KZTTS_CP_HTP=1 + KZTTS_CP_SCHED=1 active le path sched HMX.
KZTTS_CP_HTP=1 seul = poids HTP, compute CPU pur via opt_hostbuf=1 (baseline).

Mesures Pad3 (KZTTS_CP_CACHE=1, seed=42, 'Bonjour Kazeia') :
  CPU baseline                  : CP 111 ms/frame, RTF 2.95, N=33
  CP poids HTP, compute CPU     : CP 108 ms/frame, RTF 2.93, N=33  (~baseline)
  CP sched HMX (HTP-routé)      : CP 181 ms/frame, RTF 3.87, N=64  REGRESSION

GGML_SCHED_DEBUG=2 confirme que ~95% des MUL_MAT CP tombent bien sur HTP0
(blk.0.attn_q.weight : 360 HTP / 21 CPU). Donc HMX est techniquement actif.

Cause de la régression :
  - Overhead par sub-forward sched_reset + sched_alloc_graph + tensor_set/get
    × 15 sub-forwards par frame. ~5 ms/appel × 15 = 75 ms ajoutés par frame
    (cohérent avec 111 -> 181 ms).
  - N=64 vs N=33 = trajectoire talker diverge à cause des codes CP qui
    diffèrent (perte précision HMX f16 tile vs CPU NEON f32).

Pour livrer un gain CP HMX réel, il faudrait :
  - (a) ctx persistant entre sub-forwards (~refactor architectural)
  - (b) batcher les 15 sub-forwards en 1 graph autoregressif (~lourd)

Le path sched CP est laissé en opt-in (KZTTS_CP_SCHED=1, désactivé par défaut)
pour itérer dessus ultérieurement. KZTTS_CP_HTP=1 seul est neutre (~baseline).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-29 16:03:41 +02:00
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
Richard Loyer 930f3c8c1f chantier B TTS #11: libkazeia_tts.so + Kotlin wrapper, JNI validé bout-en-bout
Refactor: tts_engine.{h,cpp} = API publique de l'engine TTS (load une fois,
synthesize N fois, free). État load-once dans struct TtsEngine (talker
model+ctx, CPState, Decoder, KzTextTokenizer, fixtures + embeds spéciaux
+ role_proj pré-calculé). KV cache talker reset via llama_memory_clear
au début de chaque synthesize -> appels indépendants.

tts_pipeline.cpp devient un thin CLI dessus (refonte sans changement de
sortie : WAV md5 identique au pré-refactor sur 'Bonjour je m'appelle Kazeia').

JNI bridge: kazeia_tts_jni.cpp expose 3 fonctions :
  Java_com_kazeia_tts_TtsJni_nativeLoad / Synthesize / Free
Signatures alignées avec TtsEngine.kt (companion loadLibrary 'kazeia_tts').
Build: build_kazeia_tts.sh -> b-jni/libkazeia_tts.so (~900 KB).

Test_engine_2calls (sans JNI) : 3 synth sur même instance, KV reset OK,
2 appels identiques -> WAV md5 identique, appel 3 différent -> codes
différents.

Test_jni_tts (harness JNI sans VM Java) : dlopen libkazeia_tts.so, JNIEnv
mock minimal (GetStringUTFChars/Release + NewIntArray/SetIntArrayRegion),
appels load + 2 synth + free. WAV md5 identiques aux runs directs. exit=0.

Empreinte tablette mesurée: ~3.5 GB par instance (talker f32 1.6 GB + CP
f16 mixte 250 MB + decoder 325 MB + vocab Qwen3 vocab_only 50 MB + fixtures
text_embed/tp_* 1.2 GB). Une instance par process.

RTF stable autour de 3.0 (CPU 6t), inchangé vs avant refonte.

Reste sur la liste initiale : tuning sampling (itératif à l'oreille).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 21:54:21 +02:00