chantier: instrumentation crash dense-HTP-HMX + .pte retiré (engine seul runtime)
CHANTIER_HMX_DENSE.md: analyse + outils pour le crash matmul HMX dense. Finding: PAS un overflow fp16 (activation du matmul fautif = 9.8) — c'est un bug de tiling/buffer HMX pour k=4096 (o_proj après FLASH_ATTN_EXT). Localisé via OPLOG CPU-side (FARF DSP bloqué sans root). Étapes + repro documentés. HANDOFF: .pte retiré -> engine seul runtime LLM. Dense=HVX (40) sur l'engine; HMX (295)=ce chantier. dist/lib refreshé (libggml-hexagon.so avec OPLOG dormant, htp-v79 propre). ql -> 7d4cade. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
0407ac8b71
commit
5aa4457567
|
|
@ -0,0 +1,59 @@
|
|||
# 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>.farf` dans `/vendor/lib/rfsa/adsp` (lecture seule
|
||||
sans root). `FARF(RUNTIME_HIGH)` ne sort pas en logcat sans ce fichier. `getenv` ne 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 en `fprintf(stderr)` chaque op
|
||||
(type, dims, type/dims src, max-abs activation f32), gaté par `GGML_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=ON` dans le sous-build htp-vNN → active
|
||||
`FARF_HIGH=1` (logs par-matmul m/k/n), mais inutile ici faute de capture (root).
|
||||
|
||||
## Prochaines étapes
|
||||
1. **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 type `dual_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.
|
||||
2. **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 taille `vec_dot_size = k*2`
|
||||
(8192 o/row pour k=4096) vs le budget VTCM → débordement d'index/buffer probable à 128 dot-tiles.
|
||||
3. **Fix** : corriger le tiling/staging pour k=4096 (gate oracle = test-backend-ops -o MUL_MAT, mais ⚠ ce test a
|
||||
des FAIL `CPU=nan` PRÉ-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).
|
||||
|
|
@ -3,6 +3,10 @@
|
|||
Point d'entrée unique. Remplace le LLM ExecuTorch/Genie par llama.cpp (fork ql) + Hexagon.
|
||||
GGUF, pas de `.pte`. STT reste ORT-QAIRT (inchangé).
|
||||
|
||||
**`.pte` retiré (plus de pré-compilé) → l'engine est le SEUL runtime LLM.** Le dense (qwen3) tourne donc
|
||||
sur l'engine en **HVX** (~40 prefill, stable) ; le passer en **HMX** (~295) = chantier `CHANTIER_HMX_DENSE.md`
|
||||
(crash k=4096 localisé, non-bloquant). Le Speaker retenu (Qwen3.5 `q35-lmq4`) tourne en option C (HMX), inchangé.
|
||||
|
||||
## Générique : fait tourner N'IMPORTE QUEL LLM (détecté à l'archi, au `load`, les deux sur HTP)
|
||||
Le JNI lit `general.architecture` dans l'en-tête GGUF **avant l'init backend** (pour régler `USE_HMX`), puis route :
|
||||
- **Hybride GDN (qwen3.5 / qwen3next)** → **option C** : prefill HTP (**HMX on**) → transfert KV → decode CPU
|
||||
|
|
|
|||
Binary file not shown.
2
ql
2
ql
|
|
@ -1 +1 @@
|
|||
Subproject commit e87262370078f3d7213993773fdbc95945b32076
|
||||
Subproject commit 7d4caded58f8eb0d99035d7215647821e0feb1bf
|
||||
Loading…
Reference in New Issue