[BugFix] Pass buffer row stride to 2D scan kernel to fix silent miscomputation#2620
[BugFix] Pass buffer row stride to 2D scan kernel to fix silent miscomputation#2620ColmaLiu wants to merge 5 commits into
Conversation
|
👋 Hi! Thank you for contributing to the TileLang project. Please remember to run We appreciate you taking this step! Our team will review your contribution, and we look forward to your awesome work! 🚀 |
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughWalkthrough2D shared-buffer scan lowering now propagates separate source and destination strides through CUDA and HIP scan templates. New tests validate ChangesStrided 2D scan support
Estimated code review effort: 3 (Moderate) | ~25 minutes Sequence Diagram(s)sequenceDiagram
participant SharedScanLowering
participant ScanExtern
participant GPUScanTemplate
participant StridedScanTest
SharedScanLowering->>ScanExtern: pass extents and source/destination strides
ScanExtern->>GPUScanTemplate: invoke 2D cumsum or cummax
GPUScanTemplate->>GPUScanTemplate: address rows or columns using separate strides
StridedScanTest->>GPUScanTemplate: execute non-contiguous shared-region case
GPUScanTemplate-->>StridedScanTest: return scanned output
Possibly related issues
Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/backend/common/op/scan.h`:
- Around line 57-63: Update the 2D scan lowering branch in the scan operation to
account for destination row stride separately from the source stride. Pass the
stride derived from op.dst alongside the existing op.src stride, and update the
corresponding tl::<symbol_prefix>2D kernel run signature and indexing to use
each buffer’s own stride; alternatively validate and reject mismatched layouts
before lowering.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: c090f8a3-eb29-457b-b0ec-8435984ea650
📒 Files selected for processing (4)
src/backend/common/op/scan.hsrc/tl_templates/cuda/scan.hsrc/tl_templates/hip/scan.htesting/python/language/test_tilelang_language_scan.py
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
# Conflicts: # src/tl_templates/cuda/scan.h
Summary
T.cumsumandT.cummaxsilently return wrong results when operating on a 2‑D slice of a shared buffer whose row pitch differs from the slice width. The kernel compiles and runs without errors or crashes, but the numbers are deterministically wrong.Root cause:
LowerSharedScanpasses only the slice's logical extents(H, W)to the device kernel, without any row‑pitch argument. The device templateInclusiveScan2Dthen assumes the row stride equalsW. When the backing buffer is wider than the slice (e.g. a(8, 64)buffer scanned over only the first 40 columns), every row after the first is mis‑addressed by(NBIG − N)elements, corrupting the scan.The bug is architecture‑independent and affects both cumsum and cummax since they share the same
InclusiveScan2Dtemplate. When the region is contiguous (buffer width == slice width) results are bit‑exact.Fixes #2523.
Changes
src/backend/common/op/scan.h— In the 2‑D branch ofLowerSharedScan, compute the buffer's true row stride fromop.src->shape[last_dim]andop.dst->shape[last_dim], and pass them as a(src_stride, dst_stride)pair after the logical extents. Whensrcanddstare different buffers with different row pitches, each gets its own stride — avoiding silent mis‑addressing.src/tl_templates/cuda/scan.h— Split the singlestrideparameter intosrc_stride/dst_stridethroughout the chain:InclusiveScanLine:int stride→int src_stride, int dst_stride. Allsrc[…]indexing usessrc_stride; alldst[…]indexinguses
dst_stride.InclusiveScan1D::run: passes(1, 1)for the two strides (the contiguous in‑lane case is unchanged).InclusiveScan2D::run:int src_stride, int dst_stridereplace the singleint stride. ForAxis == 1the row address issrc + row * src_stride/dst + row * dst_stride; forAxis == 0the column stride is forwarded assrc_stride/dst_stridetoInclusive ScanLine.CumSum2D::run,CumMax2D::run: accept and pass through the stride pair.src/tl_templates/hip/scan.h— Identical changes for the ROCm/HIP template.Testing
testing/python/language/test_tilelang_language_scan.py— Add two test functions (test_cumsum_strided_region,test_cummax_strided_region) following the existing convention. Each iterates over multiple(M, N, NBIG, dim, reverse)combinations that exercise the non‑contiguous path.Summary
T.cumsumandT.cummaxresults on non-contiguous shared-buffer slices.LowerSharedScanthrough CUDA and HIP scan templates.C++ style / lint notes
docs/developer_guide/cpp_style.md.