Pull requests / #2582
#2582 sycl: select vector INT8 QSA decode on Battlemage
open · @xiangyuT · 0 commentaires · Sur GitHub
Multi-GPUNVIDIA / CUDAModels & quantsWindowsLinux
Description
## Summary INT8 QSA decode performs repeated key/value conversion. Use chunk-down reduction and vector code/value loads on the measured shapes, retaining the existing FP32 attention arithmetic. Dispatch reuses upstream `intel_gpu_gen` and selects the optimized implementation on `IntelGpuGen::Battlemage`, subject to the existing shape, alignment and configuration checks. Hardware measurements below are from B70. INT8 KV, 24 query heads / 2 KV heads, page size 4; capacity 2051 with T=1–6 or 32, or capacity 32768 with T=1–6. Other capacities, head/page layouts and KV formats retain the original dispatch. The existing prompt-attention fallback also uses this dispatch, so TTFT is measured alongside TPOT. The optimized launchers no longer request root-group synchronization, allowing native recording on the tested paths. ## What changed `sycl/src/kernels/cuda/qsa_decode_attn.dp.cpp`. ## Dispatch controls | Control | Unset (default) or `1` | `0` | |---|---|---| | **Master:** `STRATA_SYCL_QSA_CHUNK_DOWN` | Enable the chunk-down implementation and allow its vector-load subpath, subject to the dispatch guards. | Disable both optimized paths and use the original dispatch. | | **Child:** `STRATA_SYCL_QSA_VALUE8_K8_VEC` | Allow vectorized INT8 key/value loads when the master is enabled and the vector-shape guard matches. | Disable vector loads only; retain chunk-down when the master is enabled. | The master takes precedence: `STRATA_SYCL_QSA_CHUNK_DOWN=0` disables both paths even if `STRATA_SYCL_QSA_VALUE8_K8_VEC=1`. Vector loads apply to capacity 2051 with T=1–4 or 32, and capacity 32768 with T=1. Both controls retain the existing Battlemage, INT8 KV, head-layout and page-size guards. Set these variables before starting the engine and restart it when changing them: their values are cached on first use. Both are enabled by default within their guards and retained for diagnosis and fallback; normal operation needs no environment-variable setting. ## End-to-end performance: current head versus upstream PR head: `dcd8fcbb66ae400afaa2eed32c165748ca379795`. Pure upstream comparator: `296b59d2f73c8f04a805df29c2fa97655adace78`. Common frontend: `296b59d2f73c8f04a805df29c2fa97655adace78`. The candidate contains this PR's changes; these same-day measurements compare the complete current PR against upstream. At each input length, collection order is **upstream before / PR head / upstream after**. Every block starts a fresh engine, excludes one short warmup and three full-input warmups, then measures the same three requests. Each reported comparison uses six upstream and three PR-head measured requests. Both builds use identical model and runtime settings. This PR's dispatch controls listed above were explicitly set to `1` on both builds, equivalent to the default-enabled candidate dispatch within its guards; pure upstream does not read those controls. | Input / output tokens | TTFT upstream → PR (s) | Change | TPOT upstream → PR (ms/token) | Change | | --- | ---: | ---: | ---: | ---: | | 4096 / 128 | 3.456916 → 3.213325 | -7.046% | 14.311101 → 14.232907 | -0.544% | | 8192 / 256 | 7.000948 → 6.533152 | -6.682% | 13.608236 → 13.501388 | -0.784% | | 32768 / 256 | 29.592821 → 27.727491 | -6.303% | 14.086246 → 13.932750 | -1.090% | TTFT is request-to-first-nonempty-SSE latency. TPOT is first-to-last nonempty SSE arrival divided by actual output tokens minus one (127 or 255). Changes average the three request-wise ratios against the corresponding before/after upstream means. Displayed upstream times average the two baseline blocks; negative changes mean lower latency. At every input length, token IDs and text matched across both upstream blocks and the PR block for all seven corresponding requests per arm, including the four excluded warmups. Speculation settings are fixed; suffix window selection is time-adaptive, so actual work counts may differ. Here, windows/offered/accepted matched request by request at all three lengths; per-request means are reported below. Actual cache capacity: 18609 resident expert slots and 5967 mirrored experts (8.02 GiB); the mirror setting of 16384 MiB is a budget. <details> <summary>Paired changes, upstream drift and actual speculative work</summary> | Input tokens | Three TTFT pair changes | Three TPOT pair changes | Upstream TTFT drift | Upstream TPOT drift | | --- | --- | --- | ---: | ---: | | 4096 | -7.010% / -7.033% / -7.096% | -0.551% / -0.480% / -0.600% | +0.166545% | +0.014532% | | 8192 | -6.694% / -6.653% / -6.699% | -0.746% / -0.777% / -0.831% | -0.044352% | +0.014504% | | 32768 | -6.295% / -6.314% / -6.300% | -1.089% / -1.094% / -1.086% | -0.010217% | +0.007499% | Mean windows / offered / accepted per measured request: | Input tokens | Upstream before | PR head | Upstream after | | --- | --- | --- | --- | | 4096 | 54.000 / 111.000 / 74.000 | 54.000 / 111.000 / 74.000 | 54.000 / 111.000 / 74.000 | | 8192 | 102.667 / 209.000 / 153.667 | 102.667 / 209.000 / 153.667 | 102.667 / 209.000 / 153.667 | | 32768 | 103.333 / 202.333 / 154.000 | 103.333 / 202.333 / 154.000 | 103.333 / 202.333 / 154.000 | </details> ## Correctness and native recording The current code was checked against its pre-correction parent `0928ec3bbdef1716e060e215fe0ef0beeb1a090f` in direct execution and ordinary graph replay. Each mode passed 26 production, boundary and fallback cases in parent/head/parent comparisons; complete outputs, partials and canaries matched byte for byte. With native recording, the parent failed at the first optimized case. The current head passed 22 optimized/edge cases with three replays each matching direct execution, then failed on an unchanged upstream page-layout fallback. This establishes native recording for those tested optimized paths; the whole engine and unchanged fallback paths are not validated for native recording. ## Model-shape kernel measurements Measured earlier at `08a122704daf70d79fba782acfff6a83b5604747`, using synthetic query/KV inputs with the model's head/page layout and supported capacities. These values were not remeasured at the current head. The standalone comparator selected original dispatch with the optimization disabled; the candidate used default dispatch at that measured revision. | Shape | Baseline (µs) | Default (µs) | Change | Drift | | --- | ---: | ---: | ---: | ---: | | 2051/1/4 | 47.192 | 37.480 | -20.579% | -0.168% | | 2051/2/4 | 53.280 | 39.476 | -25.909% | -0.234% | | 2051/3/4 | 60.961 | 45.533 | -25.308% | -0.355% | | 2051/4/4 | 77.683 | 66.808 | -13.999% | -0.196% | | 2051/5/4 | 119.353 | 102.409 | -14.197% | -0.059% | | 2051/6/4 | 127.150 | 109.054 | -14.232% | -0.047% | | 2051/32/4 | 578.190 | 399.376 | -30.926% | -0.034% | | 32768/1/4 | 466.835 | 378.715 | -18.876% | -0.025% | | 32768/2/4 | 733.137 | 670.612 | -8.529% | +0.008% | | 32768/3/4 | 980.584 | 873.465 | -10.924% | -0.050% | | 32768/4/4 | 1227.513 | 1065.925 | -13.164% | -0.003% | | 32768/5/4 | 1478.396 | 1262.093 | -14.631% | -0.002% | | 32768/6/4 | 1723.632 | 1453.355 | -15.681% | +0.013% | Shape axes: capacity / T / page size. Each microbenchmark arm used three measured samples, a ≥2-second/1000-call warmup and ≥3 seconds/2000 calls per sample. Times include host submission and final queue wait. These component measurements are separate from the current-head endpoint comparison; kernel percentages are not added to endpoint percentages. ## Test configuration Intel Arc Pro B70 32 GB; Intel Xeon w5-3435X; Linux/xe; omix 0.4.0 and oneAPI DPC++ 2026.1.1. Container limits: 16 CPUs / 96 GiB RAM. Builds and device execution ran inside the container. Model: Qwen3.8-Flash-Next-GSQ-RCO IQ2_XS, revision `ed59f92082b1e93c0e96d60a8b11aab089b52f09`. Greedy seed42, thinking off; INT8 KV; max context131072 / resident32768; `--expert-cache 17772` experts; reserve1536 MiB; expert streaming (`--stream-experts`) with `--pcie-frac 0.30`; mirror budget16384 MiB; no prefill borrowing; auto prefill; spec4 / min-p0.5 / suffix3; adapt-every8 / decay1; prompt cache off. Both builds kept existing settings equal: `STRATA_VERIFY_DEVICE_PLAN=1`, `STRATA_VERIFY_NO_HOST=1`, `STRATA_STAGER_THREADS=12`, `STRATA_MIRROR_MIB=16384`, `STRATA_DECODE_TIMING=1`; `ONEAPI_DEVICE_SELECTOR=level_zero:gpu`, `SYCL_CACHE_PERSISTENT=0`. The endpoint results are warmed and post-readiness; the host page cache was retained. Profiled requests and warmups are excluded. Runtime and performance validation are limited to B70; other GPUs, Windows and multi-GPU operation remain unvalidated. Changes are confined to the SYCL implementation files listed above; the public documentation diff is empty.
Sur le site
Liens install, modèles, releases.