liangsu9988 commited on
Commit
8ba4faf
·
verified ·
1 Parent(s): 27bb2df

Promote latest kernel artifacts to main

Browse files
README.md CHANGED
@@ -1,9 +1,116 @@
1
- # flashrt/fp4-gemm
2
 
3
- This repository is a compatibility mirror for older `kernels` clients
4
- that resolve repositories through the default Hugging Face model repo API.
5
 
6
- Canonical Kernel Hub repo: https://huggingface.co/kernels/flashrt/fp4-gemm
 
 
 
7
 
8
- Do not edit this mirror by hand. It is generated from the Kernel Hub
9
- `vN` branches and contains the same `build/**` artifacts.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # fp4-gemm
2
 
3
+ FlashRT native Blackwell NVFP4 A4W4 GEMM kernels.
 
4
 
5
+ This package consumes packed FP4 E2M1 tensors plus CUTLASS Sm1xx SFA/SFB scale
6
+ buffers and produces BF16 output. It is designed to pair with
7
+ `flashrt/fp4-fused-ops` and other static low-bit transformer/diffuser runtime
8
+ paths.
9
 
10
+ ## Available Functions
11
+
12
+ - `sfa_size_bytes(rows, dim)`
13
+ - `quantize_fp4_sfa_fp16(x, packed=None, sfa=None, is_sfb=False)`
14
+ - `quantize_fp4_sfa_bf16(x, packed=None, sfa=None, is_sfb=False)`
15
+ - `dequantize_fp4_sfa_fp16(packed, sfa, out=None, is_sfb=False)`
16
+ - `nvfp4_gemm_bf16(a_packed, b_packed, sfa, sfb, alpha=1.0, out=None, variant=-1)`
17
+ - `nvfp4_gemm_bias_bf16(a_packed, b_packed, sfa, sfb, bias, out=None)`
18
+ - `nvfp4_gemm_bias_residual_bf16(a_packed, b_packed, sfa, sfb, bias, residual, out=None)`
19
+ - `nvfp4_gemm_residual_bf16(a_packed, b_packed, sfa, sfb, residual, alpha=1.0, out=None)`
20
+ - `nvfp4_gemm_bias_gelu_bf16(a_packed, b_packed, sfa, sfb, bias, alpha=1.0, out=None)`
21
+ - `nvfp4_gemm_bias_gelu_nvfp4(a_packed, b_packed, sfa, sfb, bias, alpha=1.0, out_packed=None, out_sfa=None)`
22
+ - `nvfp4_gemm_streamk_bf16(a_packed, b_packed, sfa, sfb, alpha=1.0, out=None)`
23
+ - `nvfp4_gemm_streamk_bias_bf16(a_packed, b_packed, sfa, sfb, bias, alpha=1.0, out=None)`
24
+ - `fp4_w4a16_linear_bf16(...)` is retained as a compatibility alias
25
+
26
+ ## Tensor Contract
27
+
28
+ - `a_packed`: `torch.uint8`, shape `(M, K / 2)`.
29
+ - `b_packed`: `torch.uint8`, shape `(N, K / 2)`.
30
+ - `sfa`: `torch.uint8`, CUTLASS SFA layout for `(M, K)`.
31
+ - `sfb`: `torch.uint8`, CUTLASS SFB layout for `(N, K)`.
32
+ - output: `torch.bfloat16`, shape `(M, N)`.
33
+ - `K` must be divisible by 16.
34
+ - Targets: Blackwell `sm_110a` (Jetson AGX Thor, CUDA 13+) and `sm_120a`
35
+ (RTX Blackwell, CUDA 12.8+).
36
+
37
+ `variant` selects the CUTLASS schedule:
38
+
39
+ - `-1`: architecture-aware auto-dispatch (public default).
40
+ - `0`: default `<128,128,256>` cooperative schedule.
41
+ - `1`: widen `<128,256,128>` schedule, intended for very large `N`.
42
+ - `2`: pingpong schedule for A/B testing shape-specific wins.
43
+
44
+ The canonical linear API and FP4/SFA quantize/dequantize helpers are available
45
+ on both SM110 and SM120. SM110 additionally provides the GROOT N1.7 production
46
+ epilogues `nvfp4_gemm_bias_bf16`, `nvfp4_gemm_bias_residual_bf16`, and
47
+ `nvfp4_gemm_bias_gelu_nvfp4`. The latter emits packed FP4 plus CUTLASS SFA so
48
+ the following projection can consume it without a BF16 materialization and a
49
+ standalone quantization launch. Stream-K and the older BF16 GELU epilogue keep
50
+ their existing SM120 dispatch and reject unsupported architectures explicitly.
51
+
52
+ The SM110 release gate includes the production `(M,N,K)` shapes
53
+ `(41,4608,1536)`, `(41,6144,1536)`, and `(41,1536,6144)`, plus the legacy
54
+ `M=51` compatibility row. The kernels are the native sources used by FlashRT's
55
+ GROOT N1.7 Thor NVFP4 pipeline.
56
+
57
+ ## Minimal Usage
58
+
59
+ ```python
60
+ from kernels import get_kernel
61
+ import torch
62
+
63
+ ops = get_kernel("flashrt/fp4-gemm", version=1, trust_remote_code=True)
64
+
65
+ x = torch.randn((32, 256), device="cuda", dtype=torch.float16)
66
+ w = torch.randn((512, 256), device="cuda", dtype=torch.float16)
67
+
68
+ a_packed, sfa = ops.quantize_fp4_sfa_fp16(x, is_sfb=False)
69
+ b_packed, sfb = ops.quantize_fp4_sfa_fp16(w, is_sfb=True)
70
+
71
+ y = ops.nvfp4_gemm_bf16(a_packed, b_packed, sfa, sfb, alpha=1.0)
72
+ ```
73
+
74
+ For BF16 model activations, use the direct producer so the hot path does not
75
+ materialize an intermediate FP16 tensor:
76
+
77
+ ```python
78
+ x_bf16 = torch.randn((1, 5120), device="cuda", dtype=torch.bfloat16)
79
+ a_packed, sfa = ops.quantize_fp4_sfa_bf16(x_bf16)
80
+ ```
81
+
82
+ The BF16 entry writes the same E2M1 bytes and CUTLASS SFA/SFB layout as
83
+ `quantize_fp4_sfa_fp16(x_bf16.to(torch.float16))` for finite FP16-range
84
+ inputs. It is an additive API; the existing FP16 producer remains unchanged.
85
+
86
+ The quantize/dequantize helpers are included for examples and validation. A
87
+ production runtime should keep weights prepacked and should avoid quantizing in
88
+ the hot path unless that producer kernel is part of the intended low-bit block.
89
+
90
+ Use the bias/GELU and residual variants to avoid returning to BF16
91
+ elementwise code between low-bit GEMMs. Stream-K variants are selected only
92
+ for the validated large down-projection shapes; unsupported shapes reject
93
+ rather than silently selecting a losing schedule.
94
+
95
+ ## Validation
96
+
97
+ ```bash
98
+ python fp4-gemm/tests/test_fp4_gemm.py --backend source --mode full
99
+ python fp4-gemm/tests/test_fp4_gemm.py --backend installed --mode full \
100
+ --artifact fp4-gemm/build/torch211-cxx11-cu128-x86_64-linux
101
+ python fp4-gemm/benchmarks/benchmark.py --backend installed --mode headline \
102
+ --artifact fp4-gemm/build/torch211-cxx11-cu128-x86_64-linux
103
+
104
+ # Thor model-shape gate
105
+ python fp4-gemm/tests/test_fp4_gemm.py --backend installed \
106
+ --mode thor-models \
107
+ --artifact fp4-gemm/build/torch211-cxx11-cu130-aarch64-linux
108
+ ```
109
+
110
+ The correctness reference dequantizes the same FP4/SFA and FP4/SFB inputs used
111
+ by the kernel, then computes the PyTorch GEMM reference from those dequantized
112
+ low-bit values.
113
+
114
+ The producer gate also checks the BF16 direct entry byte-for-byte against the
115
+ established FP16 compatibility chain at decode widths 5120, 6144 and 17408,
116
+ plus multi-row activation and SFB layouts.
build/torch213-cxx11-cu130-aarch64-linux/__init__.py CHANGED
@@ -42,6 +42,16 @@ def _linear_fp16_fake(a_packed, b_packed, sfa, sfb, out, alpha: float = 1.0, var
42
  return None
43
 
44
 
 
 
 
 
 
 
 
 
 
 
45
  @torch.library.register_fake(add_op_namespace_prefix("nvfp4_gemm_geglu_nvfp4_fp16"))
46
  def _geglu_fp4_fake(a, b, sfa, sfb, scratch, out_packed, out_sfa, skinny: bool = False) -> None:
47
  return None
@@ -94,6 +104,11 @@ def _quant_fake(x: torch.Tensor, packed: torch.Tensor, sfa: torch.Tensor, is_sfb
94
  return None
95
 
96
 
 
 
 
 
 
97
  @torch.library.register_fake(add_op_namespace_prefix("quantize_e0m3_sfa_fp16"))
98
  def _quant_e0m3_fake(x, packed, sfa, is_sfb: bool = False) -> None:
99
  return None
@@ -158,6 +173,19 @@ def quantize_fp4_sfa_fp16(
158
  return packed, sfa
159
 
160
 
 
 
 
 
 
 
 
 
 
 
 
 
 
161
  def quantize_e0m3_sfa_fp16(
162
  x: torch.Tensor,
163
  packed: torch.Tensor | None = None,
@@ -276,6 +304,52 @@ def nvfp4_gemm_fp16(
276
  return out
277
 
278
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
279
  def nvfp4_gemm_geglu_nvfp4_fp16(
280
  a_packed: torch.Tensor,
281
  b_interleaved_packed: torch.Tensor,
@@ -533,6 +607,8 @@ __all__ = [
533
  "fp4_w4a4_gemv_warpsplit_bf16",
534
  "nvfp4_gemm_bf16",
535
  "nvfp4_gemm_fp16",
 
 
536
  "nvfp4_gemm_geglu_nvfp4_fp16",
537
  "nvfp4_gemm_bias_gelu_nvfp4_fp16",
538
  "nvfp4_gemm_bias_residual_fp16",
@@ -545,6 +621,7 @@ __all__ = [
545
  "nvfp4_gemm_streamk_bf16",
546
  "nvfp4_gemm_streamk_bias_bf16",
547
  "quantize_fp4_sfa_fp16",
 
548
  "quantize_e0m3_sfa_fp16",
549
  "quantize_fp4_sfa_bf16",
550
  "sfa_size_bytes",
 
42
  return None
43
 
44
 
45
+ @torch.library.register_fake(add_op_namespace_prefix("nvfp4_gemm_variant_bf16"))
46
+ def _linear_variant_bf16_fake(a, b, sfa, sfb, out, alpha: float = 1.0, variant: int = 7) -> None:
47
+ return None
48
+
49
+
50
+ @torch.library.register_fake(add_op_namespace_prefix("nvfp4_gemm_nvfp4"))
51
+ def _linear_fp4out_fake(a, b, sfa, sfb, out_packed, out_sfa) -> None:
52
+ return None
53
+
54
+
55
  @torch.library.register_fake(add_op_namespace_prefix("nvfp4_gemm_geglu_nvfp4_fp16"))
56
  def _geglu_fp4_fake(a, b, sfa, sfb, scratch, out_packed, out_sfa, skinny: bool = False) -> None:
57
  return None
 
104
  return None
105
 
106
 
107
+ @torch.library.register_fake(add_op_namespace_prefix("quantize_fp4_sfa_mse_fp16"))
108
+ def _quant_mse_fake(x, packed, sfa, is_sfb: bool = False) -> None:
109
+ return None
110
+
111
+
112
  @torch.library.register_fake(add_op_namespace_prefix("quantize_e0m3_sfa_fp16"))
113
  def _quant_e0m3_fake(x, packed, sfa, is_sfb: bool = False) -> None:
114
  return None
 
173
  return packed, sfa
174
 
175
 
176
+ def quantize_fp4_sfa_mse_fp16(
177
+ x: torch.Tensor,
178
+ packed: torch.Tensor | None = None,
179
+ sfa: torch.Tensor | None = None,
180
+ is_sfb: bool = False,
181
+ ):
182
+ """Pack FP16 weights using per-block reconstruction-MSE scale search."""
183
+ if packed is None or sfa is None:
184
+ packed, sfa = _alloc_fp4(x.shape[0], x.shape[1], x.device)
185
+ ops.quantize_fp4_sfa_mse_fp16(x, packed, sfa, bool(is_sfb))
186
+ return packed, sfa
187
+
188
+
189
  def quantize_e0m3_sfa_fp16(
190
  x: torch.Tensor,
191
  packed: torch.Tensor | None = None,
 
304
  return out
305
 
306
 
307
+ def nvfp4_gemm_variant_bf16(
308
+ a_packed: torch.Tensor,
309
+ b_packed: torch.Tensor,
310
+ sfa: torch.Tensor,
311
+ sfb: torch.Tensor,
312
+ alpha: float = 1.0,
313
+ out: torch.Tensor | None = None,
314
+ variant: int = 7,
315
+ ) -> torch.Tensor:
316
+ """SM110 native NVFP4 GEMM with BF16 output.
317
+
318
+ ``variant=7`` serves large-M encoder/SigLIP shapes; ``variant=10`` is
319
+ the narrow-N PI0.5 decoder tile. The indices match FlashRT native.
320
+ """
321
+ if out is None:
322
+ out = torch.empty(
323
+ (a_packed.shape[0], b_packed.shape[0]),
324
+ device=a_packed.device,
325
+ dtype=torch.bfloat16,
326
+ )
327
+ ops.nvfp4_gemm_variant_bf16(
328
+ a_packed, b_packed, sfa, sfb, out, float(alpha), int(variant)
329
+ )
330
+ return out
331
+
332
+
333
+ def nvfp4_gemm_nvfp4(
334
+ a_packed: torch.Tensor,
335
+ b_packed: torch.Tensor,
336
+ sfa: torch.Tensor,
337
+ sfb: torch.Tensor,
338
+ *,
339
+ out_packed: torch.Tensor | None = None,
340
+ out_sfa: torch.Tensor | None = None,
341
+ ) -> tuple[torch.Tensor, torch.Tensor]:
342
+ """SM110 NVFP4 GEMM with an NVFP4 output and CUTLASS SFA layout."""
343
+ if out_packed is None or out_sfa is None:
344
+ out_packed, out_sfa = _alloc_fp4(
345
+ a_packed.shape[0], b_packed.shape[0], a_packed.device
346
+ )
347
+ ops.nvfp4_gemm_nvfp4(
348
+ a_packed, b_packed, sfa, sfb, out_packed, out_sfa
349
+ )
350
+ return out_packed, out_sfa
351
+
352
+
353
  def nvfp4_gemm_geglu_nvfp4_fp16(
354
  a_packed: torch.Tensor,
355
  b_interleaved_packed: torch.Tensor,
 
607
  "fp4_w4a4_gemv_warpsplit_bf16",
608
  "nvfp4_gemm_bf16",
609
  "nvfp4_gemm_fp16",
610
+ "nvfp4_gemm_variant_bf16",
611
+ "nvfp4_gemm_nvfp4",
612
  "nvfp4_gemm_geglu_nvfp4_fp16",
613
  "nvfp4_gemm_bias_gelu_nvfp4_fp16",
614
  "nvfp4_gemm_bias_residual_fp16",
 
621
  "nvfp4_gemm_streamk_bf16",
622
  "nvfp4_gemm_streamk_bias_bf16",
623
  "quantize_fp4_sfa_fp16",
624
+ "quantize_fp4_sfa_mse_fp16",
625
  "quantize_e0m3_sfa_fp16",
626
  "quantize_fp4_sfa_bf16",
627
  "sfa_size_bytes",
build/torch213-cxx11-cu130-aarch64-linux/_ops.py CHANGED
@@ -1,6 +1,6 @@
1
  import torch
2
- from . import _fp4_gemm_cuda_230e467
3
- ops = torch.ops._fp4_gemm_cuda_230e467
4
 
5
  def add_op_namespace_prefix(op_name: str):
6
- return f"_fp4_gemm_cuda_230e467::{op_name}"
 
1
  import torch
2
+ from . import fp4_gemm_source_test
3
+ ops = torch.ops.fp4_gemm_source_test
4
 
5
  def add_op_namespace_prefix(op_name: str):
6
+ return f"fp4_gemm_source_test::{op_name}"
build/torch213-cxx11-cu130-aarch64-linux/{_fp4_gemm_cuda_230e467.abi3.so → fp4_gemm_source_test.abi3.so} RENAMED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:54da8e4f3b0c728c6309dcb434fb608cf50085dfbf3051381ff6b1687316103c
3
- size 5530648
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:73b4cbcb15d13cc6452007e59961f3b217d21771f0c0937cc121cc8e0e6b1e12
3
+ size 6529016
build/torch213-cxx11-cu130-aarch64-linux/metadata.json CHANGED
@@ -1,28 +1,32 @@
1
  {
2
  "name": "fp4-gemm",
3
- "id": "_fp4_gemm_cuda_230e467",
4
  "version": 1,
5
  "license": "Apache-2.0",
6
  "python-depends": [],
7
  "backend": {
8
  "type": "cuda",
9
  "archs": [
10
- "11.0a"
11
  ]
12
  },
13
  "digest": {
14
  "algorithm": "sha256",
15
  "files": {
16
- "__init__.py": "Qfdvg/9EedWLGh34xAalDfC0IsAHCOL44L4ShaP/w5Y=",
17
- "_fp4_gemm_cuda_230e467.abi3.so": "VNqOTzsMcoxjCdy0NPtgjPUAhd+/MFE4H/axaHMWEDw=",
18
- "_ops.py": "IfU2iMVrWYRnoe6q8HI3hU8TPnAlLrXDerlv117PcXI=",
19
  "fp4_gemm/__init__.py": "v6p5XMfQzddhi1fLSAw4HX9CyS0rQsidvu9VsT01xi4="
20
  }
21
  },
22
  "provenance": {
23
  "kernel": {
24
- "sha": "230e467",
25
  "dirty": false
 
 
 
 
26
  }
27
  }
28
  }
 
1
  {
2
  "name": "fp4-gemm",
3
+ "id": "fp4_gemm_source_test",
4
  "version": 1,
5
  "license": "Apache-2.0",
6
  "python-depends": [],
7
  "backend": {
8
  "type": "cuda",
9
  "archs": [
10
+ "11.0"
11
  ]
12
  },
13
  "digest": {
14
  "algorithm": "sha256",
15
  "files": {
16
+ "__init__.py": "Fb/FDYOpDw+YGlevblUsv4AkILDQCJdB807qdDUDI1c=",
17
+ "fp4_gemm_source_test.abi3.so": "c7TLyxXRPMZFIAflmWHzshfSF3HwwJN8wSHMjg5rHhI=",
18
+ "_ops.py": "ZPjRxrYk7lCA0ZHoCjg8BaJyFY7a5i4NC3jIL6VMRJ4=",
19
  "fp4_gemm/__init__.py": "v6p5XMfQzddhi1fLSAw4HX9CyS0rQsidvu9VsT01xi4="
20
  }
21
  },
22
  "provenance": {
23
  "kernel": {
24
+ "sha": "b6588aa59dd4f8c646f90b58312a0a66886e061f",
25
  "dirty": false
26
+ },
27
+ "validation": {
28
+ "torch": "2.13.0+cu130",
29
+ "cuda": "13.0"
30
  }
31
  }
32
  }