Skip to content

Commit 83955a9

Browse files
committed
fix(tf-kernel): harden builds and enable SM90 attention
Refine architecture-specific wheel builds, runtime ABI validation, GPU capability dispatch, isolated wheel checks, and manual packaging documentation. Fix the Hopper SageAttention v2 build by disabling relocatable device code for SM90, add synchronous CUDA launch diagnostics, restore the validated SM90 backend, and prefer tf-kernel from TeleFuser ops with standalone SageAttention fallback. Preserve causal and LSE behavior through the public attention interface. Verification: tf-kernel wheel smoke tests; 384-case focused SM90 SageAttention matrix; architecture and symbol validation; pytest tests/unit/ops/test_attention_backends.py tests/unit/ops/test_tf_kernel_sage_attention.py -q; pytest tests/unit/ops with non-GPU markers; ruff check; ruff format --check; git diff --check.
1 parent 21cb289 commit 83955a9

41 files changed

Lines changed: 1331 additions & 802 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

CLAUDE.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,10 @@ telefuser/
8181
dependency to published project metadata.
8282
- Do not add GitHub Actions workflows that compile or publish `tf-kernel`. Kernel wheels require an explicitly
8383
provisioned CUDA/NVCC build host and manual validation.
84+
- Load only the wheel extension matching the single visible GPU architecture family. Keep build/runtime compatibility
85+
facts in `tf_kernel._build_info` and validated SageAttention dispatch in `tf_kernel.capabilities`.
86+
- `telefuser.ops.attention` prefers the optional `tf_kernel` SageAttention backend and falls back to the standalone
87+
`sageattention` package. Model code must continue calling the public ops layer rather than either package directly.
8488

8589
### LingBot Streaming State
8690

docs/en/attention.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ pipe_config.dit_config.attention_config = config
207207
| `FLASH_ATTN_2` | Flash Attention 2 | `flash_attn` package |
208208
| `FLASH_ATTN_3` | Flash Attention 3 | `flash_attn_interface` package |
209209
| `FLASH_ATTN_4` | Flash Attention 4 | `flash_attn` package (with `cute` submodule) |
210-
| `SAGE_ATTN_*` | SageAttention variants | `sageattention` package |
210+
| `SAGE_ATTN_*` | SageAttention variants | `tf-kernel` or `sageattention` package |
211211
| `SPARGE_ATTN` | Sparge Attention | `spas_sage_attn` package |
212212

213213
**Note on Flash Attention 4**: Flash Attention 4 is optimized for **Hopper (SM90, H100)** and **Blackwell (SM100+, B100/B200)** GPUs. It provides significant performance improvements on these architectures. For older GPUs (Ampere, Ada Lovelace), use Flash Attention 2 or 3 instead.
@@ -394,8 +394,8 @@ Source builds require Python 3.10+, PyTorch 2.11.0, CUDA Toolkit 12.8+, and CMak
394394
on SM100+. See the [tf-kernel installation and usage guide](./tf_kernel.md) for the complete compatibility matrix,
395395
H100 build command, installation verification, usage examples, and troubleshooting.
396396

397-
The currently validated H100 wheel has a known `misaligned address` failure in the architecture-selected SM90
398-
SageAttention path. Use another attention backend until the focused SM90 GPU test passes on the deployed wheel.
397+
The SM90 path is validated on H100 through both tf-kernel and the TeleFuser public ops layer. The focused GPU test
398+
synchronizes the kernel and covers causal output and log-sum-exp results.
399399

400400
### Checking Available Backends
401401

docs/en/tf_kernel.md

Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -23,17 +23,19 @@ are implemented. Install `tf-kernel` when a pipeline uses one of its optimized C
2323
| CMake | 3.26 or newer for source builds |
2424
| GPU targets | SM80, SM90, and SM100 |
2525

26-
Kernel availability depends on the selected build target. FP4 kernels require Blackwell (SM100 or newer); seeing
27-
`no fp4 operator available` on Ampere or Hopper is expected. Core operations are currently validated with Python
28-
3.11, PyTorch 2.11.0+cu128, CUDA 12.8, and H100 (SM90a). Other targets and operation families should be validated on
29-
their target GPU before production use.
26+
Kernel availability depends on the selected build target. FP4 kernels require Blackwell (SM100 or newer), and
27+
`tf_kernel.FP4_AVAILABLE` is false without an import-time warning on Ampere and Hopper. Core operations are currently
28+
validated with Python 3.11, PyTorch 2.11.0+cu128, CUDA 12.8, and H100 (SM90a). Other targets and operation families
29+
should be validated on their target GPU before production use.
3030

31-
!!! warning "Current H100 SageAttention limitation"
31+
The wheel records and verifies its PyTorch public version, PyTorch CUDA version, C++11 ABI, and target GPU family at
32+
import. A process exposing GPUs from different architecture families is rejected. SageAttention v2 auto-dispatch is
33+
enabled only for SM80, SM86, SM89, SM90, SM120, and SM121.
3234

33-
In the currently validated H100 build, the architecture-selected `tf_kernel.sageattn()` path chooses the
34-
SM90-specific FP8 kernel and can fail with `CUDA error: misaligned address`. RMSNorm, fused activations, FP8
35-
quantization, and the generic FP8 SageAttention path pass smoke tests. Do not enable the SM90-specific SageAttention
36-
backend in production until its focused GPU test passes on the wheel being deployed.
35+
!!! note "H100 SageAttention dispatch"
36+
37+
On H100, `tf_kernel.sageattn()` selects the validated SM90 FP8 implementation. TeleFuser uses the same kernel
38+
when `SAGE_ATTN_2_8_8_SM90` is configured and `tf-kernel` is available.
3739

3840
## Build and install from source
3941

@@ -55,6 +57,9 @@ The local build is independent of the TeleFuser installation. Make builds a corr
5557
into `PYTHON`. Direct `pip install .` and `pip install -e .` source builds fail with instructions to use Make; pip
5658
package-index installation is not available.
5759

60+
Local builds use a `linux_*` platform tag. The container build may use `manylinux_2_28` only after checking every
61+
shared object's GLIBC symbol versions against that policy.
62+
5863
For a reproducible target-specific build:
5964

6065
```bash
@@ -111,6 +116,10 @@ PY
111116
An H100-specific wheel should load its common extension from an `sm90` package directory. Also run
112117
`python -m pip check` to expose dependency conflicts in the environment.
113118

119+
For development validation, run `make test-cpu`, `make test-smoke`, and `make test-wheel`. The smoke and GPU targets
120+
install the wheel into an isolated temporary directory before collecting tests. `make test` is the bounded GPU suite;
121+
reserve the 6,000+ case `make test-full` matrix for a dedicated validation host.
122+
114123
## Usage
115124

116125
TeleFuser users should call the public ops layer; it selects `tf-kernel` for supported eager CUDA paths and keeps the
@@ -137,18 +146,18 @@ x = torch.randn(8, 1024, device="cuda", dtype=torch.float16)
137146
weight = torch.ones(1024, device="cuda", dtype=torch.float16)
138147
y = tf_kernel.rmsnorm(x, weight, eps=1e-6)
139148

140-
# H100-tested generic FP8 SageAttention path.
149+
# H100-tested SM90 FP8 SageAttention path.
141150
# HND layout: [batch, heads, sequence, head_dim]
142151
q = torch.randn(1, 8, 128, 64, device="cuda", dtype=torch.float16)
143152
k = torch.randn_like(q)
144153
v = torch.randn_like(q)
145-
attn_output = tf_kernel.sageattn_qk_int8_pv_fp8_cuda(
154+
attn_output = tf_kernel.sageattn_qk_int8_pv_fp8_cuda_sm90(
146155
q,
147156
k,
148157
v,
149158
tensor_layout="HND",
150159
is_causal=False,
151-
pv_accum_dtype="fp32",
160+
pv_accum_dtype="fp32+fp32",
152161
)
153162
```
154163

@@ -186,12 +195,11 @@ Check `nvcc --version`, set `CUDA_HOME` to the CUDA 12.8+ toolkit, and put `$CUD
186195
Rebuild with `make build-auto` on the target machine or use the explicit `build-sm80`, `build-sm90`, or
187196
`build-sm100` target. Architecture-specific wheels cannot provide kernels that were omitted at build time.
188197

189-
### SageAttention fails with `misaligned address` on H100
198+
### Validate an SM90 SageAttention deployment
199+
200+
The SM90-specific kernel is enabled on H100. After building the wheel, run the synchronized tf-kernel smoke test and
201+
the TeleFuser public-ops GPU integration test before deploying that artifact on a new host.
190202

191-
The architecture selector currently routes H100 to the SM90-specific FP8 implementation. Treat a failure in that
192-
path as an unsupported backend for the current wheel; select another TeleFuser attention implementation instead of
193-
continuing in the CUDA process after the asynchronous error. The generic FP8 function shown above is useful for
194-
isolated validation, but production enablement still requires parity and workload benchmarks.
195203

196204
### The build exhausts CPU or memory
197205

docs/zh/attention.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ pipe_config.dit_config.attention_config = config
207207
| `FLASH_ATTN_2` | Flash Attention 2 | `flash_attn`|
208208
| `FLASH_ATTN_3` | Flash Attention 3 | `flash_attn_interface`|
209209
| `FLASH_ATTN_4` | Flash Attention 4 | `flash_attn` 包(含 `cute` 子模块) |
210-
| `SAGE_ATTN_*` | SageAttention 变体 | `sageattention`|
210+
| `SAGE_ATTN_*` | SageAttention 变体 | `tf-kernel``sageattention`|
211211
| `SPARGE_ATTN` | Sparge Attention | `spas_sage_attn`|
212212

213213
**Flash Attention 4 说明**: Flash Attention 4 针对 **Hopper (SM90, H100)****Blackwell (SM100+, B100/B200)** GPU 架构进行了优化,在这些架构上提供显著的性能提升。对于旧版 GPU(Ampere、Ada Lovelace),请使用 Flash Attention 2 或 3。
@@ -393,8 +393,8 @@ make build-sm100 PYTHON=/path/to/venv/bin/python # Blackwell
393393
可用。完整兼容矩阵、H100 编译命令、安装验证、使用示例和常见问题见
394394
[tf-kernel 安装与使用指南](./tf_kernel.md)
395395

396-
当前验证的 H100 wheel 在架构选择的 SM90 SageAttention 路径存在已知 `misaligned address` 错误;部署的
397-
wheel 通过专项 SM90 GPU 测试前,应选择其他注意力后端
396+
SM90 路径已在 H100 上通过 tf-kernel 和 TeleFuser 公共 ops 层验证。专项 GPU 测试会同步内核,并覆盖
397+
causal 输出和 log-sum-exp 结果
398398

399399
### 检查可用后端
400400

docs/zh/tf_kernel.md

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,18 @@ TeleFuser 不安装 `tf-kernel` 也可以运行:对于已经实现回退的算
2222
| CMake | 从源码编译要求 3.26 或更高版本 |
2323
| GPU 目标 | SM80、SM90 和 SM100 |
2424

25-
具体可用内核取决于编译目标。FP4 内核要求 Blackwell(SM100 或更高);在 Ampere 或 Hopper 上看到
26-
`no fp4 operator available` 属于预期行为。目前核心算子已在 Python 3.11、PyTorch 2.11.0+cu128、
27-
CUDA 12.8 和 H100(SM90a)组合上验证。其他目标和算子族用于生产前仍应在目标 GPU 上验证。
25+
具体可用内核取决于编译目标。FP4 内核要求 Blackwell(SM100 或更高);在 Ampere 或 Hopper
26+
`tf_kernel.FP4_AVAILABLE` 为 false,导入时不会打印提示。目前核心算子已在 Python 3.11、PyTorch
27+
2.11.0+cu128、CUDA 12.8 和 H100(SM90a)组合上验证。其他目标和算子族用于生产前仍应在目标 GPU 上验证。
2828

29-
!!! warning "当前 H100 SageAttention 限制"
29+
wheel 导入时会校验构建时记录的 PyTorch 公共版本、PyTorch CUDA 版本、C++11 ABI 和目标 GPU 架构族。
30+
一个进程暴露不同架构族的 GPU 时会明确失败。SageAttention v2 自动分派目前仅支持 SM80、SM86、
31+
SM89、SM90、SM120 和 SM121。
3032

31-
当前验证的 H100 build 中,架构选择接口 `tf_kernel.sageattn()` 会进入 SM90 专用 FP8 内核,并可能报
32-
`CUDA error: misaligned address`。RMSNorm、融合激活、FP8 量化和通用 FP8 SageAttention 路径已通过
33-
smoke test。在部署 wheel 的专项 GPU 测试通过前,不应在生产环境启用 SM90 专用 SageAttention 后端。
33+
!!! note "H100 SageAttention 分派"
34+
35+
H100 上的 `tf_kernel.sageattn()` 会选择已验证的 SM90 FP8 实现。配置 `SAGE_ATTN_2_8_8_SM90` 且
36+
`tf-kernel` 可用时,TeleFuser 会使用同一个内核。
3437

3538
## 从源码编译和安装
3639

@@ -50,6 +53,9 @@ make build-auto PYTHON=/path/to/venv/bin/python
5053
本地构建独立于 TeleFuser 安装。Make 会构建带有正确 tag 的 wheel,并将其安装到 `PYTHON` 指定的解释器。
5154
直接执行 `pip install .``pip install -e .` 会失败并提示改用 Make;当前不提供 pip 包索引安装。
5255

56+
本地构建使用 `linux_*` platform tag。容器构建只有在检查所有共享库的 GLIBC 符号版本满足策略后,
57+
才可以使用 `manylinux_2_28` tag。
58+
5359
需要可复现的指定架构编译时:
5460

5561
```bash
@@ -105,6 +111,10 @@ PY
105111
H100 专用 wheel 的 common extension 应从 `sm90` 包目录加载。还应运行 `python -m pip check` 检查环境中的
106112
依赖冲突。
107113

114+
开发验证依次运行 `make test-cpu``make test-smoke``make test-wheel`。smoke 与 GPU target 会先将
115+
wheel 安装到隔离的临时目录再收集用例。`make test` 是有界 GPU 测试;超过 6,000 条用例的
116+
`make test-full` 应只在专用验证机器执行。
117+
108118
## 使用示例
109119

110120
TeleFuser 用户应调用公共 ops 层;它会在支持的 eager CUDA 路径选择 `tf-kernel`,同时保留框架回退:
@@ -130,18 +140,18 @@ x = torch.randn(8, 1024, device="cuda", dtype=torch.float16)
130140
weight = torch.ones(1024, device="cuda", dtype=torch.float16)
131141
y = tf_kernel.rmsnorm(x, weight, eps=1e-6)
132142

133-
# 已在 H100 验证的通用 FP8 SageAttention 路径。
143+
# 已在 H100 验证的 SM90 FP8 SageAttention 路径。
134144
# HND 布局:[batch, heads, sequence, head_dim]
135145
q = torch.randn(1, 8, 128, 64, device="cuda", dtype=torch.float16)
136146
k = torch.randn_like(q)
137147
v = torch.randn_like(q)
138-
attn_output = tf_kernel.sageattn_qk_int8_pv_fp8_cuda(
148+
attn_output = tf_kernel.sageattn_qk_int8_pv_fp8_cuda_sm90(
139149
q,
140150
k,
141151
v,
142152
tensor_layout="HND",
143153
is_causal=False,
144-
pv_accum_dtype="fp32",
154+
pv_accum_dtype="fp32+fp32",
145155
)
146156
```
147157

@@ -179,11 +189,10 @@ PyTorch 版本,请在干净环境中安装 TeleFuser 和 `tf-kernel`。除非
179189
在目标机器使用 `make build-auto` 重新编译,或显式选择 `build-sm80``build-sm90``build-sm100`
180190
指定架构 wheel 无法提供编译时未包含的内核。
181191

182-
### H100 上 SageAttention `misaligned address`
192+
### 验证 SM90 SageAttention 部署
183193

184-
当前架构选择接口会把 H100 路由到 SM90 专用 FP8 实现。如果该路径失败,应将其视为当前 wheel 不支持的
185-
后端并选择其他 TeleFuser 注意力实现;异步 CUDA 错误发生后不要继续复用该进程。上文的通用 FP8 函数
186-
可用于独立验证,但生产启用仍需要完成精度对齐和目标工作负载 benchmark。
194+
SM90 专用内核已在 H100 上启用。构建 wheel 后,应在新的部署主机上运行带同步的 tf-kernel smoke test
195+
和 TeleFuser 公共 ops GPU 集成测试。
187196

188197
### 编译耗尽 CPU 或内存
189198

telefuser/ops/attention/attention_impl.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,7 @@ def attention(
251251
k,
252252
v,
253253
attn_mask=attn_mask,
254+
is_causal=is_causal,
254255
sm_scale=scale,
255256
tensor_layout=sage_tensor_layout,
256257
pv_accum_dtype="fp32+fp32",
@@ -263,6 +264,7 @@ def attention(
263264
k,
264265
v,
265266
attn_mask=attn_mask,
267+
is_causal=is_causal,
266268
sm_scale=scale,
267269
tensor_layout=sage_tensor_layout,
268270
pv_accum_dtype="fp32",
@@ -275,6 +277,7 @@ def attention(
275277
k,
276278
v,
277279
attn_mask=attn_mask,
280+
is_causal=is_causal,
278281
sm_scale=scale,
279282
tensor_layout=sage_tensor_layout,
280283
pv_accum_dtype="fp32+fp32",
@@ -425,12 +428,12 @@ def _get_ring_attn_config(
425428
"""Get attention config with LSE support for ring attention."""
426429
attn_impl = attention_config.attn_impl if attention_config else AttnImplType.TORCH_SDPA
427430

428-
if not supports_return_lse(attn_impl.value):
431+
if not supports_return_lse(attn_impl.name):
429432
fallback = get_lse_fallback_impl()
430433
if fallback is None:
431434
raise RuntimeError("Ring attention requires LSE support. Install flash-attn or sageattention.")
432435
logger.info(f"Ring attention: falling back to {fallback}")
433-
return AttentionConfig(attn_impl=AttnImplType(fallback), scale=scale, is_causal=is_causal)
436+
return AttentionConfig(attn_impl=AttnImplType[fallback], scale=scale, is_causal=is_causal)
434437

435438
return attention_config
436439

telefuser/ops/attention/backends.py

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -85,16 +85,23 @@ def _try_import_sdpa() -> None:
8585

8686

8787
def _try_import_sage_attn() -> None:
88-
"""Import Sage Attention."""
88+
"""Import SageAttention, preferring the optional tf-kernel package."""
8989
global SAGE_ATTN_AVAILABLE, sageattention
9090

91-
try:
92-
if importlib.util.find_spec("sageattention") is not None:
93-
sageattention = importlib.import_module("sageattention")
94-
SAGE_ATTN_AVAILABLE = True
95-
logger.debug("Sage Attention available")
96-
except (ModuleNotFoundError, ImportError):
97-
pass
91+
SAGE_ATTN_AVAILABLE = False
92+
sageattention = None
93+
for module_name in ("tf_kernel", "sageattention"):
94+
try:
95+
if importlib.util.find_spec(module_name) is None:
96+
continue
97+
sageattention = importlib.import_module(module_name)
98+
except (ModuleNotFoundError, ImportError) as error:
99+
logger.debug("SageAttention backend %s unavailable: %s", module_name, error)
100+
continue
101+
102+
SAGE_ATTN_AVAILABLE = True
103+
logger.debug("SageAttention loaded from %s", module_name)
104+
return
98105

99106

100107
def _try_import_sparge_attn() -> None:

0 commit comments

Comments
 (0)