Skip to content

Npu decode funcall gating - #254

Draft
cavusmustafa wants to merge 34 commits into
ravi9:dev_backend_openvinofrom
cavusmustafa:npu-decode-funcall-gating
Draft

Npu decode funcall gating#254
cavusmustafa wants to merge 34 commits into
ravi9:dev_backend_openvinofrom
cavusmustafa:npu-decode-funcall-gating

Conversation

@cavusmustafa

Copy link
Copy Markdown
Collaborator

openvino: NPU decode fix for gemma3/4 — disable NPUW funcall for per-layer-embedding archs

On NPU, the decode (1-token) model wraps its non-repeated blocks as NPUW funcall
subgraphs. For gemma3/4-style architectures those blocks hold the per-layer input
embedding (inp_per_layer / per_layer_proj), so each pays a per-call function
prologue (tensor bind + closure unpack) on every decoded token. At batch-1 decode
this overhead dominates.

Fix: the decode model gets its own compile config, and for archs carrying a
per-layer input embedding we set NPUW_FUNCALL_FOR_ALL=NO for decode only.
Prefill is unchanged; other archs and CPU/GPU are unaffected. Arch detected via a
per_layer tensor in the graph (ModelParams::has_per_layer_embd).

Results (NPU, c=1024, decode steady-state):

Model Decode before Decode after Decode-model compile Output
gemma4 E2B Q4_K_M ~1.6 t/s ~13 t/s (~8x) ~62 s → ~167 s correct
Llama-3.2-1B Q4_K_M ~9.8 t/s ~9.8 t/s (no change) unchanged correct

Trade-off: decode-model compile time rises for gated archs (paid once per
process); prefill and CPU/GPU are unaffected.

Adds optional env overrides for experimentation:
GGML_OPENVINO_[DECODE_]NPUW_FOLD / _FUNCALL_FOR_ALL.

zhaixuejun1993 and others added 30 commits July 14, 2026 09:33
…g_src to recorde the src ggml tensor for OpenVINO dynamic shape infer
enable qwen35

Fix after rebase

remove logging
…t reason: the backend test initializes unary op inputs over a wide range, [-150, 150]. For FP32, exp(x) overflows around x ~= 88.7, so this test can randomly generate values right in or beyond the overflow region
In stateful mode the NEOX RoPE branch fed rank-3 data ([S, n_heads,
head_size]) into the Multiply against the rank-4 cos/sin tables
([1, S, 1, n_dims/2]). That mixed-rank broadcast is miscomputed by the
OpenVINO GPU plugin, corrupting the rotated Q/K and producing garbage
output (e.g. Phi-3-mini). Lift the data to rank-4 before the split/
Multiply so the operands are equal-rank, matching what the TYPE_NORMAL
branch already does. CPU and stateless paths are unaffected.

Phi-3-mini-Q4_K_M, wiki.test perplexity, GPU stateful:
  before: PPL = 27120.43
  after:  PPL = 6.2263   (CPU reference: 6.2251)
…ov name in ov bk; 3) fix issue in arch test & op test with latest code update
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
zhaixuejun1993 and others added 4 commits July 14, 2026 23:40
…layer-embedding archs

On NPU, the decode (1-token) model compiles the non-repeated blocks as NPUW
"funcall-everywhere" subgraphs. For gemma3/4-style architectures those blocks
carry the per-layer input embedding (inp_per_layer / per_layer_proj), so each
one pays a per-call function prologue (tensor bind + closure unpack) on every
decoded token. At batch-1 decode this per-call overhead dominates and makes
decode ~8x slower than it should be (gemma4 E2B Q4_K_M: ~1.6 -> ~13 t/s).

Fix: give the decode model its own compile config (compile_config_decode) and,
for archs that carry a per-layer input embedding, set NPUW_FUNCALL_FOR_ALL=NO
for the decode model only. Prefill is unchanged (funcalls there are amortized
over the whole prompt). The arch is detected via a per_layer tensor in the graph
(ModelParams::has_per_layer_embd); other archs and CPU/GPU are unaffected.
Verified no change on Llama-3.2-1B (no per-layer embedding).

Adds optional env overrides for experimentation:
  GGML_OPENVINO_NPUW_FOLD / _FUNCALL_FOR_ALL          (both prefill+decode)
  GGML_OPENVINO_DECODE_NPUW_FOLD / _FUNCALL_FOR_ALL   (decode only; precedence)
@cavusmustafa
cavusmustafa force-pushed the npu-decode-funcall-gating branch from 74ad6de to 18d9d77 Compare July 15, 2026 23:18
@wine99
wine99 force-pushed the dev_backend_openvino branch from 4250de7 to 175f422 Compare July 27, 2026 04:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants