Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
82eff2c
feat(kda): add GVA support to CuTeDSL recompute WU
icavan Oct 23, 2026
db48929
feat(kda): add CuTeDSL qg recomputation
icavan Oct 23, 2026
c761152
feat(kda): support GVA in CuTeDSL intra
icavan Oct 23, 2026
82827c8
feat(kda): support exact CuTeDSL varlen intra
icavan Oct 23, 2026
8583ec9
fix(kda): clamp exact intra tail gate references
icavan Oct 23, 2026
c0c092c
fix(kda): isolate CuTeDSL intra outputs
icavan Oct 23, 2026
ff243fc
feat(kda): dispatch SM100 intra through CuTeDSL
icavan Oct 23, 2026
bcb8240
fix(kda): route unaligned WU through varlen
icavan Oct 23, 2026
751e17d
bench(kda): separate WU dispatch overhead
icavan Oct 23, 2026
fc04d79
bench(kda): probe native CuTeDSL WU launch
icavan Oct 23, 2026
e5e6ec3
bench(kda): cache native tensor wrappers
icavan Oct 23, 2026
c944029
perf(kda): launch WU through scalar pointers
icavan Oct 23, 2026
2ac1b2a
perf(kda): use non-owning WU pointers
icavan Oct 23, 2026
c17ceae
bench(kda): measure pooled WU outputs
icavan Oct 23, 2026
a65c62e
perf(kda): pool short WU outputs safely
icavan Oct 23, 2026
75f7a1e
perf(kda): make WU pool leases callback-free
icavan Oct 23, 2026
cfdb455
perf(kda): streamline WU output leasing
icavan Oct 23, 2026
6634703
bench(kda): compare full CuTeDSL port to csrc
icavan Oct 23, 2026
3e4af4a
fix(bench): use stable KDA comparison inputs
icavan Oct 23, 2026
0575de9
fix(bench): exercise uniform KDA fast path
icavan Oct 23, 2026
d6987df
bench(kda): split intra and full port timings
icavan Oct 23, 2026
ebf270a
fix(kda): bound CuTeDSL intra output lifetime
icavan Oct 23, 2026
052f88f
perf(kda): evaluate in-CTA exact inverse
icavan Oct 23, 2026
4ceb285
fix(kda): clear fused inverse upper tiles
icavan Oct 23, 2026
48ecd0b
perf(kda): specialize exact intra warp roles
icavan Oct 23, 2026
ac6221c
fix(kda): index exact intra beta per batch
icavan Oct 23, 2026
47a0ec2
perf(kda): combine exact SM100 forward dispatch
icavan Oct 23, 2026
ff567e6
fix(kda): preserve full-port metadata rank
icavan Oct 23, 2026
b35907c
test(kda): cover combined CuTeDSL forward
icavan Oct 23, 2026
f5aadbb
fix(kda): propagate streams through full port
icavan Oct 23, 2026
b30cdf6
fix(kda): preserve default-stream DSL launches
icavan Oct 23, 2026
f0ab168
fix(kda): specialize optional launch streams
icavan Oct 23, 2026
3ced7e9
fix(kda): route GVA through modular CuTeDSL
icavan Oct 23, 2026
3d45521
fix(kda): preserve rank-one batch ABI
icavan Oct 23, 2026
8513bf1
refactor(kda): remove SM100 native forward
icavan Oct 23, 2026
af0e210
fix(kda): preserve signed zero in exact inverse
icavan Oct 23, 2026
64d35a5
test(kda): freeze unambiguous native vectors
icavan Oct 23, 2026
ccc9823
test(kda): bound native-equivalent precision
icavan Oct 23, 2026
eac90c0
docs(kda): record pure CuTeDSL validation
icavan Oct 23, 2026
9617095
fix(kda): preserve pooled output lifetimes
icavan Oct 23, 2026
52dfde3
fix(kda): normalize exact-port inputs
icavan Oct 23, 2026
9ccf393
chore(coderabbit): disable docstring coverage warning
icavan Oct 24, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .coderabbit.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ reviews:
drafts: false
auto_incremental_review: true

pre_merge_checks:
docstrings:
mode: "off"

path_filters:
- "!csrc/cutlass/**"
- "!third_party/**"
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,13 @@ Linear attention mechanisms reformulate standard attention to use linear-time st

cuLA supports both **Hopper (SM90)** and **Blackwell (SM10X)** GPUs.

> **Requirements (Hopper & Blackwell):** Python 3.12+, CUDA Toolkit 12.9+ (SM10X support), NVCC 12.9+, PyTorch 2.9.1+
> **Requirements (Hopper & Blackwell):** Python 3.12+, CUDA Toolkit 12.9+, PyTorch 2.9.1+. Building the optional SM90 native extension also requires NVCC.

> **Note:** The PyTorch CUDA version must match your system CUDA Toolkit version. Check with `nvcc --version` and `python -c "import torch; print(torch.version.cuda)"`.

### Pre-built Wheels

Pre-built fat-binary wheels (SM90 + SM100 + SM103) are available on [GitHub Releases](https://github.com/inclusionAI/cuLA/releases). Linux wheels target `manylinux_2_28` and require glibc 2.28 or newer:
Pre-built wheels with the SM90 native extension and CuTeDSL JIT kernels for SM100/SM103 are available on [GitHub Releases](https://github.com/inclusionAI/cuLA/releases). Linux wheels target `manylinux_2_28` and require glibc 2.28 or newer:

pip install "cuda-linear-attention==<VERSION>+<CUDA_TAG>" -f https://github.com/inclusionAI/cuLA/releases/expanded_assets/<TAG>

Expand Down Expand Up @@ -57,7 +57,7 @@ pip install -e third_party/flash-linear-attention
pip install -e . --no-build-isolation
```

**Build fat wheel (SM90 + SM100 + SM103):**
**Build a wheel with the SM90 extension (SM100/SM103 use CuTeDSL JIT):**

```bash
CULA_BUILD_ALL_ARCHS=1 python -m build --wheel --no-isolation
Expand Down
17 changes: 7 additions & 10 deletions REPO_LAYOUT.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ cuLA/
├── cula/ # Python package (pip install -e .)
│ ├── __init__.py
│ ├── backends.py # Generic backend registry, probing, verification, dispatch
│ ├── cudac.py # Lazy proxy for the per-architecture CUDA extension
│ ├── cudac.py # Lazy proxy for the remaining SM90 CUDA extension
│ ├── utils.py # Architecture, stream-buffer, and cu_seqlens helpers
│ │
│ ├── kda/ # KDA public API, wrappers, autograd, routing, and Triton support kernels
Expand All @@ -22,8 +22,8 @@ cuLA/
│ │ ├── hopper_fused_fwd_opt.py # SM90 CUDA C++ optimized/CP wrapper
│ │ ├── chunk.py # SM100 modular chunk API + autograd
│ │ ├── chunk_fwd.py # SM100 forward orchestration
│ │ ├── chunk_intra.py # C++ forward intra + Triton backward intra
│ │ ├── chunk_bwd.py # Triton + FLA + CuTeDSL + C++ backward orchestration
│ │ ├── chunk_intra.py # CuTeDSL forward intra + Triton backward intra
│ │ ├── chunk_bwd.py # Triton + FLA + CuTeDSL backward orchestration
│ │ ├── wy_intra.py / wy_recompute.py # Triton WY preparation kernels
│ │ └── gate_l2norm_fused.py / l2norm_qk_fused.py # SM90 Triton preprocessing kernels
│ │
Expand Down Expand Up @@ -52,15 +52,12 @@ cuLA/
│ │ └── prefill_kernel.py # Fixed and packed recurrent prefill kernel
│ └── experimental/ # [non-KDA] unwired prototypes
│
├── csrc/ # CUDA C++ / CUTLASS kernels for SM90 and SM100/SM103
├── csrc/ # Remaining CUDA C++ / CUTLASS kernels for SM90
│ ├── api/
│ │ ├── pybind.cu # Shared named binding definitions
│ │ ├── pybind_sm90.cu # SM90-specific binding translation unit
│ │ ├── pybind_sm100.cu # SM100/SM103-specific binding translation unit
│ │ ├── kda_sm90.cu # SM90 host API
│ │ └── kda_sm100.cu # SM100/SM103 host API
│ │ └── kda_sm90.cu # SM90 host API
│ ├── kda/sm90/ # Hopper fully-fused prefill kernels
│ ├── kda/sm100/ # Blackwell modular chunk kernels
│ ├── kerutils/include/ # Shared device and host helpers
│ └── cutlass/ # CUTLASS submodule
│
Expand All @@ -80,7 +77,7 @@ cuLA/
| `cula/kda/` | Python / Triton | Public KDA APIs, wrappers, autograd, routing, and supporting Triton kernels. `kda_prefill` dispatches SM90 calls to FlashKDA first and then the fully-fused CUDA backend; explicit backend exports remain available. See [`cula/kda/README.md`](cula/kda/README.md). |
| `cula/backends.py` · `cula/kda/backends/` | Python | Generic backend registry plus KDA-specific availability probes, capability verifiers, priorities, and adapters. |
| `cula/ops/kda/` | Python (CuTeDSL) | CuTeDSL KDA kernels organized into SM100 modular kernels, SM90 FlashKDA K1+K2 and intracard CP, decode, and experimental code. The fully-fused SM90 implementation lives under `csrc/`, not here. |
| `csrc/kda/{sm90,sm100}/` | CUDA C++ | Hopper fully-fused prefill and Blackwell modular chunk kernels. |
| `csrc/api/` · `cula/cudac.py` | CUDA C++ / Python | Per-architecture `_cudac_sm90` and `_cudac_sm100` extensions, exposed lazily through the `cula.cudac` compatibility proxy. |
| `csrc/kda/sm90/` | CUDA C++ | Hopper fully-fused prefill kernels. SM100/SM103 KDA forward is implemented entirely in CuTeDSL under `cula/ops/kda/sm100/`. |
| `csrc/api/` · `cula/cudac.py` | CUDA C++ / Python | The remaining `_cudac_sm90` extension and its lazy compatibility proxy. Blackwell public APIs do not load a native extension. |
| `cula/ops/lightning/` · `cula/ops/experimental/` | Python (CuTeDSL) | `[non-KDA]` Lightning/linear-attention kernels and prototypes. Lightning prefill dispatches to the SM90 or SM100 backend from Q's device capability. |
| `cula/ops/{inv,ptx}.py` · `cula/ops/sm100/ptx.py` | Python | Shared low-level helpers used across operators. |
18 changes: 9 additions & 9 deletions benchmarks/bench_kda_sm100_intra_fused.py
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,7 @@ def run_fla_with_gk():
)
return (gk, *fla)

def run_csrc_with_gk():
def run_cutedsl_with_gk():
gk = kda_gate_chunk_cumsum(
g=g,
A_log=a_log,
Expand All @@ -288,7 +288,7 @@ def run_csrc_with_gk():
chunk_size=BT,
lower_bound=args.lower_bound,
)
csrc = cula_chunk_kda_fwd_intra(
cutedsl = cula_chunk_kda_fwd_intra(
q=q,
k=k,
v=k,
Expand All @@ -298,7 +298,7 @@ def run_csrc_with_gk():
chunk_size=BT,
safe_gate=True,
)
return (gk, *csrc)
return (gk, *cutedsl)

valid_mask = _valid_lower_mask(args.B, args.T, args.H, q.device)

Expand Down Expand Up @@ -336,7 +336,7 @@ def compare(cutedsl: tuple[torch.Tensor, ...], fla_with_gk: tuple[torch.Tensor,

nt = args.B * (args.T // BT)
detail = f"B={args.B} T={args.T} H={args.H} K={args.K} NT={nt} bias={not args.no_bias} variant={args.cutedsl_variant}"
run_ref = run_csrc_with_gk if args.baseline == "csrc" else run_fla_with_gk
run_ref = run_cutedsl_with_gk if args.baseline == "cutedsl" else run_fla_with_gk
return BenchCase("equal", detail, run, run_ref, compare)


Expand Down Expand Up @@ -534,7 +534,7 @@ def run_fla_with_gk():
)
return (gk, *fla)

def run_csrc_with_gk():
def run_cutedsl_with_gk():
gk = kda_gate_chunk_cumsum(
g=g,
A_log=a_log,
Expand All @@ -545,7 +545,7 @@ def run_csrc_with_gk():
chunk_indices=chunk_indices,
lower_bound=args.lower_bound,
)
csrc = cula_chunk_kda_fwd_intra(
cutedsl = cula_chunk_kda_fwd_intra(
q=q,
k=k,
v=k,
Expand All @@ -557,7 +557,7 @@ def run_csrc_with_gk():
chunk_size=BT,
safe_gate=True,
)
return (gk, *csrc)
return (gk, *cutedsl)

valid_mask = _valid_lower_mask_varlen(seq_lens, args.H, q.device)

Expand Down Expand Up @@ -601,7 +601,7 @@ def compare(cutedsl: tuple[torch.Tensor, ...], fla_with_gk: tuple[torch.Tensor,
f"seqs={len(seq_lens)} total={total_t} H={args.H} K={args.K} NT={nt} "
f"T_launch={t_launch} pure={pure} dist={args.dist} bias={not args.no_bias} seq_lens=[{seq_preview}]"
)
run_ref = run_csrc_with_gk if args.baseline == "csrc" else run_fla_with_gk
run_ref = run_cutedsl_with_gk if args.baseline == "cutedsl" else run_fla_with_gk
return BenchCase("varlen", detail, run, run_ref, compare)


Expand Down Expand Up @@ -713,7 +713,7 @@ def main() -> None:
parser.add_argument(
"--no-fla", action="store_true", help="Only time CuTeDSL; skip baseline timing and accuracy comparison."
)
parser.add_argument("--baseline", choices=("csrc", "fla"), default="csrc")
parser.add_argument("--baseline", choices=("cutedsl", "fla"), default="cutedsl")
parser.add_argument(
"--with-recompute-wu",
action="store_true",
Expand Down
118 changes: 0 additions & 118 deletions benchmarks/bench_kda_sm100_recompute_wu.py

This file was deleted.

24 changes: 13 additions & 11 deletions benchmarks/bench_recompute_wu.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@

from fla.ops.kda.wy_fast import recompute_w_u_fwd as fla_recompute_w_u_fwd

import cula.cudac as cula_cuda
from benchmarks.utils import (
SEED,
exclusive_cumsum,
Expand All @@ -45,6 +44,7 @@
triton_bench_fn,
)
from cula.kda.chunk_intra import chunk_kda_fwd_intra as cula_chunk_kda_fwd_intra
from cula.ops.kda.sm100.recompute_wu import recompute_w_u_fwd as cula_recompute_w_u_fwd

# Constant params
B, H, D = 2, 64, 128
Expand Down Expand Up @@ -106,17 +106,19 @@ def run_fla_recompute_wu(k, v, beta, Akk, q, gk, cu_seqlens, chunk_indices, disa


def run_cula_recompute_wu(k, v, beta, Akk, q, gk, cu_seqlens, chunk_indices, chunk_size, disable_recompute):
"""cuLA recompute_w_u (handles both MHA and GVA; w/u/qg/kg allocated in HV head space)."""
B_flat, T, HV_out, Dv = v.shape
w = torch.empty_like(v)
u = torch.empty_like(v)
qg = torch.empty(B_flat, T, HV_out, Dv, device=q.device, dtype=q.dtype) if disable_recompute else None
kg = torch.empty_like(v) if gk is not None else None

cula_cuda.recompute_w_u_cuda(
k, v, beta, Akk, gk, cu_seqlens, chunk_indices, w, u, kg, chunk_size, q if disable_recompute else None, qg
"""Run the pure CuTeDSL recompute-WU implementation."""
if chunk_size != BT:
raise ValueError(f"CuTeDSL benchmark expects chunk_size={BT}, got {chunk_size}")
return cula_recompute_w_u_fwd(
k,
v,
beta,
Akk,
gk,
cu_seqlens=cu_seqlens,
chunk_indices=chunk_indices,
q=q if disable_recompute else None,
)
return w, u, qg, kg


# ==============================================================================
Expand Down
Loading
Loading