Skip to content

Fix missing proxy fences around TMA accesses - #25

Merged
esp0r merged 1 commit into
masterfrom
fix_barrier
Jul 28, 2026
Merged

Fix missing proxy fences around TMA accesses#25
esp0r merged 1 commit into
masterfrom
fix_barrier

Conversation

@esp0r

@esp0r esp0r commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Summary

Fixes the missing cross-proxy fences reported in #24 (found by auditing the SM90 forward kernels against the PTX ISA proxy model):

  • fwd_kernel2.cuh — FP32 state store: smem_cvt_bf16_to_fp32() writes state_fp32_buf via the generic proxy, but only __syncthreads() separated it from the TMA store (async proxy). Added fence_view_async_shared() executed by all writing threads before the rendezvous — same pattern as the existing per-iteration fence before producer_commit.
  • fwd_kernel2.cuh — zero-init state (HasStateIn=false): with an empty sequence (t_tiles == 0, reachable in varlen batches) the main loop never runs, so no fence ever covered the generic zero-init writes before the BF16 TMA state store → stale smem could be written to final_state. Added fence_view_async_shared() before the __syncthreads().
  • fwd_kernel1.cuh / fwd_kernel2.cuh — 3 standalone mbarriers: mbarrier.init (generic write) was used by TMA complete-tx (async proxy RMW) without fence.mbarrier_init. Added fence_barrier_init() after each init, matching CUTLASS PipelineTmaAsync::init_barriers.

All changes are writer-side fences placed immediately after the last write and before the existing rendezvous (__syncthreads / barrier arrive), per the PTX generic→async publication pattern. 6 lines added, no other changes.

Test

  • python setup.py build_ext --inplace — clean build (CUDA 13.0, torch 2.9.1)
  • python tests/test_fwd.py — fixed-length and varlen cases both bit-exact vs torch reference (avg/max rtol/atol = 0.0)

Closes #24

- add fence_view_async_shared() after generic smem writes that are
  later read by TMA stores: fp32 state conversion path, and the
  zero-init state path (reachable when t_tiles == 0 for empty varlen
  sequences, where the main loop's per-iteration fence never runs)
- add fence_barrier_init() after mbarrier.init for the standalone
  transaction barriers (kernel1 tma_load_barrier, kernel2
  state_acc_tma_barrier x2), matching CUTLASS PipelineTmaAsync

Closes #24

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@esp0r
esp0r merged commit a8c7335 into master Jul 28, 2026
esp0r added a commit that referenced this pull request Jul 29, 2026
- add fence_view_async_shared() after generic smem writes that are
  later read by TMA stores: fp32 state conversion path, and the
  zero-init state path (reachable when t_tiles == 0 for empty varlen
  sequences, where the main loop's per-iteration fence never runs)
- add fence_barrier_init() after mbarrier.init for the standalone
  transaction barriers (kernel1 tma_load_barrier, kernel2
  state_acc_tma_barrier x2), matching CUTLASS PipelineTmaAsync

Closes #24
@xxr3376
xxr3376 deleted the fix_barrier branch July 30, 2026 07:14
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.

Missing proxy fences around TMA accesses (smem→TMA store, mbarrier init)

1 participant