Views
No views yet
fp8_linear_bf16(input, weight, alpha=1.0, out=None, variant=0)fp8_linear_residual_bf16(input, weight, residual, alpha=1.0, variant=0)fp8_linear_bias_bf16(input, weight, bias, alpha=1.0, out=None)fp8_linear_bias_residual_bf16(input, weight, bias, residual, alpha=1.0)fp8_linear_bias_gelu_bf16(input, weight, bias, alpha=1.0, out=None)fp8_blockwise_linear_bf16(input, weight, input_scale, weight_scale, out=None)fp8_blockwise_swiglu_quantize_fp8(input, gate_up_weight, input_scale, gate_up_weight_scale, output=None, output_scale=None)select_fp8_linear_tile(m, n, k, variant=0)input: torch.float8_e4m3fn, shape (M, K), contiguous CUDA tensor.weight: torch.float8_e4m3fn, shape (N, K), contiguous CUDA tensor.out: torch.bfloat16, shape (M, N).residual: torch.bfloat16, shape (1, N) or (N,), only supported for
the M=1 decode GEMV path.K % 16 == 0; SM120 additionally requires K % 32 == 0.M == 1 uses dedicated GEMV and 2 <= M <= 64 uses small-M
GEMM tiles.M=65 through M=1024, including PI0.5 prefill QKV, O,
gate/up, and down projections at M=712..970. N and K must be divisible
by 16.(N,) bias and
preserve the same row-major FP8 (M,K) input and (N,K) weight contract.
The residual API updates a BF16 (M,N) tensor in place. The GELU API uses
the tanh approximation.variant=0 is the production auto dispatcher. Diagnostic variants are
1=Sq, 2=T1, and 3=Wide; they are correctness-tested but should not be
pinned by model integrations without a shape-specific benchmark.alpha is a host float. For per-tensor FP8 quantization, pass
float(input_scale * weight_scale) from your static calibration metadata.input: FP8 E4M3 (M, K).weight: FP8 E4M3 (N, K).input_scale: FP32 (M, K / 128).weight_scale: FP32 (N / 128, K / 128).N and K must be divisible by 128; M is unrestricted.(M, N).mma.sync.aligned.m16n8k32 GEMM/GEMV implementation.(M,K) input, FP8 (2*N,K) gate/up
weight, block-128 FP32 scales, and returns FP8 (M,N) plus FP32 (M,N/128)
output scales. Its public range is 1 <= M <= 256 with N and K divisible
by 128. It is rejected explicitly on non-SM89 GPUs.1from kernels import get_kernel
2import torch
3
4ops = get_kernel("flashrt/fp8-gemm", version=1, trust_remote_code=True)
5
6x = torch.randn((16, 4096), device="cuda", dtype=torch.bfloat16).to(torch.float8_e4m3fn)
7w = torch.randn((8192, 4096), device="cuda", dtype=torch.bfloat16).to(torch.float8_e4m3fn)
8
9y = ops.fp8_linear_bf16(x, w, alpha=1.0)1bias = torch.randn((8192,), device="cuda", dtype=torch.bfloat16)
2residual = torch.randn((16, 8192), device="cuda", dtype=torch.bfloat16)
3
4y = ops.fp8_linear_bias_bf16(x, w, bias, alpha=1.0)
5ops.fp8_linear_bias_residual_bf16(x, w, bias, residual, alpha=1.0)
6y_gelu = ops.fp8_linear_bias_gelu_bf16(x, w, bias, alpha=1.0)1x = torch.randn((1, 4096), device="cuda", dtype=torch.bfloat16).to(torch.float8_e4m3fn)
2w = torch.randn((4096, 4096), device="cuda", dtype=torch.bfloat16).to(torch.float8_e4m3fn)
3residual = torch.zeros((1, 4096), device="cuda", dtype=torch.bfloat16)
4
5ops.fp8_linear_residual_bf16(x, w, residual, alpha=1.0)1m, k, n = 51, 1536, 1536
2x = torch.randn((m, k), device="cuda").to(torch.float8_e4m3fn)
3w = torch.randn((n, k), device="cuda").to(torch.float8_e4m3fn)
4x_scale = torch.ones((m, k // 128), device="cuda", dtype=torch.float32)
5w_scale = torch.ones((n // 128, k // 128), device="cuda", dtype=torch.float32)
6
7y = ops.fp8_blockwise_linear_bf16(x, w, x_scale, w_scale)1python fp8-gemm/tests/test_fp8_gemm.py --backend source --mode full
2python fp8-gemm/benchmarks/benchmark.py --backend source --mode headline
3python fp8-gemm/benchmarks/benchmark.py --backend source --mode pi05-prefill
4python fp8-gemm/benchmarks/benchmark_bias.py --backend sourceM=65 large-M
boundary, and the three SigLIP bias epilogues. Public
benchmark tables are only updated after source correctness, installed artifact
correctness, shape/tile sweeps, torch.compile(fullgraph=True), CUDA Graph
replay, and parity against the original FlashRT native pointer entry pass.