Skip to content

[GPU] SDPA micro: use prefill config on integrated GPUs - #39316

Merged
e-ddykim merged 1 commit into
openvinotoolkit:masterfrom
kwieloch-intel:prefill/sdpa-igpu-prefill-config
Nov 2, 2026
Merged

e-ddykim merged 1 commit into
openvinotoolkit:masterfrom
kwieloch-intel:prefill/sdpa-igpu-prefill-config

Conversation

@kwieloch-intel

@kwieloch-intel kwieloch-intel commented Oct 29, 2026 •

Copy link
Copy Markdown
Contributor

This PR fixes micro SDPA config selection on integrated GPUs, which picked a decode (second-token) config for every prefill chunk.

Tickets:

This PR is one part of a set of TTFT optimizations for 2-bit LLMs on Panther Lake. The other parts are #39317 (L2 normalization into RMS), #39320 (int8 activations for u2 FullyConnected) and uxlfoundation/oneDNN#6381 (u2 weights with int8 activations).


Changes

Xe2/Xe3 reach choose_config_xehpc for head size <= 128. There were two problems:

  • Check order: the is_integrated check returned xehpc_q_h128_2nd_integrated, a second-token config, before thin_q was checked. With an f16 KV cache, every prefill chunk ran a decode-shaped kernel.
  • Unknown key count: a dynamic key count (StatelessKV) arrives as seq = 0, so a prefill over thousands of keys was sized as a short sequence.

After the fix:

  • the integrated decode config is used for thin_q only;
  • a multi-token call with an unknown key count on an integrated GPU is sized as a long sequence. With a quantized KV cache this selects xehpc_q_h128, the config that a known long sequence already gets.

Discrete GPUs, PagedAttention and decode (thin_q) take the same paths as before.


Before / after

LLM (2-bit weights, f16 KV cache), PTL 4Xe, ~8200-token prompt in 512-token chunks, TTFT median of 3 runs:

TTFT
before 28.92 s
after 24.21 s 1.19x

Greedy output is identical and decode speed is unchanged. Running a 2-bit model needs u2 FullyConnected support (#37212), so this was measured on a branch that has it. This change does not depend on it.


Validation

  • The existing SDPA unit tests give the same results with and without this PR.
  • End to end on PTL 4Xe: greedy output identical to before on all prompts.

Note

AI assistance was used. All changes were reviewed, built, tested and measured on hardware.

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
There may be pipelines that require an authorized user to comment /azp run to run.
Some pipeline(s) encountered errors during trigger evaluation.

@kwieloch-intel
kwieloch-intel force-pushed the prefill/sdpa-igpu-prefill-config branch from 69cde32 to e8826f4 Compare October 30, 2026 13:30
@e-ddykim e-ddykim self-assigned this Nov 2, 2026

@e-ddykim e-ddykim left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@e-ddykim
e-ddykim added this pull request to the merge queue Nov 2, 2026
Merged via the queue into openvinotoolkit:master with commit a3cc46f Nov 2, 2026
197 of 198 checks passed
mkruszyx pushed a commit to mkruszyx/openvino that referenced this pull request Nov 3, 2026
### This PR adds a GPU pass that fuses the L2-normalization form of RMS
norm into a single RMS op.

### Tickets:
 - [CVS-197466](https://jira.devtools.intel.com/browse/CVS-197466)
 - [CVS-197053](https://jira.devtools.intel.com/browse/CVS-197053)

This PR is one part of a set of TTFT optimizations for 2-bit LLMs on
Panther Lake. The other parts are openvinotoolkit#39316 (SDPA
prefill config), openvinotoolkit#39320 (int8 activations for u2
FullyConnected) and uxlfoundation/oneDNN#6381 (u2 weights with int8
activations).

---

### Changes

Models exported from ONNX LpNormalization compute RMS norm as `x /
sqrt(ReduceSum(x^2) + eps) * gamma`. RMSFusion only matches the
ReduceMean form with a constant gamma, so this form ran as about 7
separate kernels per norm.

The new `L2NormToRMS` pass rewrites it to `RMS(x, gamma / sqrt(N), eps /
N)`. That is mathematically identical, because `sum(x^2) = N *
mean(x^2)`. It also absorbs a trailing Convert.

It applies only when all of these hold:
- the reduction is over a static last axis;
- `keep_dims` is set;
- the row fits the RMS kernel's work group.

Gamma may be a constant or a run-time input, for example weights passed
as model inputs.

---

### Before / after

2-bit LLM, PTL 4Xe, ~8200-token prompt in 512-token chunks, TTFT median
of 3 runs, measured with the SDPA prefill config fix applied:

| | TTFT | |
|---|---|---|
| before | 24.21 s | |
| after | 22.72 s | **1.07x** |

All 81 norms of the model are fused, so each norm now runs as 1 RMS
kernel instead of about 7. Output is identical and decode speed is
unchanged.

---

### Validation

- New unit tests `L2NormToRMS*` (`l2_norm_to_rms_test.cpp`) cover the
plain pattern, f16 activations with Converts, and three negative cases
(not the last axis, no keep_dims, row too long). All 5 pass.
- End to end on PTL 4Xe: output identical to before on all prompts.

### AI assistance:
> [!NOTE]
> AI assistance was used for the analysis, the profiling and the
implementation. All changes were reviewed, built, tested and measured on
hardware.

---------

Co-authored-by: Kim, Eddy <eddy.kim@intel.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

category: GPU OpenVINO GPU plugin orca_CF

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants