Skip to content

B70 attention opt - #2

Merged
ShengchenJ merged 8 commits into
mainfrom
b70_attention_opt
Oct 19, 2026
Merged

ShengchenJ merged 8 commits into
mainfrom
b70_attention_opt

Conversation

@ShengchenJ

Copy link
Copy Markdown
Contributor

No description provided.

ShengchenJ and others added 7 commits October 12, 2026 23:17
When GPU_TARGET is not given, common.mk detects the local Intel GPU
(detect_gpu_target.sh: sycl-ls, then the sysfs PCI id; PVC fallback).
LARGE_GRF=auto adds -ze-opt-large-register-file on bmg targets: Xe2 AOT
defaults to 128 GRF and the PVC-sized tiles spill there. bmg builds also get
-DKITTENS_BMG for Battlemage launch configs. decode keeps 128 GRF
(LARGE_GRF ?= 0), it is bandwidth-bound.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Chen, Sheng S <sheng.s.chen@intel.com>
The bf16_2 vec constructor lowers to a software round-to-nearest-even
sequence (shr/and/add3 plus a NaN branch) on Xe2; converting the two lanes
with the scalar converter emits the hardware conversion.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Chen, Sheng S <sheng.s.chen@intel.com>
row_reduce now reduces all rows of a base tile with one transposing
butterfly (lane L ends up with row L): 15 shuffles for 16 rows instead of
64. Shuffles lower to serialized a0-indirect moves on Xe, so this was the
main stall in the attention softmax.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Chen, Sheng S <sheng.s.chen@intel.com>
On device, float max/sum row reductions of 16- and 8-row tiles use inline
vISA register regions (the data movement of sycl-tla's hreduce16/8,
BSD-3-Clause) instead of shuffles, so the reduction needs no a0-indirect
moves at all. The shuffle butterfly stays as the generic fallback.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Chen, Sheng S <sheng.s.chen@intel.com>
A WG x seq_q sweep on B70 (bf16 out, B in {1,4}, N 512..8192) with the
register-region reductions shows wg256/seq_q8 is fastest, or within noise,
for every causal and non-causal shape.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Chen, Sheng S <sheng.s.chen@intel.com>
The forward KV loop now builds one block2d address payload per K/V stream
(K^T, K prefetch, V, V prefetch) before the loop and only updates the row
per KV tile; all other offsets are vISA immediates. This removes the per-load
payload rebuild (364 -> 4 scalar movs per 64 DPAS; loop 504 -> 280 instrs).

gl_desc gains a transposed mode, a raw-surface init, compile-time load and
prefetch offsets, and int storage for VNNI reads (short storage made IGC
re-interleave every word).

B70, H32/8 D128 bf16: causal N4096 83 -> 89.5 TF, N8192 71.5 -> 86 TF,
non-causal N4096 77 -> 90 TF; all 11 standalone harnesses pass.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Chen, Sheng S <sheng.s.chen@intel.com>
Every subgroup of a forward WG reads the same K/V tile, yet each one
prefetched the whole next tile (8 32x32 blocks per KV tile). The next tile's
blocks are now split across the subgroups, one block each for WG256, which
cuts the per-subgroup 2D sends per KV tile from 28 to 21.

B70, H32/8 D128 bf16: causal N4096 88 -> 96 TF, N8192 86 -> 91 TF, B4 N2048
causal 78 -> 82 TF / full 83 -> 87.5 TF, N1024 +3-4%; non-causal N4096 flat
(90 -> 89). A 64-key iteration (half the reductions/rescales), early V loads
and a lazy O rescale were tried and dropped: they were slower or neutral,
the loop is load-latency bound rather than ALU bound.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Chen, Sheng S <sheng.s.chen@intel.com>
@ShengchenJ
ShengchenJ requested a balanced review from Copilot October 16, 2026 07:12

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Warning

Copilot couldn't run its full agentic review because it didn't start before the timeout. Make sure your repository has a runner available, or add a copilot-code-review.yml file specifying one with the runs-on attribute. See the docs for more details.

Copilot review overview

3 open findings
What changed in this PR

This PR optimizes attention performance on Intel Battlemage (B70/B60/B570) by adding GPU target auto-detection, introducing Battlemage-specific build defaults (notably large-GRF handling), and updating the GQA forward kernel to use block2D descriptors and faster in-register reductions.

Changes:

  • Add detect_gpu_target.sh and wire common.mk to auto-detect GPU_TARGET, with PVC as fallback.
  • Introduce LARGE_GRF auto/override logic and Battlemage-specific compile-time defines/flags.
  • Optimize gqa_forward by switching K/V loads to gl_desc (block2D) and adding register-region transpose-reductions.
File Description
kernels/​detect_gpu_target.sh Adds script to detect the first local Intel GPU architecture / map PCI IDs to AOT targets.
kernels/​decode/​Makefile Overrides LARGE_GRF default for decode to protect bandwidth-bound performance on B70.
kernels/​common.mk Auto-detects GPU_TARGET, introduces LARGE_GRF auto logic and Battlemage compile-time defines.
kernels/​attention/​gqa_forward.dp.cpp Replaces flat K/V loads + prefetch with block2D descriptor loads and cooperative prefetching; adds BMG tuning path.
include/​ops/​warp/​register/​tile/​reductions.dp.hpp Adds a faster transpose-reduce path (device-only asm) and refactors row reductions to use it.
include/​ops/​warp/​memory/​tile/​gl_desc.dp.hpp Extends gl_desc to support transpose loads and compile-time offsets; updates init API.
include/​common/​base_types.dp.hpp Changes bf16_2 conversion to reuse scalar bf16 conversion to avoid slow SW RNE sequence on Xe2.

🧠 Review effort: Lite


💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread kernels/attention/gqa_forward.dp.cpp Outdated
Comment thread include/ops/warp/memory/tile/gl_desc.dp.hpp
Comment thread kernels/common.mk
The hoisted 2D block-load payloads open-coded the per-(batch, kv_head)
slice arithmetic and then reused one set of numbers for both K and V,
taking the offset, pitch and surface height from Kg alone. Derive each
side from its own gl via the template stride<> accessor that
global_to_register and the other memory ops already use, so this site
cannot drift from the layout the rest of the library assumes and V no
longer depends on Kg's dims.

Numerically a no-op at the harness's dimensions, where Kg and Vg are
constructed identically: residuals are unchanged (causal 1.56e-03, full
2.10e-03) and a 5-trial paired A/B shows causal +0.1% and full +0.5%,
both inside the per-case noise floor. No new spills.

Note that this does not make the path safe for padded or arbitrarily
strided tensors, because gl cannot describe one: stride<axis>() is
derived from the shape (gl.dp.hpp:171) rather than stored, and
operator[] indexes densely the same way. Supporting real strides is a
gl-level change, not a per-kernel one.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@ShengchenJ
ShengchenJ merged commit 32bec6b into main Oct 19, 2026
5 of 6 checks passed
@ShengchenJ
ShengchenJ deleted the b70_attention_opt branch October 19, 2026 02:15
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.

2 participants