Skip to content

fix(cpu): default scaledDotProductAttention scale to 1/sqrt(headDim) (#860) - #880

Merged
michalharakal merged 1 commit into
developfrom
fix/860-sdpa-scale
Jul 24, 2026
Merged

fix(cpu): default scaledDotProductAttention scale to 1/sqrt(headDim) (#860)#880
michalharakal merged 1 commit into
developfrom
fix/860-sdpa-scale

Conversation

@michalharakal

Copy link
Copy Markdown
Contributor

Closes #860.

Problem

TensorOps.scaledDotProductAttention's scale parameter defaults to 0f, documented as "defaults to 1/sqrt(headDim)". The CPU backend applied the value literally, so any call that relied on the default multiplied every attention score by zero — the softmax collapsed to a uniform distribution and the attention pattern was silently discarded. No error, plausible-looking output shapes; only the numbers are wrong.

Fix

Resolve scale == 0f to 1 / sqrt(headDim) inside the CPU kernel, matching the documented contract. An explicitly passed scale (including a genuinely tiny one) is untouched.

Test

SDPAShapeValidationTest.default_scale_uses_one_over_sqrt_head_dim_not_zero: the default-scale (scale = 0f) result equals an explicit 1/sqrt(headDim) call, and differs from the near-zero (uniform) degenerate result. Full skainet-backend-cpu jvmTest green.

Found while validating a from-scratch multi-head attention against the fused op — the equivalence test caught the silent flattening. This is the last of the eight issues surfaced by that port.

The op's scale parameter defaults to 0f, documented as meaning
1/sqrt(headDim). The CPU backend applied it literally, so calling SDPA
without an explicit scale multiplied all scores by zero — the softmax
collapsed to a uniform average and the attention pattern was silently
discarded. Resolve scale == 0f to 1/sqrt(headDim) in the CPU kernel.

Adds a regression test: the default-scale result equals an explicit
1/sqrt(headDim) call and differs from the near-zero (uniform) result.

Closes #860
@michalharakal
michalharakal requested a review from aharakal July 24, 2026 18:05
@michalharakal
michalharakal merged commit 7a42129 into develop Jul 24, 2026
13 checks passed
@michalharakal
michalharakal deleted the fix/860-sdpa-scale branch July 24, 2026 18:51
MacOS pushed a commit to MacOS/SKaiNET that referenced this pull request Jul 27, 2026
Bump version 0.36.0 -> 0.37.0 (gradle.properties, docs/antora.yml,
README quickstart). Promote CHANGELOG [Unreleased] to [0.37.0]: Lstm
layer (SKaiNET-developers#824), real Dropout masking (SKaiNET-developers#867), LR schedules and mutable
optimizer lr (SKaiNET-developers#866), optional-bias and open Linear (SKaiNET-developers#870, SKaiNET-developers#875),
androidNative IO targets (SKaiNET-developers#836, SKaiNET-developers#842, SKaiNET-developers#845), the SDPA default-scale fix
(SKaiNET-developers#880), three autograd fixes (SKaiNET-developers#877), the argMax DAG output spec (SKaiNET-developers#878),
tokenizer BPE inference and N-D gather (SKaiNET-developers#879), plus the CI/docs
supply-chain hardening and toolchain bumps. Refresh README "What's New"
and add a Contributors (0.37.0) section.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
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.

CPU scaledDotProductAttention applies scale=0 literally instead of the documented 1/sqrt(headDim) default

2 participants