Skip to content

qsa_prompt_attn: tensor-core kernel for Volta (sm_70, mma.m8n8k4) - #600

Closed
fks wants to merge 4 commits into
Niko1221:mainfrom
fks:feature/v100-prompt-attn-volta
Closed

fks wants to merge 4 commits into
Niko1221:mainfrom
fks:feature/v100-prompt-attn-volta

Conversation

@fks

@fks fks commented Oct 3, 2026 •

Copy link
Copy Markdown

On sm_70 qsa_prompt_attn_batch refuses the device (#371), so the prompt path runs the QSA attention on the decode kernel, one query at a time with FP32 FMAs: 19.2% of the GPU time of a 28,650-token prompt on a V100 (nsys, 0.1.35, attn_chunk_kernel<1>).

prompt_attn_v70_kernel is the v1 kernel's structure with the two matrix products on mma.sync.m8n8k4 (FP16 in, FP32 accumulate): q.k with one 64-dim group (= one int8 scale group) per warp and 8 cells per quad-pair, p.v with 16 dims per quad-pair. q and p keep their hi + lo FP16 split, and the four dim groups' partials are added in a fixed order (deterministic). Int8, FP16 and K8V4 KV are handled; Q4_0 KV (mode 4, sm_80+ only) keeps the old kernel. The m8n8k4 fragment layout was measured on a V100 and agrees with turbomind's SM70_MMA_884. It is used for compute capability 7.0 - 7.4; STRATA_PROMPT_ATTN_OLD=1 is the old path.

Accuracy (qsa_prompt_attn_parity, synthetic, V100, 32K context, 2,048 queries per chunk, output scale ~3.6):

KV error vs FP64, old kernel error vs FP64, new kernel time per chunk, old -> new
int8 2.4e-6 5.1e-6 38.1 -> 13.4 ms (2.8x)
fp16 1.9e-6 5.3e-6 37.3 -> 28.3 ms (1.3x)

The 1,500- and 2,100-token contexts also pass. The test now skips its Q4_0 cases below sm_80 instead of exiting 2 there (the dispatcher keeps the old kernel for them).

Prompt speed (one V100-PCIE-32GB, i9-7960X, CUDA 12.8, origin/main at 99f3dbd, Unsloth UD-IQ4_XS, int8 KV; cold server, random-word prompts, greedy; same binary, STRATA_PROMPT_ATTN_OLD=1 against the default):

Prompt tokens old path (tok/s) new kernel (tok/s)
7,194 1,010 1,164 +15%
28,650 1,063 1,251 +18%
114,338 973 1,123 +15%

Decode is unaffected (it does not use this path).

Output checks

  • Needle recall (tools/needle_bench.py, 8k / 32k / 128k at five depths, a fresh server per configuration): 15 of 15 found with the old path, 15 of 15 with the new kernel.
  • Greedy output (48 tokens) is identical for the 28,650- and 114,338-token prompts. For the 7,194-token prompt it starts the same and differs later: another summation order in a greedy decode. I did not run a teacher-forced top-1 comparison.

Not covered: only the Unsloth IQ4_XS pack was run (not the GSQ-RCO quants); one request on one card. Method, profile and raw numbers: bench/results/2026-10-03-v100-prompt-attn/; build and kernel overview: docs/NVIDIA_V100.md (both in this PR). Independent of the BF16-via-FP16 change in #540: different code files, and it stacks with it (a user measured +9% on top of #540)

Written and measured with Claude Sonnet 5.5.

Klaus Friedel and others added 2 commits October 3, 2026 06:55
On sm_70 qsa_prompt_attn_batch refused the device and the prompt path fell
back to the decode kernel (FP32 FMAs, one query at a time): 19-25% of the GPU
time of a 32K prompt on a V100.

prompt_attn_v70_kernel is the v1 kernel's structure with the two matrix
products on m8n8k4 (FP16 in, FP32 accumulate): q.k with one dim group (64 dims,
= one int8 scale group) per warp and 8 cells per quad-pair, p.v with 16 dims per
quad-pair. q and p keep their hi + lo FP16 split, the four dim groups' partials
are added in a fixed order (deterministic). Int8, FP16 and K8V4 KV are handled;
Q4_0 KV (mode 4, sm_80+ only upstream) keeps the old kernel. The fragment layout
was measured on a V100 and matches turbomind's SM70_MMA_884.

qsa_prompt_attn_parity (V100): error against FP64 ~5e-6 (output scale ~3.6),
int8 3.0x and fp16 1.3x faster than the FP32 kernel per 2048-query chunk. The
test now skips its Q4_0 cases below sm_80 instead of exiting 2 there.
End to end, 32K prompt, one V100, greedy output identical:
26 s -> 22 s on current main (STRATA_PROMPT_ATTN_OLD=1 is the old path).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The experimental sm_70 build (STRATA_EXPERIMENTAL_SM60, Niko1221#236) had no page. NVIDIA_V100.md says how to build it, which kernel each
part of the prompt path uses on Volta and what the prompt attention kernel was measured at.

bench/results/2026-10-03-v100-prompt-attn: prompt speed with and without the kernel (7K / 28K / 114K tokens), the nsys share of the
attention before and after, the parity numbers, needle recall (15 of 15 with either path) and the greedy-output comparison.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@sskver

sskver commented Oct 3, 2026

Copy link
Copy Markdown
Contributor

i tried it on top of #540 on a V100 (IQ2_XS, sm_70, CUDA 12.9), with only the kernel commit (ee0843d) cherry-picked onto my branch, which is upstream 0.1.37 plus the #540 commits

prefill, one run each:

  • 8K prompt: 1104.8 -> 1205.5 tok/s (+9.1%), qsa attn 981 -> 524 ms
  • 20K prompt: 1130.1 -> 1226.3 tok/s (+8.5%), qsa attn 2676 -> 1435 ms

so it stacks with #540. #540's attention commit changes qsa_decode_attn.cu, the kernel this PR bypasses during prefill, so the two don't overlap in code. that fits your +15-18% over the old path: #540's attention commit is worth about +7% on its own, and 1.07 x 1.09 is roughly 1.17

you mention you did not run a teacher-forced comparison, so for what it is worth, first-window logits against the same build without this kernel:

  • 8K: argmax same, top-10 overlap 10/10 but order differs, KL 1.5e-3
  • 20K: argmax same, top-10 overlap 9/10, order differs, KL 6.2e-3

that is the same size as the FP16 rounding in the BF16-via-FP16 change, so it doesn't look like a bug. if you have a KL or perplexity number on a longer prompt i'd like to see it, mine is one position per prompt and heavy-tailed

caveats: single runs, V100 only, i did not run ctest on this kernel

separately: the BF16 half of #540 (BF16 GEMMs through FP16 tensor cores, same STRATA_BF16_VIA_F16 toggle) is the same change as #593, so i left a note there. this PR itself doesn't overlap with either

…ed KL, controls)

Old path against new kernel on 8.5K / 33K / 99K-token chats, 617 scored positions each, with two controls that change only the rounding
order (BF16 GEMMs without the FP16 detour, another prefill chunk), reruns of both paths (bit-identical), and the kernel's own error on the
model's data (relative 4.4e-7 mean, 4.8e-6 worst row over ~5 M rows).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@fks

fks commented Oct 3, 2026

Copy link
Copy Markdown
Author

Thanks for testing this. I measured the teacher-forced comparison on longer prompts, with the project's method (STRATA_LOGPOS, top-256).

Setup: a chat whose first message (8.5k / 33k / 99k tokens of this repository's docs and code) is read by the batched prompt path, then a ~600-token last message that goes through the verify windows and is scored (617 positions per prompt). One V100, UD-IQ4_XS, old path = STRATA_PROMPT_ATTN_OLD=1. KL is old || other over the old run's top 256 plus a bucket for the rest.

comparison KL mean (8.5k / 33k / 99k) argmax same top-10 overlap
old vs old (rerun), new vs new (rerun) 0 100% 100%
old vs new kernel 0.028 / 0.040 / 0.116 97.7 / 93.2 / 86.4% 93.3 / 91.9 / 88.4%
control: BF16 GEMMs without the FP16 detour 0.026 / 0.051 / 0.090 97.2 / 91.4 / 91.2% 92.9 / 91.4 / 88.5%
control: --prefill 2048 instead of auto 0.023 / 0.035 / 0.038 97.9 / 94.8 / 95.6% 92.9 / 92.2 / 89.7%

So the model amplifies small numeric differences a lot (heavy-tailed: the median KL at 8.5k is 7e-4, p99 0.35), and both controls, which change nothing but the rounding order, move the distribution as much as the kernel does. At 99k the kernel is somewhat above both controls; that is one document and 617 positions, so I can neither confirm nor exclude a real effect there.

Directly on the model's data, with a temporary check that ran the decode kernel beside the new one on the same inputs (every 8th query batch, all 12 QSA layers, ~5 M (query, head) rows, positions up to 98k): ||new - old|| / ||old|| per row is 4.4e-7 on average, 4.8e-6 in the worst row, max absolute difference 4e-5 against values up to 31, with no trend over layers or context length. That is FP32 rounding level.

Caveats: V100 only, one run per setting (the reruns are bit-identical), the check code is not part of the PR. The table and the method are now in bench/results/2026-10-03-v100-prompt-attn/README.md (dbb1a08).

…221#593 was closed in its favor)

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@sskver

sskver commented Oct 3, 2026

Copy link
Copy Markdown
Contributor

that row-level check pretty much settles it for me, only thing i noticed is 99k sitting a bit above the controls. looks good to me!

eelgaev added a commit to eelgaev/Strata-AC922 that referenced this pull request Oct 4, 2026
…/lo chains split

The kernel is Klaus Friedel's (fks), from his open PR Niko1221#600 to
Niko1221/Strata (Niko1221#600), commit
ee0843d:
fks@ee0843d
Thanks to him for it.

Taken as written, with one change: the hi and lo halves of the split q (in
q.k) and p (in p.v) accumulate in their own m8n8k4 chains, added in FP32 at
the end. In one chain Volta's truncating accumulation dropped most of the
lo half: error vs FP64 at 32K context 5.1e-6 -> 2.3e-6 (the FP32 per-query
kernel: 2.4e-6; P4's wmma kernel: 6.6e-6), 12.2 -> 12.4 ms per 2,048-query
chunk (wmma 14.2). A fresh accumulator per k-step: 2.45e-6 but 15.5 ms.

Opt-in, STRATA_ATTN_M884=1, int8 KV (ahead of STRATA_ATTN_WMMA, which stays
the fallback). Teacher-forced vs the reference, against the wmma kernel:
32K KL 0.0232 -> 0.0220 (max 1.80 -> 0.58, top-1 93.3 -> 95.3%), 2K
0.0144 -> 0.0154 (top-1 95.2 -> 96.3%). As submitted (one chain) it was
0.0240 / 0.0168. Prompts, 4 GPUs, launch config, two rounds: 7.8K 3,912
-> 3,992, 18K 5,450 -> 5,599, 65K 7,001 -> 7,102, 123K 7,240 -> 7,323 tok/s.

Co-Authored-By: Klaus Friedel <fks@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016ZHWKWn7UYZV64KwpGrWuN
Niko1221 added a commit that referenced this pull request Oct 4, 2026
…perimental build only (PR #600, #395 follow-up)

STRATA_EXPERIMENTAL_SM60 now reaches every target (add_compile_definitions). prompt_attn_v70_kernel with its launcher,
and Gemm::bf16's fp32 path for Pascal, exist only under it: the ready-made engine (sm_75+) loads no extra kernels for
them, while the experimental build's sm_60/61/70 cards get them.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Niko1221 added a commit that referenced this pull request Oct 4, 2026
…e; --cuda 12|13 (#395 #627 #540 #600 #601)

CUDA 13 dropped Pascal and Volta. A model whose GPUs include one (its oldest card decides: one engine runs per model)
now runs the experimental CUDA 12 engine in engine-cuda12/ - the ready-made strata-windows-x64-cuda12.zip with NVIDIA's
CUDA 12 pip libraries, or compiled here with a CUDA 12.x toolkit (Linux; STRATA_NVCC picks one, #601) - and setup says
why. engine/ and every model on it stay as they were.
- the cards are an opt-in: naming one (--gpu / --gpus), --cuda 12, STRATA_EXPERIMENTAL_SM60=1, or a PC with no newer
  NVIDIA card and no supported AMD card; a PC with a newer card keeps recommending it
- --cuda 12|13 (or STRATA_CUDA) overrides the choice and is kept, with a warning where it cannot work (recommend,
  never force); --cuda 12 also runs with a driver older than 580 (525+), which the stop now mentions
- at a start, a Pascal / Volta card added to a CUDA 13 model moves that model's config to the CUDA 12 engine
- updates look at both engine folders; a compiled CUDA 12 engine builds in build-cuda12/
- an RTX 50 card in a CUDA 12 engine is a warning (CUDA 12.8+ builds it; #220 crashed with 12.8), no longer a stop
The setup golden test (every recommended config on five PCs) is unchanged; tools/test_setup_older_gpus.py covers the rest.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Niko1221 added a commit that referenced this pull request Oct 4, 2026
…ine and how to opt in

docs/OLDER_GPUS.md: Pascal / Volta through the CUDA 12 engine (#395 #600 #540 #655), RTX 20's STRATA_BF16_TC opt-in,
AMD gfx1031 (#524), gfx1012 (#442) and gfx906 (#638, #677) with the reporters' numbers; README, AI_SETUP, AMD_HIP and
NVIDIA_V100 point to it.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@Niko1221

Niko1221 commented Oct 4, 2026

Copy link
Copy Markdown
Owner

Merged for the next release, with your commits and docs/NVIDIA_V100.md. The kernel and its launcher are compiled into the experimental build only (-DSTRATA_EXPERIMENTAL_SM60=ON), so the ready-made engine loads no extra kernels. Thanks for the teacher-forced comparison with controls.

@Niko1221 Niko1221 closed this Oct 4, 2026
eelgaev added a commit to eelgaev/Strata-AC922 that referenced this pull request Oct 4, 2026
217 upstream commits (0.1.38 -> 0.1.39: Niko1221#646 decode kernels and zero-doorbell
verify graph, Niko1221#603 long-context top-k, Niko1221#583 byte-budget ring, Niko1221#598 pipelined
layer split, Niko1221#578 helper GPUs, Niko1221#663, Niko1221#540, Niko1221#600 in the experimental build,
batch slots Niko1221#465, the SYCL port, older-CPU builds, ...). 23 files conflicted
(~70 hunks); every hunk was resolved by hand and checked against both sides.

Resolution rules:
- The prompt path's stage overlap: upstream's Niko1221#598 (equivalent to our
  e85f7ee; run() drains the whole chain on every exit), with our
  release_inherited_pin in the stage threads and our early ids copy for the
  host grouping (a5a3254) kept.
- STRATA_FP16=load's form-aware weights kept wherever upstream's new code
  assumed BF16: the shared-expert gate (sigmoid+scale fused as upstream),
  GDN alpha/beta (our kernels; upstream's new gdn_step_commit_kernel added),
  the hc v3 kernels (upstream's EXACT_T with our dot8w).
- verify.cpp: upstream's all-resident fast path, plan copy and Niko1221#578 rows,
  with our 2-GPU fetch overlap and partner fetch back in the non-resident
  branch; mapped buffers stay portable (the partner reads them).
- Volta prompt attention: upstream's dispatch (the m8n8k4 kernel on sm_70
  in this build) with our split hi/lo accumulator chains inside it; the
  wmma kernel stays opt-in (STRATA_ATTN_WMMA=1 without STRATA_ATTN_M884).
- qsa_decode_attn.cu: upstream's (our adf56cc imported the same PR Niko1221#540;
  upstream's is it plus review fixes, bit-exact).
- POWER / aarch64: upstream's new x86 intrinsics in verify.cpp through the
  portable strata_store_fence / strata_cpu_pause; its AVX2 start-up checks
  and log line behind x86 guards; stubs for the new CPU probes; the router
  lookahead keeps portable.cpp's VSX dot on non-x86 (upstream's dispatch
  would have sent POWER to its scalar fallback); the pool's ThreadAffinity
  (any CPU count) with our note_host_pin; SMT2 selection with Niko1221#642's sort.
- setup.py / tests: both sides (CUDA 12 engine, ISA floor, ARM / non-x86).

Checked:
- every line either side added since 0.1.38 is in the merge or replaced on
  purpose (script over all 45 files both sides changed);
- all parity tests pass (iq, native_expert on the real shards, mmvq_multi,
  gr, gdn, gdn_rec, qsa, qsa_topk, elementwise, router_dot, shared_expert,
  kv_*, sampler, rope, s2/s_gemv, gemm_bf16, ...);
- teacher-forced 2K and 32K logs byte-identical to the pre-merge build
  (4 GPUs, launch config);
- 4 GPUs: decode text identical, same windows and acceptance, 28.25 ->
  26.9 ms/window (~86 -> ~90 tok/s); prompts 7.8K 3,992 -> 4,038, 65K
  7,102 -> 7,172, 123K 7,323 -> 7,334 tok/s; --prefill-ring 320 applies;
- 2 GPUs: decode texts identical to the pre-merge binary on three prompts,
  decode 61.5-71.0 -> 63.5-72.7 tok/s, 65K prompt 3,975 -> 4,083.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016ZHWKWn7UYZV64KwpGrWuN
Encapsulate pushed a commit to Encapsulate/Strata that referenced this pull request Oct 5, 2026
…perimental build only (PR Niko1221#600, Niko1221#395 follow-up)

STRATA_EXPERIMENTAL_SM60 now reaches every target (add_compile_definitions). prompt_attn_v70_kernel with its launcher,
and Gemm::bf16's fp32 path for Pascal, exist only under it: the ready-made engine (sm_75+) loads no extra kernels for
them, while the experimental build's sm_60/61/70 cards get them.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Niko1221 added a commit that referenced this pull request Oct 6, 2026
…perimental build only (PR #600, #395 follow-up)

STRATA_EXPERIMENTAL_SM60 now reaches every target (add_compile_definitions). prompt_attn_v70_kernel with its launcher,
and Gemm::bf16's fp32 path for Pascal, exist only under it: the ready-made engine (sm_75+) loads no extra kernels for
them, while the experimental build's sm_60/61/70 cards get them.
Niko1221 added a commit that referenced this pull request Oct 6, 2026
…e; --cuda 12|13 (#395 #627 #540 #600 #601)

CUDA 13 dropped Pascal and Volta. A model whose GPUs include one (its oldest card decides: one engine runs per model)
now runs the experimental CUDA 12 engine in engine-cuda12/ - the ready-made strata-windows-x64-cuda12.zip with NVIDIA's
CUDA 12 pip libraries, or compiled here with a CUDA 12.x toolkit (Linux; STRATA_NVCC picks one, #601) - and setup says
why. engine/ and every model on it stay as they were.
- the cards are an opt-in: naming one (--gpu / --gpus), --cuda 12, STRATA_EXPERIMENTAL_SM60=1, or a PC with no newer
  NVIDIA card and no supported AMD card; a PC with a newer card keeps recommending it
- --cuda 12|13 (or STRATA_CUDA) overrides the choice and is kept, with a warning where it cannot work (recommend,
  never force); --cuda 12 also runs with a driver older than 580 (525+), which the stop now mentions
- at a start, a Pascal / Volta card added to a CUDA 13 model moves that model's config to the CUDA 12 engine
- updates look at both engine folders; a compiled CUDA 12 engine builds in build-cuda12/
- an RTX 50 card in a CUDA 12 engine is a warning (CUDA 12.8+ builds it; #220 crashed with 12.8), no longer a stop
The setup golden test (every recommended config on five PCs) is unchanged; tools/test_setup_older_gpus.py covers the rest.
Niko1221 added a commit that referenced this pull request Oct 6, 2026
…ine and how to opt in

docs/OLDER_GPUS.md: Pascal / Volta through the CUDA 12 engine (#395 #600 #540 #655), RTX 20's STRATA_BF16_TC opt-in,
AMD gfx1031 (#524), gfx1012 (#442) and gfx906 (#638, #677) with the reporters' numbers; README, AI_SETUP, AMD_HIP and
NVIDIA_V100 point to it.
jmnargi pushed a commit to jmnargi/Strata-V100 that referenced this pull request Oct 6, 2026
Port of oldlocal commit 4672cf9 ("kernels (sm_70): the prompt attention's
latency pipeline - 2.2x over the FP32 kernel at 32K") onto the Niko1221#600
prompt_attn_v70_kernel, the m8n8k4 Volta kernel now inline in
qsa_prompt_attn.cu.  Still gated on STRATA_EXPERIMENTAL_SM60, so the
ready-made engine keeps exactly the code it had.

Two of the commit's three changes port; the third (splitting the dependent
WMMA chains into f0/f1 and fh/fl) is already inherent to the mma884 kernel -
its scores run two tg[rb] chains and its p.v four tmp[rb][nt] chains - so
porting it would only change the summation order.  The two ported, measured
on a V100-SXM2-16GB (CUDA 12.8):

* the staging loop issues every global load of a thread before any of its
  stores (2-4 in flight), instead of paying the HBM latency per piece;
* the next chunk's ids/page-table lookups double-buffer (row[2][CH]) and run
  just before the previous p.v, where their latency hides.

The original commit measured, on the Niko1221#371 kernel, 2,048 queries of a 32K
selection: 34.4 -> 15.8 ms (2.18x) int8, 33.5 -> 15.4 ms (2.17x) fp16 KV,
35.6 -> 20.3 ms (1.76x) K8V4 (its q4_0 V dequantizes to FP16 at staging, the
sm_75/80 kernel's same trade).

This port, same 2,048 queries of a 32K selection (qsa_prompt_attn_sm70_bench,
which also gained the K8V4 pools): the Volta kernel goes int8 12.11 -> 10.25 ms,
fp16 KV 25.70 -> 17.39 ms, K8V4 25.71 -> 24.12 ms, so against the FP32 decode
kernel int8 rises 1.73x -> 2.05x and fp16 0.80x -> 1.18x (K8V4, 0.85x -> 0.91x,
keeps main's Niko1221#600 dequant-to-FP16 trade).

qsa_prompt_attn_parity passes all four cases.  An A/B against the unpatched
kernel shows the kernel's output is unchanged - every FP64 and new-vs-old
figure is identical before and after (int8 5.08e-6, fp16 5.29e-6 vs FP64,
within the 4x gate).

(cherry picked from commit 54748a5)
anon761 pushed a commit to anon761/Strata-upstream that referenced this pull request Oct 6, 2026
…perimental build only (PR Niko1221#600, Niko1221#395 follow-up)

STRATA_EXPERIMENTAL_SM60 now reaches every target (add_compile_definitions). prompt_attn_v70_kernel with its launcher,
and Gemm::bf16's fp32 path for Pascal, exist only under it: the ready-made engine (sm_75+) loads no extra kernels for
them, while the experimental build's sm_60/61/70 cards get them.
anon761 pushed a commit to anon761/Strata-upstream that referenced this pull request Oct 6, 2026
…e; --cuda 12|13 (Niko1221#395 Niko1221#627 Niko1221#540 Niko1221#600 Niko1221#601)

CUDA 13 dropped Pascal and Volta. A model whose GPUs include one (its oldest card decides: one engine runs per model)
now runs the experimental CUDA 12 engine in engine-cuda12/ - the ready-made strata-windows-x64-cuda12.zip with NVIDIA's
CUDA 12 pip libraries, or compiled here with a CUDA 12.x toolkit (Linux; STRATA_NVCC picks one, Niko1221#601) - and setup says
why. engine/ and every model on it stay as they were.
- the cards are an opt-in: naming one (--gpu / --gpus), --cuda 12, STRATA_EXPERIMENTAL_SM60=1, or a PC with no newer
  NVIDIA card and no supported AMD card; a PC with a newer card keeps recommending it
- --cuda 12|13 (or STRATA_CUDA) overrides the choice and is kept, with a warning where it cannot work (recommend,
  never force); --cuda 12 also runs with a driver older than 580 (525+), which the stop now mentions
- at a start, a Pascal / Volta card added to a CUDA 13 model moves that model's config to the CUDA 12 engine
- updates look at both engine folders; a compiled CUDA 12 engine builds in build-cuda12/
- an RTX 50 card in a CUDA 12 engine is a warning (CUDA 12.8+ builds it; Niko1221#220 crashed with 12.8), no longer a stop
The setup golden test (every recommended config on five PCs) is unchanged; tools/test_setup_older_gpus.py covers the rest.
anon761 pushed a commit to anon761/Strata-upstream that referenced this pull request Oct 6, 2026
…ine and how to opt in

docs/OLDER_GPUS.md: Pascal / Volta through the CUDA 12 engine (Niko1221#395 Niko1221#600 Niko1221#540 Niko1221#655), RTX 20's STRATA_BF16_TC opt-in,
AMD gfx1031 (Niko1221#524), gfx1012 (Niko1221#442) and gfx906 (Niko1221#638, Niko1221#677) with the reporters' numbers; README, AI_SETUP, AMD_HIP and
NVIDIA_V100 point to it.
anon761 pushed a commit to anon761/Strata-upstream that referenced this pull request Oct 6, 2026
…perimental build only (PR Niko1221#600, Niko1221#395 follow-up)

STRATA_EXPERIMENTAL_SM60 now reaches every target (add_compile_definitions). prompt_attn_v70_kernel with its launcher,
and Gemm::bf16's fp32 path for Pascal, exist only under it: the ready-made engine (sm_75+) loads no extra kernels for
them, while the experimental build's sm_60/61/70 cards get them.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
anon761 pushed a commit to anon761/Strata-upstream that referenced this pull request Oct 6, 2026
…e; --cuda 12|13 (Niko1221#395 Niko1221#627 Niko1221#540 Niko1221#600 Niko1221#601)

CUDA 13 dropped Pascal and Volta. A model whose GPUs include one (its oldest card decides: one engine runs per model)
now runs the experimental CUDA 12 engine in engine-cuda12/ - the ready-made strata-windows-x64-cuda12.zip with NVIDIA's
CUDA 12 pip libraries, or compiled here with a CUDA 12.x toolkit (Linux; STRATA_NVCC picks one, Niko1221#601) - and setup says
why. engine/ and every model on it stay as they were.
- the cards are an opt-in: naming one (--gpu / --gpus), --cuda 12, STRATA_EXPERIMENTAL_SM60=1, or a PC with no newer
  NVIDIA card and no supported AMD card; a PC with a newer card keeps recommending it
- --cuda 12|13 (or STRATA_CUDA) overrides the choice and is kept, with a warning where it cannot work (recommend,
  never force); --cuda 12 also runs with a driver older than 580 (525+), which the stop now mentions
- at a start, a Pascal / Volta card added to a CUDA 13 model moves that model's config to the CUDA 12 engine
- updates look at both engine folders; a compiled CUDA 12 engine builds in build-cuda12/
- an RTX 50 card in a CUDA 12 engine is a warning (CUDA 12.8+ builds it; Niko1221#220 crashed with 12.8), no longer a stop
The setup golden test (every recommended config on five PCs) is unchanged; tools/test_setup_older_gpus.py covers the rest.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
anon761 pushed a commit to anon761/Strata-upstream that referenced this pull request Oct 6, 2026
…ine and how to opt in

docs/OLDER_GPUS.md: Pascal / Volta through the CUDA 12 engine (Niko1221#395 Niko1221#600 Niko1221#540 Niko1221#655), RTX 20's STRATA_BF16_TC opt-in,
AMD gfx1031 (Niko1221#524), gfx1012 (Niko1221#442) and gfx906 (Niko1221#638, Niko1221#677) with the reporters' numbers; README, AI_SETUP, AMD_HIP and
NVIDIA_V100 point to it.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Niko1221 pushed a commit that referenced this pull request Oct 7, 2026
…ccumulator chains

Follow-up to #600 (fks's mma.m8n8k4 prompt attention for sm_70).

The kernel splits q (for q.k) and p (for p.v) into FP16 hi + lo halves
and runs both products into the same accumulator. Volta's tensor cores
don't keep full FP32 precision while they accumulate, so once the hi
products are in the accumulator most of the much smaller lo
contribution gets truncated away, and the split buys less than it
should. Giving the lo products their own chain and adding the two in
FP32 at the end fixes that.

qsa_prompt_attn_parity, one V100-SXM2-16GB, 2,048 queries, error vs the
FP64 reference (the FP32 kernel in brackets):

  ctx 8,192    5.88e-6 -> 3.02e-6   (2.14e-6)   11.94 -> 12.20 ms
  ctx 32,768   5.08e-6 -> 2.33e-6   (2.37e-6)   12.20 -> 12.38 ms
  ctx 131,072  5.35e-6 -> 2.75e-6   (1.81e-6)   12.34 -> 12.51 ms

Registers unchanged (166 / 226 / 163 for modes 0 / 1 / 3), no spills.
docs/NVIDIA_V100.md updated for the new error level.
0xrjman pushed a commit to 0xrjman/Strata that referenced this pull request Oct 7, 2026
…ccumulator chains

Follow-up to Niko1221#600 (fks's mma.m8n8k4 prompt attention for sm_70).

The kernel splits q (for q.k) and p (for p.v) into FP16 hi + lo halves
and runs both products into the same accumulator. Volta's tensor cores
don't keep full FP32 precision while they accumulate, so once the hi
products are in the accumulator most of the much smaller lo
contribution gets truncated away, and the split buys less than it
should. Giving the lo products their own chain and adding the two in
FP32 at the end fixes that.

qsa_prompt_attn_parity, one V100-SXM2-16GB, 2,048 queries, error vs the
FP64 reference (the FP32 kernel in brackets):

  ctx 8,192    5.88e-6 -> 3.02e-6   (2.14e-6)   11.94 -> 12.20 ms
  ctx 32,768   5.08e-6 -> 2.33e-6   (2.37e-6)   12.20 -> 12.38 ms
  ctx 131,072  5.35e-6 -> 2.75e-6   (1.81e-6)   12.34 -> 12.51 ms

Registers unchanged (166 / 226 / 163 for modes 0 / 1 / 3), no spills.
docs/NVIDIA_V100.md updated for the new error level.
merbanan pushed a commit to merbanan/Strata that referenced this pull request Oct 16, 2026
Port of oldlocal commit 4672cf9 ("kernels (sm_70): the prompt attention's
latency pipeline - 2.2x over the FP32 kernel at 32K") onto the Niko1221#600
prompt_attn_v70_kernel, the m8n8k4 Volta kernel now inline in
qsa_prompt_attn.cu.  Still gated on STRATA_EXPERIMENTAL_SM60, so the
ready-made engine keeps exactly the code it had.

Two of the commit's three changes port; the third (splitting the dependent
WMMA chains into f0/f1 and fh/fl) is already inherent to the mma884 kernel -
its scores run two tg[rb] chains and its p.v four tmp[rb][nt] chains - so
porting it would only change the summation order.  The two ported, measured
on a V100-SXM2-16GB (CUDA 12.8):

* the staging loop issues every global load of a thread before any of its
  stores (2-4 in flight), instead of paying the HBM latency per piece;
* the next chunk's ids/page-table lookups double-buffer (row[2][CH]) and run
  just before the previous p.v, where their latency hides.

The original commit measured, on the Niko1221#371 kernel, 2,048 queries of a 32K
selection: 34.4 -> 15.8 ms (2.18x) int8, 33.5 -> 15.4 ms (2.17x) fp16 KV,
35.6 -> 20.3 ms (1.76x) K8V4 (its q4_0 V dequantizes to FP16 at staging, the
sm_75/80 kernel's same trade).

This port, same 2,048 queries of a 32K selection (qsa_prompt_attn_sm70_bench,
which also gained the K8V4 pools): the Volta kernel goes int8 12.11 -> 10.25 ms,
fp16 KV 25.70 -> 17.39 ms, K8V4 25.71 -> 24.12 ms, so against the FP32 decode
kernel int8 rises 1.73x -> 2.05x and fp16 0.80x -> 1.18x (K8V4, 0.85x -> 0.91x,
keeps main's Niko1221#600 dequant-to-FP16 trade).

qsa_prompt_attn_parity passes all four cases.  An A/B against the unpatched
kernel shows the kernel's output is unchanged - every FP64 and new-vs-old
figure is identical before and after (int8 5.08e-6, fp16 5.29e-6 vs FP64,
within the 4x gate).

(cherry picked from commit 54748a5)
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.

3 participants