tf-kernel is TeleFuser's optional CUDA extension package. It provides fused elementwise operations, quantized
GEMM, SageAttention, and block-sparse attention kernels. The package lives in the tf-kernel/ directory of this
repository and has its own package metadata and version. No prebuilt package is currently published; local
installation requires a source build on a provisioned CUDA/NVCC host.
TeleFuser can run without tf-kernel: the telefuser.ops layer keeps native PyTorch or Triton fallbacks where they
are implemented. Install tf-kernel when a pipeline uses one of its optimized CUDA paths.
!!! important
TeleFuser model code must continue importing operations from `telefuser.ops`, not directly from `tf_kernel`.
Direct imports below are intended for standalone kernel use, diagnostics, and kernel development.
| Component | Requirement or target |
|---|---|
| Python | 3.10 or newer |
| PyTorch | 2.11.0 (a CUDA local version such as 2.11.0+cu128 satisfies this requirement) |
| CUDA Toolkit | 12.8 or newer for source builds |
| CMake | 3.26 or newer for source builds |
| GPU targets | SM80, SM90, and SM100 |
Kernel availability depends on the selected build target. FP4 kernels require Blackwell (SM100 or newer); seeing
no fp4 operator available on Ampere or Hopper is expected. Core operations are currently validated with Python
3.11, PyTorch 2.11.0+cu128, CUDA 12.8, and H100 (SM90a). Other targets and operation families should be validated on
their target GPU before production use.
!!! warning "Current H100 SageAttention limitation"
In the currently validated H100 build, the architecture-selected `tf_kernel.sageattn()` path chooses the
SM90-specific FP8 kernel and can fail with `CUDA error: misaligned address`. RMSNorm, fused activations, FP8
quantization, and the generic FP8 SageAttention path pass smoke tests. Do not enable the SM90-specific SageAttention
backend in production until its focused GPU test passes on the wheel being deployed.
Clone the TeleFuser monorepo, select the interpreter that already contains PyTorch 2.11.0, and enter the kernel project:
git clone https://github.com/Tele-AI/TeleFuser.git
cd TeleFuser/tf-kernelFor a local workstation, auto-detect the installed GPU:
make build-auto PYTHON=/path/to/venv/bin/pythonThe local build is independent of the TeleFuser installation. Make builds a correctly tagged wheel and installs it
into PYTHON. Direct pip install . and pip install -e . source builds fail with instructions to use Make; pip
package-index installation is not available.
For a reproducible target-specific build:
make build-sm80 PYTHON=/path/to/venv/bin/python # Ampere and Ada
make build-sm90 PYTHON=/path/to/venv/bin/python # Hopper, including H100
make build-sm100 PYTHON=/path/to/venv/bin/python # BlackwellAn H100 build with bounded host resource use can be run as follows:
PATH=/usr/local/cuda-12.8/bin:$PATH \
CUDA_HOME=/usr/local/cuda-12.8 \
make build-sm90 \
PYTHON=/path/to/venv/bin/python \
MAX_JOBS=2 \
CMAKE_BUILD_PARALLEL_LEVEL=2 \
TF_KERNEL_COMPILE_THREADS=1make build builds all supported targets. Every build target writes a wheel to dist/, adds a legal wheel build
tag containing the Torch/CUDA ABI, and installs that wheel into the interpreter selected by PYTHON. The initial
build needs network access to obtain pinned CUTLASS, FlashInfer, and other CMake dependencies.
MAX_JOBS controls the number of concurrent build jobs. TF_KERNEL_COMPILE_THREADS controls the internal NVCC
threads used by each job. Increasing them can reduce build time on a sufficiently provisioned host; their product
also increases CPU and memory pressure.
Run the check with the same interpreter that will start TeleFuser:
python - <<'PY'
from pathlib import Path
import torch
import tf_kernel
print("tf-kernel:", tf_kernel.__version__)
print("PyTorch:", torch.__version__)
print("CUDA runtime:", torch.version.cuda)
print("GPU:", torch.cuda.get_device_name())
print("extension:", Path(tf_kernel.common_ops.__file__).resolve())
x = torch.randn(8, 1024, device="cuda", dtype=torch.float16)
weight = torch.ones(1024, device="cuda", dtype=torch.float16)
y = tf_kernel.rmsnorm(x, weight)
assert y.shape == x.shape and torch.isfinite(y).all()
print("RMSNorm smoke test: OK")
PYAn H100-specific wheel should load its common extension from an sm90 package directory. Also run
python -m pip check to expose dependency conflicts in the environment.
TeleFuser users should call the public ops layer; it selects tf-kernel for supported eager CUDA paths and keeps the
framework fallback behavior:
import torch
from telefuser.ops.activations import silu_and_mul
x = torch.randn(4, 2048, device="cuda", dtype=torch.float16)
y = silu_and_mul(x) # The last dimension is split into two 1024-wide tensors.
assert y.shape == (4, 1024)Standalone users can call the kernel package directly:
import torch
import tf_kernel
# RMSNorm
x = torch.randn(8, 1024, device="cuda", dtype=torch.float16)
weight = torch.ones(1024, device="cuda", dtype=torch.float16)
y = tf_kernel.rmsnorm(x, weight, eps=1e-6)
# H100-tested generic FP8 SageAttention path.
# HND layout: [batch, heads, sequence, head_dim]
q = torch.randn(1, 8, 128, 64, device="cuda", dtype=torch.float16)
k = torch.randn_like(q)
v = torch.randn_like(q)
attn_output = tf_kernel.sageattn_qk_int8_pv_fp8_cuda(
q,
k,
v,
tensor_layout="HND",
is_causal=False,
pv_accum_dtype="fp32",
)Per-token FP8 quantization writes into caller-provided output tensors:
x = torch.randn(128, 1024, device="cuda", dtype=torch.float16)
x_q = torch.empty_like(x, dtype=torch.float8_e4m3fn)
x_scale = torch.empty((x.shape[0], 1), device="cuda", dtype=torch.float32)
tf_kernel.tf_per_token_quant_fp8(x, x_q, x_scale)See the API reference under tf-kernel/docs/ and the tests in tf-kernel/tests/ for lower-level contracts.
Always use python -m pip and pass PYTHON=/path/to/venv/bin/python to Make. Confirm both paths with
python -m pip show tf-kernel and python -c "import sys; print(sys.executable)".
tf-kernel requires PyTorch 2.11.0 because compiled extensions are tied to the PyTorch/CUDA ABI. Install TeleFuser
and tf-kernel into a clean environment if another package pins an incompatible PyTorch version. Do not bypass the
constraint unless you rebuild and validate the extension against the replacement version.
Check nvcc --version, set CUDA_HOME to the CUDA 12.8+ toolkit, and put $CUDA_HOME/bin before older toolkits in
PATH. The PyTorch CUDA runtime and the selected toolkit should be ABI-compatible.
Rebuild with make build-auto on the target machine or use the explicit build-sm80, build-sm90, or
build-sm100 target. Architecture-specific wheels cannot provide kernels that were omitted at build time.
The architecture selector currently routes H100 to the SM90-specific FP8 implementation. Treat a failure in that path as an unsupported backend for the current wheel; select another TeleFuser attention implementation instead of continuing in the CUDA process after the asynchronous error. The generic FP8 function shown above is useful for isolated validation, but production enablement still requires parity and workload benchmarks.
Lower MAX_JOBS, CMAKE_BUILD_PARALLEL_LEVEL, and TF_KERNEL_COMPILE_THREADS. Targeting one SM architecture also
substantially reduces build time and artifact size.