liangsu9988 commited on
Commit
fcc5ab1
·
verified ·
1 Parent(s): 9843dc0

Uploaded using `kernel-builder`.

Browse files
benchmarks/benchmark_nvfp4_w4a4_decode_matvec.py ADDED
@@ -0,0 +1,204 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+
3
+ from kernels.benchmark import Benchmark
4
+
5
+
6
+ _original_allclose = torch.allclose
7
+
8
+
9
+ def _bf16_max_ulp(input: torch.Tensor, other: torch.Tensor) -> int:
10
+ got_bits = input.detach().cpu().view(torch.int16).to(torch.int32) & 0xFFFF
11
+ exp_bits = other.detach().cpu().view(torch.int16).to(torch.int32) & 0xFFFF
12
+ got_ordered = torch.where((got_bits & 0x8000) != 0, 0x8000 - (got_bits & 0x7FFF), got_bits)
13
+ exp_ordered = torch.where((exp_bits & 0x8000) != 0, 0x8000 - (exp_bits & 0x7FFF), exp_bits)
14
+ return int((got_ordered - exp_ordered).abs().max().item())
15
+
16
+
17
+ def _flashrt_allclose(input, other, rtol=1e-05, atol=1e-08, equal_nan=False):
18
+ if input.dtype == torch.bfloat16 and other.dtype == torch.bfloat16:
19
+ return _bf16_max_ulp(input, other) <= 5
20
+ return _original_allclose(input, other, rtol=rtol, atol=atol, equal_nan=equal_nan)
21
+
22
+
23
+ torch.allclose = _flashrt_allclose
24
+
25
+
26
+ DECODE_SHAPES = [
27
+ ("k4096_n1024", 4096, 1024),
28
+ ("k4096_n4096", 4096, 4096),
29
+ ("k4096_n12288", 4096, 12288),
30
+ ("k12288_n1024", 12288, 1024),
31
+ ("k12288_n4096", 12288, 4096),
32
+ ("k12288_n12288", 12288, 12288),
33
+ ]
34
+
35
+
36
+ def _swizzled_bytes(rows: int, cols: int) -> int:
37
+ n_blocks = cols // 16
38
+ return ((rows + 127) // 128) * ((n_blocks + 3) // 4) * 512
39
+
40
+
41
+ def _swizzle_constant_scale(rows: int, cols: int, value: int) -> torch.Tensor:
42
+ return torch.full((_swizzled_bytes(rows, cols),), value, dtype=torch.uint8)
43
+
44
+
45
+ def _reference_swizzle(scales: torch.Tensor) -> torch.Tensor:
46
+ rows, n_blocks = scales.shape
47
+ n_col_super = (n_blocks + 3) // 4
48
+ src = scales.cpu()
49
+ out = torch.zeros(
50
+ ((rows + 127) // 128) * n_col_super * 512,
51
+ dtype=torch.uint8,
52
+ )
53
+ for row in range(rows):
54
+ rb = row // 128
55
+ ri = row % 128
56
+ for block in range(n_blocks):
57
+ cb = block // 4
58
+ ci = block % 4
59
+ super_idx = rb * n_col_super + cb
60
+ inner_off = (ri % 32) * 16 + (ri // 32) * 4 + ci
61
+ out[super_idx * 512 + inner_off] = src[row, block]
62
+ return out
63
+
64
+
65
+ def _ue4m3_to_float(byte: int) -> float:
66
+ sign = -1.0 if (byte & 0x80) else 1.0
67
+ exp = (byte >> 3) & 0x0F
68
+ mant = byte & 0x07
69
+ if exp == 0:
70
+ return sign * (mant / 8.0) * (2.0 ** -6)
71
+ if exp == 15 and mant == 7:
72
+ return 0.0
73
+ return sign * (1.0 + mant / 8.0) * (2.0 ** (exp - 7))
74
+
75
+
76
+ def _ue4m3_lut() -> torch.Tensor:
77
+ return torch.tensor([_ue4m3_to_float(i) for i in range(256)], dtype=torch.float32)
78
+
79
+
80
+ def _fp4_codebook() -> torch.Tensor:
81
+ return torch.tensor(
82
+ [
83
+ 0.0,
84
+ 0.5,
85
+ 1.0,
86
+ 1.5,
87
+ 2.0,
88
+ 3.0,
89
+ 4.0,
90
+ 6.0,
91
+ -0.0,
92
+ -0.5,
93
+ -1.0,
94
+ -1.5,
95
+ -2.0,
96
+ -3.0,
97
+ -4.0,
98
+ -6.0,
99
+ ],
100
+ dtype=torch.float32,
101
+ )
102
+
103
+
104
+ def _unpack_fp4(packed: torch.Tensor) -> torch.Tensor:
105
+ codebook = _fp4_codebook().to(packed.device)
106
+ lo = packed & 0x0F
107
+ hi = packed >> 4
108
+ out = torch.empty(
109
+ (packed.shape[0], packed.shape[1] * 2),
110
+ device=packed.device,
111
+ dtype=torch.float32,
112
+ )
113
+ out[:, 0::2] = codebook[lo.long()]
114
+ out[:, 1::2] = codebook[hi.long()]
115
+ return out
116
+
117
+
118
+ def _reference_smallm(
119
+ a_packed: torch.Tensor,
120
+ b_packed: torch.Tensor,
121
+ sfa_linear: torch.Tensor,
122
+ sfb_linear: torch.Tensor,
123
+ K: int,
124
+ alpha: float,
125
+ chunk_rows: int = 256,
126
+ ) -> torch.Tensor:
127
+ device = b_packed.device
128
+ N = b_packed.shape[0]
129
+ lut = _ue4m3_lut().to(device)
130
+ a = _unpack_fp4(a_packed.reshape(1, -1)).reshape(K)
131
+ a_scale = lut[sfa_linear.reshape(-1).to(device).long()].repeat_interleave(16)
132
+ a = a * a_scale
133
+ sfb_linear = sfb_linear.to(device)
134
+ out = torch.empty((N,), device=device, dtype=torch.bfloat16)
135
+ for start in range(0, N, chunk_rows):
136
+ end = min(start + chunk_rows, N)
137
+ b = _unpack_fp4(b_packed[start:end])
138
+ b_scale = lut[sfb_linear[start:end].long()].repeat_interleave(16, dim=1)
139
+ expected = (b * b_scale * a.reshape(1, K)).sum(dim=1) * alpha
140
+ out[start:end] = expected.to(torch.bfloat16)
141
+ return out
142
+
143
+
144
+ class Nvfp4W4A4DecodeMatvecBenchmark(Benchmark):
145
+ seed = 23
146
+
147
+ def _setup_shape(self, K: int, N: int) -> None:
148
+ torch.manual_seed(600 + K + N)
149
+ if torch.cuda.is_available():
150
+ torch.cuda.manual_seed_all(600 + K + N)
151
+ self.K = K
152
+ self.N = N
153
+ self.alpha = 0.5
154
+ self.a_packed = torch.randint(
155
+ 0, 256, (K // 2,), device=self.device, dtype=torch.uint8
156
+ )
157
+ self.b_packed = torch.randint(
158
+ 0, 256, (N, K // 2), device=self.device, dtype=torch.uint8
159
+ )
160
+ self.sfa_linear = torch.randint(0, 0x78, (1, K // 16), dtype=torch.uint8)
161
+ self.sfb_linear = torch.randint(0, 0x78, (N, K // 16), dtype=torch.uint8)
162
+ self.sfa = _reference_swizzle(self.sfa_linear).to(self.device)
163
+ self.sfb = _reference_swizzle(self.sfb_linear).to(self.device)
164
+ self.out = torch.empty((N,), device=self.device, dtype=torch.bfloat16)
165
+
166
+ def _benchmark(self) -> None:
167
+ self.kernel.nvfp4_w4a4_decode_matvec_bf16out(
168
+ self.a_packed,
169
+ self.b_packed,
170
+ self.sfa,
171
+ self.sfb,
172
+ alpha=self.alpha,
173
+ out=self.out,
174
+ )
175
+
176
+ def _reference(self) -> torch.Tensor:
177
+ return _reference_smallm(
178
+ self.a_packed,
179
+ self.b_packed,
180
+ self.sfa_linear,
181
+ self.sfb_linear,
182
+ self.K,
183
+ self.alpha,
184
+ )
185
+
186
+
187
+ def _register_shapes() -> None:
188
+ for label, K, N in DECODE_SHAPES:
189
+
190
+ def setup(self, K=K, N=N) -> None:
191
+ self._setup_shape(K, N)
192
+
193
+ def benchmark(self) -> None:
194
+ self._benchmark()
195
+
196
+ def verify(self) -> torch.Tensor:
197
+ return self._reference()
198
+
199
+ setattr(Nvfp4W4A4DecodeMatvecBenchmark, f"setup_{label}", setup)
200
+ setattr(Nvfp4W4A4DecodeMatvecBenchmark, f"benchmark_{label}", benchmark)
201
+ setattr(Nvfp4W4A4DecodeMatvecBenchmark, f"verify_{label}", verify)
202
+
203
+
204
+ _register_shapes()
build/torch211-cxx11-cu128-x86_64-linux/__init__.py ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """FlashRT small-M GEMM kernels."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Optional
6
+
7
+ import torch
8
+
9
+ from ._ops import ops
10
+
11
+
12
+ def nvfp4_w4a4_decode_matvec_bf16out(
13
+ a_packed: torch.Tensor,
14
+ b_packed: torch.Tensor,
15
+ sfa: torch.Tensor,
16
+ sfb: torch.Tensor,
17
+ *,
18
+ alpha: float = 1.0,
19
+ out: Optional[torch.Tensor] = None,
20
+ ) -> torch.Tensor:
21
+ """Compute an SM120 NVFP4 W4A4 M=1 matvec with BF16 output.
22
+
23
+ ``a_packed`` contains one packed activation row with shape ``(K / 2,)`` or
24
+ ``(1, K / 2)``. ``b_packed`` is row-major with shape ``(N, K / 2)``. ``sfa``
25
+ and ``sfb`` are CUTLASS Sm1xx swizzled UE4M3 scale-factor byte buffers.
26
+ The current kernel supports ``K in {4096, 12288}``.
27
+ """
28
+
29
+ if b_packed.dim() != 2:
30
+ raise ValueError("b_packed must have shape (N, K / 2)")
31
+ if out is None:
32
+ out = torch.empty((b_packed.shape[0],), device=b_packed.device, dtype=torch.bfloat16)
33
+ ops.nvfp4_w4a4_decode_matvec_bf16out(
34
+ a_packed,
35
+ b_packed,
36
+ sfa,
37
+ sfb,
38
+ out,
39
+ float(alpha),
40
+ )
41
+ return out
42
+
43
+
44
+ __all__ = [
45
+ "nvfp4_w4a4_decode_matvec_bf16out",
46
+ ]
build/torch211-cxx11-cu128-x86_64-linux/_flashrt_smallm_gemm_cuda_e9a1fe0.abi3.so ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:f3dab9620683469830bc894b374cbceb448bfd36a61b3a6a49d081a13ea7c0d2
3
+ size 120640
build/torch211-cxx11-cu128-x86_64-linux/_ops.py ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+ from . import _flashrt_smallm_gemm_cuda_e9a1fe0
3
+ ops = torch.ops._flashrt_smallm_gemm_cuda_e9a1fe0
4
+
5
+ def add_op_namespace_prefix(op_name: str):
6
+ """
7
+ Prefix op by namespace.
8
+ """
9
+ return f"_flashrt_smallm_gemm_cuda_e9a1fe0::{op_name}"
build/torch211-cxx11-cu128-x86_64-linux/flashrt_smallm_gemm/__init__.py ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import ctypes
2
+ import importlib.util
3
+ import sys
4
+ from pathlib import Path
5
+ from types import ModuleType
6
+
7
+
8
+ def _import_from_path(file_path: Path) -> ModuleType:
9
+ # We cannot use the module name as-is, after adding it to `sys.modules`,
10
+ # it would also be used for other imports. So, we make a module name that
11
+ # depends on the path for it to be unique using the hex-encoded hash of
12
+ # the path.
13
+ path_hash = "{:x}".format(ctypes.c_size_t(hash(file_path.absolute())).value)
14
+ module_name = path_hash
15
+ spec = importlib.util.spec_from_file_location(module_name, file_path)
16
+ if spec is None:
17
+ raise ImportError(f"Cannot load spec for {module_name} from {file_path}")
18
+ module = importlib.util.module_from_spec(spec)
19
+ if module is None:
20
+ raise ImportError(f"Cannot load module {module_name} from spec")
21
+ sys.modules[module_name] = module
22
+ spec.loader.exec_module(module) # type: ignore
23
+ return module
24
+
25
+
26
+ globals().update(vars(_import_from_path(Path(__file__).parent.parent / "__init__.py")))
build/torch211-cxx11-cu128-x86_64-linux/metadata.json ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "flashrt-smallm-gemm",
3
+ "id": "_flashrt_smallm_gemm_cuda_e9a1fe0",
4
+ "version": 1,
5
+ "license": "Apache-2.0",
6
+ "python-depends": [],
7
+ "backend": {
8
+ "type": "cuda",
9
+ "archs": [
10
+ "12.0"
11
+ ]
12
+ }
13
+ }
build/torch211-cxx11-cu130-x86_64-linux/__init__.py ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """FlashRT small-M GEMM kernels."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Optional
6
+
7
+ import torch
8
+
9
+ from ._ops import ops
10
+
11
+
12
+ def nvfp4_w4a4_decode_matvec_bf16out(
13
+ a_packed: torch.Tensor,
14
+ b_packed: torch.Tensor,
15
+ sfa: torch.Tensor,
16
+ sfb: torch.Tensor,
17
+ *,
18
+ alpha: float = 1.0,
19
+ out: Optional[torch.Tensor] = None,
20
+ ) -> torch.Tensor:
21
+ """Compute an SM120 NVFP4 W4A4 M=1 matvec with BF16 output.
22
+
23
+ ``a_packed`` contains one packed activation row with shape ``(K / 2,)`` or
24
+ ``(1, K / 2)``. ``b_packed`` is row-major with shape ``(N, K / 2)``. ``sfa``
25
+ and ``sfb`` are CUTLASS Sm1xx swizzled UE4M3 scale-factor byte buffers.
26
+ The current kernel supports ``K in {4096, 12288}``.
27
+ """
28
+
29
+ if b_packed.dim() != 2:
30
+ raise ValueError("b_packed must have shape (N, K / 2)")
31
+ if out is None:
32
+ out = torch.empty((b_packed.shape[0],), device=b_packed.device, dtype=torch.bfloat16)
33
+ ops.nvfp4_w4a4_decode_matvec_bf16out(
34
+ a_packed,
35
+ b_packed,
36
+ sfa,
37
+ sfb,
38
+ out,
39
+ float(alpha),
40
+ )
41
+ return out
42
+
43
+
44
+ __all__ = [
45
+ "nvfp4_w4a4_decode_matvec_bf16out",
46
+ ]
build/torch211-cxx11-cu130-x86_64-linux/_flashrt_smallm_gemm_cuda_e9a1fe0.abi3.so ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:8b9a7f6a78cb3784d9efa7cde5349c220f183799254f23326aba75cd1accee4e
3
+ size 122624
build/torch211-cxx11-cu130-x86_64-linux/_ops.py ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+ from . import _flashrt_smallm_gemm_cuda_e9a1fe0
3
+ ops = torch.ops._flashrt_smallm_gemm_cuda_e9a1fe0
4
+
5
+ def add_op_namespace_prefix(op_name: str):
6
+ """
7
+ Prefix op by namespace.
8
+ """
9
+ return f"_flashrt_smallm_gemm_cuda_e9a1fe0::{op_name}"
build/torch211-cxx11-cu130-x86_64-linux/flashrt_smallm_gemm/__init__.py ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import ctypes
2
+ import importlib.util
3
+ import sys
4
+ from pathlib import Path
5
+ from types import ModuleType
6
+
7
+
8
+ def _import_from_path(file_path: Path) -> ModuleType:
9
+ # We cannot use the module name as-is, after adding it to `sys.modules`,
10
+ # it would also be used for other imports. So, we make a module name that
11
+ # depends on the path for it to be unique using the hex-encoded hash of
12
+ # the path.
13
+ path_hash = "{:x}".format(ctypes.c_size_t(hash(file_path.absolute())).value)
14
+ module_name = path_hash
15
+ spec = importlib.util.spec_from_file_location(module_name, file_path)
16
+ if spec is None:
17
+ raise ImportError(f"Cannot load spec for {module_name} from {file_path}")
18
+ module = importlib.util.module_from_spec(spec)
19
+ if module is None:
20
+ raise ImportError(f"Cannot load module {module_name} from spec")
21
+ sys.modules[module_name] = module
22
+ spec.loader.exec_module(module) # type: ignore
23
+ return module
24
+
25
+
26
+ globals().update(vars(_import_from_path(Path(__file__).parent.parent / "__init__.py")))
build/torch211-cxx11-cu130-x86_64-linux/metadata.json ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "flashrt-smallm-gemm",
3
+ "id": "_flashrt_smallm_gemm_cuda_e9a1fe0",
4
+ "version": 1,
5
+ "license": "Apache-2.0",
6
+ "python-depends": [],
7
+ "backend": {
8
+ "type": "cuda",
9
+ "archs": [
10
+ "12.0"
11
+ ]
12
+ }
13
+ }
build/torch212-cxx11-cu130-x86_64-linux/__init__.py ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """FlashRT small-M GEMM kernels."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Optional
6
+
7
+ import torch
8
+
9
+ from ._ops import ops
10
+
11
+
12
+ def nvfp4_w4a4_decode_matvec_bf16out(
13
+ a_packed: torch.Tensor,
14
+ b_packed: torch.Tensor,
15
+ sfa: torch.Tensor,
16
+ sfb: torch.Tensor,
17
+ *,
18
+ alpha: float = 1.0,
19
+ out: Optional[torch.Tensor] = None,
20
+ ) -> torch.Tensor:
21
+ """Compute an SM120 NVFP4 W4A4 M=1 matvec with BF16 output.
22
+
23
+ ``a_packed`` contains one packed activation row with shape ``(K / 2,)`` or
24
+ ``(1, K / 2)``. ``b_packed`` is row-major with shape ``(N, K / 2)``. ``sfa``
25
+ and ``sfb`` are CUTLASS Sm1xx swizzled UE4M3 scale-factor byte buffers.
26
+ The current kernel supports ``K in {4096, 12288}``.
27
+ """
28
+
29
+ if b_packed.dim() != 2:
30
+ raise ValueError("b_packed must have shape (N, K / 2)")
31
+ if out is None:
32
+ out = torch.empty((b_packed.shape[0],), device=b_packed.device, dtype=torch.bfloat16)
33
+ ops.nvfp4_w4a4_decode_matvec_bf16out(
34
+ a_packed,
35
+ b_packed,
36
+ sfa,
37
+ sfb,
38
+ out,
39
+ float(alpha),
40
+ )
41
+ return out
42
+
43
+
44
+ __all__ = [
45
+ "nvfp4_w4a4_decode_matvec_bf16out",
46
+ ]
build/torch212-cxx11-cu130-x86_64-linux/_flashrt_smallm_gemm_cuda_e9a1fe0.abi3.so ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:3a673a1f997be6ea22666a1bcbade96917cb8f05137797809376e30721bba547
3
+ size 133544
build/torch212-cxx11-cu130-x86_64-linux/_ops.py ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+ from . import _flashrt_smallm_gemm_cuda_e9a1fe0
3
+ ops = torch.ops._flashrt_smallm_gemm_cuda_e9a1fe0
4
+
5
+ def add_op_namespace_prefix(op_name: str):
6
+ """
7
+ Prefix op by namespace.
8
+ """
9
+ return f"_flashrt_smallm_gemm_cuda_e9a1fe0::{op_name}"
build/torch212-cxx11-cu130-x86_64-linux/flashrt_smallm_gemm/__init__.py ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import ctypes
2
+ import importlib.util
3
+ import sys
4
+ from pathlib import Path
5
+ from types import ModuleType
6
+
7
+
8
+ def _import_from_path(file_path: Path) -> ModuleType:
9
+ # We cannot use the module name as-is, after adding it to `sys.modules`,
10
+ # it would also be used for other imports. So, we make a module name that
11
+ # depends on the path for it to be unique using the hex-encoded hash of
12
+ # the path.
13
+ path_hash = "{:x}".format(ctypes.c_size_t(hash(file_path.absolute())).value)
14
+ module_name = path_hash
15
+ spec = importlib.util.spec_from_file_location(module_name, file_path)
16
+ if spec is None:
17
+ raise ImportError(f"Cannot load spec for {module_name} from {file_path}")
18
+ module = importlib.util.module_from_spec(spec)
19
+ if module is None:
20
+ raise ImportError(f"Cannot load module {module_name} from spec")
21
+ sys.modules[module_name] = module
22
+ spec.loader.exec_module(module) # type: ignore
23
+ return module
24
+
25
+
26
+ globals().update(vars(_import_from_path(Path(__file__).parent.parent / "__init__.py")))
build/torch212-cxx11-cu130-x86_64-linux/metadata.json ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "flashrt-smallm-gemm",
3
+ "id": "_flashrt_smallm_gemm_cuda_e9a1fe0",
4
+ "version": 1,
5
+ "license": "Apache-2.0",
6
+ "python-depends": [],
7
+ "backend": {
8
+ "type": "cuda",
9
+ "archs": [
10
+ "12.0"
11
+ ]
12
+ }
13
+ }
build/torch212-cxx11-cu132-x86_64-linux/__init__.py ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """FlashRT small-M GEMM kernels."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Optional
6
+
7
+ import torch
8
+
9
+ from ._ops import ops
10
+
11
+
12
+ def nvfp4_w4a4_decode_matvec_bf16out(
13
+ a_packed: torch.Tensor,
14
+ b_packed: torch.Tensor,
15
+ sfa: torch.Tensor,
16
+ sfb: torch.Tensor,
17
+ *,
18
+ alpha: float = 1.0,
19
+ out: Optional[torch.Tensor] = None,
20
+ ) -> torch.Tensor:
21
+ """Compute an SM120 NVFP4 W4A4 M=1 matvec with BF16 output.
22
+
23
+ ``a_packed`` contains one packed activation row with shape ``(K / 2,)`` or
24
+ ``(1, K / 2)``. ``b_packed`` is row-major with shape ``(N, K / 2)``. ``sfa``
25
+ and ``sfb`` are CUTLASS Sm1xx swizzled UE4M3 scale-factor byte buffers.
26
+ The current kernel supports ``K in {4096, 12288}``.
27
+ """
28
+
29
+ if b_packed.dim() != 2:
30
+ raise ValueError("b_packed must have shape (N, K / 2)")
31
+ if out is None:
32
+ out = torch.empty((b_packed.shape[0],), device=b_packed.device, dtype=torch.bfloat16)
33
+ ops.nvfp4_w4a4_decode_matvec_bf16out(
34
+ a_packed,
35
+ b_packed,
36
+ sfa,
37
+ sfb,
38
+ out,
39
+ float(alpha),
40
+ )
41
+ return out
42
+
43
+
44
+ __all__ = [
45
+ "nvfp4_w4a4_decode_matvec_bf16out",
46
+ ]
build/torch212-cxx11-cu132-x86_64-linux/_flashrt_smallm_gemm_cuda_e9a1fe0.abi3.so ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:b6c6eeb21bcf2331def3c8f94f2b5af15d209f655475ecb07afe603c0be36eac
3
+ size 133544
build/torch212-cxx11-cu132-x86_64-linux/_ops.py ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+ from . import _flashrt_smallm_gemm_cuda_e9a1fe0
3
+ ops = torch.ops._flashrt_smallm_gemm_cuda_e9a1fe0
4
+
5
+ def add_op_namespace_prefix(op_name: str):
6
+ """
7
+ Prefix op by namespace.
8
+ """
9
+ return f"_flashrt_smallm_gemm_cuda_e9a1fe0::{op_name}"
build/torch212-cxx11-cu132-x86_64-linux/flashrt_smallm_gemm/__init__.py ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import ctypes
2
+ import importlib.util
3
+ import sys
4
+ from pathlib import Path
5
+ from types import ModuleType
6
+
7
+
8
+ def _import_from_path(file_path: Path) -> ModuleType:
9
+ # We cannot use the module name as-is, after adding it to `sys.modules`,
10
+ # it would also be used for other imports. So, we make a module name that
11
+ # depends on the path for it to be unique using the hex-encoded hash of
12
+ # the path.
13
+ path_hash = "{:x}".format(ctypes.c_size_t(hash(file_path.absolute())).value)
14
+ module_name = path_hash
15
+ spec = importlib.util.spec_from_file_location(module_name, file_path)
16
+ if spec is None:
17
+ raise ImportError(f"Cannot load spec for {module_name} from {file_path}")
18
+ module = importlib.util.module_from_spec(spec)
19
+ if module is None:
20
+ raise ImportError(f"Cannot load module {module_name} from spec")
21
+ sys.modules[module_name] = module
22
+ spec.loader.exec_module(module) # type: ignore
23
+ return module
24
+
25
+
26
+ globals().update(vars(_import_from_path(Path(__file__).parent.parent / "__init__.py")))
build/torch212-cxx11-cu132-x86_64-linux/metadata.json ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "flashrt-smallm-gemm",
3
+ "id": "_flashrt_smallm_gemm_cuda_e9a1fe0",
4
+ "version": 1,
5
+ "license": "Apache-2.0",
6
+ "python-depends": [],
7
+ "backend": {
8
+ "type": "cuda",
9
+ "archs": [
10
+ "12.0"
11
+ ]
12
+ }
13
+ }