Skip to content

[AutoSP] Rebuild query-sharded attention masks before SDPA - #8761

Merged
tohtana merged 5 commits into
deepspeedai:masterfrom
jinyouzhi:fix-autosp-attn-mask
Oct 12, 2026
Merged

tohtana merged 5 commits into
deepspeedai:masterfrom
jinyouzhi:fix-autosp-attn-mask

Conversation

@jinyouzhi

@jinyouzhi jinyouzhi commented Oct 6, 2026 •

Copy link
Copy Markdown
Contributor

Split out of #8457. This PR is stacked on #8760. It contains that PR's commit, so please review only the last commit.

Problem

AutoSP shards input_ids, labels and position_ids along the sequence dimension. A model can build its causal or attention mask from the sharded position_ids, which gives the mask the shape [B, 1, S/sp, S]. After the Ulysses all-to-all, SDPA sees all S queries, but the mask still covers only S/sp of them. The run then fails with a shape mismatch: size of tensor a (s) must match ... (s//2).

Fix

  • Add a custom op autosp::all_gather_sequence(input, dim) with a fake (meta) implementation.
  • In pass_insert_attention_all_to_all, check whether the mask's query dimension equals the local sequence length. If it does, all-gather the mask along dim -2 over the SP group. The mask can be passed as a kwarg or positionally. When several layers share one mask node, it is gathered only once.
  • If the mask's key dimension is also sharded, it cannot be rebuilt correctly from the local pieces, so raise a clear error.
  • Run pass_propagate_shapes once before the attention pass so that the mask shapes are current. This is why the PR depends on the get_node_shape_meta fix.
  • all_gather_sequence has a backward pass, an autosp::reduce_scatter_sequence op, so masks that require gradients (for example a learnable position bias) also work.
  • A mask with a full head dimension is redistributed like the query: if its query rows are sharded, it goes through all-to-all; otherwise each rank keeps only its own block of heads. A broadcast key dimension of 1 is never treated as sharded.
  • Document the behavior under AutoSP Limitations.

Tests

Added TestAutoSPAttentionMask (world_size=2):

  • With a learnable mask bias (shared, per-head with sharded queries, or per-head with full queries), the loss and all parameter gradients match a single-device reference.
  • With a query-sharded mask, passed as a kwarg and positionally, the forward loss matches a single-device full-sequence reference.
  • A mask whose key dimension is sharded is rejected with a clear error.

Without the fix, all 3 tests fail. With the fix but without the fx.py change, all 3 also fail.

Hardware: 8× Intel Arc Pro B70 (XPU), torch 2.14.0.dev+xpu, transformers 5.17. 42 AutoSP tests pass. TestAutoSPCompile is excluded because of a pre-existing environment failure that also happens on master.

jinyouzhi and others added 2 commits October 6, 2026 18:27
get_node_shape_meta() used `meta["val"] or meta["example_value"]`, which
calls bool() on the stored tensor. Once shape propagation fills meta["val"]
with a real tensor, this raises for multi-element tensors and silently
falls back to example_value for a zero-valued scalar. Compare with None
instead.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: Jin, Youzhi <youzhi.jin@intel.com>
AutoSP shards inputs along the sequence dimension before Ulysses
all-to-all. After the all-to-all, SDPA gets the full query sequence, but
an attention mask built from sharded position_ids still has only the
local query length. That fails with a shape mismatch.

Add an autosp::all_gather_sequence op and use it to gather the mask
query dimension (-2) over the SP group before the mask reaches SDPA.
Masks are gathered once even when several layers share them. A mask
whose key dimension is also sharded cannot be rebuilt from local
pieces, so raise a clear error for that case.

Depends on the get_node_shape_meta fix, because the comparison reads
shapes after FakeTensor propagation.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: Jin, Youzhi <youzhi.jin@intel.com>

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.

Copilot review overview

🟡 Changes recommended

Differentiable masks lack autograd support, and valid singleton key dimensions can be incorrectly rejected.

Review effort: Balanced
Findings: 2 Medium severity

Open (2)
What changed in this PR

Adds AutoSP support for rebuilding query-sharded SDPA attention masks after Ulysses redistribution.

Changes:

  • Adds sequence all-gather custom operation and mask-rewriting pass.
  • Refreshes shape metadata before attention transformation.
  • Adds documentation and distributed coverage for positional and keyword masks.
File Description
deepspeed/​compile/​custom_ops/​all_to_all.py Adds sequence all-gather operation and fake implementation.
deepspeed/​compile/​passes/​sp_compile.py Detects and gathers query-sharded SDPA masks.
deepspeed/​compile/​fx.py Includes the stacked shape-metadata fix.
docs/​code-docs/​source/​training.rst Documents attention-mask limitations.
tests/​unit/​v1/​compile/​test_compile_autosp.py Adds mask integration and metadata tests.

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

Comment thread deepspeed/compile/custom_ops/all_to_all.py
Comment thread deepspeed/compile/passes/sp_compile.py Outdated
jinyouzhi and others added 2 commits October 9, 2026 14:18
Address review on the attention mask gather:

- Register autograd for autosp::all_gather_sequence. Every rank uses the
  whole gathered mask, so the backward sums the gradient over the SP group
  and keeps the local shard. A new autosp::reduce_scatter_sequence op
  does this, so the backward graph does not capture process groups.
- Do not treat a broadcast key dimension of 1 as sharded.
- Redistribute masks with a full head dimension the same way as the
  query: all-to-all them when their query rows are sharded, and
  otherwise keep only this rank's block of heads.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: Jin, Youzhi <youzhi.jin@intel.com>
SDPA reads a 3D mask as [heads, queries, keys]; add the batch dimension
before redistributing its heads. With sequence_parallel_size 1 the mask is
already complete, and its key dimension must not be mistaken for a sharded
one.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: Jin, Youzhi <youzhi.jin@intel.com>

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.

🟢 Approval recommended

The mask transformations, gradient handling, validation, documentation, and distributed coverage are consistent and complete.

0 open findings

2 resolved since last review

🧠 Review effort: Balanced

@tohtana tohtana left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Thank you for your contributions, @jinyouzhi! This is a significant improvement, and I don't see a clear issue. Let's merge it.

@tohtana
tohtana enabled auto-merge October 11, 2026 23:05
@tohtana
tohtana added this pull request to the merge queue Oct 11, 2026
Merged via the queue into deepspeedai:master with commit ee222bf Oct 12, 2026
15 checks passed
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