Skip to content

[Feat]support sequence parallel all2all with transpose example - #21

Merged
chengyupku merged 2 commits into
tile-ai:mainfrom
JiaqingFu:fjq_dev
Sep 5, 2025
Merged

chengyupku merged 2 commits into
tile-ai:mainfrom
JiaqingFu:fjq_dev

Conversation

@JiaqingFu

@JiaqingFu JiaqingFu commented Sep 5, 2025 •

Copy link
Copy Markdown

pre attn is all to all Before attention and post attn is all to all after attetnion for sequence parallel

Summary by CodeRabbit

  • New Features

    • Added distributed all-to-all transpose examples for pre- and post-attention, including PyTorch golden references, NVSHMEM-backed kernels, verification helpers, and CLI options (batch size, sequence length, heads, head dim, dtype, warmup, repeat, source print).
    • Added round-trip consistency validation in the post-attention example.
  • Bug Fixes

    • Improved synchronization reliability in the pre-attention all-to-all example by inserting a memory fence to prevent ordering issues during signaling.

Copilot AI review requested due to automatic review settings September 5, 2025 02:15
@coderabbitai

coderabbitai Bot commented Sep 5, 2025 •

Copy link
Copy Markdown

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Walkthrough

Adds two new distributed example scripts demonstrating all-to-all transpose (pre-attn) and reverse all-to-all transpose (post-attn) with PyTorch golden references, TileLang NVSHMEM kernels, CLI, and verification. Also inserts a memory fence after an NVSHMEM signal in the existing pre-attn all-to-all example.

Changes

Cohort / File(s) Summary
New: Post-attn reverse all-to-all transpose example
examples/distributed/example_post_attn_all2all_transpose.py
New end-to-end script: PyTorch golden reference, TileLang NVSHMEM kernel builder for reverse transpose, verification helpers, CLI, golden-reference test, and forward+reverse roundtrip test.
New: Pre-attn all-to-all transpose example
examples/distributed/example_pre_attn_all2all_transpose.py
New end-to-end script: PyTorch golden reference, TileLang NVSHMEM kernel builder for transpose, NVSHMEM run path, verification, CLI, and golden-reference test.
Sync semantics tweak
examples/distributed/example_pre_attn_all2all.py
Inserts T.fence() immediately after NVSHMEM signal in tx==0 path before signal_wait loop; no other logic changes.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant User
  participant Script as Pre-attn Transpose Script
  participant Torch as PyTorch Ref
  participant Kernel as TileLang Kernel
  participant NV as NVSHMEM Runtime
  participant PEs as PEs (Ranks)

  User->>Script: run test_transpose_all_to_all_with_golden_reference()
  Script->>Torch: all_to_all + reshape (golden reference)
  Script->>Kernel: compile(generate params)
  Script->>NV: allocate/copy inputs
  Kernel->>NV: signal + (fence) + wait loops
  NV->>PEs: per-(batch, head) transfers (all-to-all transpose)
  PEs-->>NV: data delivered
  NV-->>Script: output buffer
  Script->>Script: verify_results(tilelang vs torch)
Loading
sequenceDiagram
  autonumber
  participant User
  participant Script as Post-attn Reverse Transpose Script
  participant Torch as PyTorch Ref
  participant Kernel as TileLang Reverse Kernel
  participant NV as NVSHMEM Runtime
  participant PEs as PEs (Ranks)

  User->>Script: run test_reverse_transpose_all_to_all_with_golden_reference()
  Script->>Torch: reverse all_to_all + reorder (golden ref)
  Script->>Kernel: compile(generate params)
  Script->>NV: allocate/copy inputs
  Kernel->>NV: putmem_nbi_block + signals + waits
  NV->>PEs: per-(batch, seq) cross-PE transfers
  PEs-->>NV: data delivered
  NV-->>Script: output buffer
  Script->>Script: verify_results(tilelang vs torch)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Poem

A rabbit compiles kernels at dawn,
Hops through ranks till tensors are gone;
All-to-all twirls, then back they stream,
Transpose reversed—like a mirrored dream.
With fences set and signals true,
The bytes line up—hip hop, woohoo! 🐇✨

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore or @coderabbit ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@github-actions

github-actions Bot commented Sep 5, 2025

Copy link
Copy Markdown

👋 Hi! Thank you for contributing to the TileLang project.

Please remember to run bash format.sh in the root directory of the project to ensure your changes are properly linted and formatted. This will help ensure your contribution passes the format check.

We appreciate you taking this step! Our team will review your contribution, and we look forward to your awesome work!

🚀

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.

Pull Request Overview

This PR introduces support for sequence parallel all-to-all communication with transpose functionality in distributed attention mechanisms. The implementation provides both pre-attention and post-attention all-to-all operations that convert between sequence-parallel and head-parallel tensor layouts.

Key changes:

  • Adds pre-attention all-to-all with transpose converting from sequence-parallel to head-parallel format
  • Adds post-attention all-to-all with transpose converting from head-parallel back to sequence-parallel format
  • Fixes a missing fence operation in the existing pre-attention all-to-all example

Reviewed Changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.

File Description
examples/distributed/example_pre_attn_all2all_transpose.py New example implementing pre-attention all-to-all with transpose from sequence-parallel to head-parallel format
examples/distributed/example_pre_attn_all2all.py Adds missing fence operation after signal for proper synchronization
examples/distributed/example_post_attn_all2all_transpose.py New example implementing post-attention all-to-all with transpose from head-parallel back to sequence-parallel format

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 2

♻️ Duplicate comments (1)
examples/distributed/example_pre_attn_all2all_transpose.py (1)

115-123: Make transfer size dtype-agnostic (avoid hardcoded 2 bytes)

The code assumes fp16. Compute element size from dtype so fp32/bf16 work too. This was flagged previously—addressing it here closes the loop.

-                    transfer_size = HEAD_DIM * 2  # float16 = 2 bytes
+                    transfer_size = HEAD_DIM * ELEM_NBYTES

Add this near the top of sequence_parallel_all_to_all_transpose (after HEADS_PER_PE):

ELEM_NBYTES = torch.tensor([], dtype=dtype_map[dtype]).element_size()
🧹 Nitpick comments (14)
examples/distributed/example_pre_attn_all2all.py (1)

129-137: Fence after signal: safe, but likely redundant; prefer explicit compare enum for wait

  • Adding T.fence() after T.signal_op is safe, yet the fence before signaling already orders the preceding puts; the post-signal fence adds little. Keep if you’ve observed ordering issues, otherwise consider removing to reduce overhead.
  • Small consistency fix: use T.CmpType.EQ instead of magic 0 to match the other examples.
-                for k in T.serial(PE_num):
-                    T.signal_wait_until(T.address_of(signal[k]), 0, NUM_BLOCKS_X)
+                for k in T.serial(PE_num):
+                    T.signal_wait_until(T.address_of(signal[k]), T.CmpType.EQ, NUM_BLOCKS_X)
examples/distributed/example_pre_attn_all2all_transpose.py (6)

28-30: Remove unused variable rank

rank is assigned but never used. Drop it to silence lint and reduce noise.

-    world_size = dist.get_world_size(group)
-    rank = dist.get_rank(group)
+    world_size = dist.get_world_size(group)

125-137: Ensure completion before kernel exit

After the waits, add T.quiet() to guarantee all nonblocking puts are complete before the kernel returns.

                 T.fence()
                 # Wait for all blocks to complete all sequence positions
                 T.signal_wait_until(T.address_of(signal[target_pe]), T.CmpType.EQ, NUM_BLOCKS_X)
 
+            T.quiet()

1-10: Trim unused imports

os, TensorSupplyType, and perf_fn are unused here.

-import os
-import tilelang
-import tilelang.language as T
-from tilelang.profiler import TensorSupplyType
-from tilelang.distributed.utils import init_distributed, dtype_map, perf_fn
+import os  # REMOVE
+import tilelang
+import tilelang.language as T
+from tilelang.profiler import TensorSupplyType  # REMOVE
+from tilelang.distributed.utils import init_distributed, dtype_map, perf_fn  # drop perf_fn

187-190: Prefer explicit validation over assert in examples

Replace runtime assert with a clear exception so the script behaves the same under optimized Python.

-    assert args.seq_len % PE_num == 0, f"seq_len {args.seq_len} must be divisible by PE_num {PE_num}"
-    assert args.num_heads % PE_num == 0, f"num_heads {args.num_heads} must be divisible by PE_num {PE_num}"
+    if args.seq_len % PE_num != 0:
+        raise ValueError(f"seq_len {args.seq_len} must be divisible by PE_num {PE_num}")
+    if args.num_heads % PE_num != 0:
+        raise ValueError(f"num_heads {args.num_heads} must be divisible by PE_num {PE_num}")

248-251: Optional: add NVSHMEM barrier for symmetry with post-attn example

Not strictly required given the signal/waits, but adding a barrier aligns both examples’ host-side sync.

         # Execute kernel
         kernel(data_src, data_dst, signal)
-
-        return data_dst
+        pynvshmem.nvshmem_barrier_all()
+        return data_dst

264-264: Drop unused variable

verification_passed isn’t used.

-    verification_passed = verify_results(tilelang_output, torch_output, RANK)
+    verify_results(tilelang_output, torch_output, RANK)
examples/distributed/example_post_attn_all2all_transpose.py (7)

28-30: Remove unused variable rank

rank is never used.

-    world_size = dist.get_world_size(group)
-    rank = dist.get_rank(group)
+    world_size = dist.get_world_size(group)

130-139: Comment and accounting mismatch

The comment says “signal the number of head chunks processed,” but the code signals 1 per block (not per head). Either increment by HEADS_PER_PE or adjust the comment to “signal block completion.” Current logic is fine since wait uses NUM_BLOCKS_X.


233-257: Barrier usage: consistent host-side sync

You call nvshmem_barrier_all() here but not in the pre-attn counterpart. Consider keeping both consistent (either both have it or both rely solely on signal/waits).


269-269: Drop unused variable

verification_passed isn’t used.

-    verification_passed = verify_results(tilelang_output, torch_output, RANK)
+    verify_results(tilelang_output, torch_output, RANK)

191-194: Prefer explicit validation over assert in examples

Use exceptions to ensure checks aren’t skipped with optimized Python.

-    assert args.seq_len % PE_num == 0, f"seq_len {args.seq_len} must be divisible by PE_num {PE_num}"
-    assert args.num_heads % PE_num == 0, f"num_heads {args.num_heads} must be divisible by PE_num {PE_num}"
+    if args.seq_len % PE_num != 0:
+        raise ValueError(f"seq_len {args.seq_len} must be divisible by PE_num {PE_num}")
+    if args.num_heads % PE_num != 0:
+        raise ValueError(f"num_heads {args.num_heads} must be divisible by PE_num {PE_num}")

1-10: Trim unused imports

os, TensorSupplyType, and perf_fn aren’t used in this file.

-import os
-import tilelang
-import tilelang.language as T
-from tilelang.profiler import TensorSupplyType
-from tilelang.distributed.utils import init_distributed, dtype_map, perf_fn
+import os  # REMOVE
+import tilelang
+import tilelang.language as T
+from tilelang.profiler import TensorSupplyType  # REMOVE
+from tilelang.distributed.utils import init_distributed, dtype_map, perf_fn  # drop perf_fn

35-45: Stale comment about transpose

The comment mentions a preparatory transpose, but the code sends contiguous [B, H, S_chunk, D]. Update the comment for accuracy.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between ad223f2 and f285750.

📒 Files selected for processing (3)
  • examples/distributed/example_post_attn_all2all_transpose.py (1 hunks)
  • examples/distributed/example_pre_attn_all2all.py (1 hunks)
  • examples/distributed/example_pre_attn_all2all_transpose.py (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (3)
examples/distributed/example_pre_attn_all2all.py (1)
tilelang/language/distributed/multi_device/nvshmem.py (1)
  • fence (61-63)
examples/distributed/example_post_attn_all2all_transpose.py (5)
tilelang/utils/tensor.py (1)
  • TensorSupplyType (15-22)
tilelang/distributed/utils.py (1)
  • perf_fn (217-238)
tilelang/env.py (1)
  • disable_cache (247-248)
examples/distributed/example_pre_attn_all2all_transpose.py (2)
  • main (91-136)
  • torch_sequence_all_to_all_transpose_reference (14-71)
tilelang/language/distributed/multi_device/nvshmem.py (6)
  • get_pe (6-8)
  • putmem_nbi_block (101-109)
  • fence (61-63)
  • signal_op (164-172)
  • signal_wait_until (175-183)
  • quiet (56-58)
examples/distributed/example_pre_attn_all2all_transpose.py (6)
tilelang/utils/tensor.py (1)
  • TensorSupplyType (15-22)
tilelang/distributed/utils.py (1)
  • perf_fn (217-238)
tilelang/env.py (1)
  • disable_cache (247-248)
examples/distributed/example_post_attn_all2all_transpose.py (2)
  • main (94-140)
  • verify_results (145-168)
examples/distributed/example_pre_attn_all2all.py (3)
  • main (92-137)
  • verify_results (142-165)
  • tilelang_all_to_all (238-255)
tilelang/language/distributed/multi_device/nvshmem.py (5)
  • get_pe (6-8)
  • putmem_nbi_block (101-109)
  • fence (61-63)
  • signal_op (164-172)
  • signal_wait_until (175-183)
🪛 Ruff (0.12.2)
examples/distributed/example_post_attn_all2all_transpose.py

29-29: Local variable rank is assigned to but never used

Remove assignment to unused variable rank

(F841)


49-49: Loop control variable pe_idx not used within loop body

(B007)


192-192: Use of assert detected

(S101)


193-193: Use of assert detected

(S101)


269-269: Local variable verification_passed is assigned to but never used

Remove assignment to unused variable verification_passed

(F841)

examples/distributed/example_pre_attn_all2all_transpose.py

29-29: Local variable rank is assigned to but never used

Remove assignment to unused variable rank

(F841)


47-47: Loop control variable pe_idx not used within loop body

(B007)


188-188: Use of assert detected

(S101)


189-189: Use of assert detected

(S101)


264-264: Local variable verification_passed is assigned to but never used

Remove assignment to unused variable verification_passed

(F841)

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