Export a kernel¶
Export a kernel as CUDA C++ source with its host launch wrapper, then build and
run it with tvm-ffi. Consumers need no TIRx, tirx-kernels, or tirx-harness
installation. You can also distribute a compiled shared library so consumers
can skip compilation.
This workflow uses TIRx’s tvm_tirx.backend.cuda.export_cuda_host API.
Export in the development environment¶
Exporting requires a compatible CUDA toolchain because compiling the kernel also compiles the device code.
Save this as export_zero.py:
from pathlib import Path
import tvm_tirx
from tvm_tirx.backend.cuda import export_cuda_host
import tirx_kernels.tirx_lite as txl
@txl.kernel()
def zero(out: txl.Tensor((32,), "float32")):
txl.device_entry(launch=txl.cuda.LaunchConfig(grid=1, block=32))
txl.ptx.st.global_.f32(out.ptr_to([txl.lane_id()]), txl.float32(0))
target = tvm_tirx.target.Target({"kind": "cuda", "arch": "sm_100a"}, host="cuda_host")
compiled = zero.compile(target=target)
Path("zero.cu").write_text(export_cuda_host(compiled.mod), encoding="utf-8")
python export_zero.py
For an existing TIRx-lite kernel, replace zero with your Kernel object.
For a native TIRx Function or IRModule, use
tvm_tirx.tirx.compile(kernel, target=target, pipeline="tirx") and pass the result’s
.mod to export_cuda_host in the same way.
The .cu file contains both device code and the host wrapper, including FFI
entry points and CUDA launches. Set host="cuda_host" before compiling;
export_cuda_host expects that module, with its retained device source.
kernel.source() and tirx_harness.dump_cuda() extract device code for
inspection and do not provide this complete launch wrapper.
Build with tvm-ffi¶
Copy zero.cu to the consumer’s project. In a separate Python environment,
install the FFI package with its build dependencies:
python -m pip install "apache-tvm-ffi[cpp]>=0.1.15.post1,<0.2"
Building requires a C++ compiler and a CUDA Toolkit with nvcc that supports
the kernel’s architecture. Set CUDA_HOME if the toolkit is outside the
default location. Save this as build_zero.py beside zero.cu:
from pathlib import Path
import tvm_ffi.cpp
library = tvm_ffi.cpp.build(
name="zero",
sources=["zero.cu"],
build_directory=str(Path("build").resolve()),
backend="cuda",
extra_ldflags=["-lcuda"],
)
print(library)
Compile for the architecture used when exporting:
TVM_FFI_CUDA_ARCH_LIST=10.0a python build_zero.py
This produces build/zero.so. tvm-ffi supplies its own headers, DLPack
headers, and link options. The generated source already exports the kernel’s
FFI entry point. It loads the embedded device binary through the CUDA driver
API, so the library links the driver with -lcuda.
Load and call the kernel¶
The application needs apache-tvm-ffi, a compatible NVIDIA driver and CUDA
runtime libraries, and a tensor library for its GPU inputs. This example uses
an existing CUDA-enabled PyTorch installation:
from pathlib import Path
import torch
import tvm_ffi
module = tvm_ffi.load_module(str(Path("build/zero.so").resolve()))
out = torch.ones(32, dtype=torch.float32, device="cuda")
module["zero"](out)
torch.cuda.synchronize()
torch.testing.assert_close(out, torch.zeros_like(out))
The exported name comes from the TIRx function’s global_symbol (zero here).
Pass tensor and scalar arguments in the original kernel’s order. Preserve its
shape, dtype, layout, and device requirements. Launches use the CUDA stream
provided through tvm-ffi; synchronize before reading results on the CPU.
To ship a binary, distribute zero.so and use only the load-and-call step.
Install apache-tvm-ffi>=0.1.15.post1,<0.2 without the [cpp] extra on machines
that only load the library. They need compatible GPU, CUDA runtime, host
platform, and FFI versions; they do not need nvcc or a C++ compiler.
Document those requirements and the kernel’s argument contract alongside the
artifact. Shipping .cu lets consumers rebuild for their deployment environment.
Kernels with additional requirements¶
TMA tensor-map encoding must use
tirx.cuda.tensormap_encode_tiled. The oldercall_packed("runtime.cuTensorMapEncodeTiled", ...)form is rejected withcuda_host requires tensormap_encode_tiled instead of a packed tensor-map encoder. TIRx-lite providestxl.cu_tensor_map_encode_tiled(...)for this purpose, and the FP16/BF16 GEMM and DeepSeek-V4 MLA kernels intirx-kernelsuse it. Any tensor-map arguments prepared outside the exported function still need equivalent preparation in the consumer application.Preserve any extra CUDA headers and compiler options required by your kernel. The export helper concatenates source; it does not package external headers or Python input preparation.
CUDA-host code generation rejects unsupported launch modes and TVM runtime services, including runtime workspace allocation. Validate the exported artifact with the same inputs and correctness checks as the original kernel before distributing it.