You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
There are two issues in the descriptorless, linear bulk TMA path:
Non-default load cache hints fail to compile. A bulk load with eviction_policy="evict_first" or "evict_last" emits tl::tma_load<tl::CacheHintSm90::...>(...), but the bulk-load overload only accepts a type template parameter for the barrier. The descriptor-load and bulk-store overloads already accept cache hints.
Shared memory is over-aligned even when the kernel only needs linear bulk copies. Bulk lowering does not record its 16-byte requirement, so allocation planning falls back to 1024-byte alignment. Independently, CUDA codegen always declares the dynamic shared-memory arena with __align__(1024). This adds allocation padding and can increase the static shared-memory footprint around barriers enough to reduce occupancy.
The unhinted copy is correct in the baseline. The second issue is unnecessary resource usage that can cross an occupancy boundary.
Reproducible example code
Run the snippets as separate Python files with a CUDA-enabled TileLang build. The first compiles for the current GPU; the second explicitly generates SM120 source without launching a kernel.
1. Bulk-load cache-hint compilation failure
importtilelangimporttilelang.languageasT# Avoid reusing a kernel compiled by a different native build.tilelang.disable_cache()
@T.prim_funcdefbulk_copy(A: T.Tensor((1024,), T.float32), B: T.Tensor((1024,), T.float32)):
withT.Kernel(1, threads=128):
b_shared=T.alloc_shared((1024,), T.float32)
T.copy(A, b_shared, prefer_instruction="tma", eviction_policy="evict_first")
T.copy(b_shared, B, prefer_instruction="sync")
kernel=tilelang.compile(bulk_copy, out_idx=[1], target="cuda")
print(kernel.get_kernel_source())
Removing eviction_policy allows the baseline to compile. "evict_last" has the same template mismatch as "evict_first".
The first buffer occupies 41,040 bytes, already a multiple of 16. The linear bulk-copy destination could therefore start at byte 41,040 instead of 41,984, with a total dynamic allocation of 49,232 bytes.
Traceback
Relevant NVCC diagnostic from the failing bulk-load test, with temporary/source-tree path prefixes omitted:
tvm_kernels.cu: error: no instance of overloaded function "tl::tma_load" matches the argument list
argument types are: (float *, const float *, Barrier, int)
tl::tma_load<tl::CacheHintSm90::EVICT_FIRST>((&(b_shared[0])), (&(A[0])), A_to_b_shared_mbarrier[0], 4096);
^
copy_sm90.h(18): note #3323-D: substituting explicit template arguments "<<expression>>" for function template "tl::tma_load(void *, const void *, BarrierType &, uint32_t)" failed
The unhinted alignment reproducer does not throw an exception.
Expected behavior
Bulk loads should compile with the supported default, evict_first, and evict_last policies and pass the selected policy to PTX rather than silently discard it.
Shared-memory allocation offsets and the arena base should honor the maximum requirement of the actual operations. This example only requires 16-byte alignment for the linear bulk copy.
Descriptor-based TMA and swizzled operands must retain their stricter alignment. This is not a request to replace all 1024-byte alignments with 16 bytes.
TMA/MMA operands whose exact alignment is unknown should retain a conservative fallback, including single-allocation kernels.
Additional context
The over-alignment was encountered while experimenting with a TMA path for a TileLang port of DeepSeek's DeepSelect. The second reproducer isolates the shared-memory padding issue observed during that migration; it is not the full DeepSelect kernel.
Related reports
#1842 reported a similar tma_load overload error, but its cause was a missing barrier when warp specialization was disabled, as documented in #2005. Here, the barrier is present and the mismatch is caused by the explicit cache-hint template argument.
#2379 and #2391 address insufficient alignment for swizzled TMA and introduce per-buffer alignment requirements. This report is a follow-up for redundant alignment in the descriptorless bulk path and the dynamic shared-memory arena. The review of [CUDA] Align swizzled TMA shared buffers #2391 also noted that stale alignment requirements after a fallback could reduce occupancy; the reproducer here stays on the bulk TMA path rather than falling back to a normal copy.
#2584 concerns a global-memory slice base that is not 16-byte aligned and causes a runtime fault. The buffers here satisfy the bulk-copy alignment requirement; the issue is unnecessary shared-memory padding.
#3178 requests cache policies for ordinary SIMT loads/stores. The compilation failure here instead affects the existing TMA eviction_policy argument.
Relevant code paths
The alignment sources are separate:
Copy::LowerBulk1D does not register a precise shared-memory alignment, unlike descriptor-based lowering.
Required prerequisites
What version of TileLang are you using?
Source build; compiler baseline:
fb5a47aed28f3b521f32c491b553220a5636e1b5.System information
6.8.0-41-generic.580.95.05.3.13.13, built with Clang22.1.3.2.7.1+cu128;torch.version.cuda == "12.8".12.9, NVCC12.9.86.Problem description
There are two issues in the descriptorless, linear bulk TMA path:
eviction_policy="evict_first"or"evict_last"emitstl::tma_load<tl::CacheHintSm90::...>(...), but the bulk-load overload only accepts a type template parameter for the barrier. The descriptor-load and bulk-store overloads already accept cache hints.__align__(1024). This adds allocation padding and can increase the static shared-memory footprint around barriers enough to reduce occupancy.The unhinted copy is correct in the baseline. The second issue is unnecessary resource usage that can cross an occupancy boundary.
Reproducible example code
Run the snippets as separate Python files with a CUDA-enabled TileLang build. The first compiles for the current GPU; the second explicitly generates SM120 source without launching a kernel.
1. Bulk-load cache-hint compilation failure
Removing
eviction_policyallows the baseline to compile."evict_last"has the same template mismatch as"evict_first".2. Bulk-copy and arena over-alignment
Baseline output includes:
The first buffer occupies 41,040 bytes, already a multiple of 16. The linear bulk-copy destination could therefore start at byte 41,040 instead of 41,984, with a total dynamic allocation of 49,232 bytes.
Traceback
Relevant NVCC diagnostic from the failing bulk-load test, with temporary/source-tree path prefixes omitted:
The unhinted alignment reproducer does not throw an exception.
Expected behavior
evict_first, andevict_lastpolicies and pass the selected policy to PTX rather than silently discard it.Additional context
The over-alignment was encountered while experimenting with a TMA path for a TileLang port of DeepSeek's DeepSelect. The second reproducer isolates the shared-memory padding issue observed during that migration; it is not the full DeepSelect kernel.
Related reports
tma_loadoverload error, but its cause was a missing barrier when warp specialization was disabled, as documented in #2005. Here, the barrier is present and the mismatch is caused by the explicit cache-hint template argument.eviction_policyargument.Relevant code paths
The alignment sources are separate:
Copy::LowerBulk1Ddoes not register a precise shared-memory alignment, unlike descriptor-based lowering.SharedMemoryAlignmentPlannerconservatively uses 1024 bytes when no explicit requirement is present.PrintStorageScopeseparately hardcodes 1024-byte arena alignment. Fixing only buffer offsets does not remove this source of padding.The PTX
cp.async.bulkspecification specifies 16-byte alignment for linear bulk copies and supports an L2 cache-policy operand.