dist: métriques vérifiées batterie pleine — KV f16 (pas q8_0), q35-lmq4 HTP=189
Reconfirmé device froid 90% (les chiffres throttlés d'hier soir étaient faux): - KV f16 >> q8_0 au decode: q35-lmq4 f16=10.9 vs q8_0=6.5 (-40%, idem d=512). Le déquant KV flash-attn coûte plus que le BW. JNI corrigé type_k/v=F16 (rebuild .so requis avant ship; le .so livré=q8_0 validé, inchangé). - q35-lmq4 prefill HTP=189 ~= 2x Qwen3.5-Q4_0 (98): embeds/output Q4 restent sur NPU vs Q6_K fallback CPU. Argument fort de plus pour q35-lmq4 (+5% decode ET ~2x prefill HTP). - decode sain: q35-lmq4 10.9, dense 11.7. prefill CPU JNI=14 (t4). Decision KV résolue; decision prefill CPU-only vs HTP ouverte (189 motive le câblage). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
fac50d69ce
commit
c9d4e625eb
|
|
@ -19,23 +19,24 @@ Config déjà correcte et alignée :
|
||||||
- API : `load(path,nCtx) → generate(h,sys,usr,maxTok) → reset(h) / free(h)`.
|
- API : `load(path,nCtx) → generate(h,sys,usr,maxTok) → reset(h) / free(h)`.
|
||||||
- **`n_gpu_layers = 0` → tout CPU** (pas de HTP). Choix après le ping-pong ngl99 (decode 0.2 t/s).
|
- **`n_gpu_layers = 0` → tout CPU** (pas de HTP). Choix après le ping-pong ngl99 (decode 0.2 t/s).
|
||||||
|
|
||||||
## ⚠ Les 2 décisions ouvertes (à toi, sur batterie pleine)
|
## Décisions (vérifiées 27/05, batterie 90%, device froid)
|
||||||
1. **Prefill : CPU-only vs HTP.** Le JNI est CPU-only → prefill ~18-19 t/s (sain). Le HTP fait
|
1. **KV = f16 (RÉSOLU, corrigé dans le JNI).** Mesuré : decode q35-lmq4 f16=**10.9** vs q8_0=**6.5**
|
||||||
89.5 t/s mais n'est PAS câblé (le ping-pong vient du mono-contexte ngl99 qui renvoie le
|
(−40%, idem à d=512). Le déquant KV en flash-attn coûte plus que le BW épargné. `type_k/v`
|
||||||
decode sur NPU). Pour des tours psy courts, CPU suffit (prompt ~100-300 tok → 5-15 s). Pour
|
repassé en `GGML_TYPE_F16`. → **rebuild `libkazeia_engine.so` avant de shipper** (le .so livré
|
||||||
du RAG/long, il faudra un vrai split (prefill HTP → bascule decode CPU), non trivial en
|
contient encore l'ancien q8_0). q8_0 seulement si OOM KV en très long contexte.
|
||||||
mono-contexte llama.cpp. **Garder CPU-only tant que les prompts restent courts.**
|
2. **Prefill : CPU-only vs HTP (à toi).** Le JNI est CPU-only (`ngl0`) → prefill **14 t/s** (t4).
|
||||||
2. **KV `q8_0` : à revérifier.** Le JNI met `type_k/v=q8_0`. Mesure (batterie faible, throttle)
|
Le HTP fait **189 t/s** avec q35-lmq4 (≈2× le Q4_0=98 : ses embeds Q4 restent sur NPU au lieu de
|
||||||
a montré decode q8_0=6.6 vs KV-f16=10.8 plus tôt → le déquant KV pourrait coûter plus que
|
retomber CPU). Câbler le prefill HTP vaut donc le coup (prompt 500 tok : ~2,6 s HTP vs ~35 s CPU).
|
||||||
le gain BW à court contexte (même effet que la quant poids sous-Q4). **A/B f16 vs q8_0 sur
|
Obstacle : ping-pong du mono-contexte ngl99 (decode GDN rebondit NPU↔CPU = 0,2 t/s). Vrai fix =
|
||||||
batterie pleine ; si f16 gagne, repasse `type_k/v=GGML_TYPE_F16`.** (q8_0 ne sert que la RAM
|
2 contextes (prefill HTP → transfert d'état → decode CPU ngl0) ou état partagé. **CPU-only suffit
|
||||||
KV en long contexte.)
|
pour des tours courts ; câbler HTP si prompts longs / RAG.**
|
||||||
|
|
||||||
## Perf (chiffres sains — la tablette throttlait à 11% ce soir, à reconfirmer)
|
## Perf (sains, 27/05, device froid)
|
||||||
| | prefill | decode | RAM |
|
| | prefill | decode | RAM |
|
||||||
|---|--:|--:|--:|
|
|---|--:|--:|--:|
|
||||||
| q35-lmq4 (JNI CPU-only) | ~18-19 (CPU) | **~10.8** (t4+fa, KV f16) | 2.4 GB |
|
| q35-lmq4 — JNI actuel (CPU-only) | 14 (CPU t4) | **10.9** (t4+fa, KV f16) | 2.4 GB |
|
||||||
| capacité HTP (si câblé) | 89.5 | — | +~3.3 ION |
|
| q35-lmq4 — capacité HTP (si câblé) | **189** | — | +~3.3 ION |
|
||||||
|
| dense Qwen3-4B (repli) | 98 HTP / ~14 CPU | 11.7 | 2.2 GB |
|
||||||
|
|
||||||
## Système (prompt) — `system_fr.txt` fourni
|
## Système (prompt) — `system_fr.txt` fourni
|
||||||
Inclut les garde-fous (3114, pas de prescription) + 2 correctifs issus de l'éval :
|
Inclut les garde-fous (3114, pas de prescription) + 2 correctifs issus de l'éval :
|
||||||
|
|
|
||||||
|
|
@ -1,20 +1,22 @@
|
||||||
# Perf mesurée SM8750/V79 — MAJ 26/05 (fork ql=qualcomm/llama.cpp)
|
# Perf mesurée SM8750/V79 — MAJ 27/05 (fork ql=qualcomm/llama.cpp), batterie pleine device froid
|
||||||
Decode optimum = **t4 / fa1** (PAS t8 : contention, 3.5-4B chute). Prefill HTP : t8 / b512.
|
Decode optimum = **t4 / fa1 / KV f16** (PAS t8 : contention ; PAS KV q8_0 : déquant coûteux). Prefill HTP : ngl99 / t8 / b512.
|
||||||
|
|
||||||
| Modèle | prefill HTP (t8/b512) | prefill CPU (t4) | decode CPU (t4+fa) | RAM |
|
| Modèle | prefill HTP | prefill CPU (t4) | decode CPU (t4+fa, KV f16) | RAM |
|
||||||
|---|--:|--:|--:|--:|
|
|---|--:|--:|--:|--:|
|
||||||
| Qwen3-4B dense | 285 | ~19 | ~11.7 | 2.2 |
|
| Qwen3-4B dense | 98 | ~14 | 11.7 | 2.2 |
|
||||||
| Qwen3.5-4B (q35-lmq4) | 89.5 | ~18-19 | **~10.8** | 2.4 |
|
| **q35-lmq4** (Qwen3.5-4B, embeds Q4) | **189** | 14 | **10.9** | 2.4 |
|
||||||
|
| Qwen3.5-4B-Q4_0 (embeds Q6_K) | 98 | ~14 | 10.8 | 2.4 |
|
||||||
| Qwen3.5-9B | 70 | — | ~4-5 | 5.0 |
|
| Qwen3.5-9B | 70 | — | ~4-5 | 5.0 |
|
||||||
|
|
||||||
Notes (chiffres sains ; reconfirmer hors throttle batterie) :
|
Notes :
|
||||||
- **GDN-compute n'est PAS le goulot du prefill** : serial f32 / fp16 / WY chunkwise donnent le
|
- **KV f16 ≫ q8_0 au decode** : q35-lmq4 f16=10.9 vs q8_0=6.5 (−40%, idem à d=512). Le déquant KV
|
||||||
même pp512 (~89.5). Piste kernel GDN **close** (RAPPORT_RD §7). Decode = plafond BW CPU ~25 GB/s.
|
en flash-attn coûte plus que le BW épargné. → JNI en `type_k/v=F16`. q8_0 seulement si OOM KV long.
|
||||||
- **Bridge JNI = CPU-only (ngl0)** → prefill ~18-19 (pas 89.5). Le 89.5 est la capacité HTP, non câblée.
|
- **q35-lmq4 prefill HTP = 189 ≈ 2× le Q4_0 (98)** : ses embeds/output Q4 restent sur NPU, alors que
|
||||||
- **KV q8_0 à revérifier** : mesure dégradée a donné decode q8_0 < f16 (déquant KV coûteux à court
|
le Q6_K par défaut retombe sur CPU (une partie du « mur prefill » était ce fallback lm_head, pas le GDN).
|
||||||
contexte, comme la quant poids). A/B sur batterie pleine ; si f16 gagne, dropper q8_0 du JNI.
|
- **GDN-compute n'est PAS le goulot prefill** : serial f32 / fp16 / WY chunkwise = même pp512. Piste
|
||||||
- `q35-lmq4` (embeds Q4) = +5% decode vs Q4_0, qualité ≈.
|
kernel GDN **close** (RAPPORT_RD §7). Decode = plafond BW CPU ~25 GB/s.
|
||||||
|
- **Bridge JNI = CPU-only (ngl0)** → prefill 14 (pas 189). Le 189 = capacité HTP, non câblée (ping-pong ngl99).
|
||||||
- NPU≈CPU au decode (GEMV M=1 latency-bound, 77 GB/s injoignable). RAM = GGUF mmap + ~3.3 GB ION/session.
|
- NPU≈CPU au decode (GEMV M=1 latency-bound, 77 GB/s injoignable). RAM = GGUF mmap + ~3.3 GB ION/session.
|
||||||
|
|
||||||
Leviers MORTS (mesurés) : spec-decode net-négatif ; ngram idem (vérif GDN coûteuse) ; IQ4_NL =
|
Leviers MORTS (mesurés) : spec-decode net-négatif ; ngram idem ; IQ4_NL = mêmes octets ;
|
||||||
mêmes octets ; **quant sous-Q4 = decode CPU plus lent** (Q3_K_M −20%) ; kernel GDN (chunkwise/HMX/fp16) = 0 sur prefill.
|
**quant sous-Q4 = decode CPU plus lent** (Q3_K_M −20%) ; **KV q8_0 = decode −40%** ; kernel GDN (chunkwise/HMX/fp16) = 0 sur prefill.
|
||||||
|
|
|
||||||
|
|
@ -17,8 +17,11 @@ Java_com_kazeia_llm_EngineJni_load(JNIEnv* e, jobject, jstring path, jint nctx)
|
||||||
auto m = llama_model_load_from_file(p, mp); e->ReleaseStringUTFChars(path, p);
|
auto m = llama_model_load_from_file(p, mp); e->ReleaseStringUTFChars(path, p);
|
||||||
if (!m) return 0;
|
if (!m) return 0;
|
||||||
auto cp = llama_context_default_params(); cp.n_ctx = nctx; cp.n_threads = 4; cp.n_batch = 512;
|
auto cp = llama_context_default_params(); cp.n_ctx = nctx; cp.n_threads = 4; cp.n_batch = 512;
|
||||||
cp.flash_attn_type = LLAMA_FLASH_ATTN_TYPE_ENABLED; // t4+fa = 14t/s decode (t8=9.8 contention; fa coupe trafic KV)
|
cp.flash_attn_type = LLAMA_FLASH_ATTN_TYPE_ENABLED; // t4+fa optimum decode (t8=contention)
|
||||||
cp.type_k = GGML_TYPE_Q8_0; cp.type_v = GGML_TYPE_Q8_0; // KV q8: 14->15.5 dense (>pte), 8.5->9.8 hyb, quasi-lossless
|
// KV f16 (PAS q8_0): mesuré 27/05 batterie pleine, q35-lmq4 decode f16=10.9 vs q8_0=6.5 (-40%,
|
||||||
|
// déquant KV en flash-attn coûte plus que le BW à court/moyen contexte; idem d=512). q8_0 ne
|
||||||
|
// servirait que la RAM KV en très long contexte. Repasser q8_0 seulement si OOM KV avéré.
|
||||||
|
cp.type_k = GGML_TYPE_F16; cp.type_v = GGML_TYPE_F16;
|
||||||
auto* k = new KEngine{m, llama_init_from_model(m, cp), llama_model_get_vocab(m),
|
auto* k = new KEngine{m, llama_init_from_model(m, cp), llama_model_get_vocab(m),
|
||||||
llama_sampler_init_greedy()};
|
llama_sampler_init_greedy()};
|
||||||
return (jlong)k;
|
return (jlong)k;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue