4.2 KiB
Chantier — matmul HMX robuste pour le DENSE sur HTP (crash 0x2e)
Objet : faire tourner le dense (qwen3) sur HTP en HMX (prefill ~295) au lieu de HVX (~40), maintenant
que le .pte est retiré (l'engine est le seul runtime LLM). Bloqueur = crash du matmul HMX sur le dense.
Symptôme
Prefill dense (qwen3-4B Q4_0) sur HTP avec HMX (défaut) → ggml-hex: dspqueue_read failed: 0x0000002e
dans flush_pending → llama_decode, dès que le prompt dépasse ~12-16 tokens. HVX (GGML_HEXAGON_USE_HMX=0)
ne crashe pas. La 3.5 (hybride) ne crashe pas en HMX.
Repro
GGML_HEXAGON_OPLOG=1 GGML_HEXAGON_OPBATCH=1 LD_LIBRARY_PATH=./lib ADSP_LIBRARY_PATH=./lib \
./llama-cli -m Qwen3-4B-Q4_0.gguf -ngl 99 -dev HTP0 -t 4 --reasoning off -cnv -st --temp 0 -n 2 \
-p 'un deux trois quatre cinq six sept huit neuf dix onze douze treize quatorze quinze seize'
Hypothèse ÉCARTÉE : overflow fp16
Le matmul fautif a une activation max-abs = 9.8 (mesuré via OPLOG s1_amax), très en-dessous de la plage
fp16 (65504). Ce n'est PAS un overflow. Confirmé : clamp ±65504 (conversion f32→f16) ET scaling activations
÷32 puis ÷256 (avec ×S en sortie) n'ont rien changé au crash. Donc ni l'entrée ni l'accumulateur fp16 ne débordent.
Localisation (via instrumentation, voir plus bas)
Dernier op avant le 0x2e = un MUL_MAT q4_0, juste après FLASH_ATTN_EXT :
KZOP MUL_MAT dst=[2560,38,1,1] src0=q4_0[4096,2560] src1=f32[4096,38] s1_amax=9.8 <- CRASHE
C'est l'o_proj (projection de sortie d'attention : in 4096 = 32 têtes×128, out 2560 = hidden), donc k=4096.
Les autres MUL_MAT du graphe ont k=2560 et passent (ffn gate/up [2560,4096], qkv [2560,1024]).
→ suspect : le chemin HMX pour k=4096 (n_dot_tiles = 4096/32 = 128). OPFILTER=MUL_MAT (matmuls→CPU)
supprime le crash, confirmant que c'est bien un MUL_MAT HMX.
Instrumentation — ce qui marche / ne marche pas sur ce device (non-rooté)
- ❌ FARF DSP : bloqué. Le watcher cherche
<process>.farfdans/vendor/lib/rfsa/adsp(lecture seule sans root).FARF(RUNTIME_HIGH)ne sort pas en logcat sans ce fichier.getenvne marche PAS côté skel DSP. - ❌ GGML_HEXAGON_VERBOSE : utilise
GGML_LOG_DEBUG, masqué par le cli. - ✅ OPLOG CPU-side (committé) :
enqueue_op(ggml-hexagon.cpp) logge enfprintf(stderr)chaque op (type, dims, type/dims src, max-abs activation f32), gaté parGGML_HEXAGON_OPLOG. Combiné àGGML_HEXAGON_OPBATCH=1(1 op par flush), le dernier KZOP avant le 0x2e = l'op fautive. - ℹ️ Build debug FARF dispo si besoin :
cmake -DHEXAGON_HTP_DEBUG=ONdans le sous-build htp-vNN → activeFARF_HIGH=1(logs par-matmul m/k/n), mais inutile ici faute de capture (root).
Prochaines étapes
- Isoler le k=4096 : reproduire le matmul seul, q4_0
[4096,2560] × f32[4096,38](k=4096, m=2560, n=38), via test-backend-ops (ajouter le cas) ou un petit harness typedual_ctx. Confirmer le crash hors modèle. Tester k=4096 avec n et m variés pour cerner si c'est k=4096 seul ou la combinaison. - Comparer k=4096 vs k=2560 dans
hmx_matmul_q_f32/core_dot_chunk_fp16(hmx-matmul-ops.c) :- le VTCM chunking
hmx_compute_chunks(taille des tuiles pour 128 dot-tiles vs 80), - la boucle k par blocs de 32 et le
range = 2048*k_block - 1(déborde-t-il un champ 16 bits cumulé ?), - le staging poids dequant (
dequantize_x4x2_weight_chunk_to_fp16_tiles) et la taillevec_dot_size = k*2(8192 o/row pour k=4096) vs le budget VTCM → débordement d'index/buffer probable à 128 dot-tiles.
- le VTCM chunking
- Fix : corriger le tiling/staging pour k=4096 (gate oracle = test-backend-ops -o MUL_MAT, mais ⚠ ce test a
des FAIL
CPU=nanPRÉ-EXISTANTS sur les petits q4_0 — comparer au baseline, ne pas s'y fier aveuglément). Fallback acceptable si le fix est trop lourd : gater le HMX pour k≥4096 → HVX (comme le gate SSM_CONV n_t>1).
État
Non-bloquant : le dense tourne déjà sur HTP en HVX (~40 prefill, stable, cohérent) via le routage
auto du JNI (USE_HMX=0 pour le dense). Ce chantier = optimisation (40→295). 3.5 intacte (HMX + option C).
Outils committés : OPLOG (GGML_HEXAGON_OPLOG, dormant par défaut).