liangsu9988 commited on
Commit
de7da55
·
verified ·
1 Parent(s): 1692dbc

Promote latest kernel artifacts to main

Browse files
Files changed (28) hide show
  1. README.md +0 -9
  2. benchmarks/benchmark.py +171 -4
  3. build/torch211-cxx11-cu128-x86_64-linux/__init__.py +204 -0
  4. build/{torch212-cxx11-cu132-x86_64-linux/_fp4_fused_ops_cuda_7e2e5b9.abi3.so → torch211-cxx11-cu128-x86_64-linux/_fp4_fused_ops_cuda_8e0b1cd.abi3.so} +2 -2
  5. build/torch211-cxx11-cu128-x86_64-linux/_ops.py +3 -3
  6. build/torch211-cxx11-cu128-x86_64-linux/metadata.json +4 -4
  7. build/torch211-cxx11-cu130-aarch64-linux/__init__.py +410 -0
  8. build/{torch211-cxx11-cu128-x86_64-linux/_fp4_fused_ops_cuda_7e2e5b9.abi3.so → torch211-cxx11-cu130-aarch64-linux/_fp4_fused_ops_cuda_916f685.abi3.so} +2 -2
  9. build/torch211-cxx11-cu130-aarch64-linux/_ops.py +6 -0
  10. build/torch211-cxx11-cu130-aarch64-linux/fp4_fused_ops/__init__.py +14 -0
  11. build/torch211-cxx11-cu130-aarch64-linux/metadata.json +32 -0
  12. build/torch211-cxx11-cu130-x86_64-linux/__init__.py +204 -0
  13. build/torch211-cxx11-cu130-x86_64-linux/{_fp4_fused_ops_cuda_7e2e5b9.abi3.so → _fp4_fused_ops_cuda_8e0b1cd.abi3.so} +2 -2
  14. build/torch211-cxx11-cu130-x86_64-linux/_ops.py +3 -3
  15. build/torch211-cxx11-cu130-x86_64-linux/metadata.json +5 -4
  16. build/torch212-cxx11-cu130-x86_64-linux/__init__.py +204 -0
  17. build/torch212-cxx11-cu130-x86_64-linux/{_fp4_fused_ops_cuda_7e2e5b9.abi3.so → _fp4_fused_ops_cuda_8e0b1cd.abi3.so} +2 -2
  18. build/torch212-cxx11-cu130-x86_64-linux/_ops.py +3 -3
  19. build/torch212-cxx11-cu130-x86_64-linux/metadata.json +5 -4
  20. build/torch212-cxx11-cu132-x86_64-linux/__init__.py +204 -0
  21. build/torch212-cxx11-cu132-x86_64-linux/_fp4_fused_ops_cuda_8e0b1cd.abi3.so +3 -0
  22. build/torch212-cxx11-cu132-x86_64-linux/_ops.py +3 -3
  23. build/torch212-cxx11-cu132-x86_64-linux/metadata.json +5 -4
  24. build/torch213-cxx11-cu130-aarch64-linux/__init__.py +410 -0
  25. build/torch213-cxx11-cu130-aarch64-linux/_ops.py +6 -0
  26. build/torch213-cxx11-cu130-aarch64-linux/fp4_fused_ops/__init__.py +14 -0
  27. build/torch213-cxx11-cu130-aarch64-linux/fp4_fused_ops_source_test.abi3.so +3 -0
  28. build/torch213-cxx11-cu130-aarch64-linux/metadata.json +32 -0
README.md DELETED
@@ -1,9 +0,0 @@
1
- # flashrt/fp4-fused-ops
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-fused-ops
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.
 
 
 
 
 
 
 
 
 
 
benchmarks/benchmark.py CHANGED
@@ -6,6 +6,7 @@ from __future__ import annotations
6
  import argparse
7
  import importlib.util
8
  import json
 
9
  import sys
10
  from dataclasses import asdict, dataclass
11
  from pathlib import Path
@@ -24,8 +25,13 @@ class BenchResult:
24
  dim: int
25
  workload: str
26
  reference_us: float | None
 
27
  flashrt_us: float
 
 
28
  speedup: float | None
 
 
29
  status: str
30
 
31
 
@@ -53,7 +59,17 @@ def measure(fn, warmup: int, iters: int) -> float:
53
  return float(start.elapsed_time(end) * 1000.0 / iters)
54
 
55
 
56
- def bench_case(helpers, ops, rows: int, dim: int, warmup: int, iters: int) -> list[BenchResult]:
 
 
 
 
 
 
 
 
 
 
57
  make_fp16 = helpers.make_fp16
58
  results: list[BenchResult] = []
59
 
@@ -76,6 +92,29 @@ def bench_case(helpers, ops, rows: int, dim: int, warmup: int, iters: int) -> li
76
  warmup,
77
  iters,
78
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
79
  results.append(
80
  BenchResult(
81
  case=f"rows{rows}_dim{dim}",
@@ -83,8 +122,13 @@ def bench_case(helpers, ops, rows: int, dim: int, warmup: int, iters: int) -> li
83
  dim=dim,
84
  workload="residual_add_rms_norm_fp4_sfa_v2",
85
  reference_us=ref_us,
 
86
  flashrt_us=f3_us,
 
 
87
  speedup=(ref_us / f3_us) if ref_us else None,
 
 
88
  status="v1 reference" if ref_us else "v2 only; v1 rejects this dim",
89
  )
90
  )
@@ -94,6 +138,25 @@ def bench_case(helpers, ops, rows: int, dim: int, warmup: int, iters: int) -> li
94
  packed_v2, sfa_v2 = ops.alloc(rows, dim)
95
  ref_us = measure(lambda: ops.silu_mul_fp4_sfa_fp16(merged, packed_v1, sfa_v1), warmup, iters)
96
  f4_us = measure(lambda: ops.silu_mul_fp4_sfa_v2_fp16(merged, packed_v2, sfa_v2), warmup, iters)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
97
  results.append(
98
  BenchResult(
99
  case=f"rows{rows}_dim{dim}",
@@ -101,14 +164,40 @@ def bench_case(helpers, ops, rows: int, dim: int, warmup: int, iters: int) -> li
101
  dim=dim,
102
  workload="silu_mul_fp4_sfa_v2",
103
  reference_us=ref_us,
 
104
  flashrt_us=f4_us,
 
 
105
  speedup=ref_us / f4_us,
 
 
106
  status="v1 reference",
107
  )
108
  )
109
 
110
  inv_s = (torch.rand((dim,), device="cuda") * 0.25 + 0.875).to(torch.float16).contiguous()
111
  awq_us = measure(lambda: ops.silu_mul_mul_fp4_sfa_v2_fp16(merged, inv_s, packed_v2, sfa_v2), warmup, iters)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
112
  results.append(
113
  BenchResult(
114
  case=f"rows{rows}_dim{dim}",
@@ -116,8 +205,13 @@ def bench_case(helpers, ops, rows: int, dim: int, warmup: int, iters: int) -> li
116
  dim=dim,
117
  workload="silu_mul_mul_fp4_sfa_v2",
118
  reference_us=None,
 
119
  flashrt_us=awq_us,
 
 
120
  speedup=None,
 
 
121
  status="fused AWQ producer latency",
122
  )
123
  )
@@ -132,11 +226,57 @@ def bench_case(helpers, ops, rows: int, dim: int, warmup: int, iters: int) -> li
132
  warmup,
133
  iters,
134
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
135
  two_mul_us = measure(
136
  lambda: ops.silu_mul_two_mul_fp4_to_fp4(gate_packed, gate_sfa, up_packed, up_sfa, inv_s, out_packed, out_sfa),
137
  warmup,
138
  iters,
139
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
140
  results.append(
141
  BenchResult(
142
  case=f"rows{rows}_dim{dim}",
@@ -144,8 +284,13 @@ def bench_case(helpers, ops, rows: int, dim: int, warmup: int, iters: int) -> li
144
  dim=dim,
145
  workload="silu_mul_two_fp4_to_fp4",
146
  reference_us=None,
 
147
  flashrt_us=two_us,
 
 
148
  speedup=None,
 
 
149
  status="FP4-to-FP4 combiner latency",
150
  )
151
  )
@@ -156,8 +301,13 @@ def bench_case(helpers, ops, rows: int, dim: int, warmup: int, iters: int) -> li
156
  dim=dim,
157
  workload="silu_mul_two_mul_fp4_to_fp4",
158
  reference_us=None,
 
159
  flashrt_us=two_mul_us,
 
 
160
  speedup=None,
 
 
161
  status="FP4-to-FP4 AWQ combiner latency",
162
  )
163
  )
@@ -166,7 +316,11 @@ def bench_case(helpers, ops, rows: int, dim: int, warmup: int, iters: int) -> li
166
 
167
  def main() -> int:
168
  parser = argparse.ArgumentParser()
169
- parser.add_argument("--mode", choices=["smoke", "headline"], default="headline")
 
 
 
 
170
  parser.add_argument("--warmup", type=int, default=20)
171
  parser.add_argument("--iterations", type=int, default=100)
172
  parser.add_argument("--json-out", default=None)
@@ -175,15 +329,28 @@ def main() -> int:
175
  if not torch.cuda.is_available():
176
  raise RuntimeError("CUDA is required")
177
  helpers = load_test_module()
178
- ops = helpers.load_source_ops()
 
 
 
 
 
 
 
 
 
 
179
 
180
  shapes = [(1, 1024), (10, 2048)] if args.mode == "smoke" else [(1, 1024), (10, 2048), (64, 2048), (128, 4096)]
 
 
181
  results: list[BenchResult] = []
182
  for rows, dim in shapes:
183
- results.extend(bench_case(helpers, ops, rows, dim, args.warmup, args.iterations))
184
 
185
  payload = {
186
  "mode": args.mode,
 
187
  "device": torch.cuda.get_device_name(),
188
  "torch": torch.__version__,
189
  "results": [asdict(item) for item in results],
 
6
  import argparse
7
  import importlib.util
8
  import json
9
+ import os
10
  import sys
11
  from dataclasses import asdict, dataclass
12
  from pathlib import Path
 
25
  dim: int
26
  workload: str
27
  reference_us: float | None
28
+ native_us: float | None
29
  flashrt_us: float
30
+ native_graph_us: float | None
31
+ flashrt_graph_us: float | None
32
  speedup: float | None
33
+ wrapper_over_native: float | None
34
+ graph_over_native: float | None
35
  status: str
36
 
37
 
 
59
  return float(start.elapsed_time(end) * 1000.0 / iters)
60
 
61
 
62
+ def measure_graph(fn, warmup: int, iters: int) -> float:
63
+ for _ in range(warmup):
64
+ fn()
65
+ torch.cuda.synchronize()
66
+ graph = torch.cuda.CUDAGraph()
67
+ with torch.cuda.graph(graph):
68
+ fn()
69
+ return measure(graph.replay, warmup, iters)
70
+
71
+
72
+ def bench_case(helpers, ops, native, rows: int, dim: int, warmup: int, iters: int) -> list[BenchResult]:
73
  make_fp16 = helpers.make_fp16
74
  results: list[BenchResult] = []
75
 
 
92
  warmup,
93
  iters,
94
  )
95
+ stream = torch.cuda.current_stream().cuda_stream
96
+ native_f3_us = measure(
97
+ lambda: native.residual_add_rms_norm_fp4_sfa_v2_fp16(
98
+ residual_v2.copy_(residual).data_ptr(), x.data_ptr(),
99
+ packed.data_ptr(), sfa.data_ptr(), rows, dim, stream
100
+ ),
101
+ warmup,
102
+ iters,
103
+ )
104
+ graph_f3_us = measure_graph(
105
+ lambda: ops.residual_add_rms_norm_fp4_sfa_v2_fp16(residual_v2.copy_(residual), x, packed, sfa),
106
+ warmup,
107
+ iters,
108
+ )
109
+ native_graph_f3_us = measure_graph(
110
+ lambda: native.residual_add_rms_norm_fp4_sfa_v2_fp16(
111
+ residual_v2.copy_(residual).data_ptr(), x.data_ptr(),
112
+ packed.data_ptr(), sfa.data_ptr(), rows, dim,
113
+ torch.cuda.current_stream().cuda_stream
114
+ ),
115
+ warmup,
116
+ iters,
117
+ )
118
  results.append(
119
  BenchResult(
120
  case=f"rows{rows}_dim{dim}",
 
122
  dim=dim,
123
  workload="residual_add_rms_norm_fp4_sfa_v2",
124
  reference_us=ref_us,
125
+ native_us=native_f3_us,
126
  flashrt_us=f3_us,
127
+ native_graph_us=native_graph_f3_us,
128
+ flashrt_graph_us=graph_f3_us,
129
  speedup=(ref_us / f3_us) if ref_us else None,
130
+ wrapper_over_native=f3_us / native_f3_us,
131
+ graph_over_native=graph_f3_us / native_graph_f3_us,
132
  status="v1 reference" if ref_us else "v2 only; v1 rejects this dim",
133
  )
134
  )
 
138
  packed_v2, sfa_v2 = ops.alloc(rows, dim)
139
  ref_us = measure(lambda: ops.silu_mul_fp4_sfa_fp16(merged, packed_v1, sfa_v1), warmup, iters)
140
  f4_us = measure(lambda: ops.silu_mul_fp4_sfa_v2_fp16(merged, packed_v2, sfa_v2), warmup, iters)
141
+ native_f4_us = measure(
142
+ lambda: native.gate_geglu_fp4_sfa_v2_fp16(
143
+ merged.data_ptr(), packed_v2.data_ptr(), sfa_v2.data_ptr(),
144
+ rows, dim, stream
145
+ ),
146
+ warmup,
147
+ iters,
148
+ )
149
+ graph_f4_us = measure_graph(
150
+ lambda: ops.silu_mul_fp4_sfa_v2_fp16(merged, packed_v2, sfa_v2), warmup, iters
151
+ )
152
+ native_graph_f4_us = measure_graph(
153
+ lambda: native.gate_geglu_fp4_sfa_v2_fp16(
154
+ merged.data_ptr(), packed_v2.data_ptr(), sfa_v2.data_ptr(), rows, dim,
155
+ torch.cuda.current_stream().cuda_stream
156
+ ),
157
+ warmup,
158
+ iters,
159
+ )
160
  results.append(
161
  BenchResult(
162
  case=f"rows{rows}_dim{dim}",
 
164
  dim=dim,
165
  workload="silu_mul_fp4_sfa_v2",
166
  reference_us=ref_us,
167
+ native_us=native_f4_us,
168
  flashrt_us=f4_us,
169
+ native_graph_us=native_graph_f4_us,
170
+ flashrt_graph_us=graph_f4_us,
171
  speedup=ref_us / f4_us,
172
+ wrapper_over_native=f4_us / native_f4_us,
173
+ graph_over_native=graph_f4_us / native_graph_f4_us,
174
  status="v1 reference",
175
  )
176
  )
177
 
178
  inv_s = (torch.rand((dim,), device="cuda") * 0.25 + 0.875).to(torch.float16).contiguous()
179
  awq_us = measure(lambda: ops.silu_mul_mul_fp4_sfa_v2_fp16(merged, inv_s, packed_v2, sfa_v2), warmup, iters)
180
+ native_awq_us = measure(
181
+ lambda: native.gate_geglu_mul_fp4_sfa_v2_fp16(
182
+ merged.data_ptr(), inv_s.data_ptr(), packed_v2.data_ptr(),
183
+ sfa_v2.data_ptr(), rows, dim, stream
184
+ ),
185
+ warmup,
186
+ iters,
187
+ )
188
+ graph_awq_us = measure_graph(
189
+ lambda: ops.silu_mul_mul_fp4_sfa_v2_fp16(merged, inv_s, packed_v2, sfa_v2),
190
+ warmup,
191
+ iters,
192
+ )
193
+ native_graph_awq_us = measure_graph(
194
+ lambda: native.gate_geglu_mul_fp4_sfa_v2_fp16(
195
+ merged.data_ptr(), inv_s.data_ptr(), packed_v2.data_ptr(),
196
+ sfa_v2.data_ptr(), rows, dim, torch.cuda.current_stream().cuda_stream
197
+ ),
198
+ warmup,
199
+ iters,
200
+ )
201
  results.append(
202
  BenchResult(
203
  case=f"rows{rows}_dim{dim}",
 
205
  dim=dim,
206
  workload="silu_mul_mul_fp4_sfa_v2",
207
  reference_us=None,
208
+ native_us=native_awq_us,
209
  flashrt_us=awq_us,
210
+ native_graph_us=native_graph_awq_us,
211
+ flashrt_graph_us=graph_awq_us,
212
  speedup=None,
213
+ wrapper_over_native=awq_us / native_awq_us,
214
+ graph_over_native=graph_awq_us / native_graph_awq_us,
215
  status="fused AWQ producer latency",
216
  )
217
  )
 
226
  warmup,
227
  iters,
228
  )
229
+ native_two_us = measure(
230
+ lambda: native.geglu_two_fp4_to_fp4(
231
+ gate_packed.data_ptr(), gate_sfa.data_ptr(), up_packed.data_ptr(),
232
+ up_sfa.data_ptr(), out_packed.data_ptr(), out_sfa.data_ptr(),
233
+ rows, dim, stream
234
+ ),
235
+ warmup,
236
+ iters,
237
+ )
238
+ graph_two_us = measure_graph(
239
+ lambda: ops.silu_mul_two_fp4_to_fp4(gate_packed, gate_sfa, up_packed, up_sfa, out_packed, out_sfa),
240
+ warmup,
241
+ iters,
242
+ )
243
+ native_graph_two_us = measure_graph(
244
+ lambda: native.geglu_two_fp4_to_fp4(
245
+ gate_packed.data_ptr(), gate_sfa.data_ptr(), up_packed.data_ptr(),
246
+ up_sfa.data_ptr(), out_packed.data_ptr(), out_sfa.data_ptr(), rows, dim,
247
+ torch.cuda.current_stream().cuda_stream
248
+ ),
249
+ warmup,
250
+ iters,
251
+ )
252
  two_mul_us = measure(
253
  lambda: ops.silu_mul_two_mul_fp4_to_fp4(gate_packed, gate_sfa, up_packed, up_sfa, inv_s, out_packed, out_sfa),
254
  warmup,
255
  iters,
256
  )
257
+ native_two_mul_us = measure(
258
+ lambda: native.geglu_two_mul_fp4_to_fp4(
259
+ gate_packed.data_ptr(), gate_sfa.data_ptr(), up_packed.data_ptr(),
260
+ up_sfa.data_ptr(), inv_s.data_ptr(), out_packed.data_ptr(),
261
+ out_sfa.data_ptr(), rows, dim, stream
262
+ ),
263
+ warmup,
264
+ iters,
265
+ )
266
+ graph_two_mul_us = measure_graph(
267
+ lambda: ops.silu_mul_two_mul_fp4_to_fp4(gate_packed, gate_sfa, up_packed, up_sfa, inv_s, out_packed, out_sfa),
268
+ warmup,
269
+ iters,
270
+ )
271
+ native_graph_two_mul_us = measure_graph(
272
+ lambda: native.geglu_two_mul_fp4_to_fp4(
273
+ gate_packed.data_ptr(), gate_sfa.data_ptr(), up_packed.data_ptr(),
274
+ up_sfa.data_ptr(), inv_s.data_ptr(), out_packed.data_ptr(),
275
+ out_sfa.data_ptr(), rows, dim, torch.cuda.current_stream().cuda_stream
276
+ ),
277
+ warmup,
278
+ iters,
279
+ )
280
  results.append(
281
  BenchResult(
282
  case=f"rows{rows}_dim{dim}",
 
284
  dim=dim,
285
  workload="silu_mul_two_fp4_to_fp4",
286
  reference_us=None,
287
+ native_us=native_two_us,
288
  flashrt_us=two_us,
289
+ native_graph_us=native_graph_two_us,
290
+ flashrt_graph_us=graph_two_us,
291
  speedup=None,
292
+ wrapper_over_native=two_us / native_two_us,
293
+ graph_over_native=graph_two_us / native_graph_two_us,
294
  status="FP4-to-FP4 combiner latency",
295
  )
296
  )
 
301
  dim=dim,
302
  workload="silu_mul_two_mul_fp4_to_fp4",
303
  reference_us=None,
304
+ native_us=native_two_mul_us,
305
  flashrt_us=two_mul_us,
306
+ native_graph_us=native_graph_two_mul_us,
307
+ flashrt_graph_us=graph_two_mul_us,
308
  speedup=None,
309
+ wrapper_over_native=two_mul_us / native_two_mul_us,
310
+ graph_over_native=graph_two_mul_us / native_graph_two_mul_us,
311
  status="FP4-to-FP4 AWQ combiner latency",
312
  )
313
  )
 
316
 
317
  def main() -> int:
318
  parser = argparse.ArgumentParser()
319
+ parser.add_argument("--backend", choices=["source", "installed"], default="source")
320
+ parser.add_argument("--artifact", default=None)
321
+ parser.add_argument(
322
+ "--mode", choices=["smoke", "headline", "thor-models"], default="headline"
323
+ )
324
  parser.add_argument("--warmup", type=int, default=20)
325
  parser.add_argument("--iterations", type=int, default=100)
326
  parser.add_argument("--json-out", default=None)
 
329
  if not torch.cuda.is_available():
330
  raise RuntimeError("CUDA is required")
331
  helpers = load_test_module()
332
+ ops = (
333
+ helpers.load_source_ops()
334
+ if args.backend == "source"
335
+ else helpers.load_installed_ops(args.artifact)
336
+ )
337
+ native_root = Path(os.environ.get("FLASHRT_NATIVE_ROOT", str(ROOT.parent / "official" / "FlashRT")))
338
+ sys.path.insert(0, str(native_root))
339
+ try:
340
+ import flash_rt.flash_rt_fp4 as native
341
+ finally:
342
+ sys.path.pop(0)
343
 
344
  shapes = [(1, 1024), (10, 2048)] if args.mode == "smoke" else [(1, 1024), (10, 2048), (64, 2048), (128, 4096)]
345
+ if args.mode == "thor-models":
346
+ shapes = list(helpers.THOR_MODEL_SHAPES.values())
347
  results: list[BenchResult] = []
348
  for rows, dim in shapes:
349
+ results.extend(bench_case(helpers, ops, native, rows, dim, args.warmup, args.iterations))
350
 
351
  payload = {
352
  "mode": args.mode,
353
+ "backend": args.backend,
354
  "device": torch.cuda.get_device_name(),
355
  "torch": torch.__version__,
356
  "results": [asdict(item) for item in results],
build/torch211-cxx11-cu128-x86_64-linux/__init__.py CHANGED
@@ -91,6 +91,57 @@ def _dequant_fake(packed: torch.Tensor, sfa: torch.Tensor, out: torch.Tensor) ->
91
  return None
92
 
93
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
94
  def rms_norm_fp4_sfa_fp16(x: torch.Tensor, packed: torch.Tensor | None = None, sfa: torch.Tensor | None = None):
95
  if packed is None or sfa is None:
96
  packed, sfa = _alloc_fp4(x.shape[0], x.shape[1], x.device)
@@ -204,3 +255,156 @@ def dequantize_fp4_sfa_fp16(
204
  out = torch.empty((packed.shape[0], packed.shape[1] * 2), device=packed.device, dtype=torch.float16)
205
  ops.dequantize_fp4_sfa_fp16(packed, sfa, out)
206
  return out
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
91
  return None
92
 
93
 
94
+ @torch.library.register_fake(add_op_namespace_prefix("rms_silu_nvfp4_ndhwc_bf16"))
95
+ def _rms_silu_nvfp4_ndhwc_bf16_fake(
96
+ x: torch.Tensor,
97
+ gamma: torch.Tensor,
98
+ awq_inv_scale: torch.Tensor | None,
99
+ eps: float,
100
+ packed: torch.Tensor,
101
+ scale_factors: torch.Tensor,
102
+ ) -> None:
103
+ del eps
104
+ if x.dim() != 5:
105
+ raise RuntimeError("x must have shape (B,C,T,H,W)")
106
+ b, c, t, h, w = x.shape
107
+ if (
108
+ c % 128 != 0
109
+ or c > 1024
110
+ or gamma.shape != (c,)
111
+ or packed.shape != (b, t, h, w, c // 2)
112
+ or scale_factors.shape != (b, t, h, w, c // 16)
113
+ or (awq_inv_scale is not None and awq_inv_scale.shape != (c,))
114
+ ):
115
+ raise RuntimeError(
116
+ "rms_silu_nvfp4_ndhwc_bf16 shape contract failed"
117
+ )
118
+ return None
119
+
120
+
121
+ @torch.library.register_fake(
122
+ add_op_namespace_prefix("quantize_bf16_to_nvfp4_linear")
123
+ )
124
+ def _quantize_bf16_to_nvfp4_linear_fake(
125
+ input: torch.Tensor,
126
+ packed: torch.Tensor,
127
+ scale_factors: torch.Tensor,
128
+ ) -> None:
129
+ if input.dim() != 2:
130
+ raise RuntimeError("input must have shape (rows, cols)")
131
+ rows, cols = input.shape
132
+ if (
133
+ rows <= 0
134
+ or cols <= 0
135
+ or cols % 16 != 0
136
+ or packed.shape != (rows, cols // 2)
137
+ or scale_factors.shape != (rows, cols // 16)
138
+ ):
139
+ raise RuntimeError(
140
+ "quantize_bf16_to_nvfp4_linear shape contract failed"
141
+ )
142
+ return None
143
+
144
+
145
  def rms_norm_fp4_sfa_fp16(x: torch.Tensor, packed: torch.Tensor | None = None, sfa: torch.Tensor | None = None):
146
  if packed is None or sfa is None:
147
  packed, sfa = _alloc_fp4(x.shape[0], x.shape[1], x.device)
 
255
  out = torch.empty((packed.shape[0], packed.shape[1] * 2), device=packed.device, dtype=torch.float16)
256
  ops.dequantize_fp4_sfa_fp16(packed, sfa, out)
257
  return out
258
+
259
+
260
+ def rms_silu_nvfp4_ndhwc_bf16(
261
+ x: torch.Tensor,
262
+ gamma: torch.Tensor,
263
+ awq_inv_scale: torch.Tensor | None = None,
264
+ eps: float = 1e-6,
265
+ *,
266
+ packed: torch.Tensor | None = None,
267
+ scale_factors: torch.Tensor | None = None,
268
+ ) -> tuple[torch.Tensor, torch.Tensor]:
269
+ """Fuse BF16 NCDHW RMSNorm, SiLU and linear-SF NVFP4 quantization."""
270
+
271
+ b, c, t, h, w = x.shape
272
+ if packed is None:
273
+ packed = torch.empty(
274
+ (b, t, h, w, c // 2), device=x.device, dtype=torch.uint8
275
+ )
276
+ if scale_factors is None:
277
+ scale_factors = torch.empty(
278
+ (b, t, h, w, c // 16), device=x.device, dtype=torch.uint8
279
+ )
280
+ ops.rms_silu_nvfp4_ndhwc_bf16(
281
+ x,
282
+ gamma,
283
+ awq_inv_scale,
284
+ float(eps),
285
+ packed,
286
+ scale_factors,
287
+ )
288
+ return packed, scale_factors
289
+
290
+
291
+ def quantize_bf16_to_nvfp4_linear(
292
+ input: torch.Tensor,
293
+ *,
294
+ packed: torch.Tensor | None = None,
295
+ scale_factors: torch.Tensor | None = None,
296
+ ) -> tuple[torch.Tensor, torch.Tensor]:
297
+ """Quantize BF16 rows to packed E2M1 with linear UE4M3 block-16 scales."""
298
+
299
+ rows, cols = input.shape
300
+ if packed is None:
301
+ packed = torch.empty(
302
+ (rows, cols // 2), device=input.device, dtype=torch.uint8
303
+ )
304
+ if scale_factors is None:
305
+ scale_factors = torch.empty(
306
+ (rows, cols // 16), device=input.device, dtype=torch.uint8
307
+ )
308
+ ops.quantize_bf16_to_nvfp4_linear(input, packed, scale_factors)
309
+ return packed, scale_factors
310
+
311
+
312
+ def _check_ncdhw(x: torch.Tensor, gamma: torch.Tensor) -> None:
313
+ if x.dim() != 5:
314
+ raise RuntimeError("x must have shape (B,C,T,H,W)")
315
+ if x.shape[1] <= 0 or x.shape[1] % 2 != 0 or x.shape[1] > 1024:
316
+ raise RuntimeError("C must be even and at most 1024")
317
+ if gamma.shape != (x.shape[1],):
318
+ raise RuntimeError("gamma must have shape (C,)")
319
+
320
+
321
+ @torch.library.register_fake(add_op_namespace_prefix("bf16_rms_silu_ncdhw"))
322
+ def _bf16_rms_silu_ncdhw_fake(
323
+ x: torch.Tensor,
324
+ gamma: torch.Tensor,
325
+ prev_cache: torch.Tensor | None,
326
+ eps: float,
327
+ out: torch.Tensor,
328
+ next_cache: torch.Tensor | None,
329
+ ) -> None:
330
+ del eps
331
+ _check_ncdhw(x, gamma)
332
+ if out.shape != x.shape:
333
+ raise RuntimeError("out must have the same shape as x")
334
+ expected_cache = (x.shape[0], x.shape[1], 2, x.shape[3], x.shape[4])
335
+ if prev_cache is not None and prev_cache.shape != expected_cache:
336
+ raise RuntimeError("prev_cache must have shape (B,C,2,H,W)")
337
+ if next_cache is not None and next_cache.shape != expected_cache:
338
+ raise RuntimeError("next_cache must have shape (B,C,2,H,W)")
339
+ return None
340
+
341
+
342
+ @torch.library.register_fake(add_op_namespace_prefix("bf16_rms_norm_ncdhw"))
343
+ def _bf16_rms_norm_ncdhw_fake(
344
+ x: torch.Tensor,
345
+ gamma: torch.Tensor,
346
+ bias: torch.Tensor | None,
347
+ eps: float,
348
+ out: torch.Tensor,
349
+ ) -> None:
350
+ del eps
351
+ _check_ncdhw(x, gamma)
352
+ if bias is not None and bias.shape != (x.shape[1],):
353
+ raise RuntimeError("bias must have shape (C,)")
354
+ if out.shape != x.shape:
355
+ raise RuntimeError("out must have the same shape as x")
356
+ return None
357
+
358
+
359
+ def bf16_rms_silu_ncdhw(
360
+ x: torch.Tensor,
361
+ gamma: torch.Tensor,
362
+ prev_cache: torch.Tensor | None = None,
363
+ eps: float = 1e-6,
364
+ *,
365
+ out: torch.Tensor | None = None,
366
+ next_cache: torch.Tensor | None = None,
367
+ ) -> tuple[torch.Tensor, torch.Tensor | None]:
368
+ """Apply channel RMSNorm and SiLU to BF16 NCDHW with optional cache update."""
369
+
370
+ if out is None:
371
+ out = torch.empty_like(x)
372
+ ops.bf16_rms_silu_ncdhw(
373
+ x, gamma, prev_cache, float(eps), out, next_cache
374
+ )
375
+ return out, next_cache
376
+
377
+
378
+ def bf16_rms_norm_ncdhw(
379
+ x: torch.Tensor,
380
+ gamma: torch.Tensor,
381
+ bias: torch.Tensor | None = None,
382
+ eps: float = 1e-6,
383
+ *,
384
+ out: torch.Tensor | None = None,
385
+ ) -> torch.Tensor:
386
+ """Apply channel RMSNorm and optional bias to BF16 NCDHW."""
387
+
388
+ if out is None:
389
+ out = torch.empty_like(x)
390
+ ops.bf16_rms_norm_ncdhw(x, gamma, bias, float(eps), out)
391
+ return out
392
+
393
+
394
+ __all__ = [
395
+ "bf16_rms_norm_ncdhw",
396
+ "bf16_rms_silu_ncdhw",
397
+ "dequantize_fp4_sfa_fp16",
398
+ "quantize_bf16_to_nvfp4_linear",
399
+ "residual_add_rms_norm_fp4_sfa_fp16",
400
+ "residual_add_rms_norm_fp4_sfa_v2_fp16",
401
+ "residual_add_rms_norm_mul_fp4_sfa_fp16",
402
+ "rms_norm_fp4_sfa_fp16",
403
+ "rms_silu_nvfp4_ndhwc_bf16",
404
+ "sfa_size_bytes",
405
+ "silu_mul_fp4_sfa_fp16",
406
+ "silu_mul_fp4_sfa_v2_fp16",
407
+ "silu_mul_mul_fp4_sfa_v2_fp16",
408
+ "silu_mul_two_fp4_to_fp4",
409
+ "silu_mul_two_mul_fp4_to_fp4",
410
+ ]
build/{torch212-cxx11-cu132-x86_64-linux/_fp4_fused_ops_cuda_7e2e5b9.abi3.so → torch211-cxx11-cu128-x86_64-linux/_fp4_fused_ops_cuda_8e0b1cd.abi3.so} RENAMED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:fbb803d2760f5ff420a311dc741b11b284819e558d00601d9a3c2f5e921d3288
3
- size 545896
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:65ea1e5a247cdb9abb385600a3208c1b55d7d4564a9dffe7b31e6c2f0adda3fc
3
+ size 592896
build/torch211-cxx11-cu128-x86_64-linux/_ops.py CHANGED
@@ -1,9 +1,9 @@
1
  import torch
2
- from . import _fp4_fused_ops_cuda_7e2e5b9
3
- ops = torch.ops._fp4_fused_ops_cuda_7e2e5b9
4
 
5
  def add_op_namespace_prefix(op_name: str):
6
  """
7
  Prefix op by namespace.
8
  """
9
- return f"_fp4_fused_ops_cuda_7e2e5b9::{op_name}"
 
1
  import torch
2
+ from . import _fp4_fused_ops_cuda_8e0b1cd
3
+ ops = torch.ops._fp4_fused_ops_cuda_8e0b1cd
4
 
5
  def add_op_namespace_prefix(op_name: str):
6
  """
7
  Prefix op by namespace.
8
  """
9
+ return f"_fp4_fused_ops_cuda_8e0b1cd::{op_name}"
build/torch211-cxx11-cu128-x86_64-linux/metadata.json CHANGED
@@ -1,6 +1,6 @@
1
  {
2
  "name": "fp4-fused-ops",
3
- "id": "_fp4_fused_ops_cuda_7e2e5b9",
4
  "version": 1,
5
  "license": "Apache-2.0",
6
  "python-depends": [],
@@ -13,9 +13,9 @@
13
  "digest": {
14
  "algorithm": "sha256",
15
  "files": {
16
- "__init__.py": "aB7foEHGoXVq7xDlENZhAsIjQvzWhMpiKhanJhtzmk8=",
17
- "_fp4_fused_ops_cuda_7e2e5b9.abi3.so": "3Q9S5xqFrpzHoz7d+WQkoZeRqkj5kfrZo1jRKjE7rgs=",
18
- "_ops.py": "qtD0ljSFCLkwC71lYCEP/FcSj+NFL+0sWWugI+4CH4s=",
19
  "fp4_fused_ops/__init__.py": "DFYPlrhXwYjEqCl/8n0SmWGZV8NFml5DPhMjKfv98GY="
20
  }
21
  }
 
1
  {
2
  "name": "fp4-fused-ops",
3
+ "id": "_fp4_fused_ops_cuda_8e0b1cd",
4
  "version": 1,
5
  "license": "Apache-2.0",
6
  "python-depends": [],
 
13
  "digest": {
14
  "algorithm": "sha256",
15
  "files": {
16
+ "__init__.py": "511/VkU+HAwubcrzG/Ck9wB3ukPbjKrWxG+9EgtcP00=",
17
+ "_fp4_fused_ops_cuda_8e0b1cd.abi3.so": "ZeoeWiR825q7OFYAoyCMG1XX1FZKnf/nsx5sLwrdo/w=",
18
+ "_ops.py": "L5M3920Afl87xMKszpaz5zL32AN6JoBJM6Aw1J19k2I=",
19
  "fp4_fused_ops/__init__.py": "DFYPlrhXwYjEqCl/8n0SmWGZV8NFml5DPhMjKfv98GY="
20
  }
21
  }
build/torch211-cxx11-cu130-aarch64-linux/__init__.py ADDED
@@ -0,0 +1,410 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """FlashRT FP4 fused producer kernels."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import torch
6
+
7
+ from ._ops import add_op_namespace_prefix, ops
8
+
9
+
10
+ def sfa_size_bytes(rows: int, dim: int, is_sfb: bool = False, device: torch.device | str | None = None) -> int:
11
+ if device is None:
12
+ device = torch.device("cuda", torch.cuda.current_device())
13
+ anchor = torch.empty((1,), device=device, dtype=torch.uint8)
14
+ return int(ops.sfa_size_bytes_for(anchor, int(rows), int(dim), bool(is_sfb)))
15
+
16
+
17
+ def _alloc_fp4(rows: int, dim: int, device: torch.device | str):
18
+ packed = torch.empty((rows, dim // 2), device=device, dtype=torch.uint8)
19
+ sfa = torch.empty((sfa_size_bytes(rows, dim, False, device=device),), device=device, dtype=torch.uint8)
20
+ return packed, sfa
21
+
22
+
23
+ @torch.library.register_fake(add_op_namespace_prefix("rms_norm_fp4_sfa_fp16"))
24
+ def _rms_norm_fake(x: torch.Tensor, packed: torch.Tensor, sfa: torch.Tensor) -> None:
25
+ return None
26
+
27
+
28
+ @torch.library.register_fake(add_op_namespace_prefix("residual_add_rms_norm_fp4_sfa_fp16"))
29
+ def _residual_fake(residual: torch.Tensor, x: torch.Tensor, packed: torch.Tensor, sfa: torch.Tensor) -> None:
30
+ return None
31
+
32
+
33
+ @torch.library.register_fake(add_op_namespace_prefix("residual_add_rms_norm_fp4_sfa_v2_fp16"))
34
+ def _residual_v2_fake(residual: torch.Tensor, x: torch.Tensor, packed: torch.Tensor, sfa: torch.Tensor) -> None:
35
+ return None
36
+
37
+
38
+ @torch.library.register_fake(add_op_namespace_prefix("residual_add_rms_norm_mul_fp4_sfa_fp16"))
39
+ def _residual_mul_fake(
40
+ residual: torch.Tensor,
41
+ x: torch.Tensor,
42
+ inv_s: torch.Tensor,
43
+ packed: torch.Tensor,
44
+ sfa: torch.Tensor,
45
+ ) -> None:
46
+ return None
47
+
48
+
49
+ @torch.library.register_fake(add_op_namespace_prefix("silu_mul_fp4_sfa_fp16"))
50
+ def _silu_fake(merged: torch.Tensor, packed: torch.Tensor, sfa: torch.Tensor) -> None:
51
+ return None
52
+
53
+
54
+ @torch.library.register_fake(add_op_namespace_prefix("silu_mul_fp4_sfa_v2_fp16"))
55
+ def _silu_v2_fake(merged: torch.Tensor, packed: torch.Tensor, sfa: torch.Tensor) -> None:
56
+ return None
57
+
58
+
59
+ @torch.library.register_fake(add_op_namespace_prefix("silu_mul_mul_fp4_sfa_v2_fp16"))
60
+ def _silu_mul_v2_fake(merged: torch.Tensor, inv_s: torch.Tensor, packed: torch.Tensor, sfa: torch.Tensor) -> None:
61
+ return None
62
+
63
+
64
+ @torch.library.register_fake(add_op_namespace_prefix("silu_mul_two_fp4_to_fp4"))
65
+ def _silu_two_fake(
66
+ gate_packed: torch.Tensor,
67
+ gate_sfa: torch.Tensor,
68
+ up_packed: torch.Tensor,
69
+ up_sfa: torch.Tensor,
70
+ out_packed: torch.Tensor,
71
+ out_sfa: torch.Tensor,
72
+ ) -> None:
73
+ return None
74
+
75
+
76
+ @torch.library.register_fake(add_op_namespace_prefix("silu_mul_two_mul_fp4_to_fp4"))
77
+ def _silu_two_mul_fake(
78
+ gate_packed: torch.Tensor,
79
+ gate_sfa: torch.Tensor,
80
+ up_packed: torch.Tensor,
81
+ up_sfa: torch.Tensor,
82
+ inv_s: torch.Tensor,
83
+ out_packed: torch.Tensor,
84
+ out_sfa: torch.Tensor,
85
+ ) -> None:
86
+ return None
87
+
88
+
89
+ @torch.library.register_fake(add_op_namespace_prefix("dequantize_fp4_sfa_fp16"))
90
+ def _dequant_fake(packed: torch.Tensor, sfa: torch.Tensor, out: torch.Tensor) -> None:
91
+ return None
92
+
93
+
94
+ @torch.library.register_fake(add_op_namespace_prefix("rms_silu_nvfp4_ndhwc_bf16"))
95
+ def _rms_silu_nvfp4_ndhwc_bf16_fake(
96
+ x: torch.Tensor,
97
+ gamma: torch.Tensor,
98
+ awq_inv_scale: torch.Tensor | None,
99
+ eps: float,
100
+ packed: torch.Tensor,
101
+ scale_factors: torch.Tensor,
102
+ ) -> None:
103
+ del eps
104
+ if x.dim() != 5:
105
+ raise RuntimeError("x must have shape (B,C,T,H,W)")
106
+ b, c, t, h, w = x.shape
107
+ if (
108
+ c % 128 != 0
109
+ or c > 1024
110
+ or gamma.shape != (c,)
111
+ or packed.shape != (b, t, h, w, c // 2)
112
+ or scale_factors.shape != (b, t, h, w, c // 16)
113
+ or (awq_inv_scale is not None and awq_inv_scale.shape != (c,))
114
+ ):
115
+ raise RuntimeError(
116
+ "rms_silu_nvfp4_ndhwc_bf16 shape contract failed"
117
+ )
118
+ return None
119
+
120
+
121
+ @torch.library.register_fake(
122
+ add_op_namespace_prefix("quantize_bf16_to_nvfp4_linear")
123
+ )
124
+ def _quantize_bf16_to_nvfp4_linear_fake(
125
+ input: torch.Tensor,
126
+ packed: torch.Tensor,
127
+ scale_factors: torch.Tensor,
128
+ ) -> None:
129
+ if input.dim() != 2:
130
+ raise RuntimeError("input must have shape (rows, cols)")
131
+ rows, cols = input.shape
132
+ if (
133
+ rows <= 0
134
+ or cols <= 0
135
+ or cols % 16 != 0
136
+ or packed.shape != (rows, cols // 2)
137
+ or scale_factors.shape != (rows, cols // 16)
138
+ ):
139
+ raise RuntimeError(
140
+ "quantize_bf16_to_nvfp4_linear shape contract failed"
141
+ )
142
+ return None
143
+
144
+
145
+ def rms_norm_fp4_sfa_fp16(x: torch.Tensor, packed: torch.Tensor | None = None, sfa: torch.Tensor | None = None):
146
+ if packed is None or sfa is None:
147
+ packed, sfa = _alloc_fp4(x.shape[0], x.shape[1], x.device)
148
+ ops.rms_norm_fp4_sfa_fp16(x, packed, sfa)
149
+ return packed, sfa
150
+
151
+
152
+ def residual_add_rms_norm_fp4_sfa_fp16(
153
+ residual: torch.Tensor,
154
+ x: torch.Tensor,
155
+ packed: torch.Tensor | None = None,
156
+ sfa: torch.Tensor | None = None,
157
+ ):
158
+ if packed is None or sfa is None:
159
+ packed, sfa = _alloc_fp4(x.shape[0], x.shape[1], x.device)
160
+ ops.residual_add_rms_norm_fp4_sfa_fp16(residual, x, packed, sfa)
161
+ return packed, sfa
162
+
163
+
164
+ def residual_add_rms_norm_fp4_sfa_v2_fp16(
165
+ residual: torch.Tensor,
166
+ x: torch.Tensor,
167
+ packed: torch.Tensor | None = None,
168
+ sfa: torch.Tensor | None = None,
169
+ ):
170
+ if packed is None or sfa is None:
171
+ packed, sfa = _alloc_fp4(x.shape[0], x.shape[1], x.device)
172
+ ops.residual_add_rms_norm_fp4_sfa_v2_fp16(residual, x, packed, sfa)
173
+ return packed, sfa
174
+
175
+
176
+ def residual_add_rms_norm_mul_fp4_sfa_fp16(
177
+ residual: torch.Tensor,
178
+ x: torch.Tensor,
179
+ inv_s: torch.Tensor,
180
+ packed: torch.Tensor | None = None,
181
+ sfa: torch.Tensor | None = None,
182
+ ):
183
+ if packed is None or sfa is None:
184
+ packed, sfa = _alloc_fp4(x.shape[0], x.shape[1], x.device)
185
+ ops.residual_add_rms_norm_mul_fp4_sfa_fp16(residual, x, inv_s, packed, sfa)
186
+ return packed, sfa
187
+
188
+
189
+ def silu_mul_fp4_sfa_fp16(merged: torch.Tensor, packed: torch.Tensor | None = None, sfa: torch.Tensor | None = None):
190
+ hidden = merged.shape[1] // 2
191
+ if packed is None or sfa is None:
192
+ packed, sfa = _alloc_fp4(merged.shape[0], hidden, merged.device)
193
+ ops.silu_mul_fp4_sfa_fp16(merged, packed, sfa)
194
+ return packed, sfa
195
+
196
+
197
+ def silu_mul_fp4_sfa_v2_fp16(merged: torch.Tensor, packed: torch.Tensor | None = None, sfa: torch.Tensor | None = None):
198
+ hidden = merged.shape[1] // 2
199
+ if packed is None or sfa is None:
200
+ packed, sfa = _alloc_fp4(merged.shape[0], hidden, merged.device)
201
+ ops.silu_mul_fp4_sfa_v2_fp16(merged, packed, sfa)
202
+ return packed, sfa
203
+
204
+
205
+ def silu_mul_mul_fp4_sfa_v2_fp16(
206
+ merged: torch.Tensor,
207
+ inv_s: torch.Tensor,
208
+ packed: torch.Tensor | None = None,
209
+ sfa: torch.Tensor | None = None,
210
+ ):
211
+ hidden = merged.shape[1] // 2
212
+ if packed is None or sfa is None:
213
+ packed, sfa = _alloc_fp4(merged.shape[0], hidden, merged.device)
214
+ ops.silu_mul_mul_fp4_sfa_v2_fp16(merged, inv_s, packed, sfa)
215
+ return packed, sfa
216
+
217
+
218
+ def silu_mul_two_fp4_to_fp4(
219
+ gate_packed: torch.Tensor,
220
+ gate_sfa: torch.Tensor,
221
+ up_packed: torch.Tensor,
222
+ up_sfa: torch.Tensor,
223
+ out_packed: torch.Tensor | None = None,
224
+ out_sfa: torch.Tensor | None = None,
225
+ ):
226
+ hidden = gate_packed.shape[1] * 2
227
+ if out_packed is None or out_sfa is None:
228
+ out_packed, out_sfa = _alloc_fp4(gate_packed.shape[0], hidden, gate_packed.device)
229
+ ops.silu_mul_two_fp4_to_fp4(gate_packed, gate_sfa, up_packed, up_sfa, out_packed, out_sfa)
230
+ return out_packed, out_sfa
231
+
232
+
233
+ def silu_mul_two_mul_fp4_to_fp4(
234
+ gate_packed: torch.Tensor,
235
+ gate_sfa: torch.Tensor,
236
+ up_packed: torch.Tensor,
237
+ up_sfa: torch.Tensor,
238
+ inv_s: torch.Tensor,
239
+ out_packed: torch.Tensor | None = None,
240
+ out_sfa: torch.Tensor | None = None,
241
+ ):
242
+ hidden = gate_packed.shape[1] * 2
243
+ if out_packed is None or out_sfa is None:
244
+ out_packed, out_sfa = _alloc_fp4(gate_packed.shape[0], hidden, gate_packed.device)
245
+ ops.silu_mul_two_mul_fp4_to_fp4(gate_packed, gate_sfa, up_packed, up_sfa, inv_s, out_packed, out_sfa)
246
+ return out_packed, out_sfa
247
+
248
+
249
+ def dequantize_fp4_sfa_fp16(
250
+ packed: torch.Tensor,
251
+ sfa: torch.Tensor,
252
+ out: torch.Tensor | None = None,
253
+ ) -> torch.Tensor:
254
+ if out is None:
255
+ out = torch.empty((packed.shape[0], packed.shape[1] * 2), device=packed.device, dtype=torch.float16)
256
+ ops.dequantize_fp4_sfa_fp16(packed, sfa, out)
257
+ return out
258
+
259
+
260
+ def rms_silu_nvfp4_ndhwc_bf16(
261
+ x: torch.Tensor,
262
+ gamma: torch.Tensor,
263
+ awq_inv_scale: torch.Tensor | None = None,
264
+ eps: float = 1e-6,
265
+ *,
266
+ packed: torch.Tensor | None = None,
267
+ scale_factors: torch.Tensor | None = None,
268
+ ) -> tuple[torch.Tensor, torch.Tensor]:
269
+ """Fuse BF16 NCDHW RMSNorm, SiLU and linear-SF NVFP4 quantization."""
270
+
271
+ b, c, t, h, w = x.shape
272
+ if packed is None:
273
+ packed = torch.empty(
274
+ (b, t, h, w, c // 2), device=x.device, dtype=torch.uint8
275
+ )
276
+ if scale_factors is None:
277
+ scale_factors = torch.empty(
278
+ (b, t, h, w, c // 16), device=x.device, dtype=torch.uint8
279
+ )
280
+ ops.rms_silu_nvfp4_ndhwc_bf16(
281
+ x,
282
+ gamma,
283
+ awq_inv_scale,
284
+ float(eps),
285
+ packed,
286
+ scale_factors,
287
+ )
288
+ return packed, scale_factors
289
+
290
+
291
+ def quantize_bf16_to_nvfp4_linear(
292
+ input: torch.Tensor,
293
+ *,
294
+ packed: torch.Tensor | None = None,
295
+ scale_factors: torch.Tensor | None = None,
296
+ ) -> tuple[torch.Tensor, torch.Tensor]:
297
+ """Quantize BF16 rows to packed E2M1 with linear UE4M3 block-16 scales."""
298
+
299
+ rows, cols = input.shape
300
+ if packed is None:
301
+ packed = torch.empty(
302
+ (rows, cols // 2), device=input.device, dtype=torch.uint8
303
+ )
304
+ if scale_factors is None:
305
+ scale_factors = torch.empty(
306
+ (rows, cols // 16), device=input.device, dtype=torch.uint8
307
+ )
308
+ ops.quantize_bf16_to_nvfp4_linear(input, packed, scale_factors)
309
+ return packed, scale_factors
310
+
311
+
312
+ def _check_ncdhw(x: torch.Tensor, gamma: torch.Tensor) -> None:
313
+ if x.dim() != 5:
314
+ raise RuntimeError("x must have shape (B,C,T,H,W)")
315
+ if x.shape[1] <= 0 or x.shape[1] % 2 != 0 or x.shape[1] > 1024:
316
+ raise RuntimeError("C must be even and at most 1024")
317
+ if gamma.shape != (x.shape[1],):
318
+ raise RuntimeError("gamma must have shape (C,)")
319
+
320
+
321
+ @torch.library.register_fake(add_op_namespace_prefix("bf16_rms_silu_ncdhw"))
322
+ def _bf16_rms_silu_ncdhw_fake(
323
+ x: torch.Tensor,
324
+ gamma: torch.Tensor,
325
+ prev_cache: torch.Tensor | None,
326
+ eps: float,
327
+ out: torch.Tensor,
328
+ next_cache: torch.Tensor | None,
329
+ ) -> None:
330
+ del eps
331
+ _check_ncdhw(x, gamma)
332
+ if out.shape != x.shape:
333
+ raise RuntimeError("out must have the same shape as x")
334
+ expected_cache = (x.shape[0], x.shape[1], 2, x.shape[3], x.shape[4])
335
+ if prev_cache is not None and prev_cache.shape != expected_cache:
336
+ raise RuntimeError("prev_cache must have shape (B,C,2,H,W)")
337
+ if next_cache is not None and next_cache.shape != expected_cache:
338
+ raise RuntimeError("next_cache must have shape (B,C,2,H,W)")
339
+ return None
340
+
341
+
342
+ @torch.library.register_fake(add_op_namespace_prefix("bf16_rms_norm_ncdhw"))
343
+ def _bf16_rms_norm_ncdhw_fake(
344
+ x: torch.Tensor,
345
+ gamma: torch.Tensor,
346
+ bias: torch.Tensor | None,
347
+ eps: float,
348
+ out: torch.Tensor,
349
+ ) -> None:
350
+ del eps
351
+ _check_ncdhw(x, gamma)
352
+ if bias is not None and bias.shape != (x.shape[1],):
353
+ raise RuntimeError("bias must have shape (C,)")
354
+ if out.shape != x.shape:
355
+ raise RuntimeError("out must have the same shape as x")
356
+ return None
357
+
358
+
359
+ def bf16_rms_silu_ncdhw(
360
+ x: torch.Tensor,
361
+ gamma: torch.Tensor,
362
+ prev_cache: torch.Tensor | None = None,
363
+ eps: float = 1e-6,
364
+ *,
365
+ out: torch.Tensor | None = None,
366
+ next_cache: torch.Tensor | None = None,
367
+ ) -> tuple[torch.Tensor, torch.Tensor | None]:
368
+ """Apply channel RMSNorm and SiLU to BF16 NCDHW with optional cache update."""
369
+
370
+ if out is None:
371
+ out = torch.empty_like(x)
372
+ ops.bf16_rms_silu_ncdhw(
373
+ x, gamma, prev_cache, float(eps), out, next_cache
374
+ )
375
+ return out, next_cache
376
+
377
+
378
+ def bf16_rms_norm_ncdhw(
379
+ x: torch.Tensor,
380
+ gamma: torch.Tensor,
381
+ bias: torch.Tensor | None = None,
382
+ eps: float = 1e-6,
383
+ *,
384
+ out: torch.Tensor | None = None,
385
+ ) -> torch.Tensor:
386
+ """Apply channel RMSNorm and optional bias to BF16 NCDHW."""
387
+
388
+ if out is None:
389
+ out = torch.empty_like(x)
390
+ ops.bf16_rms_norm_ncdhw(x, gamma, bias, float(eps), out)
391
+ return out
392
+
393
+
394
+ __all__ = [
395
+ "bf16_rms_norm_ncdhw",
396
+ "bf16_rms_silu_ncdhw",
397
+ "dequantize_fp4_sfa_fp16",
398
+ "quantize_bf16_to_nvfp4_linear",
399
+ "residual_add_rms_norm_fp4_sfa_fp16",
400
+ "residual_add_rms_norm_fp4_sfa_v2_fp16",
401
+ "residual_add_rms_norm_mul_fp4_sfa_fp16",
402
+ "rms_norm_fp4_sfa_fp16",
403
+ "rms_silu_nvfp4_ndhwc_bf16",
404
+ "sfa_size_bytes",
405
+ "silu_mul_fp4_sfa_fp16",
406
+ "silu_mul_fp4_sfa_v2_fp16",
407
+ "silu_mul_mul_fp4_sfa_v2_fp16",
408
+ "silu_mul_two_fp4_to_fp4",
409
+ "silu_mul_two_mul_fp4_to_fp4",
410
+ ]
build/{torch211-cxx11-cu128-x86_64-linux/_fp4_fused_ops_cuda_7e2e5b9.abi3.so → torch211-cxx11-cu130-aarch64-linux/_fp4_fused_ops_cuda_916f685.abi3.so} RENAMED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:dd0f52e71a85ae9cc7a33eddf96424a19791aa48f991fad9a358d12a313bae0b
3
- size 502488
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:1da63bd51d661880b027e0efaa004f80f1a4ecb1c60e67395143a5e07ebc90ff
3
+ size 689560
build/torch211-cxx11-cu130-aarch64-linux/_ops.py ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ import torch
2
+ from . import _fp4_fused_ops_cuda_916f685
3
+ ops = torch.ops._fp4_fused_ops_cuda_916f685
4
+
5
+ def add_op_namespace_prefix(op_name: str):
6
+ return f"_fp4_fused_ops_cuda_916f685::{op_name}"
build/torch211-cxx11-cu130-aarch64-linux/fp4_fused_ops/__init__.py ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import ctypes
2
+ import importlib.util
3
+ import sys
4
+ from pathlib import Path
5
+
6
+ def _import_from_path(file_path: Path):
7
+ path_hash = '{:x}'.format(ctypes.c_size_t(hash(file_path.absolute())).value)
8
+ spec = importlib.util.spec_from_file_location(path_hash, file_path)
9
+ module = importlib.util.module_from_spec(spec)
10
+ sys.modules[path_hash] = module
11
+ spec.loader.exec_module(module)
12
+ return module
13
+
14
+ globals().update(vars(_import_from_path(Path(__file__).parent.parent / '__init__.py')))
build/torch211-cxx11-cu130-aarch64-linux/metadata.json ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "fp4-fused-ops",
3
+ "id": "_fp4_fused_ops_cuda_916f685",
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": "511/VkU+HAwubcrzG/Ck9wB3ukPbjKrWxG+9EgtcP00=",
17
+ "_fp4_fused_ops_cuda_916f685.abi3.so": "HaY71R1mGICwJ+DvqgBPgPGk7LHGDmc5UUOl4H68kP8=",
18
+ "_ops.py": "IFiCUaM6wO9cSSX0QcNr+RWvWYMiOy8A+hgr+8LClME=",
19
+ "fp4_fused_ops/__init__.py": "v6p5XMfQzddhi1fLSAw4HX9CyS0rQsidvu9VsT01xi4="
20
+ }
21
+ },
22
+ "provenance": {
23
+ "kernel": {
24
+ "sha": "4c95454360b18c79bed75ec6346a7bac47ae2ca2",
25
+ "dirty": false
26
+ },
27
+ "validation": {
28
+ "torch": "2.11.0+cu130",
29
+ "cuda": "13.0"
30
+ }
31
+ }
32
+ }
build/torch211-cxx11-cu130-x86_64-linux/__init__.py CHANGED
@@ -91,6 +91,57 @@ def _dequant_fake(packed: torch.Tensor, sfa: torch.Tensor, out: torch.Tensor) ->
91
  return None
92
 
93
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
94
  def rms_norm_fp4_sfa_fp16(x: torch.Tensor, packed: torch.Tensor | None = None, sfa: torch.Tensor | None = None):
95
  if packed is None or sfa is None:
96
  packed, sfa = _alloc_fp4(x.shape[0], x.shape[1], x.device)
@@ -204,3 +255,156 @@ def dequantize_fp4_sfa_fp16(
204
  out = torch.empty((packed.shape[0], packed.shape[1] * 2), device=packed.device, dtype=torch.float16)
205
  ops.dequantize_fp4_sfa_fp16(packed, sfa, out)
206
  return out
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
91
  return None
92
 
93
 
94
+ @torch.library.register_fake(add_op_namespace_prefix("rms_silu_nvfp4_ndhwc_bf16"))
95
+ def _rms_silu_nvfp4_ndhwc_bf16_fake(
96
+ x: torch.Tensor,
97
+ gamma: torch.Tensor,
98
+ awq_inv_scale: torch.Tensor | None,
99
+ eps: float,
100
+ packed: torch.Tensor,
101
+ scale_factors: torch.Tensor,
102
+ ) -> None:
103
+ del eps
104
+ if x.dim() != 5:
105
+ raise RuntimeError("x must have shape (B,C,T,H,W)")
106
+ b, c, t, h, w = x.shape
107
+ if (
108
+ c % 128 != 0
109
+ or c > 1024
110
+ or gamma.shape != (c,)
111
+ or packed.shape != (b, t, h, w, c // 2)
112
+ or scale_factors.shape != (b, t, h, w, c // 16)
113
+ or (awq_inv_scale is not None and awq_inv_scale.shape != (c,))
114
+ ):
115
+ raise RuntimeError(
116
+ "rms_silu_nvfp4_ndhwc_bf16 shape contract failed"
117
+ )
118
+ return None
119
+
120
+
121
+ @torch.library.register_fake(
122
+ add_op_namespace_prefix("quantize_bf16_to_nvfp4_linear")
123
+ )
124
+ def _quantize_bf16_to_nvfp4_linear_fake(
125
+ input: torch.Tensor,
126
+ packed: torch.Tensor,
127
+ scale_factors: torch.Tensor,
128
+ ) -> None:
129
+ if input.dim() != 2:
130
+ raise RuntimeError("input must have shape (rows, cols)")
131
+ rows, cols = input.shape
132
+ if (
133
+ rows <= 0
134
+ or cols <= 0
135
+ or cols % 16 != 0
136
+ or packed.shape != (rows, cols // 2)
137
+ or scale_factors.shape != (rows, cols // 16)
138
+ ):
139
+ raise RuntimeError(
140
+ "quantize_bf16_to_nvfp4_linear shape contract failed"
141
+ )
142
+ return None
143
+
144
+
145
  def rms_norm_fp4_sfa_fp16(x: torch.Tensor, packed: torch.Tensor | None = None, sfa: torch.Tensor | None = None):
146
  if packed is None or sfa is None:
147
  packed, sfa = _alloc_fp4(x.shape[0], x.shape[1], x.device)
 
255
  out = torch.empty((packed.shape[0], packed.shape[1] * 2), device=packed.device, dtype=torch.float16)
256
  ops.dequantize_fp4_sfa_fp16(packed, sfa, out)
257
  return out
258
+
259
+
260
+ def rms_silu_nvfp4_ndhwc_bf16(
261
+ x: torch.Tensor,
262
+ gamma: torch.Tensor,
263
+ awq_inv_scale: torch.Tensor | None = None,
264
+ eps: float = 1e-6,
265
+ *,
266
+ packed: torch.Tensor | None = None,
267
+ scale_factors: torch.Tensor | None = None,
268
+ ) -> tuple[torch.Tensor, torch.Tensor]:
269
+ """Fuse BF16 NCDHW RMSNorm, SiLU and linear-SF NVFP4 quantization."""
270
+
271
+ b, c, t, h, w = x.shape
272
+ if packed is None:
273
+ packed = torch.empty(
274
+ (b, t, h, w, c // 2), device=x.device, dtype=torch.uint8
275
+ )
276
+ if scale_factors is None:
277
+ scale_factors = torch.empty(
278
+ (b, t, h, w, c // 16), device=x.device, dtype=torch.uint8
279
+ )
280
+ ops.rms_silu_nvfp4_ndhwc_bf16(
281
+ x,
282
+ gamma,
283
+ awq_inv_scale,
284
+ float(eps),
285
+ packed,
286
+ scale_factors,
287
+ )
288
+ return packed, scale_factors
289
+
290
+
291
+ def quantize_bf16_to_nvfp4_linear(
292
+ input: torch.Tensor,
293
+ *,
294
+ packed: torch.Tensor | None = None,
295
+ scale_factors: torch.Tensor | None = None,
296
+ ) -> tuple[torch.Tensor, torch.Tensor]:
297
+ """Quantize BF16 rows to packed E2M1 with linear UE4M3 block-16 scales."""
298
+
299
+ rows, cols = input.shape
300
+ if packed is None:
301
+ packed = torch.empty(
302
+ (rows, cols // 2), device=input.device, dtype=torch.uint8
303
+ )
304
+ if scale_factors is None:
305
+ scale_factors = torch.empty(
306
+ (rows, cols // 16), device=input.device, dtype=torch.uint8
307
+ )
308
+ ops.quantize_bf16_to_nvfp4_linear(input, packed, scale_factors)
309
+ return packed, scale_factors
310
+
311
+
312
+ def _check_ncdhw(x: torch.Tensor, gamma: torch.Tensor) -> None:
313
+ if x.dim() != 5:
314
+ raise RuntimeError("x must have shape (B,C,T,H,W)")
315
+ if x.shape[1] <= 0 or x.shape[1] % 2 != 0 or x.shape[1] > 1024:
316
+ raise RuntimeError("C must be even and at most 1024")
317
+ if gamma.shape != (x.shape[1],):
318
+ raise RuntimeError("gamma must have shape (C,)")
319
+
320
+
321
+ @torch.library.register_fake(add_op_namespace_prefix("bf16_rms_silu_ncdhw"))
322
+ def _bf16_rms_silu_ncdhw_fake(
323
+ x: torch.Tensor,
324
+ gamma: torch.Tensor,
325
+ prev_cache: torch.Tensor | None,
326
+ eps: float,
327
+ out: torch.Tensor,
328
+ next_cache: torch.Tensor | None,
329
+ ) -> None:
330
+ del eps
331
+ _check_ncdhw(x, gamma)
332
+ if out.shape != x.shape:
333
+ raise RuntimeError("out must have the same shape as x")
334
+ expected_cache = (x.shape[0], x.shape[1], 2, x.shape[3], x.shape[4])
335
+ if prev_cache is not None and prev_cache.shape != expected_cache:
336
+ raise RuntimeError("prev_cache must have shape (B,C,2,H,W)")
337
+ if next_cache is not None and next_cache.shape != expected_cache:
338
+ raise RuntimeError("next_cache must have shape (B,C,2,H,W)")
339
+ return None
340
+
341
+
342
+ @torch.library.register_fake(add_op_namespace_prefix("bf16_rms_norm_ncdhw"))
343
+ def _bf16_rms_norm_ncdhw_fake(
344
+ x: torch.Tensor,
345
+ gamma: torch.Tensor,
346
+ bias: torch.Tensor | None,
347
+ eps: float,
348
+ out: torch.Tensor,
349
+ ) -> None:
350
+ del eps
351
+ _check_ncdhw(x, gamma)
352
+ if bias is not None and bias.shape != (x.shape[1],):
353
+ raise RuntimeError("bias must have shape (C,)")
354
+ if out.shape != x.shape:
355
+ raise RuntimeError("out must have the same shape as x")
356
+ return None
357
+
358
+
359
+ def bf16_rms_silu_ncdhw(
360
+ x: torch.Tensor,
361
+ gamma: torch.Tensor,
362
+ prev_cache: torch.Tensor | None = None,
363
+ eps: float = 1e-6,
364
+ *,
365
+ out: torch.Tensor | None = None,
366
+ next_cache: torch.Tensor | None = None,
367
+ ) -> tuple[torch.Tensor, torch.Tensor | None]:
368
+ """Apply channel RMSNorm and SiLU to BF16 NCDHW with optional cache update."""
369
+
370
+ if out is None:
371
+ out = torch.empty_like(x)
372
+ ops.bf16_rms_silu_ncdhw(
373
+ x, gamma, prev_cache, float(eps), out, next_cache
374
+ )
375
+ return out, next_cache
376
+
377
+
378
+ def bf16_rms_norm_ncdhw(
379
+ x: torch.Tensor,
380
+ gamma: torch.Tensor,
381
+ bias: torch.Tensor | None = None,
382
+ eps: float = 1e-6,
383
+ *,
384
+ out: torch.Tensor | None = None,
385
+ ) -> torch.Tensor:
386
+ """Apply channel RMSNorm and optional bias to BF16 NCDHW."""
387
+
388
+ if out is None:
389
+ out = torch.empty_like(x)
390
+ ops.bf16_rms_norm_ncdhw(x, gamma, bias, float(eps), out)
391
+ return out
392
+
393
+
394
+ __all__ = [
395
+ "bf16_rms_norm_ncdhw",
396
+ "bf16_rms_silu_ncdhw",
397
+ "dequantize_fp4_sfa_fp16",
398
+ "quantize_bf16_to_nvfp4_linear",
399
+ "residual_add_rms_norm_fp4_sfa_fp16",
400
+ "residual_add_rms_norm_fp4_sfa_v2_fp16",
401
+ "residual_add_rms_norm_mul_fp4_sfa_fp16",
402
+ "rms_norm_fp4_sfa_fp16",
403
+ "rms_silu_nvfp4_ndhwc_bf16",
404
+ "sfa_size_bytes",
405
+ "silu_mul_fp4_sfa_fp16",
406
+ "silu_mul_fp4_sfa_v2_fp16",
407
+ "silu_mul_mul_fp4_sfa_v2_fp16",
408
+ "silu_mul_two_fp4_to_fp4",
409
+ "silu_mul_two_mul_fp4_to_fp4",
410
+ ]
build/torch211-cxx11-cu130-x86_64-linux/{_fp4_fused_ops_cuda_7e2e5b9.abi3.so → _fp4_fused_ops_cuda_8e0b1cd.abi3.so} RENAMED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:18ee567014dff126b5d85586845d69c6463950d1fc1ef19d528215a71ea3f6be
3
- size 535352
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:8b0f8e8fe5865d1bdc245b48c0fb71e0910acd89e4405d91c9e4c1ae08af938a
3
+ size 966768
build/torch211-cxx11-cu130-x86_64-linux/_ops.py CHANGED
@@ -1,9 +1,9 @@
1
  import torch
2
- from . import _fp4_fused_ops_cuda_7e2e5b9
3
- ops = torch.ops._fp4_fused_ops_cuda_7e2e5b9
4
 
5
  def add_op_namespace_prefix(op_name: str):
6
  """
7
  Prefix op by namespace.
8
  """
9
- return f"_fp4_fused_ops_cuda_7e2e5b9::{op_name}"
 
1
  import torch
2
+ from . import _fp4_fused_ops_cuda_8e0b1cd
3
+ ops = torch.ops._fp4_fused_ops_cuda_8e0b1cd
4
 
5
  def add_op_namespace_prefix(op_name: str):
6
  """
7
  Prefix op by namespace.
8
  """
9
+ return f"_fp4_fused_ops_cuda_8e0b1cd::{op_name}"
build/torch211-cxx11-cu130-x86_64-linux/metadata.json CHANGED
@@ -1,21 +1,22 @@
1
  {
2
  "name": "fp4-fused-ops",
3
- "id": "_fp4_fused_ops_cuda_7e2e5b9",
4
  "version": 1,
5
  "license": "Apache-2.0",
6
  "python-depends": [],
7
  "backend": {
8
  "type": "cuda",
9
  "archs": [
 
10
  "12.0a"
11
  ]
12
  },
13
  "digest": {
14
  "algorithm": "sha256",
15
  "files": {
16
- "__init__.py": "aB7foEHGoXVq7xDlENZhAsIjQvzWhMpiKhanJhtzmk8=",
17
- "_fp4_fused_ops_cuda_7e2e5b9.abi3.so": "GO5WcBTf8Sa12FWGhF1pxkY5UNH8HvGdUoIVpx6j9r4=",
18
- "_ops.py": "qtD0ljSFCLkwC71lYCEP/FcSj+NFL+0sWWugI+4CH4s=",
19
  "fp4_fused_ops/__init__.py": "DFYPlrhXwYjEqCl/8n0SmWGZV8NFml5DPhMjKfv98GY="
20
  }
21
  }
 
1
  {
2
  "name": "fp4-fused-ops",
3
+ "id": "_fp4_fused_ops_cuda_8e0b1cd",
4
  "version": 1,
5
  "license": "Apache-2.0",
6
  "python-depends": [],
7
  "backend": {
8
  "type": "cuda",
9
  "archs": [
10
+ "11.0a",
11
  "12.0a"
12
  ]
13
  },
14
  "digest": {
15
  "algorithm": "sha256",
16
  "files": {
17
+ "__init__.py": "511/VkU+HAwubcrzG/Ck9wB3ukPbjKrWxG+9EgtcP00=",
18
+ "_fp4_fused_ops_cuda_8e0b1cd.abi3.so": "iw+Oj+WGXRvcJFtIwPtx4JEKzYnkQF2RyeTBrgivk4o=",
19
+ "_ops.py": "L5M3920Afl87xMKszpaz5zL32AN6JoBJM6Aw1J19k2I=",
20
  "fp4_fused_ops/__init__.py": "DFYPlrhXwYjEqCl/8n0SmWGZV8NFml5DPhMjKfv98GY="
21
  }
22
  }
build/torch212-cxx11-cu130-x86_64-linux/__init__.py CHANGED
@@ -91,6 +91,57 @@ def _dequant_fake(packed: torch.Tensor, sfa: torch.Tensor, out: torch.Tensor) ->
91
  return None
92
 
93
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
94
  def rms_norm_fp4_sfa_fp16(x: torch.Tensor, packed: torch.Tensor | None = None, sfa: torch.Tensor | None = None):
95
  if packed is None or sfa is None:
96
  packed, sfa = _alloc_fp4(x.shape[0], x.shape[1], x.device)
@@ -204,3 +255,156 @@ def dequantize_fp4_sfa_fp16(
204
  out = torch.empty((packed.shape[0], packed.shape[1] * 2), device=packed.device, dtype=torch.float16)
205
  ops.dequantize_fp4_sfa_fp16(packed, sfa, out)
206
  return out
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
91
  return None
92
 
93
 
94
+ @torch.library.register_fake(add_op_namespace_prefix("rms_silu_nvfp4_ndhwc_bf16"))
95
+ def _rms_silu_nvfp4_ndhwc_bf16_fake(
96
+ x: torch.Tensor,
97
+ gamma: torch.Tensor,
98
+ awq_inv_scale: torch.Tensor | None,
99
+ eps: float,
100
+ packed: torch.Tensor,
101
+ scale_factors: torch.Tensor,
102
+ ) -> None:
103
+ del eps
104
+ if x.dim() != 5:
105
+ raise RuntimeError("x must have shape (B,C,T,H,W)")
106
+ b, c, t, h, w = x.shape
107
+ if (
108
+ c % 128 != 0
109
+ or c > 1024
110
+ or gamma.shape != (c,)
111
+ or packed.shape != (b, t, h, w, c // 2)
112
+ or scale_factors.shape != (b, t, h, w, c // 16)
113
+ or (awq_inv_scale is not None and awq_inv_scale.shape != (c,))
114
+ ):
115
+ raise RuntimeError(
116
+ "rms_silu_nvfp4_ndhwc_bf16 shape contract failed"
117
+ )
118
+ return None
119
+
120
+
121
+ @torch.library.register_fake(
122
+ add_op_namespace_prefix("quantize_bf16_to_nvfp4_linear")
123
+ )
124
+ def _quantize_bf16_to_nvfp4_linear_fake(
125
+ input: torch.Tensor,
126
+ packed: torch.Tensor,
127
+ scale_factors: torch.Tensor,
128
+ ) -> None:
129
+ if input.dim() != 2:
130
+ raise RuntimeError("input must have shape (rows, cols)")
131
+ rows, cols = input.shape
132
+ if (
133
+ rows <= 0
134
+ or cols <= 0
135
+ or cols % 16 != 0
136
+ or packed.shape != (rows, cols // 2)
137
+ or scale_factors.shape != (rows, cols // 16)
138
+ ):
139
+ raise RuntimeError(
140
+ "quantize_bf16_to_nvfp4_linear shape contract failed"
141
+ )
142
+ return None
143
+
144
+
145
  def rms_norm_fp4_sfa_fp16(x: torch.Tensor, packed: torch.Tensor | None = None, sfa: torch.Tensor | None = None):
146
  if packed is None or sfa is None:
147
  packed, sfa = _alloc_fp4(x.shape[0], x.shape[1], x.device)
 
255
  out = torch.empty((packed.shape[0], packed.shape[1] * 2), device=packed.device, dtype=torch.float16)
256
  ops.dequantize_fp4_sfa_fp16(packed, sfa, out)
257
  return out
258
+
259
+
260
+ def rms_silu_nvfp4_ndhwc_bf16(
261
+ x: torch.Tensor,
262
+ gamma: torch.Tensor,
263
+ awq_inv_scale: torch.Tensor | None = None,
264
+ eps: float = 1e-6,
265
+ *,
266
+ packed: torch.Tensor | None = None,
267
+ scale_factors: torch.Tensor | None = None,
268
+ ) -> tuple[torch.Tensor, torch.Tensor]:
269
+ """Fuse BF16 NCDHW RMSNorm, SiLU and linear-SF NVFP4 quantization."""
270
+
271
+ b, c, t, h, w = x.shape
272
+ if packed is None:
273
+ packed = torch.empty(
274
+ (b, t, h, w, c // 2), device=x.device, dtype=torch.uint8
275
+ )
276
+ if scale_factors is None:
277
+ scale_factors = torch.empty(
278
+ (b, t, h, w, c // 16), device=x.device, dtype=torch.uint8
279
+ )
280
+ ops.rms_silu_nvfp4_ndhwc_bf16(
281
+ x,
282
+ gamma,
283
+ awq_inv_scale,
284
+ float(eps),
285
+ packed,
286
+ scale_factors,
287
+ )
288
+ return packed, scale_factors
289
+
290
+
291
+ def quantize_bf16_to_nvfp4_linear(
292
+ input: torch.Tensor,
293
+ *,
294
+ packed: torch.Tensor | None = None,
295
+ scale_factors: torch.Tensor | None = None,
296
+ ) -> tuple[torch.Tensor, torch.Tensor]:
297
+ """Quantize BF16 rows to packed E2M1 with linear UE4M3 block-16 scales."""
298
+
299
+ rows, cols = input.shape
300
+ if packed is None:
301
+ packed = torch.empty(
302
+ (rows, cols // 2), device=input.device, dtype=torch.uint8
303
+ )
304
+ if scale_factors is None:
305
+ scale_factors = torch.empty(
306
+ (rows, cols // 16), device=input.device, dtype=torch.uint8
307
+ )
308
+ ops.quantize_bf16_to_nvfp4_linear(input, packed, scale_factors)
309
+ return packed, scale_factors
310
+
311
+
312
+ def _check_ncdhw(x: torch.Tensor, gamma: torch.Tensor) -> None:
313
+ if x.dim() != 5:
314
+ raise RuntimeError("x must have shape (B,C,T,H,W)")
315
+ if x.shape[1] <= 0 or x.shape[1] % 2 != 0 or x.shape[1] > 1024:
316
+ raise RuntimeError("C must be even and at most 1024")
317
+ if gamma.shape != (x.shape[1],):
318
+ raise RuntimeError("gamma must have shape (C,)")
319
+
320
+
321
+ @torch.library.register_fake(add_op_namespace_prefix("bf16_rms_silu_ncdhw"))
322
+ def _bf16_rms_silu_ncdhw_fake(
323
+ x: torch.Tensor,
324
+ gamma: torch.Tensor,
325
+ prev_cache: torch.Tensor | None,
326
+ eps: float,
327
+ out: torch.Tensor,
328
+ next_cache: torch.Tensor | None,
329
+ ) -> None:
330
+ del eps
331
+ _check_ncdhw(x, gamma)
332
+ if out.shape != x.shape:
333
+ raise RuntimeError("out must have the same shape as x")
334
+ expected_cache = (x.shape[0], x.shape[1], 2, x.shape[3], x.shape[4])
335
+ if prev_cache is not None and prev_cache.shape != expected_cache:
336
+ raise RuntimeError("prev_cache must have shape (B,C,2,H,W)")
337
+ if next_cache is not None and next_cache.shape != expected_cache:
338
+ raise RuntimeError("next_cache must have shape (B,C,2,H,W)")
339
+ return None
340
+
341
+
342
+ @torch.library.register_fake(add_op_namespace_prefix("bf16_rms_norm_ncdhw"))
343
+ def _bf16_rms_norm_ncdhw_fake(
344
+ x: torch.Tensor,
345
+ gamma: torch.Tensor,
346
+ bias: torch.Tensor | None,
347
+ eps: float,
348
+ out: torch.Tensor,
349
+ ) -> None:
350
+ del eps
351
+ _check_ncdhw(x, gamma)
352
+ if bias is not None and bias.shape != (x.shape[1],):
353
+ raise RuntimeError("bias must have shape (C,)")
354
+ if out.shape != x.shape:
355
+ raise RuntimeError("out must have the same shape as x")
356
+ return None
357
+
358
+
359
+ def bf16_rms_silu_ncdhw(
360
+ x: torch.Tensor,
361
+ gamma: torch.Tensor,
362
+ prev_cache: torch.Tensor | None = None,
363
+ eps: float = 1e-6,
364
+ *,
365
+ out: torch.Tensor | None = None,
366
+ next_cache: torch.Tensor | None = None,
367
+ ) -> tuple[torch.Tensor, torch.Tensor | None]:
368
+ """Apply channel RMSNorm and SiLU to BF16 NCDHW with optional cache update."""
369
+
370
+ if out is None:
371
+ out = torch.empty_like(x)
372
+ ops.bf16_rms_silu_ncdhw(
373
+ x, gamma, prev_cache, float(eps), out, next_cache
374
+ )
375
+ return out, next_cache
376
+
377
+
378
+ def bf16_rms_norm_ncdhw(
379
+ x: torch.Tensor,
380
+ gamma: torch.Tensor,
381
+ bias: torch.Tensor | None = None,
382
+ eps: float = 1e-6,
383
+ *,
384
+ out: torch.Tensor | None = None,
385
+ ) -> torch.Tensor:
386
+ """Apply channel RMSNorm and optional bias to BF16 NCDHW."""
387
+
388
+ if out is None:
389
+ out = torch.empty_like(x)
390
+ ops.bf16_rms_norm_ncdhw(x, gamma, bias, float(eps), out)
391
+ return out
392
+
393
+
394
+ __all__ = [
395
+ "bf16_rms_norm_ncdhw",
396
+ "bf16_rms_silu_ncdhw",
397
+ "dequantize_fp4_sfa_fp16",
398
+ "quantize_bf16_to_nvfp4_linear",
399
+ "residual_add_rms_norm_fp4_sfa_fp16",
400
+ "residual_add_rms_norm_fp4_sfa_v2_fp16",
401
+ "residual_add_rms_norm_mul_fp4_sfa_fp16",
402
+ "rms_norm_fp4_sfa_fp16",
403
+ "rms_silu_nvfp4_ndhwc_bf16",
404
+ "sfa_size_bytes",
405
+ "silu_mul_fp4_sfa_fp16",
406
+ "silu_mul_fp4_sfa_v2_fp16",
407
+ "silu_mul_mul_fp4_sfa_v2_fp16",
408
+ "silu_mul_two_fp4_to_fp4",
409
+ "silu_mul_two_mul_fp4_to_fp4",
410
+ ]
build/torch212-cxx11-cu130-x86_64-linux/{_fp4_fused_ops_cuda_7e2e5b9.abi3.so → _fp4_fused_ops_cuda_8e0b1cd.abi3.so} RENAMED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:f24cde57e006bc22f3e087331b3bf75f223e796eb8526444792d779ac5c191b0
3
- size 545840
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:3b9aede5c54c9d74330dcd256ebecf8b77ef96ce5d0561e03f1996b625395c85
3
+ size 973216
build/torch212-cxx11-cu130-x86_64-linux/_ops.py CHANGED
@@ -1,9 +1,9 @@
1
  import torch
2
- from . import _fp4_fused_ops_cuda_7e2e5b9
3
- ops = torch.ops._fp4_fused_ops_cuda_7e2e5b9
4
 
5
  def add_op_namespace_prefix(op_name: str):
6
  """
7
  Prefix op by namespace.
8
  """
9
- return f"_fp4_fused_ops_cuda_7e2e5b9::{op_name}"
 
1
  import torch
2
+ from . import _fp4_fused_ops_cuda_8e0b1cd
3
+ ops = torch.ops._fp4_fused_ops_cuda_8e0b1cd
4
 
5
  def add_op_namespace_prefix(op_name: str):
6
  """
7
  Prefix op by namespace.
8
  """
9
+ return f"_fp4_fused_ops_cuda_8e0b1cd::{op_name}"
build/torch212-cxx11-cu130-x86_64-linux/metadata.json CHANGED
@@ -1,21 +1,22 @@
1
  {
2
  "name": "fp4-fused-ops",
3
- "id": "_fp4_fused_ops_cuda_7e2e5b9",
4
  "version": 1,
5
  "license": "Apache-2.0",
6
  "python-depends": [],
7
  "backend": {
8
  "type": "cuda",
9
  "archs": [
 
10
  "12.0a"
11
  ]
12
  },
13
  "digest": {
14
  "algorithm": "sha256",
15
  "files": {
16
- "__init__.py": "aB7foEHGoXVq7xDlENZhAsIjQvzWhMpiKhanJhtzmk8=",
17
- "_fp4_fused_ops_cuda_7e2e5b9.abi3.so": "8kzeV+AGvCLz4IczGzv3XyI+eW64UmREeS13msXBkbA=",
18
- "_ops.py": "qtD0ljSFCLkwC71lYCEP/FcSj+NFL+0sWWugI+4CH4s=",
19
  "fp4_fused_ops/__init__.py": "DFYPlrhXwYjEqCl/8n0SmWGZV8NFml5DPhMjKfv98GY="
20
  }
21
  }
 
1
  {
2
  "name": "fp4-fused-ops",
3
+ "id": "_fp4_fused_ops_cuda_8e0b1cd",
4
  "version": 1,
5
  "license": "Apache-2.0",
6
  "python-depends": [],
7
  "backend": {
8
  "type": "cuda",
9
  "archs": [
10
+ "11.0a",
11
  "12.0a"
12
  ]
13
  },
14
  "digest": {
15
  "algorithm": "sha256",
16
  "files": {
17
+ "__init__.py": "511/VkU+HAwubcrzG/Ck9wB3ukPbjKrWxG+9EgtcP00=",
18
+ "_fp4_fused_ops_cuda_8e0b1cd.abi3.so": "O5rt5cVMnXQzDc0lbr7Pi3fvls5dBWHgPxmWtiU5XIU=",
19
+ "_ops.py": "L5M3920Afl87xMKszpaz5zL32AN6JoBJM6Aw1J19k2I=",
20
  "fp4_fused_ops/__init__.py": "DFYPlrhXwYjEqCl/8n0SmWGZV8NFml5DPhMjKfv98GY="
21
  }
22
  }
build/torch212-cxx11-cu132-x86_64-linux/__init__.py CHANGED
@@ -91,6 +91,57 @@ def _dequant_fake(packed: torch.Tensor, sfa: torch.Tensor, out: torch.Tensor) ->
91
  return None
92
 
93
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
94
  def rms_norm_fp4_sfa_fp16(x: torch.Tensor, packed: torch.Tensor | None = None, sfa: torch.Tensor | None = None):
95
  if packed is None or sfa is None:
96
  packed, sfa = _alloc_fp4(x.shape[0], x.shape[1], x.device)
@@ -204,3 +255,156 @@ def dequantize_fp4_sfa_fp16(
204
  out = torch.empty((packed.shape[0], packed.shape[1] * 2), device=packed.device, dtype=torch.float16)
205
  ops.dequantize_fp4_sfa_fp16(packed, sfa, out)
206
  return out
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
91
  return None
92
 
93
 
94
+ @torch.library.register_fake(add_op_namespace_prefix("rms_silu_nvfp4_ndhwc_bf16"))
95
+ def _rms_silu_nvfp4_ndhwc_bf16_fake(
96
+ x: torch.Tensor,
97
+ gamma: torch.Tensor,
98
+ awq_inv_scale: torch.Tensor | None,
99
+ eps: float,
100
+ packed: torch.Tensor,
101
+ scale_factors: torch.Tensor,
102
+ ) -> None:
103
+ del eps
104
+ if x.dim() != 5:
105
+ raise RuntimeError("x must have shape (B,C,T,H,W)")
106
+ b, c, t, h, w = x.shape
107
+ if (
108
+ c % 128 != 0
109
+ or c > 1024
110
+ or gamma.shape != (c,)
111
+ or packed.shape != (b, t, h, w, c // 2)
112
+ or scale_factors.shape != (b, t, h, w, c // 16)
113
+ or (awq_inv_scale is not None and awq_inv_scale.shape != (c,))
114
+ ):
115
+ raise RuntimeError(
116
+ "rms_silu_nvfp4_ndhwc_bf16 shape contract failed"
117
+ )
118
+ return None
119
+
120
+
121
+ @torch.library.register_fake(
122
+ add_op_namespace_prefix("quantize_bf16_to_nvfp4_linear")
123
+ )
124
+ def _quantize_bf16_to_nvfp4_linear_fake(
125
+ input: torch.Tensor,
126
+ packed: torch.Tensor,
127
+ scale_factors: torch.Tensor,
128
+ ) -> None:
129
+ if input.dim() != 2:
130
+ raise RuntimeError("input must have shape (rows, cols)")
131
+ rows, cols = input.shape
132
+ if (
133
+ rows <= 0
134
+ or cols <= 0
135
+ or cols % 16 != 0
136
+ or packed.shape != (rows, cols // 2)
137
+ or scale_factors.shape != (rows, cols // 16)
138
+ ):
139
+ raise RuntimeError(
140
+ "quantize_bf16_to_nvfp4_linear shape contract failed"
141
+ )
142
+ return None
143
+
144
+
145
  def rms_norm_fp4_sfa_fp16(x: torch.Tensor, packed: torch.Tensor | None = None, sfa: torch.Tensor | None = None):
146
  if packed is None or sfa is None:
147
  packed, sfa = _alloc_fp4(x.shape[0], x.shape[1], x.device)
 
255
  out = torch.empty((packed.shape[0], packed.shape[1] * 2), device=packed.device, dtype=torch.float16)
256
  ops.dequantize_fp4_sfa_fp16(packed, sfa, out)
257
  return out
258
+
259
+
260
+ def rms_silu_nvfp4_ndhwc_bf16(
261
+ x: torch.Tensor,
262
+ gamma: torch.Tensor,
263
+ awq_inv_scale: torch.Tensor | None = None,
264
+ eps: float = 1e-6,
265
+ *,
266
+ packed: torch.Tensor | None = None,
267
+ scale_factors: torch.Tensor | None = None,
268
+ ) -> tuple[torch.Tensor, torch.Tensor]:
269
+ """Fuse BF16 NCDHW RMSNorm, SiLU and linear-SF NVFP4 quantization."""
270
+
271
+ b, c, t, h, w = x.shape
272
+ if packed is None:
273
+ packed = torch.empty(
274
+ (b, t, h, w, c // 2), device=x.device, dtype=torch.uint8
275
+ )
276
+ if scale_factors is None:
277
+ scale_factors = torch.empty(
278
+ (b, t, h, w, c // 16), device=x.device, dtype=torch.uint8
279
+ )
280
+ ops.rms_silu_nvfp4_ndhwc_bf16(
281
+ x,
282
+ gamma,
283
+ awq_inv_scale,
284
+ float(eps),
285
+ packed,
286
+ scale_factors,
287
+ )
288
+ return packed, scale_factors
289
+
290
+
291
+ def quantize_bf16_to_nvfp4_linear(
292
+ input: torch.Tensor,
293
+ *,
294
+ packed: torch.Tensor | None = None,
295
+ scale_factors: torch.Tensor | None = None,
296
+ ) -> tuple[torch.Tensor, torch.Tensor]:
297
+ """Quantize BF16 rows to packed E2M1 with linear UE4M3 block-16 scales."""
298
+
299
+ rows, cols = input.shape
300
+ if packed is None:
301
+ packed = torch.empty(
302
+ (rows, cols // 2), device=input.device, dtype=torch.uint8
303
+ )
304
+ if scale_factors is None:
305
+ scale_factors = torch.empty(
306
+ (rows, cols // 16), device=input.device, dtype=torch.uint8
307
+ )
308
+ ops.quantize_bf16_to_nvfp4_linear(input, packed, scale_factors)
309
+ return packed, scale_factors
310
+
311
+
312
+ def _check_ncdhw(x: torch.Tensor, gamma: torch.Tensor) -> None:
313
+ if x.dim() != 5:
314
+ raise RuntimeError("x must have shape (B,C,T,H,W)")
315
+ if x.shape[1] <= 0 or x.shape[1] % 2 != 0 or x.shape[1] > 1024:
316
+ raise RuntimeError("C must be even and at most 1024")
317
+ if gamma.shape != (x.shape[1],):
318
+ raise RuntimeError("gamma must have shape (C,)")
319
+
320
+
321
+ @torch.library.register_fake(add_op_namespace_prefix("bf16_rms_silu_ncdhw"))
322
+ def _bf16_rms_silu_ncdhw_fake(
323
+ x: torch.Tensor,
324
+ gamma: torch.Tensor,
325
+ prev_cache: torch.Tensor | None,
326
+ eps: float,
327
+ out: torch.Tensor,
328
+ next_cache: torch.Tensor | None,
329
+ ) -> None:
330
+ del eps
331
+ _check_ncdhw(x, gamma)
332
+ if out.shape != x.shape:
333
+ raise RuntimeError("out must have the same shape as x")
334
+ expected_cache = (x.shape[0], x.shape[1], 2, x.shape[3], x.shape[4])
335
+ if prev_cache is not None and prev_cache.shape != expected_cache:
336
+ raise RuntimeError("prev_cache must have shape (B,C,2,H,W)")
337
+ if next_cache is not None and next_cache.shape != expected_cache:
338
+ raise RuntimeError("next_cache must have shape (B,C,2,H,W)")
339
+ return None
340
+
341
+
342
+ @torch.library.register_fake(add_op_namespace_prefix("bf16_rms_norm_ncdhw"))
343
+ def _bf16_rms_norm_ncdhw_fake(
344
+ x: torch.Tensor,
345
+ gamma: torch.Tensor,
346
+ bias: torch.Tensor | None,
347
+ eps: float,
348
+ out: torch.Tensor,
349
+ ) -> None:
350
+ del eps
351
+ _check_ncdhw(x, gamma)
352
+ if bias is not None and bias.shape != (x.shape[1],):
353
+ raise RuntimeError("bias must have shape (C,)")
354
+ if out.shape != x.shape:
355
+ raise RuntimeError("out must have the same shape as x")
356
+ return None
357
+
358
+
359
+ def bf16_rms_silu_ncdhw(
360
+ x: torch.Tensor,
361
+ gamma: torch.Tensor,
362
+ prev_cache: torch.Tensor | None = None,
363
+ eps: float = 1e-6,
364
+ *,
365
+ out: torch.Tensor | None = None,
366
+ next_cache: torch.Tensor | None = None,
367
+ ) -> tuple[torch.Tensor, torch.Tensor | None]:
368
+ """Apply channel RMSNorm and SiLU to BF16 NCDHW with optional cache update."""
369
+
370
+ if out is None:
371
+ out = torch.empty_like(x)
372
+ ops.bf16_rms_silu_ncdhw(
373
+ x, gamma, prev_cache, float(eps), out, next_cache
374
+ )
375
+ return out, next_cache
376
+
377
+
378
+ def bf16_rms_norm_ncdhw(
379
+ x: torch.Tensor,
380
+ gamma: torch.Tensor,
381
+ bias: torch.Tensor | None = None,
382
+ eps: float = 1e-6,
383
+ *,
384
+ out: torch.Tensor | None = None,
385
+ ) -> torch.Tensor:
386
+ """Apply channel RMSNorm and optional bias to BF16 NCDHW."""
387
+
388
+ if out is None:
389
+ out = torch.empty_like(x)
390
+ ops.bf16_rms_norm_ncdhw(x, gamma, bias, float(eps), out)
391
+ return out
392
+
393
+
394
+ __all__ = [
395
+ "bf16_rms_norm_ncdhw",
396
+ "bf16_rms_silu_ncdhw",
397
+ "dequantize_fp4_sfa_fp16",
398
+ "quantize_bf16_to_nvfp4_linear",
399
+ "residual_add_rms_norm_fp4_sfa_fp16",
400
+ "residual_add_rms_norm_fp4_sfa_v2_fp16",
401
+ "residual_add_rms_norm_mul_fp4_sfa_fp16",
402
+ "rms_norm_fp4_sfa_fp16",
403
+ "rms_silu_nvfp4_ndhwc_bf16",
404
+ "sfa_size_bytes",
405
+ "silu_mul_fp4_sfa_fp16",
406
+ "silu_mul_fp4_sfa_v2_fp16",
407
+ "silu_mul_mul_fp4_sfa_v2_fp16",
408
+ "silu_mul_two_fp4_to_fp4",
409
+ "silu_mul_two_mul_fp4_to_fp4",
410
+ ]
build/torch212-cxx11-cu132-x86_64-linux/_fp4_fused_ops_cuda_8e0b1cd.abi3.so ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:98fbf2c4a25a0b476d653f02eb6b502895482007348e10ceeda57ca12fb87788
3
+ size 981456
build/torch212-cxx11-cu132-x86_64-linux/_ops.py CHANGED
@@ -1,9 +1,9 @@
1
  import torch
2
- from . import _fp4_fused_ops_cuda_7e2e5b9
3
- ops = torch.ops._fp4_fused_ops_cuda_7e2e5b9
4
 
5
  def add_op_namespace_prefix(op_name: str):
6
  """
7
  Prefix op by namespace.
8
  """
9
- return f"_fp4_fused_ops_cuda_7e2e5b9::{op_name}"
 
1
  import torch
2
+ from . import _fp4_fused_ops_cuda_8e0b1cd
3
+ ops = torch.ops._fp4_fused_ops_cuda_8e0b1cd
4
 
5
  def add_op_namespace_prefix(op_name: str):
6
  """
7
  Prefix op by namespace.
8
  """
9
+ return f"_fp4_fused_ops_cuda_8e0b1cd::{op_name}"
build/torch212-cxx11-cu132-x86_64-linux/metadata.json CHANGED
@@ -1,21 +1,22 @@
1
  {
2
  "name": "fp4-fused-ops",
3
- "id": "_fp4_fused_ops_cuda_7e2e5b9",
4
  "version": 1,
5
  "license": "Apache-2.0",
6
  "python-depends": [],
7
  "backend": {
8
  "type": "cuda",
9
  "archs": [
 
10
  "12.0a"
11
  ]
12
  },
13
  "digest": {
14
  "algorithm": "sha256",
15
  "files": {
16
- "__init__.py": "aB7foEHGoXVq7xDlENZhAsIjQvzWhMpiKhanJhtzmk8=",
17
- "_fp4_fused_ops_cuda_7e2e5b9.abi3.so": "+7gD0nYPX/QgoxHcdBsRsoSBnlWNAGAdmjwvXpIdMog=",
18
- "_ops.py": "qtD0ljSFCLkwC71lYCEP/FcSj+NFL+0sWWugI+4CH4s=",
19
  "fp4_fused_ops/__init__.py": "DFYPlrhXwYjEqCl/8n0SmWGZV8NFml5DPhMjKfv98GY="
20
  }
21
  }
 
1
  {
2
  "name": "fp4-fused-ops",
3
+ "id": "_fp4_fused_ops_cuda_8e0b1cd",
4
  "version": 1,
5
  "license": "Apache-2.0",
6
  "python-depends": [],
7
  "backend": {
8
  "type": "cuda",
9
  "archs": [
10
+ "11.0a",
11
  "12.0a"
12
  ]
13
  },
14
  "digest": {
15
  "algorithm": "sha256",
16
  "files": {
17
+ "__init__.py": "511/VkU+HAwubcrzG/Ck9wB3ukPbjKrWxG+9EgtcP00=",
18
+ "_fp4_fused_ops_cuda_8e0b1cd.abi3.so": "mPvyxKJaC0dtZT8C62tQKJVIIAc0jhDO7aV8oS+4d4g=",
19
+ "_ops.py": "L5M3920Afl87xMKszpaz5zL32AN6JoBJM6Aw1J19k2I=",
20
  "fp4_fused_ops/__init__.py": "DFYPlrhXwYjEqCl/8n0SmWGZV8NFml5DPhMjKfv98GY="
21
  }
22
  }
build/torch213-cxx11-cu130-aarch64-linux/__init__.py ADDED
@@ -0,0 +1,410 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """FlashRT FP4 fused producer kernels."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import torch
6
+
7
+ from ._ops import add_op_namespace_prefix, ops
8
+
9
+
10
+ def sfa_size_bytes(rows: int, dim: int, is_sfb: bool = False, device: torch.device | str | None = None) -> int:
11
+ if device is None:
12
+ device = torch.device("cuda", torch.cuda.current_device())
13
+ anchor = torch.empty((1,), device=device, dtype=torch.uint8)
14
+ return int(ops.sfa_size_bytes_for(anchor, int(rows), int(dim), bool(is_sfb)))
15
+
16
+
17
+ def _alloc_fp4(rows: int, dim: int, device: torch.device | str):
18
+ packed = torch.empty((rows, dim // 2), device=device, dtype=torch.uint8)
19
+ sfa = torch.empty((sfa_size_bytes(rows, dim, False, device=device),), device=device, dtype=torch.uint8)
20
+ return packed, sfa
21
+
22
+
23
+ @torch.library.register_fake(add_op_namespace_prefix("rms_norm_fp4_sfa_fp16"))
24
+ def _rms_norm_fake(x: torch.Tensor, packed: torch.Tensor, sfa: torch.Tensor) -> None:
25
+ return None
26
+
27
+
28
+ @torch.library.register_fake(add_op_namespace_prefix("residual_add_rms_norm_fp4_sfa_fp16"))
29
+ def _residual_fake(residual: torch.Tensor, x: torch.Tensor, packed: torch.Tensor, sfa: torch.Tensor) -> None:
30
+ return None
31
+
32
+
33
+ @torch.library.register_fake(add_op_namespace_prefix("residual_add_rms_norm_fp4_sfa_v2_fp16"))
34
+ def _residual_v2_fake(residual: torch.Tensor, x: torch.Tensor, packed: torch.Tensor, sfa: torch.Tensor) -> None:
35
+ return None
36
+
37
+
38
+ @torch.library.register_fake(add_op_namespace_prefix("residual_add_rms_norm_mul_fp4_sfa_fp16"))
39
+ def _residual_mul_fake(
40
+ residual: torch.Tensor,
41
+ x: torch.Tensor,
42
+ inv_s: torch.Tensor,
43
+ packed: torch.Tensor,
44
+ sfa: torch.Tensor,
45
+ ) -> None:
46
+ return None
47
+
48
+
49
+ @torch.library.register_fake(add_op_namespace_prefix("silu_mul_fp4_sfa_fp16"))
50
+ def _silu_fake(merged: torch.Tensor, packed: torch.Tensor, sfa: torch.Tensor) -> None:
51
+ return None
52
+
53
+
54
+ @torch.library.register_fake(add_op_namespace_prefix("silu_mul_fp4_sfa_v2_fp16"))
55
+ def _silu_v2_fake(merged: torch.Tensor, packed: torch.Tensor, sfa: torch.Tensor) -> None:
56
+ return None
57
+
58
+
59
+ @torch.library.register_fake(add_op_namespace_prefix("silu_mul_mul_fp4_sfa_v2_fp16"))
60
+ def _silu_mul_v2_fake(merged: torch.Tensor, inv_s: torch.Tensor, packed: torch.Tensor, sfa: torch.Tensor) -> None:
61
+ return None
62
+
63
+
64
+ @torch.library.register_fake(add_op_namespace_prefix("silu_mul_two_fp4_to_fp4"))
65
+ def _silu_two_fake(
66
+ gate_packed: torch.Tensor,
67
+ gate_sfa: torch.Tensor,
68
+ up_packed: torch.Tensor,
69
+ up_sfa: torch.Tensor,
70
+ out_packed: torch.Tensor,
71
+ out_sfa: torch.Tensor,
72
+ ) -> None:
73
+ return None
74
+
75
+
76
+ @torch.library.register_fake(add_op_namespace_prefix("silu_mul_two_mul_fp4_to_fp4"))
77
+ def _silu_two_mul_fake(
78
+ gate_packed: torch.Tensor,
79
+ gate_sfa: torch.Tensor,
80
+ up_packed: torch.Tensor,
81
+ up_sfa: torch.Tensor,
82
+ inv_s: torch.Tensor,
83
+ out_packed: torch.Tensor,
84
+ out_sfa: torch.Tensor,
85
+ ) -> None:
86
+ return None
87
+
88
+
89
+ @torch.library.register_fake(add_op_namespace_prefix("dequantize_fp4_sfa_fp16"))
90
+ def _dequant_fake(packed: torch.Tensor, sfa: torch.Tensor, out: torch.Tensor) -> None:
91
+ return None
92
+
93
+
94
+ @torch.library.register_fake(add_op_namespace_prefix("rms_silu_nvfp4_ndhwc_bf16"))
95
+ def _rms_silu_nvfp4_ndhwc_bf16_fake(
96
+ x: torch.Tensor,
97
+ gamma: torch.Tensor,
98
+ awq_inv_scale: torch.Tensor | None,
99
+ eps: float,
100
+ packed: torch.Tensor,
101
+ scale_factors: torch.Tensor,
102
+ ) -> None:
103
+ del eps
104
+ if x.dim() != 5:
105
+ raise RuntimeError("x must have shape (B,C,T,H,W)")
106
+ b, c, t, h, w = x.shape
107
+ if (
108
+ c % 128 != 0
109
+ or c > 1024
110
+ or gamma.shape != (c,)
111
+ or packed.shape != (b, t, h, w, c // 2)
112
+ or scale_factors.shape != (b, t, h, w, c // 16)
113
+ or (awq_inv_scale is not None and awq_inv_scale.shape != (c,))
114
+ ):
115
+ raise RuntimeError(
116
+ "rms_silu_nvfp4_ndhwc_bf16 shape contract failed"
117
+ )
118
+ return None
119
+
120
+
121
+ @torch.library.register_fake(
122
+ add_op_namespace_prefix("quantize_bf16_to_nvfp4_linear")
123
+ )
124
+ def _quantize_bf16_to_nvfp4_linear_fake(
125
+ input: torch.Tensor,
126
+ packed: torch.Tensor,
127
+ scale_factors: torch.Tensor,
128
+ ) -> None:
129
+ if input.dim() != 2:
130
+ raise RuntimeError("input must have shape (rows, cols)")
131
+ rows, cols = input.shape
132
+ if (
133
+ rows <= 0
134
+ or cols <= 0
135
+ or cols % 16 != 0
136
+ or packed.shape != (rows, cols // 2)
137
+ or scale_factors.shape != (rows, cols // 16)
138
+ ):
139
+ raise RuntimeError(
140
+ "quantize_bf16_to_nvfp4_linear shape contract failed"
141
+ )
142
+ return None
143
+
144
+
145
+ def rms_norm_fp4_sfa_fp16(x: torch.Tensor, packed: torch.Tensor | None = None, sfa: torch.Tensor | None = None):
146
+ if packed is None or sfa is None:
147
+ packed, sfa = _alloc_fp4(x.shape[0], x.shape[1], x.device)
148
+ ops.rms_norm_fp4_sfa_fp16(x, packed, sfa)
149
+ return packed, sfa
150
+
151
+
152
+ def residual_add_rms_norm_fp4_sfa_fp16(
153
+ residual: torch.Tensor,
154
+ x: torch.Tensor,
155
+ packed: torch.Tensor | None = None,
156
+ sfa: torch.Tensor | None = None,
157
+ ):
158
+ if packed is None or sfa is None:
159
+ packed, sfa = _alloc_fp4(x.shape[0], x.shape[1], x.device)
160
+ ops.residual_add_rms_norm_fp4_sfa_fp16(residual, x, packed, sfa)
161
+ return packed, sfa
162
+
163
+
164
+ def residual_add_rms_norm_fp4_sfa_v2_fp16(
165
+ residual: torch.Tensor,
166
+ x: torch.Tensor,
167
+ packed: torch.Tensor | None = None,
168
+ sfa: torch.Tensor | None = None,
169
+ ):
170
+ if packed is None or sfa is None:
171
+ packed, sfa = _alloc_fp4(x.shape[0], x.shape[1], x.device)
172
+ ops.residual_add_rms_norm_fp4_sfa_v2_fp16(residual, x, packed, sfa)
173
+ return packed, sfa
174
+
175
+
176
+ def residual_add_rms_norm_mul_fp4_sfa_fp16(
177
+ residual: torch.Tensor,
178
+ x: torch.Tensor,
179
+ inv_s: torch.Tensor,
180
+ packed: torch.Tensor | None = None,
181
+ sfa: torch.Tensor | None = None,
182
+ ):
183
+ if packed is None or sfa is None:
184
+ packed, sfa = _alloc_fp4(x.shape[0], x.shape[1], x.device)
185
+ ops.residual_add_rms_norm_mul_fp4_sfa_fp16(residual, x, inv_s, packed, sfa)
186
+ return packed, sfa
187
+
188
+
189
+ def silu_mul_fp4_sfa_fp16(merged: torch.Tensor, packed: torch.Tensor | None = None, sfa: torch.Tensor | None = None):
190
+ hidden = merged.shape[1] // 2
191
+ if packed is None or sfa is None:
192
+ packed, sfa = _alloc_fp4(merged.shape[0], hidden, merged.device)
193
+ ops.silu_mul_fp4_sfa_fp16(merged, packed, sfa)
194
+ return packed, sfa
195
+
196
+
197
+ def silu_mul_fp4_sfa_v2_fp16(merged: torch.Tensor, packed: torch.Tensor | None = None, sfa: torch.Tensor | None = None):
198
+ hidden = merged.shape[1] // 2
199
+ if packed is None or sfa is None:
200
+ packed, sfa = _alloc_fp4(merged.shape[0], hidden, merged.device)
201
+ ops.silu_mul_fp4_sfa_v2_fp16(merged, packed, sfa)
202
+ return packed, sfa
203
+
204
+
205
+ def silu_mul_mul_fp4_sfa_v2_fp16(
206
+ merged: torch.Tensor,
207
+ inv_s: torch.Tensor,
208
+ packed: torch.Tensor | None = None,
209
+ sfa: torch.Tensor | None = None,
210
+ ):
211
+ hidden = merged.shape[1] // 2
212
+ if packed is None or sfa is None:
213
+ packed, sfa = _alloc_fp4(merged.shape[0], hidden, merged.device)
214
+ ops.silu_mul_mul_fp4_sfa_v2_fp16(merged, inv_s, packed, sfa)
215
+ return packed, sfa
216
+
217
+
218
+ def silu_mul_two_fp4_to_fp4(
219
+ gate_packed: torch.Tensor,
220
+ gate_sfa: torch.Tensor,
221
+ up_packed: torch.Tensor,
222
+ up_sfa: torch.Tensor,
223
+ out_packed: torch.Tensor | None = None,
224
+ out_sfa: torch.Tensor | None = None,
225
+ ):
226
+ hidden = gate_packed.shape[1] * 2
227
+ if out_packed is None or out_sfa is None:
228
+ out_packed, out_sfa = _alloc_fp4(gate_packed.shape[0], hidden, gate_packed.device)
229
+ ops.silu_mul_two_fp4_to_fp4(gate_packed, gate_sfa, up_packed, up_sfa, out_packed, out_sfa)
230
+ return out_packed, out_sfa
231
+
232
+
233
+ def silu_mul_two_mul_fp4_to_fp4(
234
+ gate_packed: torch.Tensor,
235
+ gate_sfa: torch.Tensor,
236
+ up_packed: torch.Tensor,
237
+ up_sfa: torch.Tensor,
238
+ inv_s: torch.Tensor,
239
+ out_packed: torch.Tensor | None = None,
240
+ out_sfa: torch.Tensor | None = None,
241
+ ):
242
+ hidden = gate_packed.shape[1] * 2
243
+ if out_packed is None or out_sfa is None:
244
+ out_packed, out_sfa = _alloc_fp4(gate_packed.shape[0], hidden, gate_packed.device)
245
+ ops.silu_mul_two_mul_fp4_to_fp4(gate_packed, gate_sfa, up_packed, up_sfa, inv_s, out_packed, out_sfa)
246
+ return out_packed, out_sfa
247
+
248
+
249
+ def dequantize_fp4_sfa_fp16(
250
+ packed: torch.Tensor,
251
+ sfa: torch.Tensor,
252
+ out: torch.Tensor | None = None,
253
+ ) -> torch.Tensor:
254
+ if out is None:
255
+ out = torch.empty((packed.shape[0], packed.shape[1] * 2), device=packed.device, dtype=torch.float16)
256
+ ops.dequantize_fp4_sfa_fp16(packed, sfa, out)
257
+ return out
258
+
259
+
260
+ def rms_silu_nvfp4_ndhwc_bf16(
261
+ x: torch.Tensor,
262
+ gamma: torch.Tensor,
263
+ awq_inv_scale: torch.Tensor | None = None,
264
+ eps: float = 1e-6,
265
+ *,
266
+ packed: torch.Tensor | None = None,
267
+ scale_factors: torch.Tensor | None = None,
268
+ ) -> tuple[torch.Tensor, torch.Tensor]:
269
+ """Fuse BF16 NCDHW RMSNorm, SiLU and linear-SF NVFP4 quantization."""
270
+
271
+ b, c, t, h, w = x.shape
272
+ if packed is None:
273
+ packed = torch.empty(
274
+ (b, t, h, w, c // 2), device=x.device, dtype=torch.uint8
275
+ )
276
+ if scale_factors is None:
277
+ scale_factors = torch.empty(
278
+ (b, t, h, w, c // 16), device=x.device, dtype=torch.uint8
279
+ )
280
+ ops.rms_silu_nvfp4_ndhwc_bf16(
281
+ x,
282
+ gamma,
283
+ awq_inv_scale,
284
+ float(eps),
285
+ packed,
286
+ scale_factors,
287
+ )
288
+ return packed, scale_factors
289
+
290
+
291
+ def quantize_bf16_to_nvfp4_linear(
292
+ input: torch.Tensor,
293
+ *,
294
+ packed: torch.Tensor | None = None,
295
+ scale_factors: torch.Tensor | None = None,
296
+ ) -> tuple[torch.Tensor, torch.Tensor]:
297
+ """Quantize BF16 rows to packed E2M1 with linear UE4M3 block-16 scales."""
298
+
299
+ rows, cols = input.shape
300
+ if packed is None:
301
+ packed = torch.empty(
302
+ (rows, cols // 2), device=input.device, dtype=torch.uint8
303
+ )
304
+ if scale_factors is None:
305
+ scale_factors = torch.empty(
306
+ (rows, cols // 16), device=input.device, dtype=torch.uint8
307
+ )
308
+ ops.quantize_bf16_to_nvfp4_linear(input, packed, scale_factors)
309
+ return packed, scale_factors
310
+
311
+
312
+ def _check_ncdhw(x: torch.Tensor, gamma: torch.Tensor) -> None:
313
+ if x.dim() != 5:
314
+ raise RuntimeError("x must have shape (B,C,T,H,W)")
315
+ if x.shape[1] <= 0 or x.shape[1] % 2 != 0 or x.shape[1] > 1024:
316
+ raise RuntimeError("C must be even and at most 1024")
317
+ if gamma.shape != (x.shape[1],):
318
+ raise RuntimeError("gamma must have shape (C,)")
319
+
320
+
321
+ @torch.library.register_fake(add_op_namespace_prefix("bf16_rms_silu_ncdhw"))
322
+ def _bf16_rms_silu_ncdhw_fake(
323
+ x: torch.Tensor,
324
+ gamma: torch.Tensor,
325
+ prev_cache: torch.Tensor | None,
326
+ eps: float,
327
+ out: torch.Tensor,
328
+ next_cache: torch.Tensor | None,
329
+ ) -> None:
330
+ del eps
331
+ _check_ncdhw(x, gamma)
332
+ if out.shape != x.shape:
333
+ raise RuntimeError("out must have the same shape as x")
334
+ expected_cache = (x.shape[0], x.shape[1], 2, x.shape[3], x.shape[4])
335
+ if prev_cache is not None and prev_cache.shape != expected_cache:
336
+ raise RuntimeError("prev_cache must have shape (B,C,2,H,W)")
337
+ if next_cache is not None and next_cache.shape != expected_cache:
338
+ raise RuntimeError("next_cache must have shape (B,C,2,H,W)")
339
+ return None
340
+
341
+
342
+ @torch.library.register_fake(add_op_namespace_prefix("bf16_rms_norm_ncdhw"))
343
+ def _bf16_rms_norm_ncdhw_fake(
344
+ x: torch.Tensor,
345
+ gamma: torch.Tensor,
346
+ bias: torch.Tensor | None,
347
+ eps: float,
348
+ out: torch.Tensor,
349
+ ) -> None:
350
+ del eps
351
+ _check_ncdhw(x, gamma)
352
+ if bias is not None and bias.shape != (x.shape[1],):
353
+ raise RuntimeError("bias must have shape (C,)")
354
+ if out.shape != x.shape:
355
+ raise RuntimeError("out must have the same shape as x")
356
+ return None
357
+
358
+
359
+ def bf16_rms_silu_ncdhw(
360
+ x: torch.Tensor,
361
+ gamma: torch.Tensor,
362
+ prev_cache: torch.Tensor | None = None,
363
+ eps: float = 1e-6,
364
+ *,
365
+ out: torch.Tensor | None = None,
366
+ next_cache: torch.Tensor | None = None,
367
+ ) -> tuple[torch.Tensor, torch.Tensor | None]:
368
+ """Apply channel RMSNorm and SiLU to BF16 NCDHW with optional cache update."""
369
+
370
+ if out is None:
371
+ out = torch.empty_like(x)
372
+ ops.bf16_rms_silu_ncdhw(
373
+ x, gamma, prev_cache, float(eps), out, next_cache
374
+ )
375
+ return out, next_cache
376
+
377
+
378
+ def bf16_rms_norm_ncdhw(
379
+ x: torch.Tensor,
380
+ gamma: torch.Tensor,
381
+ bias: torch.Tensor | None = None,
382
+ eps: float = 1e-6,
383
+ *,
384
+ out: torch.Tensor | None = None,
385
+ ) -> torch.Tensor:
386
+ """Apply channel RMSNorm and optional bias to BF16 NCDHW."""
387
+
388
+ if out is None:
389
+ out = torch.empty_like(x)
390
+ ops.bf16_rms_norm_ncdhw(x, gamma, bias, float(eps), out)
391
+ return out
392
+
393
+
394
+ __all__ = [
395
+ "bf16_rms_norm_ncdhw",
396
+ "bf16_rms_silu_ncdhw",
397
+ "dequantize_fp4_sfa_fp16",
398
+ "quantize_bf16_to_nvfp4_linear",
399
+ "residual_add_rms_norm_fp4_sfa_fp16",
400
+ "residual_add_rms_norm_fp4_sfa_v2_fp16",
401
+ "residual_add_rms_norm_mul_fp4_sfa_fp16",
402
+ "rms_norm_fp4_sfa_fp16",
403
+ "rms_silu_nvfp4_ndhwc_bf16",
404
+ "sfa_size_bytes",
405
+ "silu_mul_fp4_sfa_fp16",
406
+ "silu_mul_fp4_sfa_v2_fp16",
407
+ "silu_mul_mul_fp4_sfa_v2_fp16",
408
+ "silu_mul_two_fp4_to_fp4",
409
+ "silu_mul_two_mul_fp4_to_fp4",
410
+ ]
build/torch213-cxx11-cu130-aarch64-linux/_ops.py ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ import torch
2
+ from . import fp4_fused_ops_source_test
3
+ ops = torch.ops.fp4_fused_ops_source_test
4
+
5
+ def add_op_namespace_prefix(op_name: str):
6
+ return f"fp4_fused_ops_source_test::{op_name}"
build/torch213-cxx11-cu130-aarch64-linux/fp4_fused_ops/__init__.py ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import ctypes
2
+ import importlib.util
3
+ import sys
4
+ from pathlib import Path
5
+
6
+ def _import_from_path(file_path: Path):
7
+ path_hash = '{:x}'.format(ctypes.c_size_t(hash(file_path.absolute())).value)
8
+ spec = importlib.util.spec_from_file_location(path_hash, file_path)
9
+ module = importlib.util.module_from_spec(spec)
10
+ sys.modules[path_hash] = module
11
+ spec.loader.exec_module(module)
12
+ return module
13
+
14
+ globals().update(vars(_import_from_path(Path(__file__).parent.parent / '__init__.py')))
build/torch213-cxx11-cu130-aarch64-linux/fp4_fused_ops_source_test.abi3.so ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:3a77ebe036649fd7571664aaeae1fe6619218fd94d5c707f1879972399841c41
3
+ size 691752
build/torch213-cxx11-cu130-aarch64-linux/metadata.json ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "fp4-fused-ops",
3
+ "id": "fp4_fused_ops_source_test",
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": "511/VkU+HAwubcrzG/Ck9wB3ukPbjKrWxG+9EgtcP00=",
17
+ "fp4_fused_ops_source_test.abi3.so": "Onfr4DZkn9dXFmSq6uH+Zhkhj9lNXHB/GHmXI5mEHEE=",
18
+ "_ops.py": "uZrqOE8sQDwTb0/km0N/KGsHFOC8TmQOIPHR2bVdj24=",
19
+ "fp4_fused_ops/__init__.py": "v6p5XMfQzddhi1fLSAw4HX9CyS0rQsidvu9VsT01xi4="
20
+ }
21
+ },
22
+ "provenance": {
23
+ "kernel": {
24
+ "sha": "456d297",
25
+ "dirty": false
26
+ },
27
+ "validation": {
28
+ "torch": "2.13.0+cu130",
29
+ "cuda": "13.0"
30
+ }
31
+ }
32
+ }