Frosty40 commited on
Commit
ea2ed3e
·
verified ·
1 Parent(s): 0be25ec

DGX Spark serving config: source, kernels, receipts, validated env (part 3)

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. labs/swiglu_nvfp4/native_cuda/gate_fc1_nvfp4_scaled_tma128n128k4.py +129 -0
  2. labs/swiglu_nvfp4/native_cuda/gate_fc1_nvfp4_scaled_tma128n128k4_20423.json +16 -0
  3. labs/swiglu_nvfp4/native_cuda/gate_fc1_nvfp4_scaled_tma128n128k4_ldm.py +127 -0
  4. labs/swiglu_nvfp4/native_cuda/gate_fc1_nvfp4_scaled_tma128n128k4_ldm_20423.json +16 -0
  5. labs/swiglu_nvfp4/native_cuda/gate_fc1_nvfp4_scaled_tma128n128k4_pipe.py +126 -0
  6. labs/swiglu_nvfp4/native_cuda/gate_fc1_nvfp4_scaled_tma128n128k4_pipe_20423.json +16 -0
  7. labs/swiglu_nvfp4/native_cuda/gate_fc1_nvfp4_scaled_tma128n128k4_sw.py +134 -0
  8. labs/swiglu_nvfp4/native_cuda/gate_fc1_nvfp4_scaled_tma128n128k4_sw_20423.json +19 -0
  9. labs/swiglu_nvfp4/native_cuda/gate_fc1_nvfp4_scaled_tma128n128k4ws.py +138 -0
  10. labs/swiglu_nvfp4/native_cuda/gate_fc1_nvfp4_scaled_tma128n128k4ws_20423.json +30 -0
  11. labs/swiglu_nvfp4/native_cuda/gate_fc1_nvfp4_scaled_tma256.py +170 -0
  12. labs/swiglu_nvfp4/native_cuda/gate_fc1_nvfp4_scaled_tma256_20423.json +24 -0
  13. labs/swiglu_nvfp4/native_cuda/gate_fc1_nvfp4_scaled_tma256_sw.py +170 -0
  14. labs/swiglu_nvfp4/native_cuda/gate_fc1_nvfp4_scaled_tma256_sw_20423.json +24 -0
  15. labs/swiglu_nvfp4/native_cuda/gate_fc1_nvfp4_scaled_tma256k2.py +170 -0
  16. labs/swiglu_nvfp4/native_cuda/gate_fc1_nvfp4_scaled_tma256k2_20423.json +24 -0
  17. labs/swiglu_nvfp4/native_cuda/gate_fc1_nvfp4_scaled_tma256k2_ldm.py +127 -0
  18. labs/swiglu_nvfp4/native_cuda/gate_fc1_nvfp4_scaled_tma256k2_ldm_20423.json +16 -0
  19. labs/swiglu_nvfp4/native_cuda/gate_fc1_nvfp4_scaled_tma256k2_ldmb.py +127 -0
  20. labs/swiglu_nvfp4/native_cuda/gate_fc1_nvfp4_scaled_tma256k2_ldmb_20423.json +16 -0
  21. labs/swiglu_nvfp4/native_cuda/gate_fc1_nvfp4_scaled_tma256k2_leads.py +131 -0
  22. labs/swiglu_nvfp4/native_cuda/gate_fc1_nvfp4_scaled_tma256k2_leads_20423.json +16 -0
  23. labs/swiglu_nvfp4/native_cuda/gate_fc1_nvfp4_scaled_tma256k2_pipe.py +127 -0
  24. labs/swiglu_nvfp4/native_cuda/gate_fc1_nvfp4_scaled_tma256k2_pipe_20423.json +16 -0
  25. labs/swiglu_nvfp4/native_cuda/gate_fc1_nvfp4_scaled_tma256k2_pipea.py +129 -0
  26. labs/swiglu_nvfp4/native_cuda/gate_fc1_nvfp4_scaled_tma256k2_pipea_20423.json +16 -0
  27. labs/swiglu_nvfp4/native_cuda/gate_fc1_nvfp4_scaled_tma256k2_sw.py +170 -0
  28. labs/swiglu_nvfp4/native_cuda/gate_fc1_nvfp4_scaled_tma256k2_sw_20423.json +24 -0
  29. labs/swiglu_nvfp4/native_cuda/gate_fc1_nvfp4_scaled_tma256k2n2.py +94 -0
  30. labs/swiglu_nvfp4/native_cuda/gate_fc1_nvfp4_scaled_tma256k2n2_20423.json +17 -0
  31. labs/swiglu_nvfp4/native_cuda/gate_fc1_nvfp4_scaled_tma256k2p.py +171 -0
  32. labs/swiglu_nvfp4/native_cuda/gate_fc1_nvfp4_scaled_tma256k2p_20423.json +24 -0
  33. labs/swiglu_nvfp4/native_cuda/gate_fc1_nvfp4_scaled_tma256k2s1.py +136 -0
  34. labs/swiglu_nvfp4/native_cuda/gate_fc1_nvfp4_scaled_tma256k2s1_20423.json +22 -0
  35. labs/swiglu_nvfp4/native_cuda/gate_fc1_nvfp4_scaled_tma256k2ws.py +171 -0
  36. labs/swiglu_nvfp4/native_cuda/gate_fc1_nvfp4_scaled_tma256k2ws4.py +142 -0
  37. labs/swiglu_nvfp4/native_cuda/gate_fc1_nvfp4_scaled_tma256k2ws4_20423.json +23 -0
  38. labs/swiglu_nvfp4/native_cuda/gate_fc1_nvfp4_scaled_tma256k2ws_20423.json +24 -0
  39. labs/swiglu_nvfp4/native_cuda/gate_fc1_nvfp4_scaled_tma256k4.py +173 -0
  40. labs/swiglu_nvfp4/native_cuda/gate_fc1_nvfp4_scaled_tma256k4_20423.json +24 -0
  41. labs/swiglu_nvfp4/native_cuda/gate_fc1_nvfp4_scaled_tma256k4n1.py +130 -0
  42. labs/swiglu_nvfp4/native_cuda/gate_fc1_nvfp4_scaled_tma256k4n1_20423.json +17 -0
  43. labs/swiglu_nvfp4/native_cuda/gate_fc1_nvfp4_scaled_tma256n32.py +133 -0
  44. labs/swiglu_nvfp4/native_cuda/gate_fc1_nvfp4_scaled_tma256n32_20423.json +18 -0
  45. labs/swiglu_nvfp4/native_cuda/gate_fc1_nvfp4_scaled_tma_20423.json +24 -0
  46. labs/swiglu_nvfp4/native_cuda/gate_fc1_nvfp4_scaled_tma_sf.py +170 -0
  47. labs/swiglu_nvfp4/native_cuda/gate_fc1_nvfp4_scaled_tma_sf_20423.json +24 -0
  48. labs/swiglu_nvfp4/native_cuda/gate_fc1_nvfp4_tiled.py +138 -0
  49. labs/swiglu_nvfp4/native_cuda/gate_fc1_nvfp4_tiled_20423.json +24 -0
  50. labs/swiglu_nvfp4/native_cuda/gate_fc1_paired.py +125 -0
labs/swiglu_nvfp4/native_cuda/gate_fc1_nvfp4_scaled_tma128n128k4.py ADDED
@@ -0,0 +1,129 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """Byte-exact gate: kitchen 128x128x256 single-N tile == cublasLt.
3
+
4
+ Profiler name: cutlass3x_sm120_..._128x128x256_1x1x1. Pairing both
5
+ arms doubles B smem; this tile holds one N operand. Same m16n8k64.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ import json
11
+ from pathlib import Path
12
+
13
+ import torch
14
+
15
+ import comfy_kitchen as ck
16
+
17
+ from swiglu_nvfp4 import (
18
+ fc1_nvfp4_scaled_tma128n128k4,
19
+ fc1_paired_nvfp4_scaled_tma256k2,
20
+ load_extension,
21
+ )
22
+
23
+
24
+ ROWS = 20423
25
+ K = 5376
26
+ N = 14336
27
+
28
+
29
+ def nvfp4_scale(x: torch.Tensor) -> torch.Tensor:
30
+ return (x.abs().amax() / (6.0 * 448.0)).to(torch.float32).reshape(1)
31
+
32
+
33
+ def kitchen_gemm(qx, sx, qw, sw, scale_x, scale_w) -> torch.Tensor:
34
+ alpha = (scale_x * scale_w).reshape(1)
35
+ y = ck.scaled_mm_nvfp4(
36
+ qx, qw, scale_x, scale_w, sx, sw, out_dtype=torch.bfloat16, alpha=alpha
37
+ )
38
+ return y[:ROWS]
39
+
40
+
41
+ def byte_diff(left: torch.Tensor, right: torch.Tensor) -> int:
42
+ return int((left.view(torch.uint8) != right.view(torch.uint8)).sum().item())
43
+
44
+
45
+ def max_abs_diff(left: torch.Tensor, right: torch.Tensor) -> float:
46
+ return float((left.float() - right.float()).abs().max().item())
47
+
48
+
49
+ def time_ms(fn) -> float:
50
+ starter = torch.cuda.Event(enable_timing=True)
51
+ ender = torch.cuda.Event(enable_timing=True)
52
+ fn()
53
+ torch.cuda.synchronize()
54
+ starter.record()
55
+ fn()
56
+ ender.record()
57
+ torch.cuda.synchronize()
58
+ return starter.elapsed_time(ender)
59
+
60
+
61
+ def main() -> int:
62
+ load_extension(verbose=False)
63
+ device = torch.device("cuda")
64
+ torch.manual_seed(26081250)
65
+ x = torch.randn(ROWS, K, device=device, dtype=torch.bfloat16)
66
+ weight = torch.randn(2 * N, K, device=device, dtype=torch.bfloat16) * 0.02
67
+ sx = nvfp4_scale(x)
68
+ sw = nvfp4_scale(weight)
69
+ qx, qxs = ck.quantize_nvfp4(x, sx, pad_16x=True, hi_first=True)
70
+ qw, qws = ck.quantize_nvfp4(weight, sw, pad_16x=True, hi_first=True)
71
+ qx_live = qx[:ROWS].contiguous()
72
+ alpha = (sx * sw).reshape(1).contiguous()
73
+ kitchen = kitchen_gemm(qx, qxs, qw, qws, sx, sw)
74
+ full = fc1_nvfp4_scaled_tma128n128k4(qx_live, qxs, qw, qws, alpha)
75
+ payload = {
76
+ "identity": (
77
+ "Kitchen 128x128x256 single-N tile == cublasLt on the "
78
+ "m16n8k64 atom. One B operand (not paired arms). 2-stage "
79
+ "K=256. Profiler: 128x128x256_1x1x1 s16864."
80
+ ),
81
+ "kitchen_kernel": (
82
+ "cutlass3x_sm120_bstensorop_s16864gemm_block_scaled_"
83
+ "ue4m3xe2m1_ue4m3xe2m1_f32_bf16_bf16_128x128x256_1x1x1"
84
+ ),
85
+ "rows": ROWS,
86
+ "k": K,
87
+ "n": 2 * N,
88
+ "device": torch.cuda.get_device_name(device),
89
+ "kit_vs_kitchen_mismatches": byte_diff(full, kitchen),
90
+ "kit_vs_kitchen_max_abs": round(max_abs_diff(full, kitchen), 6),
91
+ "full_finite": bool(torch.isfinite(full.float()).all().item()),
92
+ "kitchen_gemm_min_ms": round(
93
+ time_ms(lambda: kitchen_gemm(qx, qxs, qw, qws, sx, sw)), 4
94
+ ),
95
+ "kit_full_min_ms": round(
96
+ time_ms(
97
+ lambda: fc1_nvfp4_scaled_tma128n128k4(
98
+ qx_live, qxs, qw, qws, alpha
99
+ )
100
+ ),
101
+ 4,
102
+ ),
103
+ "k2_prod_min_ms": round(
104
+ time_ms(
105
+ lambda: fc1_paired_nvfp4_scaled_tma256k2(
106
+ qx_live, qxs, qw, qws, alpha, product=True
107
+ )
108
+ ),
109
+ 4,
110
+ ),
111
+ }
112
+ payload["pass"] = (
113
+ payload["kit_vs_kitchen_mismatches"] == 0
114
+ and payload["full_finite"]
115
+ )
116
+ if payload["pass"]:
117
+ payload["vs_kitchen_ms"] = round(
118
+ payload["kitchen_gemm_min_ms"] - payload["kit_full_min_ms"], 4
119
+ )
120
+ text = json.dumps(payload, indent=2, sort_keys=True)
121
+ Path(__file__).with_name(
122
+ "gate_fc1_nvfp4_scaled_tma128n128k4_20423.json"
123
+ ).write_text(text + "\n")
124
+ print(text)
125
+ return 0 if payload["pass"] else 2
126
+
127
+
128
+ if __name__ == "__main__":
129
+ raise SystemExit(main())
labs/swiglu_nvfp4/native_cuda/gate_fc1_nvfp4_scaled_tma128n128k4_20423.json ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "device": "NVIDIA GB10",
3
+ "full_finite": true,
4
+ "identity": "Kitchen 128x128x256 single-N tile == cublasLt on the m16n8k64 atom. One B operand (not paired arms). 2-stage K=256. Profiler: 128x128x256_1x1x1 s16864.",
5
+ "k": 5376,
6
+ "k2_prod_min_ms": 37.0229,
7
+ "kit_full_min_ms": 67.7126,
8
+ "kit_vs_kitchen_max_abs": 0.0,
9
+ "kit_vs_kitchen_mismatches": 0,
10
+ "kitchen_gemm_min_ms": 20.1805,
11
+ "kitchen_kernel": "cutlass3x_sm120_bstensorop_s16864gemm_block_scaled_ue4m3xe2m1_ue4m3xe2m1_f32_bf16_bf16_128x128x256_1x1x1",
12
+ "n": 28672,
13
+ "pass": true,
14
+ "rows": 20423,
15
+ "vs_kitchen_ms": -47.5321
16
+ }
labs/swiglu_nvfp4/native_cuda/gate_fc1_nvfp4_scaled_tma128n128k4_ldm.py ADDED
@@ -0,0 +1,127 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """Byte-exact gate: ldmatrix.x4 A fragment == kitchen group/tidg 4xu32.
3
+
4
+ Probe: ldmatrix from smem[lane&15][(lane>>4)*16] matches the scalar
5
+ kitchen A map (0/32 lanes). Same 128x128x256 single-N tile.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ import json
11
+ from pathlib import Path
12
+
13
+ import torch
14
+
15
+ import comfy_kitchen as ck
16
+
17
+ from swiglu_nvfp4 import (
18
+ fc1_nvfp4_scaled_tma128n128k4,
19
+ fc1_nvfp4_scaled_tma128n128k4_ldm,
20
+ load_extension,
21
+ )
22
+
23
+
24
+ ROWS = 20423
25
+ K = 5376
26
+ N = 14336
27
+
28
+
29
+ def nvfp4_scale(x: torch.Tensor) -> torch.Tensor:
30
+ return (x.abs().amax() / (6.0 * 448.0)).to(torch.float32).reshape(1)
31
+
32
+
33
+ def kitchen_gemm(qx, sx, qw, sw, scale_x, scale_w) -> torch.Tensor:
34
+ alpha = (scale_x * scale_w).reshape(1)
35
+ y = ck.scaled_mm_nvfp4(
36
+ qx, qw, scale_x, scale_w, sx, sw, out_dtype=torch.bfloat16, alpha=alpha
37
+ )
38
+ return y[:ROWS]
39
+
40
+
41
+ def byte_diff(left: torch.Tensor, right: torch.Tensor) -> int:
42
+ return int((left.view(torch.uint8) != right.view(torch.uint8)).sum().item())
43
+
44
+
45
+ def time_ms(fn) -> float:
46
+ starter = torch.cuda.Event(enable_timing=True)
47
+ ender = torch.cuda.Event(enable_timing=True)
48
+ fn()
49
+ torch.cuda.synchronize()
50
+ starter.record()
51
+ fn()
52
+ ender.record()
53
+ torch.cuda.synchronize()
54
+ return starter.elapsed_time(ender)
55
+
56
+
57
+ def main() -> int:
58
+ load_extension(verbose=False)
59
+ device = torch.device("cuda")
60
+ torch.manual_seed(26081261)
61
+ x = torch.randn(ROWS, K, device=device, dtype=torch.bfloat16)
62
+ weight = torch.randn(2 * N, K, device=device, dtype=torch.bfloat16) * 0.02
63
+ sx = nvfp4_scale(x)
64
+ sw = nvfp4_scale(weight)
65
+ qx, qxs = ck.quantize_nvfp4(x, sx, pad_16x=True, hi_first=True)
66
+ qw, qws = ck.quantize_nvfp4(weight, sw, pad_16x=True, hi_first=True)
67
+ qx_live = qx[:ROWS].contiguous()
68
+ alpha = (sx * sw).reshape(1).contiguous()
69
+ kitchen = kitchen_gemm(qx, qxs, qw, qws, sx, sw)
70
+ linear = fc1_nvfp4_scaled_tma128n128k4(qx_live, qxs, qw, qws, alpha)
71
+ ldm = fc1_nvfp4_scaled_tma128n128k4_ldm(qx_live, qxs, qw, qws, alpha)
72
+ payload = {
73
+ "identity": (
74
+ "ldmatrix.x4 from smem[lane&15][(lane>>4)*16] == kitchen "
75
+ "group/tidg A fragment on 128x128x256. Probe 0/32. Not "
76
+ "the unit-scale consecutive-K uint4 map (that skips "
77
+ "ldmatrix redistribute)."
78
+ ),
79
+ "rows": ROWS,
80
+ "k": K,
81
+ "n": 2 * N,
82
+ "device": torch.cuda.get_device_name(device),
83
+ "ldm_vs_kitchen_mismatches": byte_diff(ldm, kitchen),
84
+ "ldm_vs_linear_mismatches": byte_diff(ldm, linear),
85
+ "full_finite": bool(torch.isfinite(ldm.float()).all().item()),
86
+ "kitchen_gemm_min_ms": round(
87
+ time_ms(lambda: kitchen_gemm(qx, qxs, qw, qws, sx, sw)), 4
88
+ ),
89
+ "ldm_full_min_ms": round(
90
+ time_ms(
91
+ lambda: fc1_nvfp4_scaled_tma128n128k4_ldm(
92
+ qx_live, qxs, qw, qws, alpha
93
+ )
94
+ ),
95
+ 4,
96
+ ),
97
+ "linear_full_min_ms": round(
98
+ time_ms(
99
+ lambda: fc1_nvfp4_scaled_tma128n128k4(
100
+ qx_live, qxs, qw, qws, alpha
101
+ )
102
+ ),
103
+ 4,
104
+ ),
105
+ }
106
+ payload["pass"] = (
107
+ payload["ldm_vs_kitchen_mismatches"] == 0
108
+ and payload["ldm_vs_linear_mismatches"] == 0
109
+ and payload["full_finite"]
110
+ )
111
+ if payload["pass"]:
112
+ payload["vs_kitchen_ms"] = round(
113
+ payload["kitchen_gemm_min_ms"] - payload["ldm_full_min_ms"], 4
114
+ )
115
+ payload["vs_linear_ms"] = round(
116
+ payload["linear_full_min_ms"] - payload["ldm_full_min_ms"], 4
117
+ )
118
+ text = json.dumps(payload, indent=2, sort_keys=True)
119
+ Path(__file__).with_name(
120
+ "gate_fc1_nvfp4_scaled_tma128n128k4_ldm_20423.json"
121
+ ).write_text(text + "\n")
122
+ print(text)
123
+ return 0 if payload["pass"] else 2
124
+
125
+
126
+ if __name__ == "__main__":
127
+ raise SystemExit(main())
labs/swiglu_nvfp4/native_cuda/gate_fc1_nvfp4_scaled_tma128n128k4_ldm_20423.json ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "device": "NVIDIA GB10",
3
+ "full_finite": true,
4
+ "identity": "ldmatrix.x4 from smem[lane&15][(lane>>4)*16] == kitchen group/tidg A fragment on 128x128x256. Probe 0/32. Not the unit-scale consecutive-K uint4 map (that skips ldmatrix redistribute).",
5
+ "k": 5376,
6
+ "kitchen_gemm_min_ms": 20.3012,
7
+ "ldm_full_min_ms": 67.9157,
8
+ "ldm_vs_kitchen_mismatches": 0,
9
+ "ldm_vs_linear_mismatches": 0,
10
+ "linear_full_min_ms": 67.9085,
11
+ "n": 28672,
12
+ "pass": true,
13
+ "rows": 20423,
14
+ "vs_kitchen_ms": -47.6145,
15
+ "vs_linear_ms": -0.0072
16
+ }
labs/swiglu_nvfp4/native_cuda/gate_fc1_nvfp4_scaled_tma128n128k4_pipe.py ADDED
@@ -0,0 +1,126 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """Byte-exact gate: software-pipelined B fragments == kitchen tile.
3
+
4
+ Next N-subtile B/SFB loads overlap the current m16n8k64. Same
5
+ 128x128x256 single-N atom as the linear clone.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ import json
11
+ from pathlib import Path
12
+
13
+ import torch
14
+
15
+ import comfy_kitchen as ck
16
+
17
+ from swiglu_nvfp4 import (
18
+ fc1_nvfp4_scaled_tma128n128k4,
19
+ fc1_nvfp4_scaled_tma128n128k4_pipe,
20
+ load_extension,
21
+ )
22
+
23
+
24
+ ROWS = 20423
25
+ K = 5376
26
+ N = 14336
27
+
28
+
29
+ def nvfp4_scale(x: torch.Tensor) -> torch.Tensor:
30
+ return (x.abs().amax() / (6.0 * 448.0)).to(torch.float32).reshape(1)
31
+
32
+
33
+ def kitchen_gemm(qx, sx, qw, sw, scale_x, scale_w) -> torch.Tensor:
34
+ alpha = (scale_x * scale_w).reshape(1)
35
+ y = ck.scaled_mm_nvfp4(
36
+ qx, qw, scale_x, scale_w, sx, sw, out_dtype=torch.bfloat16, alpha=alpha
37
+ )
38
+ return y[:ROWS]
39
+
40
+
41
+ def byte_diff(left: torch.Tensor, right: torch.Tensor) -> int:
42
+ return int((left.view(torch.uint8) != right.view(torch.uint8)).sum().item())
43
+
44
+
45
+ def time_ms(fn) -> float:
46
+ starter = torch.cuda.Event(enable_timing=True)
47
+ ender = torch.cuda.Event(enable_timing=True)
48
+ fn()
49
+ torch.cuda.synchronize()
50
+ starter.record()
51
+ fn()
52
+ ender.record()
53
+ torch.cuda.synchronize()
54
+ return starter.elapsed_time(ender)
55
+
56
+
57
+ def main() -> int:
58
+ load_extension(verbose=False)
59
+ device = torch.device("cuda")
60
+ torch.manual_seed(26081259)
61
+ x = torch.randn(ROWS, K, device=device, dtype=torch.bfloat16)
62
+ weight = torch.randn(2 * N, K, device=device, dtype=torch.bfloat16) * 0.02
63
+ sx = nvfp4_scale(x)
64
+ sw = nvfp4_scale(weight)
65
+ qx, qxs = ck.quantize_nvfp4(x, sx, pad_16x=True, hi_first=True)
66
+ qw, qws = ck.quantize_nvfp4(weight, sw, pad_16x=True, hi_first=True)
67
+ qx_live = qx[:ROWS].contiguous()
68
+ alpha = (sx * sw).reshape(1).contiguous()
69
+ kitchen = kitchen_gemm(qx, qxs, qw, qws, sx, sw)
70
+ linear = fc1_nvfp4_scaled_tma128n128k4(qx_live, qxs, qw, qws, alpha)
71
+ piped = fc1_nvfp4_scaled_tma128n128k4_pipe(qx_live, qxs, qw, qws, alpha)
72
+ payload = {
73
+ "identity": (
74
+ "Software-pipelined B fragments on 128x128x256 == linear "
75
+ "clone == kitchen. Next N-subtile B/SFB overlaps m16n8k64. "
76
+ "Same atom and tile; ILP only."
77
+ ),
78
+ "rows": ROWS,
79
+ "k": K,
80
+ "n": 2 * N,
81
+ "device": torch.cuda.get_device_name(device),
82
+ "pipe_vs_kitchen_mismatches": byte_diff(piped, kitchen),
83
+ "pipe_vs_linear_mismatches": byte_diff(piped, linear),
84
+ "full_finite": bool(torch.isfinite(piped.float()).all().item()),
85
+ "kitchen_gemm_min_ms": round(
86
+ time_ms(lambda: kitchen_gemm(qx, qxs, qw, qws, sx, sw)), 4
87
+ ),
88
+ "pipe_full_min_ms": round(
89
+ time_ms(
90
+ lambda: fc1_nvfp4_scaled_tma128n128k4_pipe(
91
+ qx_live, qxs, qw, qws, alpha
92
+ )
93
+ ),
94
+ 4,
95
+ ),
96
+ "linear_full_min_ms": round(
97
+ time_ms(
98
+ lambda: fc1_nvfp4_scaled_tma128n128k4(
99
+ qx_live, qxs, qw, qws, alpha
100
+ )
101
+ ),
102
+ 4,
103
+ ),
104
+ }
105
+ payload["pass"] = (
106
+ payload["pipe_vs_kitchen_mismatches"] == 0
107
+ and payload["pipe_vs_linear_mismatches"] == 0
108
+ and payload["full_finite"]
109
+ )
110
+ if payload["pass"]:
111
+ payload["vs_kitchen_ms"] = round(
112
+ payload["kitchen_gemm_min_ms"] - payload["pipe_full_min_ms"], 4
113
+ )
114
+ payload["vs_linear_ms"] = round(
115
+ payload["linear_full_min_ms"] - payload["pipe_full_min_ms"], 4
116
+ )
117
+ text = json.dumps(payload, indent=2, sort_keys=True)
118
+ Path(__file__).with_name(
119
+ "gate_fc1_nvfp4_scaled_tma128n128k4_pipe_20423.json"
120
+ ).write_text(text + "\n")
121
+ print(text)
122
+ return 0 if payload["pass"] else 2
123
+
124
+
125
+ if __name__ == "__main__":
126
+ raise SystemExit(main())
labs/swiglu_nvfp4/native_cuda/gate_fc1_nvfp4_scaled_tma128n128k4_pipe_20423.json ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "device": "NVIDIA GB10",
3
+ "full_finite": true,
4
+ "identity": "Software-pipelined B fragments on 128x128x256 == linear clone == kitchen. Next N-subtile B/SFB overlaps m16n8k64. Same atom and tile; ILP only.",
5
+ "k": 5376,
6
+ "kitchen_gemm_min_ms": 20.2951,
7
+ "linear_full_min_ms": 67.6802,
8
+ "n": 28672,
9
+ "pass": true,
10
+ "pipe_full_min_ms": 67.5507,
11
+ "pipe_vs_kitchen_mismatches": 0,
12
+ "pipe_vs_linear_mismatches": 0,
13
+ "rows": 20423,
14
+ "vs_kitchen_ms": -47.2556,
15
+ "vs_linear_ms": 0.1295
16
+ }
labs/swiglu_nvfp4/native_cuda/gate_fc1_nvfp4_scaled_tma128n128k4_sw.py ADDED
@@ -0,0 +1,134 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """Byte-exact gate: SWIZZLE_128B remapped on the 128-byte K-row.
3
+
4
+ phys_col = col XOR ((row & 7) << 4). Measured on sm_121a. Same
5
+ 128x128x256 single-N m16n8k64 tile as the linear kitchen clone.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ import json
11
+ from pathlib import Path
12
+
13
+ import torch
14
+
15
+ import comfy_kitchen as ck
16
+
17
+ from swiglu_nvfp4 import (
18
+ fc1_nvfp4_scaled_tma128n128k4,
19
+ fc1_nvfp4_scaled_tma128n128k4_sw,
20
+ load_extension,
21
+ )
22
+
23
+
24
+ ROWS = 20423
25
+ K = 5376
26
+ N = 14336
27
+
28
+
29
+ def nvfp4_scale(x: torch.Tensor) -> torch.Tensor:
30
+ return (x.abs().amax() / (6.0 * 448.0)).to(torch.float32).reshape(1)
31
+
32
+
33
+ def kitchen_gemm(qx, sx, qw, sw, scale_x, scale_w) -> torch.Tensor:
34
+ alpha = (scale_x * scale_w).reshape(1)
35
+ y = ck.scaled_mm_nvfp4(
36
+ qx, qw, scale_x, scale_w, sx, sw, out_dtype=torch.bfloat16, alpha=alpha
37
+ )
38
+ return y[:ROWS]
39
+
40
+
41
+ def byte_diff(left: torch.Tensor, right: torch.Tensor) -> int:
42
+ return int((left.view(torch.uint8) != right.view(torch.uint8)).sum().item())
43
+
44
+
45
+ def max_abs_diff(left: torch.Tensor, right: torch.Tensor) -> float:
46
+ return float((left.float() - right.float()).abs().max().item())
47
+
48
+
49
+ def time_ms(fn) -> float:
50
+ starter = torch.cuda.Event(enable_timing=True)
51
+ ender = torch.cuda.Event(enable_timing=True)
52
+ fn()
53
+ torch.cuda.synchronize()
54
+ starter.record()
55
+ fn()
56
+ ender.record()
57
+ torch.cuda.synchronize()
58
+ return starter.elapsed_time(ender)
59
+
60
+
61
+ def main() -> int:
62
+ load_extension(verbose=False)
63
+ device = torch.device("cuda")
64
+ torch.manual_seed(26081256)
65
+ x = torch.randn(ROWS, K, device=device, dtype=torch.bfloat16)
66
+ weight = torch.randn(2 * N, K, device=device, dtype=torch.bfloat16) * 0.02
67
+ sx = nvfp4_scale(x)
68
+ sw = nvfp4_scale(weight)
69
+ qx, qxs = ck.quantize_nvfp4(x, sx, pad_16x=True, hi_first=True)
70
+ qw, qws = ck.quantize_nvfp4(weight, sw, pad_16x=True, hi_first=True)
71
+ qx_live = qx[:ROWS].contiguous()
72
+ alpha = (sx * sw).reshape(1).contiguous()
73
+ kitchen = kitchen_gemm(qx, qxs, qw, qws, sx, sw)
74
+ linear = fc1_nvfp4_scaled_tma128n128k4(qx_live, qxs, qw, qws, alpha)
75
+ swiz = fc1_nvfp4_scaled_tma128n128k4_sw(qx_live, qxs, qw, qws, alpha)
76
+ payload = {
77
+ "identity": (
78
+ "SWIZZLE_128B TMA == linear fragment under "
79
+ "phys_col = col XOR ((row&7)<<4) on the 128-byte K-row "
80
+ "of the 128x128x256 single-N m16n8k64 tile. Map measured "
81
+ "on sm_121a (probe_swizzle128, 0/16384)."
82
+ ),
83
+ "rows": ROWS,
84
+ "k": K,
85
+ "n": 2 * N,
86
+ "device": torch.cuda.get_device_name(device),
87
+ "xor_map": "col XOR ((row & 7) << 4)",
88
+ "sw_vs_kitchen_mismatches": byte_diff(swiz, kitchen),
89
+ "sw_vs_kitchen_max_abs": round(max_abs_diff(swiz, kitchen), 6),
90
+ "sw_vs_linear_mismatches": byte_diff(swiz, linear),
91
+ "sw_vs_linear_max_abs": round(max_abs_diff(swiz, linear), 6),
92
+ "full_finite": bool(torch.isfinite(swiz.float()).all().item()),
93
+ "kitchen_gemm_min_ms": round(
94
+ time_ms(lambda: kitchen_gemm(qx, qxs, qw, qws, sx, sw)), 4
95
+ ),
96
+ "sw_full_min_ms": round(
97
+ time_ms(
98
+ lambda: fc1_nvfp4_scaled_tma128n128k4_sw(
99
+ qx_live, qxs, qw, qws, alpha
100
+ )
101
+ ),
102
+ 4,
103
+ ),
104
+ "linear_full_min_ms": round(
105
+ time_ms(
106
+ lambda: fc1_nvfp4_scaled_tma128n128k4(
107
+ qx_live, qxs, qw, qws, alpha
108
+ )
109
+ ),
110
+ 4,
111
+ ),
112
+ }
113
+ payload["pass"] = (
114
+ payload["sw_vs_kitchen_mismatches"] == 0
115
+ and payload["sw_vs_linear_mismatches"] == 0
116
+ and payload["full_finite"]
117
+ )
118
+ if payload["pass"]:
119
+ payload["vs_kitchen_ms"] = round(
120
+ payload["kitchen_gemm_min_ms"] - payload["sw_full_min_ms"], 4
121
+ )
122
+ payload["vs_linear_ms"] = round(
123
+ payload["linear_full_min_ms"] - payload["sw_full_min_ms"], 4
124
+ )
125
+ text = json.dumps(payload, indent=2, sort_keys=True)
126
+ Path(__file__).with_name(
127
+ "gate_fc1_nvfp4_scaled_tma128n128k4_sw_20423.json"
128
+ ).write_text(text + "\n")
129
+ print(text)
130
+ return 0 if payload["pass"] else 2
131
+
132
+
133
+ if __name__ == "__main__":
134
+ raise SystemExit(main())
labs/swiglu_nvfp4/native_cuda/gate_fc1_nvfp4_scaled_tma128n128k4_sw_20423.json ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "device": "NVIDIA GB10",
3
+ "full_finite": true,
4
+ "identity": "SWIZZLE_128B TMA == linear fragment under phys_col = col XOR ((row&7)<<4) on the 128-byte K-row of the 128x128x256 single-N m16n8k64 tile. Map measured on sm_121a (probe_swizzle128, 0/16384).",
5
+ "k": 5376,
6
+ "kitchen_gemm_min_ms": 20.1582,
7
+ "linear_full_min_ms": 67.5818,
8
+ "n": 28672,
9
+ "pass": true,
10
+ "rows": 20423,
11
+ "sw_full_min_ms": 66.6565,
12
+ "sw_vs_kitchen_max_abs": 0.0,
13
+ "sw_vs_kitchen_mismatches": 0,
14
+ "sw_vs_linear_max_abs": 0.0,
15
+ "sw_vs_linear_mismatches": 0,
16
+ "vs_kitchen_ms": -46.4983,
17
+ "vs_linear_ms": 0.9253,
18
+ "xor_map": "col XOR ((row & 7) << 4)"
19
+ }
labs/swiglu_nvfp4/native_cuda/gate_fc1_nvfp4_scaled_tma128n128k4ws.py ADDED
@@ -0,0 +1,138 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """Byte-exact gate: 12-warp 128x128x256 == kitchen / 8-warp clone.
3
+
4
+ Kitchen launches 384 threads, 88064 B dynamic smem. Four producer
5
+ warps issue A/B/SFA/SFB; eight MMA warps keep the m16n8k64 atom.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ import json
11
+ from pathlib import Path
12
+
13
+ import torch
14
+
15
+ import comfy_kitchen as ck
16
+
17
+ from swiglu_nvfp4 import (
18
+ fc1_nvfp4_scaled_tma128n128k4,
19
+ fc1_nvfp4_scaled_tma128n128k4ws,
20
+ fc1_nvfp4_scaled_tma128n128k4ws_attrs,
21
+ load_extension,
22
+ )
23
+
24
+
25
+ ROWS = 20423
26
+ K = 5376
27
+ N = 14336
28
+
29
+
30
+ def nvfp4_scale(x: torch.Tensor) -> torch.Tensor:
31
+ return (x.abs().amax() / (6.0 * 448.0)).to(torch.float32).reshape(1)
32
+
33
+
34
+ def kitchen_gemm(qx, sx, qw, sw, scale_x, scale_w) -> torch.Tensor:
35
+ alpha = (scale_x * scale_w).reshape(1)
36
+ y = ck.scaled_mm_nvfp4(
37
+ qx, qw, scale_x, scale_w, sx, sw, out_dtype=torch.bfloat16, alpha=alpha
38
+ )
39
+ return y[:ROWS]
40
+
41
+
42
+ def byte_diff(left: torch.Tensor, right: torch.Tensor) -> int:
43
+ return int((left.view(torch.uint8) != right.view(torch.uint8)).sum().item())
44
+
45
+
46
+ def max_abs_diff(left: torch.Tensor, right: torch.Tensor) -> float:
47
+ return float((left.float() - right.float()).abs().max().item())
48
+
49
+
50
+ def time_ms(fn) -> float:
51
+ starter = torch.cuda.Event(enable_timing=True)
52
+ ender = torch.cuda.Event(enable_timing=True)
53
+ fn()
54
+ torch.cuda.synchronize()
55
+ starter.record()
56
+ fn()
57
+ ender.record()
58
+ torch.cuda.synchronize()
59
+ return starter.elapsed_time(ender)
60
+
61
+
62
+ def main() -> int:
63
+ load_extension(verbose=False)
64
+ device = torch.device("cuda")
65
+ torch.manual_seed(26081255)
66
+ x = torch.randn(ROWS, K, device=device, dtype=torch.bfloat16)
67
+ weight = torch.randn(2 * N, K, device=device, dtype=torch.bfloat16) * 0.02
68
+ sx = nvfp4_scale(x)
69
+ sw = nvfp4_scale(weight)
70
+ qx, qxs = ck.quantize_nvfp4(x, sx, pad_16x=True, hi_first=True)
71
+ qw, qws = ck.quantize_nvfp4(weight, sw, pad_16x=True, hi_first=True)
72
+ qx_live = qx[:ROWS].contiguous()
73
+ alpha = (sx * sw).reshape(1).contiguous()
74
+ kitchen = kitchen_gemm(qx, qxs, qw, qws, sx, sw)
75
+ clone8 = fc1_nvfp4_scaled_tma128n128k4(qx_live, qxs, qw, qws, alpha)
76
+ ws = fc1_nvfp4_scaled_tma128n128k4ws(qx_live, qxs, qw, qws, alpha)
77
+ attrs = fc1_nvfp4_scaled_tma128n128k4ws_attrs()
78
+ payload = {
79
+ "identity": (
80
+ "Kitchen 128x128x256 12-warp launch: 4 producer warps "
81
+ "issue A/B/SFA/SFB TMA; 8 MMA warps keep the m16n8k64 "
82
+ "atom and 16x4 acc. 88064 B dynamic smem. Same tile as "
83
+ "the 8-warp clone (already byte-exact)."
84
+ ),
85
+ "rows": ROWS,
86
+ "k": K,
87
+ "n": 2 * N,
88
+ "device": torch.cuda.get_device_name(device),
89
+ "launch": attrs,
90
+ "ws_vs_kitchen_mismatches": byte_diff(ws, kitchen),
91
+ "ws_vs_kitchen_max_abs": round(max_abs_diff(ws, kitchen), 6),
92
+ "ws_vs_clone8_mismatches": byte_diff(ws, clone8),
93
+ "ws_vs_clone8_max_abs": round(max_abs_diff(ws, clone8), 6),
94
+ "full_finite": bool(torch.isfinite(ws.float()).all().item()),
95
+ "kitchen_gemm_min_ms": round(
96
+ time_ms(lambda: kitchen_gemm(qx, qxs, qw, qws, sx, sw)), 4
97
+ ),
98
+ "ws_full_min_ms": round(
99
+ time_ms(
100
+ lambda: fc1_nvfp4_scaled_tma128n128k4ws(
101
+ qx_live, qxs, qw, qws, alpha
102
+ )
103
+ ),
104
+ 4,
105
+ ),
106
+ "clone8_full_min_ms": round(
107
+ time_ms(
108
+ lambda: fc1_nvfp4_scaled_tma128n128k4(
109
+ qx_live, qxs, qw, qws, alpha
110
+ )
111
+ ),
112
+ 4,
113
+ ),
114
+ }
115
+ payload["pass"] = (
116
+ payload["ws_vs_kitchen_mismatches"] == 0
117
+ and payload["ws_vs_clone8_mismatches"] == 0
118
+ and payload["full_finite"]
119
+ and int(attrs["threads"]) == 384
120
+ and int(attrs["dynamic_smem"]) == 88064
121
+ )
122
+ if payload["pass"]:
123
+ payload["vs_kitchen_ms"] = round(
124
+ payload["kitchen_gemm_min_ms"] - payload["ws_full_min_ms"], 4
125
+ )
126
+ payload["vs_clone8_ms"] = round(
127
+ payload["clone8_full_min_ms"] - payload["ws_full_min_ms"], 4
128
+ )
129
+ text = json.dumps(payload, indent=2, sort_keys=True)
130
+ Path(__file__).with_name(
131
+ "gate_fc1_nvfp4_scaled_tma128n128k4ws_20423.json"
132
+ ).write_text(text + "\n")
133
+ print(text)
134
+ return 0 if payload["pass"] else 2
135
+
136
+
137
+ if __name__ == "__main__":
138
+ raise SystemExit(main())
labs/swiglu_nvfp4/native_cuda/gate_fc1_nvfp4_scaled_tma128n128k4ws_20423.json ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "clone8_full_min_ms": 68.3289,
3
+ "device": "NVIDIA GB10",
4
+ "full_finite": true,
5
+ "identity": "Kitchen 128x128x256 12-warp launch: 4 producer warps issue A/B/SFA/SFB TMA; 8 MMA warps keep the m16n8k64 atom and 16x4 acc. 88064 B dynamic smem. Same tile as the 8-warp clone (already byte-exact).",
6
+ "k": 5376,
7
+ "kitchen_gemm_min_ms": 20.134,
8
+ "launch": {
9
+ "dynamic_smem": 88064,
10
+ "local_size_bytes": 8,
11
+ "max_dynamic_shared_size_bytes": 88064,
12
+ "mma_warps": 8,
13
+ "num_regs": 150,
14
+ "producer_warps": 4,
15
+ "shared_size_bytes": 0,
16
+ "smem_struct_bytes": 73856,
17
+ "threads": 384,
18
+ "warps": 12
19
+ },
20
+ "n": 28672,
21
+ "pass": true,
22
+ "rows": 20423,
23
+ "vs_clone8_ms": 0.9203,
24
+ "vs_kitchen_ms": -47.2746,
25
+ "ws_full_min_ms": 67.4086,
26
+ "ws_vs_clone8_max_abs": 0.0,
27
+ "ws_vs_clone8_mismatches": 0,
28
+ "ws_vs_kitchen_max_abs": 0.0,
29
+ "ws_vs_kitchen_mismatches": 0
30
+ }
labs/swiglu_nvfp4/native_cuda/gate_fc1_nvfp4_scaled_tma256.py ADDED
@@ -0,0 +1,170 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """Byte-exact gate: TMA 256x64 3-stage NVFP4 paired-N vs kitchen.
3
+
4
+ Same PTX fragment + cuBLAS 128x4 scale slabs. Launch structure: larger
5
+ M tile (two scale slabs) and a 3-stage TMA K pipeline.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ import json
11
+ from pathlib import Path
12
+
13
+ import torch
14
+ import torch.nn.functional as F
15
+
16
+ import comfy_kitchen as ck
17
+
18
+ from swiglu_nvfp4 import (
19
+ bf16_nvfp4_dynamic,
20
+ fc1_paired_nvfp4_scaled_tma256,
21
+ fc1_paired_nvfp4_scaled_tma_sf,
22
+ load_extension,
23
+ swiglu_nvfp4_dynamic,
24
+ )
25
+
26
+
27
+ ROWS = 20423
28
+ K = 5376
29
+ N = 14336
30
+
31
+
32
+ def nvfp4_scale(x: torch.Tensor) -> torch.Tensor:
33
+ return (x.abs().amax() / (6.0 * 448.0)).to(torch.float32).reshape(1)
34
+
35
+
36
+ def kitchen_gemm(qx, sx, qw, sw, scale_x, scale_w) -> torch.Tensor:
37
+ alpha = (scale_x * scale_w).reshape(1)
38
+ y = ck.scaled_mm_nvfp4(
39
+ qx, qw, scale_x, scale_w, sx, sw, out_dtype=torch.bfloat16, alpha=alpha
40
+ )
41
+ return y[:ROWS]
42
+
43
+
44
+ def eager_act(raw: torch.Tensor) -> torch.Tensor:
45
+ gate, up = raw.chunk(2, dim=-1)
46
+ return F.silu(gate).mul_(up)
47
+
48
+
49
+ def byte_diff(left: torch.Tensor, right: torch.Tensor) -> int:
50
+ return int((left.view(torch.uint8) != right.view(torch.uint8)).sum().item())
51
+
52
+
53
+ def max_abs_diff(left: torch.Tensor, right: torch.Tensor) -> float:
54
+ return float((left.float() - right.float()).abs().max().item())
55
+
56
+
57
+ def time_ms(fn) -> float:
58
+ starter = torch.cuda.Event(enable_timing=True)
59
+ ender = torch.cuda.Event(enable_timing=True)
60
+ fn()
61
+ torch.cuda.synchronize()
62
+ starter.record()
63
+ fn()
64
+ ender.record()
65
+ torch.cuda.synchronize()
66
+ return starter.elapsed_time(ender)
67
+
68
+
69
+ def main() -> int:
70
+ load_extension(verbose=False)
71
+ device = torch.device("cuda")
72
+ torch.manual_seed(26081240)
73
+ x = torch.randn(ROWS, K, device=device, dtype=torch.bfloat16)
74
+ weight = torch.randn(2 * N, K, device=device, dtype=torch.bfloat16) * 0.02
75
+ sx = nvfp4_scale(x)
76
+ sw = nvfp4_scale(weight)
77
+ qx, qxs = ck.quantize_nvfp4(x, sx, pad_16x=True, hi_first=True)
78
+ qw, qws = ck.quantize_nvfp4(weight, sw, pad_16x=True, hi_first=True)
79
+ qx_live = qx[:ROWS].contiguous()
80
+ alpha = (sx * sw).reshape(1).contiguous()
81
+ kitchen = kitchen_gemm(qx, qxs, qw, qws, sx, sw)
82
+ full = fc1_paired_nvfp4_scaled_tma256(
83
+ qx_live, qxs, qw, qws, alpha, product=False
84
+ )
85
+ prod = fc1_paired_nvfp4_scaled_tma256(
86
+ qx_live, qxs, qw, qws, alpha, product=True
87
+ )
88
+ sf = fc1_paired_nvfp4_scaled_tma_sf(
89
+ qx_live, qxs, qw, qws, alpha, product=True
90
+ )
91
+ eager_kit = eager_act(kitchen.contiguous())
92
+ eager_full = eager_act(full)
93
+ two_q, two_s, two_g = swiglu_nvfp4_dynamic(kitchen.contiguous())
94
+ prod_q, prod_s, prod_g = bf16_nvfp4_dynamic(prod)
95
+ payload = {
96
+ "identity": (
97
+ "256x64 3-stage TMA on the kitchen-legal m16n8k64 atom: "
98
+ "two 128x4 scale slabs cover 256 M; K pipeline depth 3; "
99
+ "same PTX fragment, UE4M3 map, and eager product"
100
+ ),
101
+ "rows": ROWS,
102
+ "k": K,
103
+ "n": N,
104
+ "device": torch.cuda.get_device_name(device),
105
+ "t256_full_vs_kitchen_mismatches": byte_diff(full, kitchen),
106
+ "t256_full_vs_kitchen_max_abs": round(max_abs_diff(full, kitchen), 6),
107
+ "t256_prod_vs_sf_prod": byte_diff(prod, sf),
108
+ "product_vs_eager_full_mismatches": byte_diff(prod, eager_full),
109
+ "product_vs_eager_kitchen_mismatches": byte_diff(prod, eager_kit),
110
+ "from_product_vs_kitchen_q": byte_diff(prod_q, two_q),
111
+ "from_product_vs_kitchen_s": byte_diff(prod_s, two_s),
112
+ "from_product_vs_kitchen_scale_exact": bool(torch.equal(prod_g, two_g)),
113
+ "full_finite": bool(torch.isfinite(full.float()).all().item()),
114
+ "prod_finite": bool(torch.isfinite(prod.float()).all().item()),
115
+ "kitchen_gemm_min_ms": round(
116
+ time_ms(lambda: kitchen_gemm(qx, qxs, qw, qws, sx, sw)), 4
117
+ ),
118
+ "t256_full_min_ms": round(
119
+ time_ms(
120
+ lambda: fc1_paired_nvfp4_scaled_tma256(
121
+ qx_live, qxs, qw, qws, alpha, product=False
122
+ )
123
+ ),
124
+ 4,
125
+ ),
126
+ "t256_prod_min_ms": round(
127
+ time_ms(
128
+ lambda: fc1_paired_nvfp4_scaled_tma256(
129
+ qx_live, qxs, qw, qws, alpha, product=True
130
+ )
131
+ ),
132
+ 4,
133
+ ),
134
+ "sf_prod_min_ms": round(
135
+ time_ms(
136
+ lambda: fc1_paired_nvfp4_scaled_tma_sf(
137
+ qx_live, qxs, qw, qws, alpha, product=True
138
+ )
139
+ ),
140
+ 4,
141
+ ),
142
+ "from_product_min_ms": round(
143
+ time_ms(lambda: bf16_nvfp4_dynamic(prod)), 4
144
+ ),
145
+ }
146
+ payload["pass"] = (
147
+ payload["t256_full_vs_kitchen_mismatches"] == 0
148
+ and payload["t256_prod_vs_sf_prod"] == 0
149
+ and payload["product_vs_eager_full_mismatches"] == 0
150
+ and payload["product_vs_eager_kitchen_mismatches"] == 0
151
+ and payload["from_product_vs_kitchen_q"] == 0
152
+ and payload["from_product_vs_kitchen_s"] == 0
153
+ and payload["from_product_vs_kitchen_scale_exact"]
154
+ and payload["full_finite"]
155
+ and payload["prod_finite"]
156
+ )
157
+ if payload["pass"]:
158
+ payload["vs_sf_ms"] = round(
159
+ payload["sf_prod_min_ms"] - payload["t256_prod_min_ms"], 4
160
+ )
161
+ text = json.dumps(payload, indent=2, sort_keys=True)
162
+ Path(__file__).with_name(
163
+ "gate_fc1_nvfp4_scaled_tma256_20423.json"
164
+ ).write_text(text + "\n")
165
+ print(text)
166
+ return 0 if payload["pass"] else 2
167
+
168
+
169
+ if __name__ == "__main__":
170
+ raise SystemExit(main())
labs/swiglu_nvfp4/native_cuda/gate_fc1_nvfp4_scaled_tma256_20423.json ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "device": "NVIDIA GB10",
3
+ "from_product_min_ms": 5.7456,
4
+ "from_product_vs_kitchen_q": 0,
5
+ "from_product_vs_kitchen_s": 0,
6
+ "from_product_vs_kitchen_scale_exact": true,
7
+ "full_finite": true,
8
+ "identity": "256x64 3-stage TMA on the kitchen-legal m16n8k64 atom: two 128x4 scale slabs cover 256 M; K pipeline depth 3; same PTX fragment, UE4M3 map, and eager product",
9
+ "k": 5376,
10
+ "kitchen_gemm_min_ms": 20.2712,
11
+ "n": 14336,
12
+ "pass": true,
13
+ "prod_finite": true,
14
+ "product_vs_eager_full_mismatches": 0,
15
+ "product_vs_eager_kitchen_mismatches": 0,
16
+ "rows": 20423,
17
+ "sf_prod_min_ms": 105.2268,
18
+ "t256_full_min_ms": 57.507,
19
+ "t256_full_vs_kitchen_max_abs": 0.0,
20
+ "t256_full_vs_kitchen_mismatches": 0,
21
+ "t256_prod_min_ms": 54.7271,
22
+ "t256_prod_vs_sf_prod": 0,
23
+ "vs_sf_ms": 50.4997
24
+ }
labs/swiglu_nvfp4/native_cuda/gate_fc1_nvfp4_scaled_tma256_sw.py ADDED
@@ -0,0 +1,170 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """Byte-exact gate: SWIZZLE_32B TMA remapped to the PTX fragment.
3
+
4
+ Same 256x64 3-stage atom. TMA writes 16B chunks swizzled inside each
5
+ 32B row; loads XOR ((row&1)<<4) to recover the linear fragment.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ import json
11
+ from pathlib import Path
12
+
13
+ import torch
14
+ import torch.nn.functional as F
15
+
16
+ import comfy_kitchen as ck
17
+
18
+ from swiglu_nvfp4 import (
19
+ bf16_nvfp4_dynamic,
20
+ fc1_paired_nvfp4_scaled_tma256,
21
+ fc1_paired_nvfp4_scaled_tma256_sw,
22
+ load_extension,
23
+ swiglu_nvfp4_dynamic,
24
+ )
25
+
26
+
27
+ ROWS = 20423
28
+ K = 5376
29
+ N = 14336
30
+
31
+
32
+ def nvfp4_scale(x: torch.Tensor) -> torch.Tensor:
33
+ return (x.abs().amax() / (6.0 * 448.0)).to(torch.float32).reshape(1)
34
+
35
+
36
+ def kitchen_gemm(qx, sx, qw, sw, scale_x, scale_w) -> torch.Tensor:
37
+ alpha = (scale_x * scale_w).reshape(1)
38
+ y = ck.scaled_mm_nvfp4(
39
+ qx, qw, scale_x, scale_w, sx, sw, out_dtype=torch.bfloat16, alpha=alpha
40
+ )
41
+ return y[:ROWS]
42
+
43
+
44
+ def eager_act(raw: torch.Tensor) -> torch.Tensor:
45
+ gate, up = raw.chunk(2, dim=-1)
46
+ return F.silu(gate).mul_(up)
47
+
48
+
49
+ def byte_diff(left: torch.Tensor, right: torch.Tensor) -> int:
50
+ return int((left.view(torch.uint8) != right.view(torch.uint8)).sum().item())
51
+
52
+
53
+ def max_abs_diff(left: torch.Tensor, right: torch.Tensor) -> float:
54
+ return float((left.float() - right.float()).abs().max().item())
55
+
56
+
57
+ def time_ms(fn) -> float:
58
+ starter = torch.cuda.Event(enable_timing=True)
59
+ ender = torch.cuda.Event(enable_timing=True)
60
+ fn()
61
+ torch.cuda.synchronize()
62
+ starter.record()
63
+ fn()
64
+ ender.record()
65
+ torch.cuda.synchronize()
66
+ return starter.elapsed_time(ender)
67
+
68
+
69
+ def main() -> int:
70
+ load_extension(verbose=False)
71
+ device = torch.device("cuda")
72
+ torch.manual_seed(26081241)
73
+ x = torch.randn(ROWS, K, device=device, dtype=torch.bfloat16)
74
+ weight = torch.randn(2 * N, K, device=device, dtype=torch.bfloat16) * 0.02
75
+ sx = nvfp4_scale(x)
76
+ sw = nvfp4_scale(weight)
77
+ qx, qxs = ck.quantize_nvfp4(x, sx, pad_16x=True, hi_first=True)
78
+ qw, qws = ck.quantize_nvfp4(weight, sw, pad_16x=True, hi_first=True)
79
+ qx_live = qx[:ROWS].contiguous()
80
+ alpha = (sx * sw).reshape(1).contiguous()
81
+ kitchen = kitchen_gemm(qx, qxs, qw, qws, sx, sw)
82
+ full = fc1_paired_nvfp4_scaled_tma256_sw(
83
+ qx_live, qxs, qw, qws, alpha, product=False
84
+ )
85
+ prod = fc1_paired_nvfp4_scaled_tma256_sw(
86
+ qx_live, qxs, qw, qws, alpha, product=True
87
+ )
88
+ base = fc1_paired_nvfp4_scaled_tma256(
89
+ qx_live, qxs, qw, qws, alpha, product=True
90
+ )
91
+ eager_kit = eager_act(kitchen.contiguous())
92
+ eager_full = eager_act(full)
93
+ two_q, two_s, two_g = swiglu_nvfp4_dynamic(kitchen.contiguous())
94
+ prod_q, prod_s, prod_g = bf16_nvfp4_dynamic(prod)
95
+ payload = {
96
+ "identity": (
97
+ "SWIZZLE_32B TMA == linear fragment under "
98
+ "phys_col = col XOR ((row&4)<<2) on the kitchen-legal "
99
+ "256x64 3-stage m16n8k64 paired-N atom"
100
+ ),
101
+ "rows": ROWS,
102
+ "k": K,
103
+ "n": N,
104
+ "device": torch.cuda.get_device_name(device),
105
+ "sw_full_vs_kitchen_mismatches": byte_diff(full, kitchen),
106
+ "sw_full_vs_kitchen_max_abs": round(max_abs_diff(full, kitchen), 6),
107
+ "sw_prod_vs_t256_prod": byte_diff(prod, base),
108
+ "product_vs_eager_full_mismatches": byte_diff(prod, eager_full),
109
+ "product_vs_eager_kitchen_mismatches": byte_diff(prod, eager_kit),
110
+ "from_product_vs_kitchen_q": byte_diff(prod_q, two_q),
111
+ "from_product_vs_kitchen_s": byte_diff(prod_s, two_s),
112
+ "from_product_vs_kitchen_scale_exact": bool(torch.equal(prod_g, two_g)),
113
+ "full_finite": bool(torch.isfinite(full.float()).all().item()),
114
+ "prod_finite": bool(torch.isfinite(prod.float()).all().item()),
115
+ "kitchen_gemm_min_ms": round(
116
+ time_ms(lambda: kitchen_gemm(qx, qxs, qw, qws, sx, sw)), 4
117
+ ),
118
+ "sw_full_min_ms": round(
119
+ time_ms(
120
+ lambda: fc1_paired_nvfp4_scaled_tma256_sw(
121
+ qx_live, qxs, qw, qws, alpha, product=False
122
+ )
123
+ ),
124
+ 4,
125
+ ),
126
+ "sw_prod_min_ms": round(
127
+ time_ms(
128
+ lambda: fc1_paired_nvfp4_scaled_tma256_sw(
129
+ qx_live, qxs, qw, qws, alpha, product=True
130
+ )
131
+ ),
132
+ 4,
133
+ ),
134
+ "t256_prod_min_ms": round(
135
+ time_ms(
136
+ lambda: fc1_paired_nvfp4_scaled_tma256(
137
+ qx_live, qxs, qw, qws, alpha, product=True
138
+ )
139
+ ),
140
+ 4,
141
+ ),
142
+ "from_product_min_ms": round(
143
+ time_ms(lambda: bf16_nvfp4_dynamic(prod)), 4
144
+ ),
145
+ }
146
+ payload["pass"] = (
147
+ payload["sw_full_vs_kitchen_mismatches"] == 0
148
+ and payload["sw_prod_vs_t256_prod"] == 0
149
+ and payload["product_vs_eager_full_mismatches"] == 0
150
+ and payload["product_vs_eager_kitchen_mismatches"] == 0
151
+ and payload["from_product_vs_kitchen_q"] == 0
152
+ and payload["from_product_vs_kitchen_s"] == 0
153
+ and payload["from_product_vs_kitchen_scale_exact"]
154
+ and payload["full_finite"]
155
+ and payload["prod_finite"]
156
+ )
157
+ if payload["pass"]:
158
+ payload["vs_t256_ms"] = round(
159
+ payload["t256_prod_min_ms"] - payload["sw_prod_min_ms"], 4
160
+ )
161
+ text = json.dumps(payload, indent=2, sort_keys=True)
162
+ Path(__file__).with_name(
163
+ "gate_fc1_nvfp4_scaled_tma256_sw_20423.json"
164
+ ).write_text(text + "\n")
165
+ print(text)
166
+ return 0 if payload["pass"] else 2
167
+
168
+
169
+ if __name__ == "__main__":
170
+ raise SystemExit(main())
labs/swiglu_nvfp4/native_cuda/gate_fc1_nvfp4_scaled_tma256_sw_20423.json ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "device": "NVIDIA GB10",
3
+ "from_product_min_ms": 5.7545,
4
+ "from_product_vs_kitchen_q": 0,
5
+ "from_product_vs_kitchen_s": 0,
6
+ "from_product_vs_kitchen_scale_exact": true,
7
+ "full_finite": true,
8
+ "identity": "SWIZZLE_32B TMA == linear fragment under phys_col = col XOR ((row&4)<<2) on the kitchen-legal 256x64 3-stage m16n8k64 paired-N atom",
9
+ "k": 5376,
10
+ "kitchen_gemm_min_ms": 20.2633,
11
+ "n": 14336,
12
+ "pass": true,
13
+ "prod_finite": true,
14
+ "product_vs_eager_full_mismatches": 0,
15
+ "product_vs_eager_kitchen_mismatches": 0,
16
+ "rows": 20423,
17
+ "sw_full_min_ms": 57.6358,
18
+ "sw_full_vs_kitchen_max_abs": 0.0,
19
+ "sw_full_vs_kitchen_mismatches": 0,
20
+ "sw_prod_min_ms": 55.2272,
21
+ "sw_prod_vs_t256_prod": 0,
22
+ "t256_prod_min_ms": 54.41,
23
+ "vs_t256_ms": -0.8172
24
+ }
labs/swiglu_nvfp4/native_cuda/gate_fc1_nvfp4_scaled_tma256k2.py ADDED
@@ -0,0 +1,170 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """Byte-exact gate: K=128 TMA box == two K=64 MMA steps.
3
+
4
+ One TMA of 64 packed bytes feeds two m16n8k64 atoms. Same 256x64
5
+ 3-stage tile, PTX fragment, and cuBLAS 128x4 scale slabs (two groups).
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ import json
11
+ from pathlib import Path
12
+
13
+ import torch
14
+ import torch.nn.functional as F
15
+
16
+ import comfy_kitchen as ck
17
+
18
+ from swiglu_nvfp4 import (
19
+ bf16_nvfp4_dynamic,
20
+ fc1_paired_nvfp4_scaled_tma256,
21
+ fc1_paired_nvfp4_scaled_tma256k2,
22
+ load_extension,
23
+ swiglu_nvfp4_dynamic,
24
+ )
25
+
26
+
27
+ ROWS = 20423
28
+ K = 5376
29
+ N = 14336
30
+
31
+
32
+ def nvfp4_scale(x: torch.Tensor) -> torch.Tensor:
33
+ return (x.abs().amax() / (6.0 * 448.0)).to(torch.float32).reshape(1)
34
+
35
+
36
+ def kitchen_gemm(qx, sx, qw, sw, scale_x, scale_w) -> torch.Tensor:
37
+ alpha = (scale_x * scale_w).reshape(1)
38
+ y = ck.scaled_mm_nvfp4(
39
+ qx, qw, scale_x, scale_w, sx, sw, out_dtype=torch.bfloat16, alpha=alpha
40
+ )
41
+ return y[:ROWS]
42
+
43
+
44
+ def eager_act(raw: torch.Tensor) -> torch.Tensor:
45
+ gate, up = raw.chunk(2, dim=-1)
46
+ return F.silu(gate).mul_(up)
47
+
48
+
49
+ def byte_diff(left: torch.Tensor, right: torch.Tensor) -> int:
50
+ return int((left.view(torch.uint8) != right.view(torch.uint8)).sum().item())
51
+
52
+
53
+ def max_abs_diff(left: torch.Tensor, right: torch.Tensor) -> float:
54
+ return float((left.float() - right.float()).abs().max().item())
55
+
56
+
57
+ def time_ms(fn) -> float:
58
+ starter = torch.cuda.Event(enable_timing=True)
59
+ ender = torch.cuda.Event(enable_timing=True)
60
+ fn()
61
+ torch.cuda.synchronize()
62
+ starter.record()
63
+ fn()
64
+ ender.record()
65
+ torch.cuda.synchronize()
66
+ return starter.elapsed_time(ender)
67
+
68
+
69
+ def main() -> int:
70
+ load_extension(verbose=False)
71
+ device = torch.device("cuda")
72
+ torch.manual_seed(26081242)
73
+ x = torch.randn(ROWS, K, device=device, dtype=torch.bfloat16)
74
+ weight = torch.randn(2 * N, K, device=device, dtype=torch.bfloat16) * 0.02
75
+ sx = nvfp4_scale(x)
76
+ sw = nvfp4_scale(weight)
77
+ qx, qxs = ck.quantize_nvfp4(x, sx, pad_16x=True, hi_first=True)
78
+ qw, qws = ck.quantize_nvfp4(weight, sw, pad_16x=True, hi_first=True)
79
+ qx_live = qx[:ROWS].contiguous()
80
+ alpha = (sx * sw).reshape(1).contiguous()
81
+ kitchen = kitchen_gemm(qx, qxs, qw, qws, sx, sw)
82
+ full = fc1_paired_nvfp4_scaled_tma256k2(
83
+ qx_live, qxs, qw, qws, alpha, product=False
84
+ )
85
+ prod = fc1_paired_nvfp4_scaled_tma256k2(
86
+ qx_live, qxs, qw, qws, alpha, product=True
87
+ )
88
+ base = fc1_paired_nvfp4_scaled_tma256(
89
+ qx_live, qxs, qw, qws, alpha, product=True
90
+ )
91
+ eager_kit = eager_act(kitchen.contiguous())
92
+ eager_full = eager_act(full)
93
+ two_q, two_s, two_g = swiglu_nvfp4_dynamic(kitchen.contiguous())
94
+ prod_q, prod_s, prod_g = bf16_nvfp4_dynamic(prod)
95
+ payload = {
96
+ "identity": (
97
+ "K=128 TMA box == two sequential K=64 MMA steps: one 64-byte "
98
+ "packed row feeds two m16n8k64 atoms; two 128x4 scale slabs "
99
+ "cover the 8 K-scale columns. Same 256x64 3-stage tile."
100
+ ),
101
+ "rows": ROWS,
102
+ "k": K,
103
+ "n": N,
104
+ "device": torch.cuda.get_device_name(device),
105
+ "k2_full_vs_kitchen_mismatches": byte_diff(full, kitchen),
106
+ "k2_full_vs_kitchen_max_abs": round(max_abs_diff(full, kitchen), 6),
107
+ "k2_prod_vs_t256_prod": byte_diff(prod, base),
108
+ "product_vs_eager_full_mismatches": byte_diff(prod, eager_full),
109
+ "product_vs_eager_kitchen_mismatches": byte_diff(prod, eager_kit),
110
+ "from_product_vs_kitchen_q": byte_diff(prod_q, two_q),
111
+ "from_product_vs_kitchen_s": byte_diff(prod_s, two_s),
112
+ "from_product_vs_kitchen_scale_exact": bool(torch.equal(prod_g, two_g)),
113
+ "full_finite": bool(torch.isfinite(full.float()).all().item()),
114
+ "prod_finite": bool(torch.isfinite(prod.float()).all().item()),
115
+ "kitchen_gemm_min_ms": round(
116
+ time_ms(lambda: kitchen_gemm(qx, qxs, qw, qws, sx, sw)), 4
117
+ ),
118
+ "k2_full_min_ms": round(
119
+ time_ms(
120
+ lambda: fc1_paired_nvfp4_scaled_tma256k2(
121
+ qx_live, qxs, qw, qws, alpha, product=False
122
+ )
123
+ ),
124
+ 4,
125
+ ),
126
+ "k2_prod_min_ms": round(
127
+ time_ms(
128
+ lambda: fc1_paired_nvfp4_scaled_tma256k2(
129
+ qx_live, qxs, qw, qws, alpha, product=True
130
+ )
131
+ ),
132
+ 4,
133
+ ),
134
+ "t256_prod_min_ms": round(
135
+ time_ms(
136
+ lambda: fc1_paired_nvfp4_scaled_tma256(
137
+ qx_live, qxs, qw, qws, alpha, product=True
138
+ )
139
+ ),
140
+ 4,
141
+ ),
142
+ "from_product_min_ms": round(
143
+ time_ms(lambda: bf16_nvfp4_dynamic(prod)), 4
144
+ ),
145
+ }
146
+ payload["pass"] = (
147
+ payload["k2_full_vs_kitchen_mismatches"] == 0
148
+ and payload["k2_prod_vs_t256_prod"] == 0
149
+ and payload["product_vs_eager_full_mismatches"] == 0
150
+ and payload["product_vs_eager_kitchen_mismatches"] == 0
151
+ and payload["from_product_vs_kitchen_q"] == 0
152
+ and payload["from_product_vs_kitchen_s"] == 0
153
+ and payload["from_product_vs_kitchen_scale_exact"]
154
+ and payload["full_finite"]
155
+ and payload["prod_finite"]
156
+ )
157
+ if payload["pass"]:
158
+ payload["vs_t256_ms"] = round(
159
+ payload["t256_prod_min_ms"] - payload["k2_prod_min_ms"], 4
160
+ )
161
+ text = json.dumps(payload, indent=2, sort_keys=True)
162
+ Path(__file__).with_name(
163
+ "gate_fc1_nvfp4_scaled_tma256k2_20423.json"
164
+ ).write_text(text + "\n")
165
+ print(text)
166
+ return 0 if payload["pass"] else 2
167
+
168
+
169
+ if __name__ == "__main__":
170
+ raise SystemExit(main())
labs/swiglu_nvfp4/native_cuda/gate_fc1_nvfp4_scaled_tma256k2_20423.json ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "device": "NVIDIA GB10",
3
+ "from_product_min_ms": 5.7447,
4
+ "from_product_vs_kitchen_q": 0,
5
+ "from_product_vs_kitchen_s": 0,
6
+ "from_product_vs_kitchen_scale_exact": true,
7
+ "full_finite": true,
8
+ "identity": "K=128 TMA box == two sequential K=64 MMA steps: one 64-byte packed row feeds two m16n8k64 atoms; two 128x4 scale slabs cover the 8 K-scale columns. Same 256x64 3-stage tile.",
9
+ "k": 5376,
10
+ "k2_full_min_ms": 40.1835,
11
+ "k2_full_vs_kitchen_max_abs": 0.0,
12
+ "k2_full_vs_kitchen_mismatches": 0,
13
+ "k2_prod_min_ms": 36.8901,
14
+ "k2_prod_vs_t256_prod": 0,
15
+ "kitchen_gemm_min_ms": 20.1649,
16
+ "n": 14336,
17
+ "pass": true,
18
+ "prod_finite": true,
19
+ "product_vs_eager_full_mismatches": 0,
20
+ "product_vs_eager_kitchen_mismatches": 0,
21
+ "rows": 20423,
22
+ "t256_prod_min_ms": 56.1152,
23
+ "vs_t256_ms": 19.2251
24
+ }
labs/swiglu_nvfp4/native_cuda/gate_fc1_nvfp4_scaled_tma256k2_ldm.py ADDED
@@ -0,0 +1,127 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """Byte-exact gate: ldmatrix.x4 A on k2 == kitchen / scalar k2.
3
+
4
+ Best lab mainloop (256x64 K=128 3-stage) with the kitchen A fragment
5
+ via ldmatrix. Same paired-N store.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ import json
11
+ from pathlib import Path
12
+
13
+ import torch
14
+
15
+ import comfy_kitchen as ck
16
+
17
+ from swiglu_nvfp4 import (
18
+ fc1_paired_nvfp4_scaled_tma256k2,
19
+ fc1_paired_nvfp4_scaled_tma256k2_ldm,
20
+ load_extension,
21
+ )
22
+
23
+
24
+ ROWS = 20423
25
+ K = 5376
26
+ N = 14336
27
+
28
+
29
+ def nvfp4_scale(x: torch.Tensor) -> torch.Tensor:
30
+ return (x.abs().amax() / (6.0 * 448.0)).to(torch.float32).reshape(1)
31
+
32
+
33
+ def kitchen_gemm(qx, sx, qw, sw, scale_x, scale_w) -> torch.Tensor:
34
+ alpha = (scale_x * scale_w).reshape(1)
35
+ y = ck.scaled_mm_nvfp4(
36
+ qx, qw, scale_x, scale_w, sx, sw, out_dtype=torch.bfloat16, alpha=alpha
37
+ )
38
+ return y[:ROWS]
39
+
40
+
41
+ def byte_diff(left: torch.Tensor, right: torch.Tensor) -> int:
42
+ return int((left.view(torch.uint8) != right.view(torch.uint8)).sum().item())
43
+
44
+
45
+ def time_ms(fn) -> float:
46
+ starter = torch.cuda.Event(enable_timing=True)
47
+ ender = torch.cuda.Event(enable_timing=True)
48
+ fn()
49
+ torch.cuda.synchronize()
50
+ starter.record()
51
+ fn()
52
+ ender.record()
53
+ torch.cuda.synchronize()
54
+ return starter.elapsed_time(ender)
55
+
56
+
57
+ def main() -> int:
58
+ load_extension(verbose=False)
59
+ device = torch.device("cuda")
60
+ torch.manual_seed(26081263)
61
+ x = torch.randn(ROWS, K, device=device, dtype=torch.bfloat16)
62
+ weight = torch.randn(2 * N, K, device=device, dtype=torch.bfloat16) * 0.02
63
+ sx = nvfp4_scale(x)
64
+ sw = nvfp4_scale(weight)
65
+ qx, qxs = ck.quantize_nvfp4(x, sx, pad_16x=True, hi_first=True)
66
+ qw, qws = ck.quantize_nvfp4(weight, sw, pad_16x=True, hi_first=True)
67
+ qx_live = qx[:ROWS].contiguous()
68
+ alpha = (sx * sw).reshape(1).contiguous()
69
+ kitchen = kitchen_gemm(qx, qxs, qw, qws, sx, sw)
70
+ k2 = fc1_paired_nvfp4_scaled_tma256k2(
71
+ qx_live, qxs, qw, qws, alpha, product=False
72
+ )
73
+ ldm = fc1_paired_nvfp4_scaled_tma256k2_ldm(qx_live, qxs, qw, qws, alpha)
74
+ payload = {
75
+ "identity": (
76
+ "ldmatrix.x4 A on k2 (256x64 K=128) == kitchen group/tidg "
77
+ "fragment == scalar k2. Best lab mainloop + kitchen A load."
78
+ ),
79
+ "rows": ROWS,
80
+ "k": K,
81
+ "n": 2 * N,
82
+ "device": torch.cuda.get_device_name(device),
83
+ "ldm_vs_kitchen_mismatches": byte_diff(ldm, kitchen),
84
+ "ldm_vs_k2_mismatches": byte_diff(ldm, k2),
85
+ "full_finite": bool(torch.isfinite(ldm.float()).all().item()),
86
+ "kitchen_gemm_min_ms": round(
87
+ time_ms(lambda: kitchen_gemm(qx, qxs, qw, qws, sx, sw)), 4
88
+ ),
89
+ "ldm_full_min_ms": round(
90
+ time_ms(
91
+ lambda: fc1_paired_nvfp4_scaled_tma256k2_ldm(
92
+ qx_live, qxs, qw, qws, alpha
93
+ )
94
+ ),
95
+ 4,
96
+ ),
97
+ "k2_full_min_ms": round(
98
+ time_ms(
99
+ lambda: fc1_paired_nvfp4_scaled_tma256k2(
100
+ qx_live, qxs, qw, qws, alpha, product=False
101
+ )
102
+ ),
103
+ 4,
104
+ ),
105
+ }
106
+ payload["pass"] = (
107
+ payload["ldm_vs_kitchen_mismatches"] == 0
108
+ and payload["ldm_vs_k2_mismatches"] == 0
109
+ and payload["full_finite"]
110
+ )
111
+ if payload["pass"]:
112
+ payload["vs_kitchen_ms"] = round(
113
+ payload["kitchen_gemm_min_ms"] - payload["ldm_full_min_ms"], 4
114
+ )
115
+ payload["vs_k2_ms"] = round(
116
+ payload["k2_full_min_ms"] - payload["ldm_full_min_ms"], 4
117
+ )
118
+ text = json.dumps(payload, indent=2, sort_keys=True)
119
+ Path(__file__).with_name(
120
+ "gate_fc1_nvfp4_scaled_tma256k2_ldm_20423.json"
121
+ ).write_text(text + "\n")
122
+ print(text)
123
+ return 0 if payload["pass"] else 2
124
+
125
+
126
+ if __name__ == "__main__":
127
+ raise SystemExit(main())
labs/swiglu_nvfp4/native_cuda/gate_fc1_nvfp4_scaled_tma256k2_ldm_20423.json ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "device": "NVIDIA GB10",
3
+ "full_finite": true,
4
+ "identity": "ldmatrix.x4 A on k2 (256x64 K=128) == kitchen group/tidg fragment == scalar k2. Best lab mainloop + kitchen A load.",
5
+ "k": 5376,
6
+ "k2_full_min_ms": 38.9594,
7
+ "kitchen_gemm_min_ms": 20.2181,
8
+ "ldm_full_min_ms": 38.9408,
9
+ "ldm_vs_k2_mismatches": 0,
10
+ "ldm_vs_kitchen_mismatches": 0,
11
+ "n": 28672,
12
+ "pass": true,
13
+ "rows": 20423,
14
+ "vs_k2_ms": 0.0186,
15
+ "vs_kitchen_ms": -18.7227
16
+ }
labs/swiglu_nvfp4/native_cuda/gate_fc1_nvfp4_scaled_tma256k2_ldmb.py ADDED
@@ -0,0 +1,127 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """Byte-exact gate: ldmatrix.x4 B on k2 == kitchen / scalar k2.
3
+
4
+ One x4 covers two 8-N subtiles via the proven A-fragment map
5
+ smem[lane&15][(lane>>4)*16]. Same 256x64 K=128 paired-N store.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ import json
11
+ from pathlib import Path
12
+
13
+ import torch
14
+
15
+ import comfy_kitchen as ck
16
+
17
+ from swiglu_nvfp4 import (
18
+ fc1_paired_nvfp4_scaled_tma256k2,
19
+ fc1_paired_nvfp4_scaled_tma256k2_ldmb,
20
+ load_extension,
21
+ )
22
+
23
+
24
+ ROWS = 20423
25
+ K = 5376
26
+ N = 14336
27
+
28
+
29
+ def nvfp4_scale(x: torch.Tensor) -> torch.Tensor:
30
+ return (x.abs().amax() / (6.0 * 448.0)).to(torch.float32).reshape(1)
31
+
32
+
33
+ def kitchen_gemm(qx, sx, qw, sw, scale_x, scale_w) -> torch.Tensor:
34
+ alpha = (scale_x * scale_w).reshape(1)
35
+ y = ck.scaled_mm_nvfp4(
36
+ qx, qw, scale_x, scale_w, sx, sw, out_dtype=torch.bfloat16, alpha=alpha
37
+ )
38
+ return y[:ROWS]
39
+
40
+
41
+ def byte_diff(left: torch.Tensor, right: torch.Tensor) -> int:
42
+ return int((left.view(torch.uint8) != right.view(torch.uint8)).sum().item())
43
+
44
+
45
+ def time_ms(fn) -> float:
46
+ starter = torch.cuda.Event(enable_timing=True)
47
+ ender = torch.cuda.Event(enable_timing=True)
48
+ fn()
49
+ torch.cuda.synchronize()
50
+ starter.record()
51
+ fn()
52
+ ender.record()
53
+ torch.cuda.synchronize()
54
+ return starter.elapsed_time(ender)
55
+
56
+
57
+ def main() -> int:
58
+ load_extension(verbose=False)
59
+ device = torch.device("cuda")
60
+ torch.manual_seed(26081264)
61
+ x = torch.randn(ROWS, K, device=device, dtype=torch.bfloat16)
62
+ weight = torch.randn(2 * N, K, device=device, dtype=torch.bfloat16) * 0.02
63
+ sx = nvfp4_scale(x)
64
+ sw = nvfp4_scale(weight)
65
+ qx, qxs = ck.quantize_nvfp4(x, sx, pad_16x=True, hi_first=True)
66
+ qw, qws = ck.quantize_nvfp4(weight, sw, pad_16x=True, hi_first=True)
67
+ qx_live = qx[:ROWS].contiguous()
68
+ alpha = (sx * sw).reshape(1).contiguous()
69
+ kitchen = kitchen_gemm(qx, qxs, qw, qws, sx, sw)
70
+ k2 = fc1_paired_nvfp4_scaled_tma256k2(
71
+ qx_live, qxs, qw, qws, alpha, product=False
72
+ )
73
+ ldmb = fc1_paired_nvfp4_scaled_tma256k2_ldmb(qx_live, qxs, qw, qws, alpha)
74
+ payload = {
75
+ "identity": (
76
+ "ldmatrix.x4 B on k2 (256x64 K=128) pairs two 8-N subtiles "
77
+ "via the A-fragment map == kitchen == scalar k2."
78
+ ),
79
+ "rows": ROWS,
80
+ "k": K,
81
+ "n": 2 * N,
82
+ "device": torch.cuda.get_device_name(device),
83
+ "ldmb_vs_kitchen_mismatches": byte_diff(ldmb, kitchen),
84
+ "ldmb_vs_k2_mismatches": byte_diff(ldmb, k2),
85
+ "full_finite": bool(torch.isfinite(ldmb.float()).all().item()),
86
+ "kitchen_gemm_min_ms": round(
87
+ time_ms(lambda: kitchen_gemm(qx, qxs, qw, qws, sx, sw)), 4
88
+ ),
89
+ "ldmb_full_min_ms": round(
90
+ time_ms(
91
+ lambda: fc1_paired_nvfp4_scaled_tma256k2_ldmb(
92
+ qx_live, qxs, qw, qws, alpha
93
+ )
94
+ ),
95
+ 4,
96
+ ),
97
+ "k2_full_min_ms": round(
98
+ time_ms(
99
+ lambda: fc1_paired_nvfp4_scaled_tma256k2(
100
+ qx_live, qxs, qw, qws, alpha, product=False
101
+ )
102
+ ),
103
+ 4,
104
+ ),
105
+ }
106
+ payload["pass"] = (
107
+ payload["ldmb_vs_kitchen_mismatches"] == 0
108
+ and payload["ldmb_vs_k2_mismatches"] == 0
109
+ and payload["full_finite"]
110
+ )
111
+ if payload["pass"]:
112
+ payload["vs_kitchen_ms"] = round(
113
+ payload["kitchen_gemm_min_ms"] - payload["ldmb_full_min_ms"], 4
114
+ )
115
+ payload["vs_k2_ms"] = round(
116
+ payload["k2_full_min_ms"] - payload["ldmb_full_min_ms"], 4
117
+ )
118
+ text = json.dumps(payload, indent=2, sort_keys=True)
119
+ Path(__file__).with_name(
120
+ "gate_fc1_nvfp4_scaled_tma256k2_ldmb_20423.json"
121
+ ).write_text(text + "\n")
122
+ print(text)
123
+ return 0 if payload["pass"] else 2
124
+
125
+
126
+ if __name__ == "__main__":
127
+ raise SystemExit(main())
labs/swiglu_nvfp4/native_cuda/gate_fc1_nvfp4_scaled_tma256k2_ldmb_20423.json ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "device": "NVIDIA GB10",
3
+ "full_finite": true,
4
+ "identity": "ldmatrix.x4 B on k2 (256x64 K=128) pairs two 8-N subtiles via the A-fragment map == kitchen == scalar k2.",
5
+ "k": 5376,
6
+ "k2_full_min_ms": 40.1911,
7
+ "kitchen_gemm_min_ms": 20.2815,
8
+ "ldmb_full_min_ms": 39.4436,
9
+ "ldmb_vs_k2_mismatches": 0,
10
+ "ldmb_vs_kitchen_mismatches": 0,
11
+ "n": 28672,
12
+ "pass": true,
13
+ "rows": 20423,
14
+ "vs_k2_ms": 0.7475,
15
+ "vs_kitchen_ms": -19.1621
16
+ }
labs/swiglu_nvfp4/native_cuda/gate_fc1_nvfp4_scaled_tma256k2_leads.py ADDED
@@ -0,0 +1,131 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """Byte-exact gate: leader-only SFA/SFB on k2 == kitchen / scalar k2.
3
+
4
+ scale_vec::4X with selectors {0,0}: SFA from 16 lanes
5
+ ((lane>>1)&1)==0; SFB from 8 lanes (lane&3)==0. Other lanes
6
+ pass 0. Same 256x64 K=128 paired-N store.
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ import json
12
+ from pathlib import Path
13
+
14
+ import torch
15
+
16
+ import comfy_kitchen as ck
17
+
18
+ from swiglu_nvfp4 import (
19
+ fc1_paired_nvfp4_scaled_tma256k2,
20
+ fc1_paired_nvfp4_scaled_tma256k2_leads,
21
+ load_extension,
22
+ )
23
+
24
+
25
+ ROWS = 20423
26
+ K = 5376
27
+ N = 14336
28
+
29
+
30
+ def nvfp4_scale(x: torch.Tensor) -> torch.Tensor:
31
+ return (x.abs().amax() / (6.0 * 448.0)).to(torch.float32).reshape(1)
32
+
33
+
34
+ def kitchen_gemm(qx, sx, qw, sw, scale_x, scale_w) -> torch.Tensor:
35
+ alpha = (scale_x * scale_w).reshape(1)
36
+ y = ck.scaled_mm_nvfp4(
37
+ qx, qw, scale_x, scale_w, sx, sw, out_dtype=torch.bfloat16, alpha=alpha
38
+ )
39
+ return y[:ROWS]
40
+
41
+
42
+ def byte_diff(left: torch.Tensor, right: torch.Tensor) -> int:
43
+ return int((left.view(torch.uint8) != right.view(torch.uint8)).sum().item())
44
+
45
+
46
+ def time_ms(fn) -> float:
47
+ starter = torch.cuda.Event(enable_timing=True)
48
+ ender = torch.cuda.Event(enable_timing=True)
49
+ fn()
50
+ torch.cuda.synchronize()
51
+ starter.record()
52
+ fn()
53
+ ender.record()
54
+ torch.cuda.synchronize()
55
+ return starter.elapsed_time(ender)
56
+
57
+
58
+ def main() -> int:
59
+ load_extension(verbose=False)
60
+ device = torch.device("cuda")
61
+ torch.manual_seed(26081267)
62
+ x = torch.randn(ROWS, K, device=device, dtype=torch.bfloat16)
63
+ weight = torch.randn(2 * N, K, device=device, dtype=torch.bfloat16) * 0.02
64
+ sx = nvfp4_scale(x)
65
+ sw = nvfp4_scale(weight)
66
+ qx, qxs = ck.quantize_nvfp4(x, sx, pad_16x=True, hi_first=True)
67
+ qw, qws = ck.quantize_nvfp4(weight, sw, pad_16x=True, hi_first=True)
68
+ qx_live = qx[:ROWS].contiguous()
69
+ alpha = (sx * sw).reshape(1).contiguous()
70
+ kitchen = kitchen_gemm(qx, qxs, qw, qws, sx, sw)
71
+ k2 = fc1_paired_nvfp4_scaled_tma256k2(
72
+ qx_live, qxs, qw, qws, alpha, product=False
73
+ )
74
+ leads = fc1_paired_nvfp4_scaled_tma256k2_leads(
75
+ qx_live, qxs, qw, qws, alpha
76
+ )
77
+ payload = {
78
+ "identity": (
79
+ "leader-only SFA/SFB on k2 (256x64 K=128): scale_vec::4X "
80
+ "selectors {0,0} read 16 SFA + 8 SFB lanes; others 0 "
81
+ "== kitchen == scalar k2."
82
+ ),
83
+ "rows": ROWS,
84
+ "k": K,
85
+ "n": 2 * N,
86
+ "device": torch.cuda.get_device_name(device),
87
+ "leads_vs_kitchen_mismatches": byte_diff(leads, kitchen),
88
+ "leads_vs_k2_mismatches": byte_diff(leads, k2),
89
+ "full_finite": bool(torch.isfinite(leads.float()).all().item()),
90
+ "kitchen_gemm_min_ms": round(
91
+ time_ms(lambda: kitchen_gemm(qx, qxs, qw, qws, sx, sw)), 4
92
+ ),
93
+ "leads_full_min_ms": round(
94
+ time_ms(
95
+ lambda: fc1_paired_nvfp4_scaled_tma256k2_leads(
96
+ qx_live, qxs, qw, qws, alpha
97
+ )
98
+ ),
99
+ 4,
100
+ ),
101
+ "k2_full_min_ms": round(
102
+ time_ms(
103
+ lambda: fc1_paired_nvfp4_scaled_tma256k2(
104
+ qx_live, qxs, qw, qws, alpha, product=False
105
+ )
106
+ ),
107
+ 4,
108
+ ),
109
+ }
110
+ payload["pass"] = (
111
+ payload["leads_vs_kitchen_mismatches"] == 0
112
+ and payload["leads_vs_k2_mismatches"] == 0
113
+ and payload["full_finite"]
114
+ )
115
+ if payload["pass"]:
116
+ payload["vs_kitchen_ms"] = round(
117
+ payload["kitchen_gemm_min_ms"] - payload["leads_full_min_ms"], 4
118
+ )
119
+ payload["vs_k2_ms"] = round(
120
+ payload["k2_full_min_ms"] - payload["leads_full_min_ms"], 4
121
+ )
122
+ text = json.dumps(payload, indent=2, sort_keys=True)
123
+ Path(__file__).with_name(
124
+ "gate_fc1_nvfp4_scaled_tma256k2_leads_20423.json"
125
+ ).write_text(text + "\n")
126
+ print(text)
127
+ return 0 if payload["pass"] else 2
128
+
129
+
130
+ if __name__ == "__main__":
131
+ raise SystemExit(main())
labs/swiglu_nvfp4/native_cuda/gate_fc1_nvfp4_scaled_tma256k2_leads_20423.json ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "device": "NVIDIA GB10",
3
+ "full_finite": true,
4
+ "identity": "leader-only SFA/SFB on k2 (256x64 K=128): scale_vec::4X selectors {0,0} read 16 SFA + 8 SFB lanes; others 0 == kitchen == scalar k2.",
5
+ "k": 5376,
6
+ "k2_full_min_ms": 39.226,
7
+ "kitchen_gemm_min_ms": 19.4048,
8
+ "leads_full_min_ms": 39.8251,
9
+ "leads_vs_k2_mismatches": 0,
10
+ "leads_vs_kitchen_mismatches": 0,
11
+ "n": 28672,
12
+ "pass": true,
13
+ "rows": 20423,
14
+ "vs_k2_ms": -0.5991,
15
+ "vs_kitchen_ms": -20.4203
16
+ }
labs/swiglu_nvfp4/native_cuda/gate_fc1_nvfp4_scaled_tma256k2_pipe.py ADDED
@@ -0,0 +1,127 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """Byte-exact gate: software-pipelined B on k2 == kitchen / scalar k2.
3
+
4
+ Next N-subtile B/SFB (both arms) overlaps m16n8k64. Same 256x64
5
+ K=128 paired-N store. Not the 128x128x256 pipe.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ import json
11
+ from pathlib import Path
12
+
13
+ import torch
14
+
15
+ import comfy_kitchen as ck
16
+
17
+ from swiglu_nvfp4 import (
18
+ fc1_paired_nvfp4_scaled_tma256k2,
19
+ fc1_paired_nvfp4_scaled_tma256k2_pipe,
20
+ load_extension,
21
+ )
22
+
23
+
24
+ ROWS = 20423
25
+ K = 5376
26
+ N = 14336
27
+
28
+
29
+ def nvfp4_scale(x: torch.Tensor) -> torch.Tensor:
30
+ return (x.abs().amax() / (6.0 * 448.0)).to(torch.float32).reshape(1)
31
+
32
+
33
+ def kitchen_gemm(qx, sx, qw, sw, scale_x, scale_w) -> torch.Tensor:
34
+ alpha = (scale_x * scale_w).reshape(1)
35
+ y = ck.scaled_mm_nvfp4(
36
+ qx, qw, scale_x, scale_w, sx, sw, out_dtype=torch.bfloat16, alpha=alpha
37
+ )
38
+ return y[:ROWS]
39
+
40
+
41
+ def byte_diff(left: torch.Tensor, right: torch.Tensor) -> int:
42
+ return int((left.view(torch.uint8) != right.view(torch.uint8)).sum().item())
43
+
44
+
45
+ def time_ms(fn) -> float:
46
+ starter = torch.cuda.Event(enable_timing=True)
47
+ ender = torch.cuda.Event(enable_timing=True)
48
+ fn()
49
+ torch.cuda.synchronize()
50
+ starter.record()
51
+ fn()
52
+ ender.record()
53
+ torch.cuda.synchronize()
54
+ return starter.elapsed_time(ender)
55
+
56
+
57
+ def main() -> int:
58
+ load_extension(verbose=False)
59
+ device = torch.device("cuda")
60
+ torch.manual_seed(26081266)
61
+ x = torch.randn(ROWS, K, device=device, dtype=torch.bfloat16)
62
+ weight = torch.randn(2 * N, K, device=device, dtype=torch.bfloat16) * 0.02
63
+ sx = nvfp4_scale(x)
64
+ sw = nvfp4_scale(weight)
65
+ qx, qxs = ck.quantize_nvfp4(x, sx, pad_16x=True, hi_first=True)
66
+ qw, qws = ck.quantize_nvfp4(weight, sw, pad_16x=True, hi_first=True)
67
+ qx_live = qx[:ROWS].contiguous()
68
+ alpha = (sx * sw).reshape(1).contiguous()
69
+ kitchen = kitchen_gemm(qx, qxs, qw, qws, sx, sw)
70
+ k2 = fc1_paired_nvfp4_scaled_tma256k2(
71
+ qx_live, qxs, qw, qws, alpha, product=False
72
+ )
73
+ pipe = fc1_paired_nvfp4_scaled_tma256k2_pipe(qx_live, qxs, qw, qws, alpha)
74
+ payload = {
75
+ "identity": (
76
+ "software-pipelined B on k2 (256x64 K=128): next N-subtile "
77
+ "B/SFB both arms overlap m16n8k64 == kitchen == scalar k2."
78
+ ),
79
+ "rows": ROWS,
80
+ "k": K,
81
+ "n": 2 * N,
82
+ "device": torch.cuda.get_device_name(device),
83
+ "pipe_vs_kitchen_mismatches": byte_diff(pipe, kitchen),
84
+ "pipe_vs_k2_mismatches": byte_diff(pipe, k2),
85
+ "full_finite": bool(torch.isfinite(pipe.float()).all().item()),
86
+ "kitchen_gemm_min_ms": round(
87
+ time_ms(lambda: kitchen_gemm(qx, qxs, qw, qws, sx, sw)), 4
88
+ ),
89
+ "pipe_full_min_ms": round(
90
+ time_ms(
91
+ lambda: fc1_paired_nvfp4_scaled_tma256k2_pipe(
92
+ qx_live, qxs, qw, qws, alpha
93
+ )
94
+ ),
95
+ 4,
96
+ ),
97
+ "k2_full_min_ms": round(
98
+ time_ms(
99
+ lambda: fc1_paired_nvfp4_scaled_tma256k2(
100
+ qx_live, qxs, qw, qws, alpha, product=False
101
+ )
102
+ ),
103
+ 4,
104
+ ),
105
+ }
106
+ payload["pass"] = (
107
+ payload["pipe_vs_kitchen_mismatches"] == 0
108
+ and payload["pipe_vs_k2_mismatches"] == 0
109
+ and payload["full_finite"]
110
+ )
111
+ if payload["pass"]:
112
+ payload["vs_kitchen_ms"] = round(
113
+ payload["kitchen_gemm_min_ms"] - payload["pipe_full_min_ms"], 4
114
+ )
115
+ payload["vs_k2_ms"] = round(
116
+ payload["k2_full_min_ms"] - payload["pipe_full_min_ms"], 4
117
+ )
118
+ text = json.dumps(payload, indent=2, sort_keys=True)
119
+ Path(__file__).with_name(
120
+ "gate_fc1_nvfp4_scaled_tma256k2_pipe_20423.json"
121
+ ).write_text(text + "\n")
122
+ print(text)
123
+ return 0 if payload["pass"] else 2
124
+
125
+
126
+ if __name__ == "__main__":
127
+ raise SystemExit(main())
labs/swiglu_nvfp4/native_cuda/gate_fc1_nvfp4_scaled_tma256k2_pipe_20423.json ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "device": "NVIDIA GB10",
3
+ "full_finite": true,
4
+ "identity": "software-pipelined B on k2 (256x64 K=128): next N-subtile B/SFB both arms overlap m16n8k64 == kitchen == scalar k2.",
5
+ "k": 5376,
6
+ "k2_full_min_ms": 39.9199,
7
+ "kitchen_gemm_min_ms": 20.1408,
8
+ "n": 28672,
9
+ "pass": true,
10
+ "pipe_full_min_ms": 40.6522,
11
+ "pipe_vs_k2_mismatches": 0,
12
+ "pipe_vs_kitchen_mismatches": 0,
13
+ "rows": 20423,
14
+ "vs_k2_ms": -0.7323,
15
+ "vs_kitchen_ms": -20.5114
16
+ }
labs/swiglu_nvfp4/native_cuda/gate_fc1_nvfp4_scaled_tma256k2_pipea.py ADDED
@@ -0,0 +1,129 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """Byte-exact gate: software-pipelined A on k2 == kitchen / scalar k2.
3
+
4
+ Next K=64 A/SFA overlaps m16n8k64. Same 256x64 K=128 paired-N store.
5
+ Not the B-pipe identity.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ import json
11
+ from pathlib import Path
12
+
13
+ import torch
14
+
15
+ import comfy_kitchen as ck
16
+
17
+ from swiglu_nvfp4 import (
18
+ fc1_paired_nvfp4_scaled_tma256k2,
19
+ fc1_paired_nvfp4_scaled_tma256k2_pipea,
20
+ load_extension,
21
+ )
22
+
23
+
24
+ ROWS = 20423
25
+ K = 5376
26
+ N = 14336
27
+
28
+
29
+ def nvfp4_scale(x: torch.Tensor) -> torch.Tensor:
30
+ return (x.abs().amax() / (6.0 * 448.0)).to(torch.float32).reshape(1)
31
+
32
+
33
+ def kitchen_gemm(qx, sx, qw, sw, scale_x, scale_w) -> torch.Tensor:
34
+ alpha = (scale_x * scale_w).reshape(1)
35
+ y = ck.scaled_mm_nvfp4(
36
+ qx, qw, scale_x, scale_w, sx, sw, out_dtype=torch.bfloat16, alpha=alpha
37
+ )
38
+ return y[:ROWS]
39
+
40
+
41
+ def byte_diff(left: torch.Tensor, right: torch.Tensor) -> int:
42
+ return int((left.view(torch.uint8) != right.view(torch.uint8)).sum().item())
43
+
44
+
45
+ def time_ms(fn) -> float:
46
+ starter = torch.cuda.Event(enable_timing=True)
47
+ ender = torch.cuda.Event(enable_timing=True)
48
+ fn()
49
+ torch.cuda.synchronize()
50
+ starter.record()
51
+ fn()
52
+ ender.record()
53
+ torch.cuda.synchronize()
54
+ return starter.elapsed_time(ender)
55
+
56
+
57
+ def main() -> int:
58
+ load_extension(verbose=False)
59
+ device = torch.device("cuda")
60
+ torch.manual_seed(26081269)
61
+ x = torch.randn(ROWS, K, device=device, dtype=torch.bfloat16)
62
+ weight = torch.randn(2 * N, K, device=device, dtype=torch.bfloat16) * 0.02
63
+ sx = nvfp4_scale(x)
64
+ sw = nvfp4_scale(weight)
65
+ qx, qxs = ck.quantize_nvfp4(x, sx, pad_16x=True, hi_first=True)
66
+ qw, qws = ck.quantize_nvfp4(weight, sw, pad_16x=True, hi_first=True)
67
+ qx_live = qx[:ROWS].contiguous()
68
+ alpha = (sx * sw).reshape(1).contiguous()
69
+ kitchen = kitchen_gemm(qx, qxs, qw, qws, sx, sw)
70
+ k2 = fc1_paired_nvfp4_scaled_tma256k2(
71
+ qx_live, qxs, qw, qws, alpha, product=False
72
+ )
73
+ pipea = fc1_paired_nvfp4_scaled_tma256k2_pipea(
74
+ qx_live, qxs, qw, qws, alpha
75
+ )
76
+ payload = {
77
+ "identity": (
78
+ "software-pipelined A on k2 (256x64 K=128): next K=64 "
79
+ "A/SFA overlaps m16n8k64 == kitchen == scalar k2."
80
+ ),
81
+ "rows": ROWS,
82
+ "k": K,
83
+ "n": 2 * N,
84
+ "device": torch.cuda.get_device_name(device),
85
+ "pipea_vs_kitchen_mismatches": byte_diff(pipea, kitchen),
86
+ "pipea_vs_k2_mismatches": byte_diff(pipea, k2),
87
+ "full_finite": bool(torch.isfinite(pipea.float()).all().item()),
88
+ "kitchen_gemm_min_ms": round(
89
+ time_ms(lambda: kitchen_gemm(qx, qxs, qw, qws, sx, sw)), 4
90
+ ),
91
+ "pipea_full_min_ms": round(
92
+ time_ms(
93
+ lambda: fc1_paired_nvfp4_scaled_tma256k2_pipea(
94
+ qx_live, qxs, qw, qws, alpha
95
+ )
96
+ ),
97
+ 4,
98
+ ),
99
+ "k2_full_min_ms": round(
100
+ time_ms(
101
+ lambda: fc1_paired_nvfp4_scaled_tma256k2(
102
+ qx_live, qxs, qw, qws, alpha, product=False
103
+ )
104
+ ),
105
+ 4,
106
+ ),
107
+ }
108
+ payload["pass"] = (
109
+ payload["pipea_vs_kitchen_mismatches"] == 0
110
+ and payload["pipea_vs_k2_mismatches"] == 0
111
+ and payload["full_finite"]
112
+ )
113
+ if payload["pass"]:
114
+ payload["vs_kitchen_ms"] = round(
115
+ payload["kitchen_gemm_min_ms"] - payload["pipea_full_min_ms"], 4
116
+ )
117
+ payload["vs_k2_ms"] = round(
118
+ payload["k2_full_min_ms"] - payload["pipea_full_min_ms"], 4
119
+ )
120
+ text = json.dumps(payload, indent=2, sort_keys=True)
121
+ Path(__file__).with_name(
122
+ "gate_fc1_nvfp4_scaled_tma256k2_pipea_20423.json"
123
+ ).write_text(text + "\n")
124
+ print(text)
125
+ return 0 if payload["pass"] else 2
126
+
127
+
128
+ if __name__ == "__main__":
129
+ raise SystemExit(main())
labs/swiglu_nvfp4/native_cuda/gate_fc1_nvfp4_scaled_tma256k2_pipea_20423.json ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "device": "NVIDIA GB10",
3
+ "full_finite": true,
4
+ "identity": "software-pipelined A on k2 (256x64 K=128): next K=64 A/SFA overlaps m16n8k64 == kitchen == scalar k2.",
5
+ "k": 5376,
6
+ "k2_full_min_ms": 39.3463,
7
+ "kitchen_gemm_min_ms": 20.2426,
8
+ "n": 28672,
9
+ "pass": true,
10
+ "pipea_full_min_ms": 39.3357,
11
+ "pipea_vs_k2_mismatches": 0,
12
+ "pipea_vs_kitchen_mismatches": 0,
13
+ "rows": 20423,
14
+ "vs_k2_ms": 0.0106,
15
+ "vs_kitchen_ms": -19.0931
16
+ }
labs/swiglu_nvfp4/native_cuda/gate_fc1_nvfp4_scaled_tma256k2_sw.py ADDED
@@ -0,0 +1,170 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """Byte-exact gate: SWIZZLE_64B remapped on the K=128 TMA box.
3
+
4
+ phys_col = col XOR (((row >> 1) & 3) << 4). Same two m16n8k64 atoms,
5
+ 256x64 3-stage tile, and cuBLAS 128x4 scale slabs.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ import json
11
+ from pathlib import Path
12
+
13
+ import torch
14
+ import torch.nn.functional as F
15
+
16
+ import comfy_kitchen as ck
17
+
18
+ from swiglu_nvfp4 import (
19
+ bf16_nvfp4_dynamic,
20
+ fc1_paired_nvfp4_scaled_tma256k2,
21
+ fc1_paired_nvfp4_scaled_tma256k2_sw,
22
+ load_extension,
23
+ swiglu_nvfp4_dynamic,
24
+ )
25
+
26
+
27
+ ROWS = 20423
28
+ K = 5376
29
+ N = 14336
30
+
31
+
32
+ def nvfp4_scale(x: torch.Tensor) -> torch.Tensor:
33
+ return (x.abs().amax() / (6.0 * 448.0)).to(torch.float32).reshape(1)
34
+
35
+
36
+ def kitchen_gemm(qx, sx, qw, sw, scale_x, scale_w) -> torch.Tensor:
37
+ alpha = (scale_x * scale_w).reshape(1)
38
+ y = ck.scaled_mm_nvfp4(
39
+ qx, qw, scale_x, scale_w, sx, sw, out_dtype=torch.bfloat16, alpha=alpha
40
+ )
41
+ return y[:ROWS]
42
+
43
+
44
+ def eager_act(raw: torch.Tensor) -> torch.Tensor:
45
+ gate, up = raw.chunk(2, dim=-1)
46
+ return F.silu(gate).mul_(up)
47
+
48
+
49
+ def byte_diff(left: torch.Tensor, right: torch.Tensor) -> int:
50
+ return int((left.view(torch.uint8) != right.view(torch.uint8)).sum().item())
51
+
52
+
53
+ def max_abs_diff(left: torch.Tensor, right: torch.Tensor) -> float:
54
+ return float((left.float() - right.float()).abs().max().item())
55
+
56
+
57
+ def time_ms(fn) -> float:
58
+ starter = torch.cuda.Event(enable_timing=True)
59
+ ender = torch.cuda.Event(enable_timing=True)
60
+ fn()
61
+ torch.cuda.synchronize()
62
+ starter.record()
63
+ fn()
64
+ ender.record()
65
+ torch.cuda.synchronize()
66
+ return starter.elapsed_time(ender)
67
+
68
+
69
+ def main() -> int:
70
+ load_extension(verbose=False)
71
+ device = torch.device("cuda")
72
+ torch.manual_seed(26081243)
73
+ x = torch.randn(ROWS, K, device=device, dtype=torch.bfloat16)
74
+ weight = torch.randn(2 * N, K, device=device, dtype=torch.bfloat16) * 0.02
75
+ sx = nvfp4_scale(x)
76
+ sw = nvfp4_scale(weight)
77
+ qx, qxs = ck.quantize_nvfp4(x, sx, pad_16x=True, hi_first=True)
78
+ qw, qws = ck.quantize_nvfp4(weight, sw, pad_16x=True, hi_first=True)
79
+ qx_live = qx[:ROWS].contiguous()
80
+ alpha = (sx * sw).reshape(1).contiguous()
81
+ kitchen = kitchen_gemm(qx, qxs, qw, qws, sx, sw)
82
+ full = fc1_paired_nvfp4_scaled_tma256k2_sw(
83
+ qx_live, qxs, qw, qws, alpha, product=False
84
+ )
85
+ prod = fc1_paired_nvfp4_scaled_tma256k2_sw(
86
+ qx_live, qxs, qw, qws, alpha, product=True
87
+ )
88
+ base = fc1_paired_nvfp4_scaled_tma256k2(
89
+ qx_live, qxs, qw, qws, alpha, product=True
90
+ )
91
+ eager_kit = eager_act(kitchen.contiguous())
92
+ eager_full = eager_act(full)
93
+ two_q, two_s, two_g = swiglu_nvfp4_dynamic(kitchen.contiguous())
94
+ prod_q, prod_s, prod_g = bf16_nvfp4_dynamic(prod)
95
+ payload = {
96
+ "identity": (
97
+ "SWIZZLE_64B TMA == linear fragment under "
98
+ "phys_col = col XOR (((row>>1)&3)<<4) on the kitchen-legal "
99
+ "K=128 / 256x64 3-stage m16n8k64 paired-N atom"
100
+ ),
101
+ "rows": ROWS,
102
+ "k": K,
103
+ "n": N,
104
+ "device": torch.cuda.get_device_name(device),
105
+ "sw_full_vs_kitchen_mismatches": byte_diff(full, kitchen),
106
+ "sw_full_vs_kitchen_max_abs": round(max_abs_diff(full, kitchen), 6),
107
+ "sw_prod_vs_k2_prod": byte_diff(prod, base),
108
+ "product_vs_eager_full_mismatches": byte_diff(prod, eager_full),
109
+ "product_vs_eager_kitchen_mismatches": byte_diff(prod, eager_kit),
110
+ "from_product_vs_kitchen_q": byte_diff(prod_q, two_q),
111
+ "from_product_vs_kitchen_s": byte_diff(prod_s, two_s),
112
+ "from_product_vs_kitchen_scale_exact": bool(torch.equal(prod_g, two_g)),
113
+ "full_finite": bool(torch.isfinite(full.float()).all().item()),
114
+ "prod_finite": bool(torch.isfinite(prod.float()).all().item()),
115
+ "kitchen_gemm_min_ms": round(
116
+ time_ms(lambda: kitchen_gemm(qx, qxs, qw, qws, sx, sw)), 4
117
+ ),
118
+ "sw_full_min_ms": round(
119
+ time_ms(
120
+ lambda: fc1_paired_nvfp4_scaled_tma256k2_sw(
121
+ qx_live, qxs, qw, qws, alpha, product=False
122
+ )
123
+ ),
124
+ 4,
125
+ ),
126
+ "sw_prod_min_ms": round(
127
+ time_ms(
128
+ lambda: fc1_paired_nvfp4_scaled_tma256k2_sw(
129
+ qx_live, qxs, qw, qws, alpha, product=True
130
+ )
131
+ ),
132
+ 4,
133
+ ),
134
+ "k2_prod_min_ms": round(
135
+ time_ms(
136
+ lambda: fc1_paired_nvfp4_scaled_tma256k2(
137
+ qx_live, qxs, qw, qws, alpha, product=True
138
+ )
139
+ ),
140
+ 4,
141
+ ),
142
+ "from_product_min_ms": round(
143
+ time_ms(lambda: bf16_nvfp4_dynamic(prod)), 4
144
+ ),
145
+ }
146
+ payload["pass"] = (
147
+ payload["sw_full_vs_kitchen_mismatches"] == 0
148
+ and payload["sw_prod_vs_k2_prod"] == 0
149
+ and payload["product_vs_eager_full_mismatches"] == 0
150
+ and payload["product_vs_eager_kitchen_mismatches"] == 0
151
+ and payload["from_product_vs_kitchen_q"] == 0
152
+ and payload["from_product_vs_kitchen_s"] == 0
153
+ and payload["from_product_vs_kitchen_scale_exact"]
154
+ and payload["full_finite"]
155
+ and payload["prod_finite"]
156
+ )
157
+ if payload["pass"]:
158
+ payload["vs_k2_ms"] = round(
159
+ payload["k2_prod_min_ms"] - payload["sw_prod_min_ms"], 4
160
+ )
161
+ text = json.dumps(payload, indent=2, sort_keys=True)
162
+ Path(__file__).with_name(
163
+ "gate_fc1_nvfp4_scaled_tma256k2_sw_20423.json"
164
+ ).write_text(text + "\n")
165
+ print(text)
166
+ return 0 if payload["pass"] else 2
167
+
168
+
169
+ if __name__ == "__main__":
170
+ raise SystemExit(main())
labs/swiglu_nvfp4/native_cuda/gate_fc1_nvfp4_scaled_tma256k2_sw_20423.json ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "device": "NVIDIA GB10",
3
+ "from_product_min_ms": 6.1193,
4
+ "from_product_vs_kitchen_q": 0,
5
+ "from_product_vs_kitchen_s": 0,
6
+ "from_product_vs_kitchen_scale_exact": true,
7
+ "full_finite": true,
8
+ "identity": "SWIZZLE_64B TMA == linear fragment under phys_col = col XOR (((row>>1)&3)<<4) on the kitchen-legal K=128 / 256x64 3-stage m16n8k64 paired-N atom",
9
+ "k": 5376,
10
+ "k2_prod_min_ms": 36.5662,
11
+ "kitchen_gemm_min_ms": 20.2433,
12
+ "n": 14336,
13
+ "pass": true,
14
+ "prod_finite": true,
15
+ "product_vs_eager_full_mismatches": 0,
16
+ "product_vs_eager_kitchen_mismatches": 0,
17
+ "rows": 20423,
18
+ "sw_full_min_ms": 39.6867,
19
+ "sw_full_vs_kitchen_max_abs": 0.0,
20
+ "sw_full_vs_kitchen_mismatches": 0,
21
+ "sw_prod_min_ms": 37.5803,
22
+ "sw_prod_vs_k2_prod": 0,
23
+ "vs_k2_ms": -1.0141
24
+ }
labs/swiglu_nvfp4/native_cuda/gate_fc1_nvfp4_scaled_tma256k2n2.py ADDED
@@ -0,0 +1,94 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """Byte-exact gate: sequential N-halves stream A once on 256x64 acc.
3
+
4
+ One A K=128 TMA feeds two 64-wide N-halves. Acc0 stays in the k2
5
+ 2x8x4 register budget; acc1 swaps through opt-in smem. Same PTX
6
+ fragment and cuBLAS 128x4 scale slabs.
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ import json
12
+ from pathlib import Path
13
+
14
+ import torch
15
+
16
+ import comfy_kitchen as ck
17
+
18
+ from swiglu_nvfp4 import (
19
+ fc1_paired_nvfp4_scaled_tma256k2n2,
20
+ load_extension,
21
+ )
22
+
23
+
24
+ ROWS = 20423
25
+ K = 5376
26
+ N = 14336
27
+
28
+
29
+ def nvfp4_scale(x: torch.Tensor) -> torch.Tensor:
30
+ return (x.abs().amax() / (6.0 * 448.0)).to(torch.float32).reshape(1)
31
+
32
+
33
+ def main() -> int:
34
+ load_extension(verbose=False)
35
+ device = torch.device("cuda")
36
+ props = torch.cuda.get_device_properties(device)
37
+ optin = int(getattr(props, "shared_memory_per_block_optin", 0))
38
+ acc_bytes = 256 * 128 * 4
39
+ tile_smem = 209024
40
+ torch.manual_seed(26081247)
41
+ x = torch.randn(ROWS, K, device=device, dtype=torch.bfloat16)
42
+ weight = torch.randn(2 * N, K, device=device, dtype=torch.bfloat16) * 0.02
43
+ sx = nvfp4_scale(x)
44
+ sw = nvfp4_scale(weight)
45
+ qx, qxs = ck.quantize_nvfp4(x, sx, pad_16x=True, hi_first=True)
46
+ qw, qws = ck.quantize_nvfp4(weight, sw, pad_16x=True, hi_first=True)
47
+ qx_live = qx[:ROWS].contiguous()
48
+ alpha = (sx * sw).reshape(1).contiguous()
49
+ launch_error = ""
50
+ launched = False
51
+ try:
52
+ _ = fc1_paired_nvfp4_scaled_tma256k2n2(
53
+ qx_live, qxs, qw, qws, alpha, product=False
54
+ )
55
+ launched = True
56
+ except RuntimeError as exc:
57
+ launch_error = str(exc)
58
+ payload = {
59
+ "identity": (
60
+ "Sequential N-halves that stream A once need a second "
61
+ "256x64 FP32 acc (128 KiB) plus TMA. GB10 block opt-in "
62
+ "is 99 KiB, so acc1 cannot live in smem. Fail-closed."
63
+ ),
64
+ "rows": ROWS,
65
+ "k": K,
66
+ "n": N,
67
+ "device": torch.cuda.get_device_name(device),
68
+ "smem_per_block": int(props.shared_memory_per_block),
69
+ "smem_per_sm": int(props.shared_memory_per_multiprocessor),
70
+ "smem_optin": optin,
71
+ "acc1_bytes": acc_bytes,
72
+ "tile_smem_bytes": tile_smem,
73
+ "acc1_exceeds_optin": acc_bytes > optin,
74
+ "tile_exceeds_optin": tile_smem > optin,
75
+ "launched": launched,
76
+ "launch_error": launch_error,
77
+ }
78
+ payload["pass"] = (
79
+ not launched
80
+ and acc_bytes > optin
81
+ and tile_smem > optin
82
+ and optin <= 101376
83
+ and "opt-in" in launch_error
84
+ )
85
+ text = json.dumps(payload, indent=2, sort_keys=True)
86
+ Path(__file__).with_name(
87
+ "gate_fc1_nvfp4_scaled_tma256k2n2_20423.json"
88
+ ).write_text(text + "\n")
89
+ print(text)
90
+ return 0 if payload["pass"] else 2
91
+
92
+
93
+ if __name__ == "__main__":
94
+ raise SystemExit(main())
labs/swiglu_nvfp4/native_cuda/gate_fc1_nvfp4_scaled_tma256k2n2_20423.json ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "acc1_bytes": 131072,
3
+ "acc1_exceeds_optin": true,
4
+ "device": "NVIDIA GB10",
5
+ "identity": "Sequential N-halves that stream A once need a second 256x64 FP32 acc (128 KiB) plus TMA. GB10 block opt-in is 99 KiB, so acc1 cannot live in smem. Fail-closed.",
6
+ "k": 5376,
7
+ "launch_error": "sequential N-halves need 209024 B smem (131072 B FP32 acc1 + TMA); device opt-in is 101376 B",
8
+ "launched": false,
9
+ "n": 14336,
10
+ "pass": true,
11
+ "rows": 20423,
12
+ "smem_optin": 101376,
13
+ "smem_per_block": 49152,
14
+ "smem_per_sm": 102400,
15
+ "tile_exceeds_optin": true,
16
+ "tile_smem_bytes": 209024
17
+ }
labs/swiglu_nvfp4/native_cuda/gate_fc1_nvfp4_scaled_tma256k2p.py ADDED
@@ -0,0 +1,171 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """Byte-exact gate: persistent k2 N-walk == grid k2.
3
+
4
+ One 8-warp CTA owns 256 M and walks every 64-wide N tile. Same
5
+ m16n8k64 atom, 2x8x4 acc, and 3-stage K=128 TMA. A-stationary
6
+ so L2 can reuse the 256-row panel. Smem matches k2 (under 99 KiB).
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ import json
12
+ from pathlib import Path
13
+
14
+ import torch
15
+ import torch.nn.functional as F
16
+
17
+ import comfy_kitchen as ck
18
+
19
+ from swiglu_nvfp4 import (
20
+ bf16_nvfp4_dynamic,
21
+ fc1_paired_nvfp4_scaled_tma256k2,
22
+ fc1_paired_nvfp4_scaled_tma256k2p,
23
+ load_extension,
24
+ swiglu_nvfp4_dynamic,
25
+ )
26
+
27
+
28
+ ROWS = 20423
29
+ K = 5376
30
+ N = 14336
31
+
32
+
33
+ def nvfp4_scale(x: torch.Tensor) -> torch.Tensor:
34
+ return (x.abs().amax() / (6.0 * 448.0)).to(torch.float32).reshape(1)
35
+
36
+
37
+ def kitchen_gemm(qx, sx, qw, sw, scale_x, scale_w) -> torch.Tensor:
38
+ alpha = (scale_x * scale_w).reshape(1)
39
+ y = ck.scaled_mm_nvfp4(
40
+ qx, qw, scale_x, scale_w, sx, sw, out_dtype=torch.bfloat16, alpha=alpha
41
+ )
42
+ return y[:ROWS]
43
+
44
+
45
+ def eager_act(raw: torch.Tensor) -> torch.Tensor:
46
+ gate, up = raw.chunk(2, dim=-1)
47
+ return F.silu(gate).mul_(up)
48
+
49
+
50
+ def byte_diff(left: torch.Tensor, right: torch.Tensor) -> int:
51
+ return int((left.view(torch.uint8) != right.view(torch.uint8)).sum().item())
52
+
53
+
54
+ def max_abs_diff(left: torch.Tensor, right: torch.Tensor) -> float:
55
+ return float((left.float() - right.float()).abs().max().item())
56
+
57
+
58
+ def time_ms(fn) -> float:
59
+ starter = torch.cuda.Event(enable_timing=True)
60
+ ender = torch.cuda.Event(enable_timing=True)
61
+ fn()
62
+ torch.cuda.synchronize()
63
+ starter.record()
64
+ fn()
65
+ ender.record()
66
+ torch.cuda.synchronize()
67
+ return starter.elapsed_time(ender)
68
+
69
+
70
+ def main() -> int:
71
+ load_extension(verbose=False)
72
+ device = torch.device("cuda")
73
+ torch.manual_seed(26081249)
74
+ x = torch.randn(ROWS, K, device=device, dtype=torch.bfloat16)
75
+ weight = torch.randn(2 * N, K, device=device, dtype=torch.bfloat16) * 0.02
76
+ sx = nvfp4_scale(x)
77
+ sw = nvfp4_scale(weight)
78
+ qx, qxs = ck.quantize_nvfp4(x, sx, pad_16x=True, hi_first=True)
79
+ qw, qws = ck.quantize_nvfp4(weight, sw, pad_16x=True, hi_first=True)
80
+ qx_live = qx[:ROWS].contiguous()
81
+ alpha = (sx * sw).reshape(1).contiguous()
82
+ kitchen = kitchen_gemm(qx, qxs, qw, qws, sx, sw)
83
+ full = fc1_paired_nvfp4_scaled_tma256k2p(
84
+ qx_live, qxs, qw, qws, alpha, product=False
85
+ )
86
+ prod = fc1_paired_nvfp4_scaled_tma256k2p(
87
+ qx_live, qxs, qw, qws, alpha, product=True
88
+ )
89
+ k2 = fc1_paired_nvfp4_scaled_tma256k2(
90
+ qx_live, qxs, qw, qws, alpha, product=True
91
+ )
92
+ eager_kit = eager_act(kitchen.contiguous())
93
+ eager_full = eager_act(full)
94
+ two_q, two_s, two_g = swiglu_nvfp4_dynamic(kitchen.contiguous())
95
+ prod_q, prod_s, prod_g = bf16_nvfp4_dynamic(prod)
96
+ payload = {
97
+ "identity": (
98
+ "Persistent 8-warp k2 N-walk == grid k2: one CTA owns "
99
+ "256 M and walks every 64-wide N tile. Same m16n8k64 "
100
+ "atom, 2x8x4 acc, 3-stage K=128 TMA. A-stationary."
101
+ ),
102
+ "rows": ROWS,
103
+ "k": K,
104
+ "n": N,
105
+ "device": torch.cuda.get_device_name(device),
106
+ "p_full_vs_kitchen_mismatches": byte_diff(full, kitchen),
107
+ "p_full_vs_kitchen_max_abs": round(max_abs_diff(full, kitchen), 6),
108
+ "p_prod_vs_k2_prod": byte_diff(prod, k2),
109
+ "product_vs_eager_full_mismatches": byte_diff(prod, eager_full),
110
+ "product_vs_eager_kitchen_mismatches": byte_diff(prod, eager_kit),
111
+ "from_product_vs_kitchen_q": byte_diff(prod_q, two_q),
112
+ "from_product_vs_kitchen_s": byte_diff(prod_s, two_s),
113
+ "from_product_vs_kitchen_scale_exact": bool(torch.equal(prod_g, two_g)),
114
+ "full_finite": bool(torch.isfinite(full.float()).all().item()),
115
+ "prod_finite": bool(torch.isfinite(prod.float()).all().item()),
116
+ "kitchen_gemm_min_ms": round(
117
+ time_ms(lambda: kitchen_gemm(qx, qxs, qw, qws, sx, sw)), 4
118
+ ),
119
+ "p_full_min_ms": round(
120
+ time_ms(
121
+ lambda: fc1_paired_nvfp4_scaled_tma256k2p(
122
+ qx_live, qxs, qw, qws, alpha, product=False
123
+ )
124
+ ),
125
+ 4,
126
+ ),
127
+ "p_prod_min_ms": round(
128
+ time_ms(
129
+ lambda: fc1_paired_nvfp4_scaled_tma256k2p(
130
+ qx_live, qxs, qw, qws, alpha, product=True
131
+ )
132
+ ),
133
+ 4,
134
+ ),
135
+ "k2_prod_min_ms": round(
136
+ time_ms(
137
+ lambda: fc1_paired_nvfp4_scaled_tma256k2(
138
+ qx_live, qxs, qw, qws, alpha, product=True
139
+ )
140
+ ),
141
+ 4,
142
+ ),
143
+ "from_product_min_ms": round(
144
+ time_ms(lambda: bf16_nvfp4_dynamic(prod)), 4
145
+ ),
146
+ }
147
+ payload["pass"] = (
148
+ payload["p_full_vs_kitchen_mismatches"] == 0
149
+ and payload["p_prod_vs_k2_prod"] == 0
150
+ and payload["product_vs_eager_full_mismatches"] == 0
151
+ and payload["product_vs_eager_kitchen_mismatches"] == 0
152
+ and payload["from_product_vs_kitchen_q"] == 0
153
+ and payload["from_product_vs_kitchen_s"] == 0
154
+ and payload["from_product_vs_kitchen_scale_exact"]
155
+ and payload["full_finite"]
156
+ and payload["prod_finite"]
157
+ )
158
+ if payload["pass"]:
159
+ payload["vs_k2_ms"] = round(
160
+ payload["k2_prod_min_ms"] - payload["p_prod_min_ms"], 4
161
+ )
162
+ text = json.dumps(payload, indent=2, sort_keys=True)
163
+ Path(__file__).with_name(
164
+ "gate_fc1_nvfp4_scaled_tma256k2p_20423.json"
165
+ ).write_text(text + "\n")
166
+ print(text)
167
+ return 0 if payload["pass"] else 2
168
+
169
+
170
+ if __name__ == "__main__":
171
+ raise SystemExit(main())
labs/swiglu_nvfp4/native_cuda/gate_fc1_nvfp4_scaled_tma256k2p_20423.json ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "device": "NVIDIA GB10",
3
+ "from_product_min_ms": 6.057,
4
+ "from_product_vs_kitchen_q": 0,
5
+ "from_product_vs_kitchen_s": 0,
6
+ "from_product_vs_kitchen_scale_exact": true,
7
+ "full_finite": true,
8
+ "identity": "Persistent 8-warp k2 N-walk == grid k2: one CTA owns 256 M and walks every 64-wide N tile. Same m16n8k64 atom, 2x8x4 acc, 3-stage K=128 TMA. A-stationary.",
9
+ "k": 5376,
10
+ "k2_prod_min_ms": 38.1653,
11
+ "kitchen_gemm_min_ms": 20.2363,
12
+ "n": 14336,
13
+ "p_full_min_ms": 72.0819,
14
+ "p_full_vs_kitchen_max_abs": 0.0,
15
+ "p_full_vs_kitchen_mismatches": 0,
16
+ "p_prod_min_ms": 64.0328,
17
+ "p_prod_vs_k2_prod": 0,
18
+ "pass": true,
19
+ "prod_finite": true,
20
+ "product_vs_eager_full_mismatches": 0,
21
+ "product_vs_eager_kitchen_mismatches": 0,
22
+ "rows": 20423,
23
+ "vs_k2_ms": -25.8675
24
+ }
labs/swiglu_nvfp4/native_cuda/gate_fc1_nvfp4_scaled_tma256k2s1.py ADDED
@@ -0,0 +1,136 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """Byte-exact gate: 1-stage k2 == kitchen / 3-stage k2.
3
+
4
+ Same 256x64 K=128 paired-N atom. ~29 KiB smem so 2 CTAs/SM
5
+ is legal if the register file allows. Occupancy is the launch
6
+ variable; 3-stage k2 is ~86 KiB and 1-way.
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ import json
12
+ from pathlib import Path
13
+
14
+ import torch
15
+
16
+ import comfy_kitchen as ck
17
+
18
+ from swiglu_nvfp4 import (
19
+ fc1_paired_nvfp4_scaled_tma256k2,
20
+ fc1_paired_nvfp4_scaled_tma256k2s1,
21
+ fc1_paired_nvfp4_scaled_tma256k2s1_attrs,
22
+ load_extension,
23
+ )
24
+
25
+
26
+ ROWS = 20423
27
+ K = 5376
28
+ N = 14336
29
+
30
+
31
+ def nvfp4_scale(x: torch.Tensor) -> torch.Tensor:
32
+ return (x.abs().amax() / (6.0 * 448.0)).to(torch.float32).reshape(1)
33
+
34
+
35
+ def kitchen_gemm(qx, sx, qw, sw, scale_x, scale_w) -> torch.Tensor:
36
+ alpha = (scale_x * scale_w).reshape(1)
37
+ y = ck.scaled_mm_nvfp4(
38
+ qx, qw, scale_x, scale_w, sx, sw, out_dtype=torch.bfloat16, alpha=alpha
39
+ )
40
+ return y[:ROWS]
41
+
42
+
43
+ def byte_diff(left: torch.Tensor, right: torch.Tensor) -> int:
44
+ return int((left.view(torch.uint8) != right.view(torch.uint8)).sum().item())
45
+
46
+
47
+ def time_ms(fn) -> float:
48
+ starter = torch.cuda.Event(enable_timing=True)
49
+ ender = torch.cuda.Event(enable_timing=True)
50
+ fn()
51
+ torch.cuda.synchronize()
52
+ starter.record()
53
+ fn()
54
+ ender.record()
55
+ torch.cuda.synchronize()
56
+ return starter.elapsed_time(ender)
57
+
58
+
59
+ def main() -> int:
60
+ load_extension(verbose=False)
61
+ device = torch.device("cuda")
62
+ torch.manual_seed(26081271)
63
+ x = torch.randn(ROWS, K, device=device, dtype=torch.bfloat16)
64
+ weight = torch.randn(2 * N, K, device=device, dtype=torch.bfloat16) * 0.02
65
+ sx = nvfp4_scale(x)
66
+ sw = nvfp4_scale(weight)
67
+ qx, qxs = ck.quantize_nvfp4(x, sx, pad_16x=True, hi_first=True)
68
+ qw, qws = ck.quantize_nvfp4(weight, sw, pad_16x=True, hi_first=True)
69
+ qx_live = qx[:ROWS].contiguous()
70
+ alpha = (sx * sw).reshape(1).contiguous()
71
+ kitchen = kitchen_gemm(qx, qxs, qw, qws, sx, sw)
72
+ k2 = fc1_paired_nvfp4_scaled_tma256k2(
73
+ qx_live, qxs, qw, qws, alpha, product=False
74
+ )
75
+ s1 = fc1_paired_nvfp4_scaled_tma256k2s1(qx_live, qxs, qw, qws, alpha)
76
+ attrs = fc1_paired_nvfp4_scaled_tma256k2s1_attrs()
77
+ payload = {
78
+ "identity": (
79
+ "1-stage K=128 256x64 paired-N == kitchen == 3-stage k2. "
80
+ "Smem drop is the occupancy variable."
81
+ ),
82
+ "rows": ROWS,
83
+ "k": K,
84
+ "n": 2 * N,
85
+ "device": torch.cuda.get_device_name(device),
86
+ "s1_vs_kitchen_mismatches": byte_diff(s1, kitchen),
87
+ "s1_vs_k2_mismatches": byte_diff(s1, k2),
88
+ "full_finite": bool(torch.isfinite(s1.float()).all().item()),
89
+ "s1_regs": int(attrs["s1_regs"]),
90
+ "s1_smem": int(attrs["s1_smem"]),
91
+ "s1_occupancy": int(attrs["s1_occupancy"]),
92
+ "k2_regs": int(attrs["k2_regs"]),
93
+ "k2_smem": int(attrs["k2_smem"]),
94
+ "k2_occupancy": int(attrs["k2_occupancy"]),
95
+ "kitchen_gemm_min_ms": round(
96
+ time_ms(lambda: kitchen_gemm(qx, qxs, qw, qws, sx, sw)), 4
97
+ ),
98
+ "s1_full_min_ms": round(
99
+ time_ms(
100
+ lambda: fc1_paired_nvfp4_scaled_tma256k2s1(
101
+ qx_live, qxs, qw, qws, alpha
102
+ )
103
+ ),
104
+ 4,
105
+ ),
106
+ "k2_full_min_ms": round(
107
+ time_ms(
108
+ lambda: fc1_paired_nvfp4_scaled_tma256k2(
109
+ qx_live, qxs, qw, qws, alpha, product=False
110
+ )
111
+ ),
112
+ 4,
113
+ ),
114
+ }
115
+ payload["pass"] = (
116
+ payload["s1_vs_kitchen_mismatches"] == 0
117
+ and payload["s1_vs_k2_mismatches"] == 0
118
+ and payload["full_finite"]
119
+ )
120
+ if payload["pass"]:
121
+ payload["vs_kitchen_ms"] = round(
122
+ payload["kitchen_gemm_min_ms"] - payload["s1_full_min_ms"], 4
123
+ )
124
+ payload["vs_k2_ms"] = round(
125
+ payload["k2_full_min_ms"] - payload["s1_full_min_ms"], 4
126
+ )
127
+ text = json.dumps(payload, indent=2, sort_keys=True)
128
+ Path(__file__).with_name(
129
+ "gate_fc1_nvfp4_scaled_tma256k2s1_20423.json"
130
+ ).write_text(text + "\n")
131
+ print(text)
132
+ return 0 if payload["pass"] else 2
133
+
134
+
135
+ if __name__ == "__main__":
136
+ raise SystemExit(main())
labs/swiglu_nvfp4/native_cuda/gate_fc1_nvfp4_scaled_tma256k2s1_20423.json ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "device": "NVIDIA GB10",
3
+ "full_finite": true,
4
+ "identity": "1-stage K=128 256x64 paired-N == kitchen == 3-stage k2. Smem drop is the occupancy variable.",
5
+ "k": 5376,
6
+ "k2_full_min_ms": 40.4624,
7
+ "k2_occupancy": 1,
8
+ "k2_regs": 167,
9
+ "k2_smem": 86144,
10
+ "kitchen_gemm_min_ms": 20.0947,
11
+ "n": 28672,
12
+ "pass": true,
13
+ "rows": 20423,
14
+ "s1_full_min_ms": 47.8348,
15
+ "s1_occupancy": 1,
16
+ "s1_regs": 166,
17
+ "s1_smem": 28800,
18
+ "s1_vs_k2_mismatches": 0,
19
+ "s1_vs_kitchen_mismatches": 0,
20
+ "vs_k2_ms": -7.3724,
21
+ "vs_kitchen_ms": -27.7401
22
+ }
labs/swiglu_nvfp4/native_cuda/gate_fc1_nvfp4_scaled_tma256k2ws.py ADDED
@@ -0,0 +1,171 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """Byte-exact gate: warp-specialized k2 == unified k2.
3
+
4
+ Producer warp issues TMA; eight MMA warps keep the 256x64
5
+ m16n8k64 atom and 2x8x4 acc. Same smem as k2 (under 99 KiB).
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ import json
11
+ from pathlib import Path
12
+
13
+ import torch
14
+ import torch.nn.functional as F
15
+
16
+ import comfy_kitchen as ck
17
+
18
+ from swiglu_nvfp4 import (
19
+ bf16_nvfp4_dynamic,
20
+ fc1_paired_nvfp4_scaled_tma256k2,
21
+ fc1_paired_nvfp4_scaled_tma256k2ws,
22
+ load_extension,
23
+ swiglu_nvfp4_dynamic,
24
+ )
25
+
26
+
27
+ ROWS = 20423
28
+ K = 5376
29
+ N = 14336
30
+
31
+
32
+ def nvfp4_scale(x: torch.Tensor) -> torch.Tensor:
33
+ return (x.abs().amax() / (6.0 * 448.0)).to(torch.float32).reshape(1)
34
+
35
+
36
+ def kitchen_gemm(qx, sx, qw, sw, scale_x, scale_w) -> torch.Tensor:
37
+ alpha = (scale_x * scale_w).reshape(1)
38
+ y = ck.scaled_mm_nvfp4(
39
+ qx, qw, scale_x, scale_w, sx, sw, out_dtype=torch.bfloat16, alpha=alpha
40
+ )
41
+ return y[:ROWS]
42
+
43
+
44
+ def eager_act(raw: torch.Tensor) -> torch.Tensor:
45
+ gate, up = raw.chunk(2, dim=-1)
46
+ return F.silu(gate).mul_(up)
47
+
48
+
49
+ def byte_diff(left: torch.Tensor, right: torch.Tensor) -> int:
50
+ return int((left.view(torch.uint8) != right.view(torch.uint8)).sum().item())
51
+
52
+
53
+ def max_abs_diff(left: torch.Tensor, right: torch.Tensor) -> float:
54
+ return float((left.float() - right.float()).abs().max().item())
55
+
56
+
57
+ def time_ms(fn) -> float:
58
+ starter = torch.cuda.Event(enable_timing=True)
59
+ ender = torch.cuda.Event(enable_timing=True)
60
+ fn()
61
+ torch.cuda.synchronize()
62
+ starter.record()
63
+ fn()
64
+ ender.record()
65
+ torch.cuda.synchronize()
66
+ return starter.elapsed_time(ender)
67
+
68
+
69
+ def main() -> int:
70
+ load_extension(verbose=False)
71
+ device = torch.device("cuda")
72
+ torch.manual_seed(26081248)
73
+ x = torch.randn(ROWS, K, device=device, dtype=torch.bfloat16)
74
+ weight = torch.randn(2 * N, K, device=device, dtype=torch.bfloat16) * 0.02
75
+ sx = nvfp4_scale(x)
76
+ sw = nvfp4_scale(weight)
77
+ qx, qxs = ck.quantize_nvfp4(x, sx, pad_16x=True, hi_first=True)
78
+ qw, qws = ck.quantize_nvfp4(weight, sw, pad_16x=True, hi_first=True)
79
+ qx_live = qx[:ROWS].contiguous()
80
+ alpha = (sx * sw).reshape(1).contiguous()
81
+ kitchen = kitchen_gemm(qx, qxs, qw, qws, sx, sw)
82
+ full = fc1_paired_nvfp4_scaled_tma256k2ws(
83
+ qx_live, qxs, qw, qws, alpha, product=False
84
+ )
85
+ prod = fc1_paired_nvfp4_scaled_tma256k2ws(
86
+ qx_live, qxs, qw, qws, alpha, product=True
87
+ )
88
+ k2 = fc1_paired_nvfp4_scaled_tma256k2(
89
+ qx_live, qxs, qw, qws, alpha, product=True
90
+ )
91
+ eager_kit = eager_act(kitchen.contiguous())
92
+ eager_full = eager_act(full)
93
+ two_q, two_s, two_g = swiglu_nvfp4_dynamic(kitchen.contiguous())
94
+ prod_q, prod_s, prod_g = bf16_nvfp4_dynamic(prod)
95
+ payload = {
96
+ "identity": (
97
+ "Warp-specialized k2 == unified k2: producer warp issues "
98
+ "TMA; eight MMA warps keep the 256x64 m16n8k64 atom and "
99
+ "2x8x4 acc. Full/empty mbarriers, no mainloop syncthreads. "
100
+ "Smem matches k2 (under 99 KiB)."
101
+ ),
102
+ "rows": ROWS,
103
+ "k": K,
104
+ "n": N,
105
+ "device": torch.cuda.get_device_name(device),
106
+ "ws_full_vs_kitchen_mismatches": byte_diff(full, kitchen),
107
+ "ws_full_vs_kitchen_max_abs": round(max_abs_diff(full, kitchen), 6),
108
+ "ws_prod_vs_k2_prod": byte_diff(prod, k2),
109
+ "product_vs_eager_full_mismatches": byte_diff(prod, eager_full),
110
+ "product_vs_eager_kitchen_mismatches": byte_diff(prod, eager_kit),
111
+ "from_product_vs_kitchen_q": byte_diff(prod_q, two_q),
112
+ "from_product_vs_kitchen_s": byte_diff(prod_s, two_s),
113
+ "from_product_vs_kitchen_scale_exact": bool(torch.equal(prod_g, two_g)),
114
+ "full_finite": bool(torch.isfinite(full.float()).all().item()),
115
+ "prod_finite": bool(torch.isfinite(prod.float()).all().item()),
116
+ "kitchen_gemm_min_ms": round(
117
+ time_ms(lambda: kitchen_gemm(qx, qxs, qw, qws, sx, sw)), 4
118
+ ),
119
+ "ws_full_min_ms": round(
120
+ time_ms(
121
+ lambda: fc1_paired_nvfp4_scaled_tma256k2ws(
122
+ qx_live, qxs, qw, qws, alpha, product=False
123
+ )
124
+ ),
125
+ 4,
126
+ ),
127
+ "ws_prod_min_ms": round(
128
+ time_ms(
129
+ lambda: fc1_paired_nvfp4_scaled_tma256k2ws(
130
+ qx_live, qxs, qw, qws, alpha, product=True
131
+ )
132
+ ),
133
+ 4,
134
+ ),
135
+ "k2_prod_min_ms": round(
136
+ time_ms(
137
+ lambda: fc1_paired_nvfp4_scaled_tma256k2(
138
+ qx_live, qxs, qw, qws, alpha, product=True
139
+ )
140
+ ),
141
+ 4,
142
+ ),
143
+ "from_product_min_ms": round(
144
+ time_ms(lambda: bf16_nvfp4_dynamic(prod)), 4
145
+ ),
146
+ }
147
+ payload["pass"] = (
148
+ payload["ws_full_vs_kitchen_mismatches"] == 0
149
+ and payload["ws_prod_vs_k2_prod"] == 0
150
+ and payload["product_vs_eager_full_mismatches"] == 0
151
+ and payload["product_vs_eager_kitchen_mismatches"] == 0
152
+ and payload["from_product_vs_kitchen_q"] == 0
153
+ and payload["from_product_vs_kitchen_s"] == 0
154
+ and payload["from_product_vs_kitchen_scale_exact"]
155
+ and payload["full_finite"]
156
+ and payload["prod_finite"]
157
+ )
158
+ if payload["pass"]:
159
+ payload["vs_k2_ms"] = round(
160
+ payload["k2_prod_min_ms"] - payload["ws_prod_min_ms"], 4
161
+ )
162
+ text = json.dumps(payload, indent=2, sort_keys=True)
163
+ Path(__file__).with_name(
164
+ "gate_fc1_nvfp4_scaled_tma256k2ws_20423.json"
165
+ ).write_text(text + "\n")
166
+ print(text)
167
+ return 0 if payload["pass"] else 2
168
+
169
+
170
+ if __name__ == "__main__":
171
+ raise SystemExit(main())
labs/swiglu_nvfp4/native_cuda/gate_fc1_nvfp4_scaled_tma256k2ws4.py ADDED
@@ -0,0 +1,142 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """Byte-exact gate: 12-warp 4-producer k2 == kitchen == k2.
3
+
4
+ Kitchen launch structure (4 TMA warps + 8 MMA) on the best lab
5
+ tile (256x64 K=128 paired-N). 9-warp k2ws serializes every TMA
6
+ on one lane; this issues A / Bg / Bu / scales in parallel.
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ import json
12
+ from pathlib import Path
13
+
14
+ import torch
15
+
16
+ import comfy_kitchen as ck
17
+
18
+ from swiglu_nvfp4 import (
19
+ fc1_paired_nvfp4_scaled_tma256k2,
20
+ fc1_paired_nvfp4_scaled_tma256k2ws4,
21
+ fc1_paired_nvfp4_scaled_tma256k2ws4_attrs,
22
+ load_extension,
23
+ )
24
+
25
+
26
+ ROWS = 20423
27
+ K = 5376
28
+ N = 14336
29
+
30
+
31
+ def nvfp4_scale(x: torch.Tensor) -> torch.Tensor:
32
+ return (x.abs().amax() / (6.0 * 448.0)).to(torch.float32).reshape(1)
33
+
34
+
35
+ def kitchen_gemm(qx, sx, qw, sw, scale_x, scale_w) -> torch.Tensor:
36
+ alpha = (scale_x * scale_w).reshape(1)
37
+ y = ck.scaled_mm_nvfp4(
38
+ qx, qw, scale_x, scale_w, sx, sw, out_dtype=torch.bfloat16, alpha=alpha
39
+ )
40
+ return y[:ROWS]
41
+
42
+
43
+ def byte_diff(left: torch.Tensor, right: torch.Tensor) -> int:
44
+ return int((left.view(torch.uint8) != right.view(torch.uint8)).sum().item())
45
+
46
+
47
+ def max_abs_diff(left: torch.Tensor, right: torch.Tensor) -> float:
48
+ return float((left.float() - right.float()).abs().max().item())
49
+
50
+
51
+ def time_ms(fn) -> float:
52
+ starter = torch.cuda.Event(enable_timing=True)
53
+ ender = torch.cuda.Event(enable_timing=True)
54
+ fn()
55
+ torch.cuda.synchronize()
56
+ starter.record()
57
+ fn()
58
+ ender.record()
59
+ torch.cuda.synchronize()
60
+ return starter.elapsed_time(ender)
61
+
62
+
63
+ def main() -> int:
64
+ load_extension(verbose=False)
65
+ device = torch.device("cuda")
66
+ torch.manual_seed(26081274)
67
+ x = torch.randn(ROWS, K, device=device, dtype=torch.bfloat16)
68
+ weight = torch.randn(2 * N, K, device=device, dtype=torch.bfloat16) * 0.02
69
+ sx = nvfp4_scale(x)
70
+ sw = nvfp4_scale(weight)
71
+ qx, qxs = ck.quantize_nvfp4(x, sx, pad_16x=True, hi_first=True)
72
+ qw, qws = ck.quantize_nvfp4(weight, sw, pad_16x=True, hi_first=True)
73
+ qx_live = qx[:ROWS].contiguous()
74
+ alpha = (sx * sw).reshape(1).contiguous()
75
+ kitchen = kitchen_gemm(qx, qxs, qw, qws, sx, sw)
76
+ k2 = fc1_paired_nvfp4_scaled_tma256k2(
77
+ qx_live, qxs, qw, qws, alpha, product=False
78
+ )
79
+ ws4 = fc1_paired_nvfp4_scaled_tma256k2ws4(qx_live, qxs, qw, qws, alpha)
80
+ attrs = fc1_paired_nvfp4_scaled_tma256k2ws4_attrs()
81
+ payload = {
82
+ "identity": (
83
+ "12-warp 4-producer + 8-MMA on k2 256x64 K=128 == kitchen "
84
+ "== unified k2. Kitchen launch split: A / Bg / Bu / scales "
85
+ "issue in parallel. Same atom and smem as k2."
86
+ ),
87
+ "rows": ROWS,
88
+ "k": K,
89
+ "n": 2 * N,
90
+ "device": torch.cuda.get_device_name(device),
91
+ "ws4_vs_kitchen_mismatches": byte_diff(ws4, kitchen),
92
+ "ws4_vs_kitchen_max_abs": round(max_abs_diff(ws4, kitchen), 6),
93
+ "ws4_vs_k2_mismatches": byte_diff(ws4, k2),
94
+ "full_finite": bool(torch.isfinite(ws4.float()).all().item()),
95
+ "ws4_regs": int(attrs["regs"]),
96
+ "ws4_smem": int(attrs["smem"]),
97
+ "ws4_occupancy": int(attrs["occupancy"]),
98
+ "ws4_threads": int(attrs["threads"]),
99
+ "ws4_warps": int(attrs["warps"]),
100
+ "ws4_prod_warps": int(attrs["prod_warps"]),
101
+ "kitchen_gemm_min_ms": round(
102
+ time_ms(lambda: kitchen_gemm(qx, qxs, qw, qws, sx, sw)), 4
103
+ ),
104
+ "ws4_full_min_ms": round(
105
+ time_ms(
106
+ lambda: fc1_paired_nvfp4_scaled_tma256k2ws4(
107
+ qx_live, qxs, qw, qws, alpha
108
+ )
109
+ ),
110
+ 4,
111
+ ),
112
+ "k2_full_min_ms": round(
113
+ time_ms(
114
+ lambda: fc1_paired_nvfp4_scaled_tma256k2(
115
+ qx_live, qxs, qw, qws, alpha, product=False
116
+ )
117
+ ),
118
+ 4,
119
+ ),
120
+ }
121
+ payload["pass"] = (
122
+ payload["ws4_vs_kitchen_mismatches"] == 0
123
+ and payload["ws4_vs_k2_mismatches"] == 0
124
+ and payload["full_finite"]
125
+ )
126
+ if payload["pass"]:
127
+ payload["vs_kitchen_ms"] = round(
128
+ payload["kitchen_gemm_min_ms"] - payload["ws4_full_min_ms"], 4
129
+ )
130
+ payload["vs_k2_ms"] = round(
131
+ payload["k2_full_min_ms"] - payload["ws4_full_min_ms"], 4
132
+ )
133
+ text = json.dumps(payload, indent=2, sort_keys=True)
134
+ Path(__file__).with_name(
135
+ "gate_fc1_nvfp4_scaled_tma256k2ws4_20423.json"
136
+ ).write_text(text + "\n")
137
+ print(text)
138
+ return 0 if payload["pass"] else 2
139
+
140
+
141
+ if __name__ == "__main__":
142
+ raise SystemExit(main())
labs/swiglu_nvfp4/native_cuda/gate_fc1_nvfp4_scaled_tma256k2ws4_20423.json ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "device": "NVIDIA GB10",
3
+ "full_finite": true,
4
+ "identity": "12-warp 4-producer + 8-MMA on k2 256x64 K=128 == kitchen == unified k2. Kitchen launch split: A / Bg / Bu / scales issue in parallel. Same atom and smem as k2.",
5
+ "k": 5376,
6
+ "k2_full_min_ms": 39.2012,
7
+ "kitchen_gemm_min_ms": 20.1714,
8
+ "n": 28672,
9
+ "pass": true,
10
+ "rows": 20423,
11
+ "vs_k2_ms": -1.5219,
12
+ "vs_kitchen_ms": -20.5517,
13
+ "ws4_full_min_ms": 40.7231,
14
+ "ws4_occupancy": 1,
15
+ "ws4_prod_warps": 4,
16
+ "ws4_regs": 168,
17
+ "ws4_smem": 86144,
18
+ "ws4_threads": 384,
19
+ "ws4_vs_k2_mismatches": 0,
20
+ "ws4_vs_kitchen_max_abs": 0.0,
21
+ "ws4_vs_kitchen_mismatches": 0,
22
+ "ws4_warps": 12
23
+ }
labs/swiglu_nvfp4/native_cuda/gate_fc1_nvfp4_scaled_tma256k2ws_20423.json ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "device": "NVIDIA GB10",
3
+ "from_product_min_ms": 5.7406,
4
+ "from_product_vs_kitchen_q": 0,
5
+ "from_product_vs_kitchen_s": 0,
6
+ "from_product_vs_kitchen_scale_exact": true,
7
+ "full_finite": true,
8
+ "identity": "Warp-specialized k2 == unified k2: producer warp issues TMA; eight MMA warps keep the 256x64 m16n8k64 atom and 2x8x4 acc. Full/empty mbarriers, no mainloop syncthreads. Smem matches k2 (under 99 KiB).",
9
+ "k": 5376,
10
+ "k2_prod_min_ms": 35.79,
11
+ "kitchen_gemm_min_ms": 20.1856,
12
+ "n": 14336,
13
+ "pass": true,
14
+ "prod_finite": true,
15
+ "product_vs_eager_full_mismatches": 0,
16
+ "product_vs_eager_kitchen_mismatches": 0,
17
+ "rows": 20423,
18
+ "vs_k2_ms": -1.5863,
19
+ "ws_full_min_ms": 48.2706,
20
+ "ws_full_vs_kitchen_max_abs": 0.0,
21
+ "ws_full_vs_kitchen_mismatches": 0,
22
+ "ws_prod_min_ms": 37.3763,
23
+ "ws_prod_vs_k2_prod": 0
24
+ }
labs/swiglu_nvfp4/native_cuda/gate_fc1_nvfp4_scaled_tma256k4.py ADDED
@@ -0,0 +1,173 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """Byte-exact gate: K=256 TMA box on the 256x64 tile.
3
+
4
+ One TMA of 128 packed bytes feeds four m16n8k64 atoms. Keeps the
5
+ 256x64 k2 register budget (2x8x4). 1-stage: 2-stage at this box
6
+ is 112 KiB and exceeds the 99 KiB static smem cap.
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ import json
12
+ from pathlib import Path
13
+
14
+ import torch
15
+ import torch.nn.functional as F
16
+
17
+ import comfy_kitchen as ck
18
+
19
+ from swiglu_nvfp4 import (
20
+ bf16_nvfp4_dynamic,
21
+ fc1_paired_nvfp4_scaled_tma256k2,
22
+ fc1_paired_nvfp4_scaled_tma256k4,
23
+ load_extension,
24
+ swiglu_nvfp4_dynamic,
25
+ )
26
+
27
+
28
+ ROWS = 20423
29
+ K = 5376
30
+ N = 14336
31
+
32
+
33
+ def nvfp4_scale(x: torch.Tensor) -> torch.Tensor:
34
+ return (x.abs().amax() / (6.0 * 448.0)).to(torch.float32).reshape(1)
35
+
36
+
37
+ def kitchen_gemm(qx, sx, qw, sw, scale_x, scale_w) -> torch.Tensor:
38
+ alpha = (scale_x * scale_w).reshape(1)
39
+ y = ck.scaled_mm_nvfp4(
40
+ qx, qw, scale_x, scale_w, sx, sw, out_dtype=torch.bfloat16, alpha=alpha
41
+ )
42
+ return y[:ROWS]
43
+
44
+
45
+ def eager_act(raw: torch.Tensor) -> torch.Tensor:
46
+ gate, up = raw.chunk(2, dim=-1)
47
+ return F.silu(gate).mul_(up)
48
+
49
+
50
+ def byte_diff(left: torch.Tensor, right: torch.Tensor) -> int:
51
+ return int((left.view(torch.uint8) != right.view(torch.uint8)).sum().item())
52
+
53
+
54
+ def max_abs_diff(left: torch.Tensor, right: torch.Tensor) -> float:
55
+ return float((left.float() - right.float()).abs().max().item())
56
+
57
+
58
+ def time_ms(fn) -> float:
59
+ starter = torch.cuda.Event(enable_timing=True)
60
+ ender = torch.cuda.Event(enable_timing=True)
61
+ fn()
62
+ torch.cuda.synchronize()
63
+ starter.record()
64
+ fn()
65
+ ender.record()
66
+ torch.cuda.synchronize()
67
+ return starter.elapsed_time(ender)
68
+
69
+
70
+ def main() -> int:
71
+ load_extension(verbose=False)
72
+ device = torch.device("cuda")
73
+ torch.manual_seed(26081246)
74
+ x = torch.randn(ROWS, K, device=device, dtype=torch.bfloat16)
75
+ weight = torch.randn(2 * N, K, device=device, dtype=torch.bfloat16) * 0.02
76
+ sx = nvfp4_scale(x)
77
+ sw = nvfp4_scale(weight)
78
+ qx, qxs = ck.quantize_nvfp4(x, sx, pad_16x=True, hi_first=True)
79
+ qw, qws = ck.quantize_nvfp4(weight, sw, pad_16x=True, hi_first=True)
80
+ qx_live = qx[:ROWS].contiguous()
81
+ alpha = (sx * sw).reshape(1).contiguous()
82
+ kitchen = kitchen_gemm(qx, qxs, qw, qws, sx, sw)
83
+ full = fc1_paired_nvfp4_scaled_tma256k4(
84
+ qx_live, qxs, qw, qws, alpha, product=False
85
+ )
86
+ prod = fc1_paired_nvfp4_scaled_tma256k4(
87
+ qx_live, qxs, qw, qws, alpha, product=True
88
+ )
89
+ k2 = fc1_paired_nvfp4_scaled_tma256k2(
90
+ qx_live, qxs, qw, qws, alpha, product=True
91
+ )
92
+ eager_kit = eager_act(kitchen.contiguous())
93
+ eager_full = eager_act(full)
94
+ two_q, two_s, two_g = swiglu_nvfp4_dynamic(kitchen.contiguous())
95
+ prod_q, prod_s, prod_g = bf16_nvfp4_dynamic(prod)
96
+ payload = {
97
+ "identity": (
98
+ "K=256 TMA box == four sequential K=64 MMA steps on the "
99
+ "256x64 tile: one 128-byte packed row feeds four m16n8k64 "
100
+ "atoms; four 128x4 scale slabs cover the 16 K-scale columns. "
101
+ "Same 2x8x4 register acc as k2. 1-stage: 2-stage box "
102
+ "exceeds the 99 KiB static smem cap."
103
+ ),
104
+ "rows": ROWS,
105
+ "k": K,
106
+ "n": N,
107
+ "device": torch.cuda.get_device_name(device),
108
+ "k4_full_vs_kitchen_mismatches": byte_diff(full, kitchen),
109
+ "k4_full_vs_kitchen_max_abs": round(max_abs_diff(full, kitchen), 6),
110
+ "k4_prod_vs_k2_prod": byte_diff(prod, k2),
111
+ "product_vs_eager_full_mismatches": byte_diff(prod, eager_full),
112
+ "product_vs_eager_kitchen_mismatches": byte_diff(prod, eager_kit),
113
+ "from_product_vs_kitchen_q": byte_diff(prod_q, two_q),
114
+ "from_product_vs_kitchen_s": byte_diff(prod_s, two_s),
115
+ "from_product_vs_kitchen_scale_exact": bool(torch.equal(prod_g, two_g)),
116
+ "full_finite": bool(torch.isfinite(full.float()).all().item()),
117
+ "prod_finite": bool(torch.isfinite(prod.float()).all().item()),
118
+ "kitchen_gemm_min_ms": round(
119
+ time_ms(lambda: kitchen_gemm(qx, qxs, qw, qws, sx, sw)), 4
120
+ ),
121
+ "k4_full_min_ms": round(
122
+ time_ms(
123
+ lambda: fc1_paired_nvfp4_scaled_tma256k4(
124
+ qx_live, qxs, qw, qws, alpha, product=False
125
+ )
126
+ ),
127
+ 4,
128
+ ),
129
+ "k4_prod_min_ms": round(
130
+ time_ms(
131
+ lambda: fc1_paired_nvfp4_scaled_tma256k4(
132
+ qx_live, qxs, qw, qws, alpha, product=True
133
+ )
134
+ ),
135
+ 4,
136
+ ),
137
+ "k2_prod_min_ms": round(
138
+ time_ms(
139
+ lambda: fc1_paired_nvfp4_scaled_tma256k2(
140
+ qx_live, qxs, qw, qws, alpha, product=True
141
+ )
142
+ ),
143
+ 4,
144
+ ),
145
+ "from_product_min_ms": round(
146
+ time_ms(lambda: bf16_nvfp4_dynamic(prod)), 4
147
+ ),
148
+ }
149
+ payload["pass"] = (
150
+ payload["k4_full_vs_kitchen_mismatches"] == 0
151
+ and payload["k4_prod_vs_k2_prod"] == 0
152
+ and payload["product_vs_eager_full_mismatches"] == 0
153
+ and payload["product_vs_eager_kitchen_mismatches"] == 0
154
+ and payload["from_product_vs_kitchen_q"] == 0
155
+ and payload["from_product_vs_kitchen_s"] == 0
156
+ and payload["from_product_vs_kitchen_scale_exact"]
157
+ and payload["full_finite"]
158
+ and payload["prod_finite"]
159
+ )
160
+ if payload["pass"]:
161
+ payload["vs_k2_ms"] = round(
162
+ payload["k2_prod_min_ms"] - payload["k4_prod_min_ms"], 4
163
+ )
164
+ text = json.dumps(payload, indent=2, sort_keys=True)
165
+ Path(__file__).with_name(
166
+ "gate_fc1_nvfp4_scaled_tma256k4_20423.json"
167
+ ).write_text(text + "\n")
168
+ print(text)
169
+ return 0 if payload["pass"] else 2
170
+
171
+
172
+ if __name__ == "__main__":
173
+ raise SystemExit(main())
labs/swiglu_nvfp4/native_cuda/gate_fc1_nvfp4_scaled_tma256k4_20423.json ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "device": "NVIDIA GB10",
3
+ "from_product_min_ms": 5.7432,
4
+ "from_product_vs_kitchen_q": 0,
5
+ "from_product_vs_kitchen_s": 0,
6
+ "from_product_vs_kitchen_scale_exact": true,
7
+ "full_finite": true,
8
+ "identity": "K=256 TMA box == four sequential K=64 MMA steps on the 256x64 tile: one 128-byte packed row feeds four m16n8k64 atoms; four 128x4 scale slabs cover the 16 K-scale columns. Same 2x8x4 register acc as k2. 1-stage: 2-stage box exceeds the 99 KiB static smem cap.",
9
+ "k": 5376,
10
+ "k2_prod_min_ms": 36.4231,
11
+ "k4_full_min_ms": 71.0255,
12
+ "k4_full_vs_kitchen_max_abs": 0.0,
13
+ "k4_full_vs_kitchen_mismatches": 0,
14
+ "k4_prod_min_ms": 65.1102,
15
+ "k4_prod_vs_k2_prod": 0,
16
+ "kitchen_gemm_min_ms": 19.9771,
17
+ "n": 14336,
18
+ "pass": true,
19
+ "prod_finite": true,
20
+ "product_vs_eager_full_mismatches": 0,
21
+ "product_vs_eager_kitchen_mismatches": 0,
22
+ "rows": 20423,
23
+ "vs_k2_ms": -28.6871
24
+ }
labs/swiglu_nvfp4/native_cuda/gate_fc1_nvfp4_scaled_tma256k4n1.py ADDED
@@ -0,0 +1,130 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """Byte-exact gate: K=256 2-stage on 256x64 single-N == kitchen / k2.
3
+
4
+ Paired 256x64 K=256 2-stage is 112 KiB (over the 99 KiB cap).
5
+ Dropping the second B operand (kitchen single-N) is 94 KiB and
6
+ gives a legal pipeline on the k2 M tile + kitchen K box.
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ import json
12
+ from pathlib import Path
13
+
14
+ import torch
15
+
16
+ import comfy_kitchen as ck
17
+
18
+ from swiglu_nvfp4 import (
19
+ fc1_nvfp4_scaled_tma256k4n1,
20
+ fc1_paired_nvfp4_scaled_tma256k2,
21
+ load_extension,
22
+ )
23
+
24
+
25
+ ROWS = 20423
26
+ K = 5376
27
+ N = 14336
28
+
29
+
30
+ def nvfp4_scale(x: torch.Tensor) -> torch.Tensor:
31
+ return (x.abs().amax() / (6.0 * 448.0)).to(torch.float32).reshape(1)
32
+
33
+
34
+ def kitchen_gemm(qx, sx, qw, sw, scale_x, scale_w) -> torch.Tensor:
35
+ alpha = (scale_x * scale_w).reshape(1)
36
+ y = ck.scaled_mm_nvfp4(
37
+ qx, qw, scale_x, scale_w, sx, sw, out_dtype=torch.bfloat16, alpha=alpha
38
+ )
39
+ return y[:ROWS]
40
+
41
+
42
+ def byte_diff(left: torch.Tensor, right: torch.Tensor) -> int:
43
+ return int((left.view(torch.uint8) != right.view(torch.uint8)).sum().item())
44
+
45
+
46
+ def time_ms(fn) -> float:
47
+ starter = torch.cuda.Event(enable_timing=True)
48
+ ender = torch.cuda.Event(enable_timing=True)
49
+ fn()
50
+ torch.cuda.synchronize()
51
+ starter.record()
52
+ fn()
53
+ ender.record()
54
+ torch.cuda.synchronize()
55
+ return starter.elapsed_time(ender)
56
+
57
+
58
+ def main() -> int:
59
+ load_extension(verbose=False)
60
+ device = torch.device("cuda")
61
+ torch.manual_seed(26081265)
62
+ x = torch.randn(ROWS, K, device=device, dtype=torch.bfloat16)
63
+ weight = torch.randn(2 * N, K, device=device, dtype=torch.bfloat16) * 0.02
64
+ sx = nvfp4_scale(x)
65
+ sw = nvfp4_scale(weight)
66
+ qx, qxs = ck.quantize_nvfp4(x, sx, pad_16x=True, hi_first=True)
67
+ qw, qws = ck.quantize_nvfp4(weight, sw, pad_16x=True, hi_first=True)
68
+ qx_live = qx[:ROWS].contiguous()
69
+ alpha = (sx * sw).reshape(1).contiguous()
70
+ kitchen = kitchen_gemm(qx, qxs, qw, qws, sx, sw)
71
+ k2 = fc1_paired_nvfp4_scaled_tma256k2(
72
+ qx_live, qxs, qw, qws, alpha, product=False
73
+ )
74
+ n1 = fc1_nvfp4_scaled_tma256k4n1(qx_live, qxs, qw, qws, alpha)
75
+ payload = {
76
+ "identity": (
77
+ "K=256 2-stage TMA on 256x64 single-N == four K=64 MMA "
78
+ "== kitchen == paired k2. Paired 2-stage is 112 KiB; "
79
+ "single-N is 94 KiB under the 99 KiB cap."
80
+ ),
81
+ "rows": ROWS,
82
+ "k": K,
83
+ "n": 2 * N,
84
+ "smem_bytes": 94336,
85
+ "device": torch.cuda.get_device_name(device),
86
+ "n1_vs_kitchen_mismatches": byte_diff(n1, kitchen),
87
+ "n1_vs_k2_mismatches": byte_diff(n1, k2),
88
+ "full_finite": bool(torch.isfinite(n1.float()).all().item()),
89
+ "kitchen_gemm_min_ms": round(
90
+ time_ms(lambda: kitchen_gemm(qx, qxs, qw, qws, sx, sw)), 4
91
+ ),
92
+ "n1_full_min_ms": round(
93
+ time_ms(
94
+ lambda: fc1_nvfp4_scaled_tma256k4n1(
95
+ qx_live, qxs, qw, qws, alpha
96
+ )
97
+ ),
98
+ 4,
99
+ ),
100
+ "k2_full_min_ms": round(
101
+ time_ms(
102
+ lambda: fc1_paired_nvfp4_scaled_tma256k2(
103
+ qx_live, qxs, qw, qws, alpha, product=False
104
+ )
105
+ ),
106
+ 4,
107
+ ),
108
+ }
109
+ payload["pass"] = (
110
+ payload["n1_vs_kitchen_mismatches"] == 0
111
+ and payload["n1_vs_k2_mismatches"] == 0
112
+ and payload["full_finite"]
113
+ )
114
+ if payload["pass"]:
115
+ payload["vs_kitchen_ms"] = round(
116
+ payload["kitchen_gemm_min_ms"] - payload["n1_full_min_ms"], 4
117
+ )
118
+ payload["vs_k2_ms"] = round(
119
+ payload["k2_full_min_ms"] - payload["n1_full_min_ms"], 4
120
+ )
121
+ text = json.dumps(payload, indent=2, sort_keys=True)
122
+ Path(__file__).with_name(
123
+ "gate_fc1_nvfp4_scaled_tma256k4n1_20423.json"
124
+ ).write_text(text + "\n")
125
+ print(text)
126
+ return 0 if payload["pass"] else 2
127
+
128
+
129
+ if __name__ == "__main__":
130
+ raise SystemExit(main())
labs/swiglu_nvfp4/native_cuda/gate_fc1_nvfp4_scaled_tma256k4n1_20423.json ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "device": "NVIDIA GB10",
3
+ "full_finite": true,
4
+ "identity": "K=256 2-stage TMA on 256x64 single-N == four K=64 MMA == kitchen == paired k2. Paired 2-stage is 112 KiB; single-N is 94 KiB under the 99 KiB cap.",
5
+ "k": 5376,
6
+ "k2_full_min_ms": 40.1932,
7
+ "kitchen_gemm_min_ms": 20.1874,
8
+ "n": 28672,
9
+ "n1_full_min_ms": 48.913,
10
+ "n1_vs_k2_mismatches": 0,
11
+ "n1_vs_kitchen_mismatches": 0,
12
+ "pass": true,
13
+ "rows": 20423,
14
+ "smem_bytes": 94336,
15
+ "vs_k2_ms": -8.7198,
16
+ "vs_kitchen_ms": -28.7256
17
+ }
labs/swiglu_nvfp4/native_cuda/gate_fc1_nvfp4_scaled_tma256n32.py ADDED
@@ -0,0 +1,133 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """Byte-exact gate: 256x32 K=128 1-stage == kitchen / k2.
3
+
4
+ Half-N of k2: 4 n-subtiles, 64-float acc. TMA B box is 64
5
+ (N=32 tile faults). 1-stage so two CTAs/SM can fit.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ import json
11
+ from pathlib import Path
12
+
13
+ import torch
14
+
15
+ import comfy_kitchen as ck
16
+
17
+ from swiglu_nvfp4 import (
18
+ fc1_paired_nvfp4_scaled_tma256k2,
19
+ fc1_paired_nvfp4_scaled_tma256n32,
20
+ fc1_paired_nvfp4_scaled_tma256n32_attrs,
21
+ load_extension,
22
+ )
23
+
24
+
25
+ ROWS = 20423
26
+ K = 5376
27
+ N = 14336
28
+
29
+
30
+ def nvfp4_scale(x: torch.Tensor) -> torch.Tensor:
31
+ return (x.abs().amax() / (6.0 * 448.0)).to(torch.float32).reshape(1)
32
+
33
+
34
+ def kitchen_gemm(qx, sx, qw, sw, scale_x, scale_w) -> torch.Tensor:
35
+ alpha = (scale_x * scale_w).reshape(1)
36
+ y = ck.scaled_mm_nvfp4(
37
+ qx, qw, scale_x, scale_w, sx, sw, out_dtype=torch.bfloat16, alpha=alpha
38
+ )
39
+ return y[:ROWS]
40
+
41
+
42
+ def byte_diff(left: torch.Tensor, right: torch.Tensor) -> int:
43
+ return int((left.view(torch.uint8) != right.view(torch.uint8)).sum().item())
44
+
45
+
46
+ def time_ms(fn) -> float:
47
+ starter = torch.cuda.Event(enable_timing=True)
48
+ ender = torch.cuda.Event(enable_timing=True)
49
+ fn()
50
+ torch.cuda.synchronize()
51
+ starter.record()
52
+ fn()
53
+ ender.record()
54
+ torch.cuda.synchronize()
55
+ return starter.elapsed_time(ender)
56
+
57
+
58
+ def main() -> int:
59
+ load_extension(verbose=False)
60
+ device = torch.device("cuda")
61
+ torch.manual_seed(26081272)
62
+ x = torch.randn(ROWS, K, device=device, dtype=torch.bfloat16)
63
+ weight = torch.randn(2 * N, K, device=device, dtype=torch.bfloat16) * 0.02
64
+ sx = nvfp4_scale(x)
65
+ sw = nvfp4_scale(weight)
66
+ qx, qxs = ck.quantize_nvfp4(x, sx, pad_16x=True, hi_first=True)
67
+ qw, qws = ck.quantize_nvfp4(weight, sw, pad_16x=True, hi_first=True)
68
+ qx_live = qx[:ROWS].contiguous()
69
+ alpha = (sx * sw).reshape(1).contiguous()
70
+ kitchen = kitchen_gemm(qx, qxs, qw, qws, sx, sw)
71
+ k2 = fc1_paired_nvfp4_scaled_tma256k2(
72
+ qx_live, qxs, qw, qws, alpha, product=False
73
+ )
74
+ n32 = fc1_paired_nvfp4_scaled_tma256n32(qx_live, qxs, qw, qws, alpha)
75
+ attrs = fc1_paired_nvfp4_scaled_tma256n32_attrs()
76
+ payload = {
77
+ "identity": (
78
+ "256x32 K=128 1-stage paired-N == kitchen == k2. "
79
+ "TMA B is 64; compute is 32. 64-float acc is the occupancy cut."
80
+ ),
81
+ "rows": ROWS,
82
+ "k": K,
83
+ "n": 2 * N,
84
+ "device": torch.cuda.get_device_name(device),
85
+ "n32_vs_kitchen_mismatches": byte_diff(n32, kitchen),
86
+ "n32_vs_k2_mismatches": byte_diff(n32, k2),
87
+ "full_finite": bool(torch.isfinite(n32.float()).all().item()),
88
+ "n32_regs": int(attrs["regs"]),
89
+ "n32_smem": int(attrs["smem"]),
90
+ "n32_occupancy": int(attrs["occupancy"]),
91
+ "n32_smem_struct": int(attrs["smem_struct"]),
92
+ "kitchen_gemm_min_ms": round(
93
+ time_ms(lambda: kitchen_gemm(qx, qxs, qw, qws, sx, sw)), 4
94
+ ),
95
+ "n32_full_min_ms": round(
96
+ time_ms(
97
+ lambda: fc1_paired_nvfp4_scaled_tma256n32(
98
+ qx_live, qxs, qw, qws, alpha
99
+ )
100
+ ),
101
+ 4,
102
+ ),
103
+ "k2_full_min_ms": round(
104
+ time_ms(
105
+ lambda: fc1_paired_nvfp4_scaled_tma256k2(
106
+ qx_live, qxs, qw, qws, alpha, product=False
107
+ )
108
+ ),
109
+ 4,
110
+ ),
111
+ }
112
+ payload["pass"] = (
113
+ payload["n32_vs_kitchen_mismatches"] == 0
114
+ and payload["n32_vs_k2_mismatches"] == 0
115
+ and payload["full_finite"]
116
+ )
117
+ if payload["pass"]:
118
+ payload["vs_kitchen_ms"] = round(
119
+ payload["kitchen_gemm_min_ms"] - payload["n32_full_min_ms"], 4
120
+ )
121
+ payload["vs_k2_ms"] = round(
122
+ payload["k2_full_min_ms"] - payload["n32_full_min_ms"], 4
123
+ )
124
+ text = json.dumps(payload, indent=2, sort_keys=True)
125
+ Path(__file__).with_name(
126
+ "gate_fc1_nvfp4_scaled_tma256n32_20423.json"
127
+ ).write_text(text + "\n")
128
+ print(text)
129
+ return 0 if payload["pass"] else 2
130
+
131
+
132
+ if __name__ == "__main__":
133
+ raise SystemExit(main())
labs/swiglu_nvfp4/native_cuda/gate_fc1_nvfp4_scaled_tma256n32_20423.json ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "device": "NVIDIA GB10",
3
+ "full_finite": true,
4
+ "identity": "256x32 K=128 1-stage paired-N == kitchen == k2. TMA B is 64; compute is 32. 64-float acc is the occupancy cut.",
5
+ "k": 5376,
6
+ "k2_full_min_ms": 39.0139,
7
+ "kitchen_gemm_min_ms": 19.3708,
8
+ "n": 28672,
9
+ "n32_full_min_ms": 44.013,
10
+ "n32_occupancy": 2,
11
+ "n32_regs": 125,
12
+ "n32_smem": 28800,
13
+ "n32_smem_struct": 28800,
14
+ "n32_vs_k2_mismatches": 2362273,
15
+ "n32_vs_kitchen_mismatches": 2362273,
16
+ "pass": false,
17
+ "rows": 20423
18
+ }
labs/swiglu_nvfp4/native_cuda/gate_fc1_nvfp4_scaled_tma_20423.json ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "device": "NVIDIA GB10",
3
+ "from_product_min_ms": 5.7439,
4
+ "from_product_vs_kitchen_q": 0,
5
+ "from_product_vs_kitchen_s": 0,
6
+ "from_product_vs_kitchen_scale_exact": true,
7
+ "full_finite": true,
8
+ "identity": "TMA 2-stage K pipeline on the kitchen-legal m16n8k64 atom: 128x128 2D tile, tensor-map + mbarrier, A reused across 16 n-subtiles and both arms; same PTX fragment, UE4M3 map, and eager product",
9
+ "k": 5376,
10
+ "kitchen_gemm_min_ms": 20.1758,
11
+ "n": 14336,
12
+ "pass": true,
13
+ "piped_prod_min_ms": 218.6166,
14
+ "prod_finite": true,
15
+ "product_vs_eager_full_mismatches": 0,
16
+ "product_vs_eager_kitchen_mismatches": 0,
17
+ "rows": 20423,
18
+ "tma_full_min_ms": 115.2573,
19
+ "tma_full_vs_kitchen_max_abs": 0.0,
20
+ "tma_full_vs_kitchen_mismatches": 0,
21
+ "tma_prod_min_ms": 104.7121,
22
+ "tma_prod_vs_piped_prod": 0,
23
+ "vs_piped_ms": 113.9045
24
+ }
labs/swiglu_nvfp4/native_cuda/gate_fc1_nvfp4_scaled_tma_sf.py ADDED
@@ -0,0 +1,170 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """Byte-exact gate: TMA scale-slab NVFP4 paired-N vs kitchen.
3
+
4
+ Same PTX fragment + 128x128 TMA data path. Scales come from one
5
+ cuBLAS 128x4 / 512-byte slab per K-tile, remapped to pack_four_scales.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ import json
11
+ from pathlib import Path
12
+
13
+ import torch
14
+ import torch.nn.functional as F
15
+
16
+ import comfy_kitchen as ck
17
+
18
+ from swiglu_nvfp4 import (
19
+ bf16_nvfp4_dynamic,
20
+ fc1_paired_nvfp4_scaled_tma,
21
+ fc1_paired_nvfp4_scaled_tma_sf,
22
+ load_extension,
23
+ swiglu_nvfp4_dynamic,
24
+ )
25
+
26
+
27
+ ROWS = 20423
28
+ K = 5376
29
+ N = 14336
30
+
31
+
32
+ def nvfp4_scale(x: torch.Tensor) -> torch.Tensor:
33
+ return (x.abs().amax() / (6.0 * 448.0)).to(torch.float32).reshape(1)
34
+
35
+
36
+ def kitchen_gemm(qx, sx, qw, sw, scale_x, scale_w) -> torch.Tensor:
37
+ alpha = (scale_x * scale_w).reshape(1)
38
+ y = ck.scaled_mm_nvfp4(
39
+ qx, qw, scale_x, scale_w, sx, sw, out_dtype=torch.bfloat16, alpha=alpha
40
+ )
41
+ return y[:ROWS]
42
+
43
+
44
+ def eager_act(raw: torch.Tensor) -> torch.Tensor:
45
+ gate, up = raw.chunk(2, dim=-1)
46
+ return F.silu(gate).mul_(up)
47
+
48
+
49
+ def byte_diff(left: torch.Tensor, right: torch.Tensor) -> int:
50
+ return int((left.view(torch.uint8) != right.view(torch.uint8)).sum().item())
51
+
52
+
53
+ def max_abs_diff(left: torch.Tensor, right: torch.Tensor) -> float:
54
+ return float((left.float() - right.float()).abs().max().item())
55
+
56
+
57
+ def time_ms(fn) -> float:
58
+ starter = torch.cuda.Event(enable_timing=True)
59
+ ender = torch.cuda.Event(enable_timing=True)
60
+ fn()
61
+ torch.cuda.synchronize()
62
+ starter.record()
63
+ fn()
64
+ ender.record()
65
+ torch.cuda.synchronize()
66
+ return starter.elapsed_time(ender)
67
+
68
+
69
+ def main() -> int:
70
+ load_extension(verbose=False)
71
+ device = torch.device("cuda")
72
+ torch.manual_seed(26081239)
73
+ x = torch.randn(ROWS, K, device=device, dtype=torch.bfloat16)
74
+ weight = torch.randn(2 * N, K, device=device, dtype=torch.bfloat16) * 0.02
75
+ sx = nvfp4_scale(x)
76
+ sw = nvfp4_scale(weight)
77
+ qx, qxs = ck.quantize_nvfp4(x, sx, pad_16x=True, hi_first=True)
78
+ qw, qws = ck.quantize_nvfp4(weight, sw, pad_16x=True, hi_first=True)
79
+ qx_live = qx[:ROWS].contiguous()
80
+ alpha = (sx * sw).reshape(1).contiguous()
81
+ kitchen = kitchen_gemm(qx, qxs, qw, qws, sx, sw)
82
+ full = fc1_paired_nvfp4_scaled_tma_sf(
83
+ qx_live, qxs, qw, qws, alpha, product=False
84
+ )
85
+ prod = fc1_paired_nvfp4_scaled_tma_sf(
86
+ qx_live, qxs, qw, qws, alpha, product=True
87
+ )
88
+ tma = fc1_paired_nvfp4_scaled_tma(
89
+ qx_live, qxs, qw, qws, alpha, product=True
90
+ )
91
+ eager_kit = eager_act(kitchen.contiguous())
92
+ eager_full = eager_act(full)
93
+ two_q, two_s, two_g = swiglu_nvfp4_dynamic(kitchen.contiguous())
94
+ prod_q, prod_s, prod_g = bf16_nvfp4_dynamic(prod)
95
+ payload = {
96
+ "identity": (
97
+ "cuBLAS 128x4 E4M3 scale slab == pack_four_scales: TMA 1D bulk "
98
+ "of the 512-byte slab, indexed as (row%32)*16+(row/32)*4, on "
99
+ "the kitchen-legal 128x128 m16n8k64 paired-N atom"
100
+ ),
101
+ "rows": ROWS,
102
+ "k": K,
103
+ "n": N,
104
+ "device": torch.cuda.get_device_name(device),
105
+ "sf_full_vs_kitchen_mismatches": byte_diff(full, kitchen),
106
+ "sf_full_vs_kitchen_max_abs": round(max_abs_diff(full, kitchen), 6),
107
+ "sf_prod_vs_tma_prod": byte_diff(prod, tma),
108
+ "product_vs_eager_full_mismatches": byte_diff(prod, eager_full),
109
+ "product_vs_eager_kitchen_mismatches": byte_diff(prod, eager_kit),
110
+ "from_product_vs_kitchen_q": byte_diff(prod_q, two_q),
111
+ "from_product_vs_kitchen_s": byte_diff(prod_s, two_s),
112
+ "from_product_vs_kitchen_scale_exact": bool(torch.equal(prod_g, two_g)),
113
+ "full_finite": bool(torch.isfinite(full.float()).all().item()),
114
+ "prod_finite": bool(torch.isfinite(prod.float()).all().item()),
115
+ "kitchen_gemm_min_ms": round(
116
+ time_ms(lambda: kitchen_gemm(qx, qxs, qw, qws, sx, sw)), 4
117
+ ),
118
+ "sf_full_min_ms": round(
119
+ time_ms(
120
+ lambda: fc1_paired_nvfp4_scaled_tma_sf(
121
+ qx_live, qxs, qw, qws, alpha, product=False
122
+ )
123
+ ),
124
+ 4,
125
+ ),
126
+ "sf_prod_min_ms": round(
127
+ time_ms(
128
+ lambda: fc1_paired_nvfp4_scaled_tma_sf(
129
+ qx_live, qxs, qw, qws, alpha, product=True
130
+ )
131
+ ),
132
+ 4,
133
+ ),
134
+ "tma_prod_min_ms": round(
135
+ time_ms(
136
+ lambda: fc1_paired_nvfp4_scaled_tma(
137
+ qx_live, qxs, qw, qws, alpha, product=True
138
+ )
139
+ ),
140
+ 4,
141
+ ),
142
+ "from_product_min_ms": round(
143
+ time_ms(lambda: bf16_nvfp4_dynamic(prod)), 4
144
+ ),
145
+ }
146
+ payload["pass"] = (
147
+ payload["sf_full_vs_kitchen_mismatches"] == 0
148
+ and payload["sf_prod_vs_tma_prod"] == 0
149
+ and payload["product_vs_eager_full_mismatches"] == 0
150
+ and payload["product_vs_eager_kitchen_mismatches"] == 0
151
+ and payload["from_product_vs_kitchen_q"] == 0
152
+ and payload["from_product_vs_kitchen_s"] == 0
153
+ and payload["from_product_vs_kitchen_scale_exact"]
154
+ and payload["full_finite"]
155
+ and payload["prod_finite"]
156
+ )
157
+ if payload["pass"]:
158
+ payload["vs_tma_ms"] = round(
159
+ payload["tma_prod_min_ms"] - payload["sf_prod_min_ms"], 4
160
+ )
161
+ text = json.dumps(payload, indent=2, sort_keys=True)
162
+ Path(__file__).with_name(
163
+ "gate_fc1_nvfp4_scaled_tma_sf_20423.json"
164
+ ).write_text(text + "\n")
165
+ print(text)
166
+ return 0 if payload["pass"] else 2
167
+
168
+
169
+ if __name__ == "__main__":
170
+ raise SystemExit(main())
labs/swiglu_nvfp4/native_cuda/gate_fc1_nvfp4_scaled_tma_sf_20423.json ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "device": "NVIDIA GB10",
3
+ "from_product_min_ms": 5.7291,
4
+ "from_product_vs_kitchen_q": 0,
5
+ "from_product_vs_kitchen_s": 0,
6
+ "from_product_vs_kitchen_scale_exact": true,
7
+ "full_finite": true,
8
+ "identity": "cuBLAS 128x4 E4M3 scale slab == pack_four_scales: TMA 1D bulk of the 512-byte slab, indexed as (row%32)*16+(row/32)*4, on the kitchen-legal 128x128 m16n8k64 paired-N atom",
9
+ "k": 5376,
10
+ "kitchen_gemm_min_ms": 20.2346,
11
+ "n": 14336,
12
+ "pass": true,
13
+ "prod_finite": true,
14
+ "product_vs_eager_full_mismatches": 0,
15
+ "product_vs_eager_kitchen_mismatches": 0,
16
+ "rows": 20423,
17
+ "sf_full_min_ms": 107.2147,
18
+ "sf_full_vs_kitchen_max_abs": 0.0,
19
+ "sf_full_vs_kitchen_mismatches": 0,
20
+ "sf_prod_min_ms": 104.2306,
21
+ "sf_prod_vs_tma_prod": 0,
22
+ "tma_prod_min_ms": 104.6651,
23
+ "vs_tma_ms": 0.4345
24
+ }
labs/swiglu_nvfp4/native_cuda/gate_fc1_nvfp4_tiled.py ADDED
@@ -0,0 +1,138 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """Byte-exact gate: persistent tiled NVFP4 paired-N vs 1-warp and eager.
3
+
4
+ Same atom. CTA owns 64 N, streams M, reuses A across the panel.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ import json
10
+ from pathlib import Path
11
+
12
+ import torch
13
+ import torch.nn.functional as F
14
+
15
+ import comfy_kitchen as ck
16
+
17
+ from swiglu_nvfp4 import (
18
+ bf16_nvfp4_dynamic,
19
+ fc1_paired_nvfp4,
20
+ fc1_paired_nvfp4_tiled,
21
+ load_extension,
22
+ swiglu_nvfp4_dynamic,
23
+ )
24
+
25
+
26
+ ROWS = 20423
27
+ K = 5376
28
+ N = 14336
29
+
30
+
31
+ def nvfp4_scale(x: torch.Tensor) -> torch.Tensor:
32
+ return (x.abs().amax() / (6.0 * 448.0)).to(torch.float32).reshape(1)
33
+
34
+
35
+ def eager_act(raw: torch.Tensor) -> torch.Tensor:
36
+ gate, up = raw.chunk(2, dim=-1)
37
+ return F.silu(gate).mul_(up)
38
+
39
+
40
+ def eager_pack(activated: torch.Tensor):
41
+ scale = (activated.abs().amax() / (6.0 * 448.0)).to(torch.float32).reshape(1)
42
+ packed, block_scales = ck.quantize_nvfp4(
43
+ activated, scale, pad_16x=True, hi_first=True
44
+ )
45
+ return packed, block_scales, scale
46
+
47
+
48
+ def byte_diff(left: torch.Tensor, right: torch.Tensor) -> int:
49
+ return int((left.view(torch.uint8) != right.view(torch.uint8)).sum().item())
50
+
51
+
52
+ def time_ms(fn) -> float:
53
+ starter = torch.cuda.Event(enable_timing=True)
54
+ ender = torch.cuda.Event(enable_timing=True)
55
+ fn()
56
+ torch.cuda.synchronize()
57
+ starter.record()
58
+ fn()
59
+ ender.record()
60
+ torch.cuda.synchronize()
61
+ return starter.elapsed_time(ender)
62
+
63
+
64
+ def main() -> int:
65
+ load_extension(verbose=False)
66
+ device = torch.device("cuda")
67
+ torch.manual_seed(26081235)
68
+ x = torch.randn(ROWS, K, device=device, dtype=torch.bfloat16)
69
+ weight = torch.randn(2 * N, K, device=device, dtype=torch.bfloat16) * 0.02
70
+ qx, _ = ck.quantize_nvfp4(x, nvfp4_scale(x), pad_16x=True, hi_first=True)
71
+ qw, _ = ck.quantize_nvfp4(
72
+ weight, nvfp4_scale(weight), pad_16x=True, hi_first=True
73
+ )
74
+ qx = qx[:ROWS].contiguous()
75
+ full = fc1_paired_nvfp4_tiled(qx, qw, product=False)
76
+ prod = fc1_paired_nvfp4_tiled(qx, qw, product=True)
77
+ onew = fc1_paired_nvfp4(qx, qw, product=True)
78
+ eager = eager_act(full)
79
+ two_q, two_s, two_g = swiglu_nvfp4_dynamic(full)
80
+ prod_q, prod_s, prod_g = bf16_nvfp4_dynamic(prod)
81
+ ref_q, ref_s, ref_g = eager_pack(eager)
82
+ payload = {
83
+ "identity": (
84
+ "persistent 64x64 NVFP4 paired-N: A K-slab reused across 8 "
85
+ "n-subtiles and both arms; eager product epilogue"
86
+ ),
87
+ "rows": ROWS,
88
+ "k": K,
89
+ "n": N,
90
+ "device": torch.cuda.get_device_name(device),
91
+ "product_vs_eager_full_mismatches": byte_diff(prod, eager),
92
+ "tiled_vs_onewarp_prod": byte_diff(prod, onew),
93
+ "from_product_vs_twopass_q": byte_diff(prod_q, two_q),
94
+ "from_product_vs_twopass_s": byte_diff(prod_s, two_s),
95
+ "from_product_vs_twopass_scale_exact": bool(torch.equal(prod_g, two_g)),
96
+ "from_product_vs_eager_q": byte_diff(prod_q, ref_q),
97
+ "from_product_vs_eager_s": byte_diff(prod_s, ref_s),
98
+ "from_product_vs_eager_scale_exact": bool(torch.equal(prod_g, ref_g)),
99
+ "full_finite": bool(torch.isfinite(full.float()).all().item()),
100
+ "prod_finite": bool(torch.isfinite(prod.float()).all().item()),
101
+ "tiled_full_min_ms": round(
102
+ time_ms(lambda: fc1_paired_nvfp4_tiled(qx, qw, product=False)), 4
103
+ ),
104
+ "tiled_prod_min_ms": round(
105
+ time_ms(lambda: fc1_paired_nvfp4_tiled(qx, qw, product=True)), 4
106
+ ),
107
+ "onewarp_prod_min_ms": round(
108
+ time_ms(lambda: fc1_paired_nvfp4(qx, qw, product=True)), 4
109
+ ),
110
+ "twopass_min_ms": round(time_ms(lambda: swiglu_nvfp4_dynamic(full)), 4),
111
+ "from_product_min_ms": round(time_ms(lambda: bf16_nvfp4_dynamic(prod)), 4),
112
+ }
113
+ payload["pass"] = (
114
+ payload["product_vs_eager_full_mismatches"] == 0
115
+ and payload["tiled_vs_onewarp_prod"] == 0
116
+ and payload["from_product_vs_twopass_q"] == 0
117
+ and payload["from_product_vs_twopass_s"] == 0
118
+ and payload["from_product_vs_twopass_scale_exact"]
119
+ and payload["from_product_vs_eager_q"] == 0
120
+ and payload["from_product_vs_eager_s"] == 0
121
+ and payload["from_product_vs_eager_scale_exact"]
122
+ and payload["full_finite"]
123
+ and payload["prod_finite"]
124
+ )
125
+ if payload["pass"]:
126
+ payload["vs_onewarp_ms"] = round(
127
+ payload["onewarp_prod_min_ms"] - payload["tiled_prod_min_ms"], 4
128
+ )
129
+ text = json.dumps(payload, indent=2, sort_keys=True)
130
+ Path(__file__).with_name("gate_fc1_nvfp4_tiled_20423.json").write_text(
131
+ text + "\n"
132
+ )
133
+ print(text)
134
+ return 0 if payload["pass"] else 2
135
+
136
+
137
+ if __name__ == "__main__":
138
+ raise SystemExit(main())
labs/swiglu_nvfp4/native_cuda/gate_fc1_nvfp4_tiled_20423.json ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "device": "NVIDIA GB10",
3
+ "from_product_min_ms": 5.8331,
4
+ "from_product_vs_eager_q": 0,
5
+ "from_product_vs_eager_s": 0,
6
+ "from_product_vs_eager_scale_exact": true,
7
+ "from_product_vs_twopass_q": 0,
8
+ "from_product_vs_twopass_s": 0,
9
+ "from_product_vs_twopass_scale_exact": true,
10
+ "full_finite": true,
11
+ "identity": "persistent 64x64 NVFP4 paired-N: A K-slab reused across 8 n-subtiles and both arms; eager product epilogue",
12
+ "k": 5376,
13
+ "n": 14336,
14
+ "onewarp_prod_min_ms": 1225.824,
15
+ "pass": true,
16
+ "prod_finite": true,
17
+ "product_vs_eager_full_mismatches": 0,
18
+ "rows": 20423,
19
+ "tiled_full_min_ms": 221.7096,
20
+ "tiled_prod_min_ms": 208.4988,
21
+ "tiled_vs_onewarp_prod": 0,
22
+ "twopass_min_ms": 10.8047,
23
+ "vs_onewarp_ms": 1017.3252
24
+ }
labs/swiglu_nvfp4/native_cuda/gate_fc1_paired.py ADDED
@@ -0,0 +1,125 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """Byte-exact gate: paired-N FC1 MMA store of eager product vs [gate|up].
3
+
4
+ Same mainloop, two epilogues. Kitchen GEMM is not modified.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ import json
10
+ from pathlib import Path
11
+
12
+ import torch
13
+ import torch.nn.functional as F
14
+
15
+ import comfy_kitchen as ck
16
+
17
+ from swiglu_nvfp4 import (
18
+ bf16_nvfp4_dynamic,
19
+ fc1_paired_store,
20
+ load_extension,
21
+ swiglu_nvfp4_dynamic,
22
+ )
23
+
24
+
25
+ ROWS = 20423
26
+ K = 5376
27
+ N = 14336
28
+ REPEATS = 1
29
+
30
+
31
+ def eager_act(raw: torch.Tensor) -> torch.Tensor:
32
+ gate, up = raw.chunk(2, dim=-1)
33
+ return F.silu(gate).mul_(up)
34
+
35
+
36
+ def eager_pack(activated: torch.Tensor):
37
+ scale = (activated.abs().amax() / (6.0 * 448.0)).to(torch.float32).reshape(1)
38
+ packed, block_scales = ck.quantize_nvfp4(
39
+ activated, scale, pad_16x=True, hi_first=True
40
+ )
41
+ return packed, block_scales, scale
42
+
43
+
44
+ def byte_diff(left: torch.Tensor, right: torch.Tensor) -> int:
45
+ return int((left.view(torch.uint8) != right.view(torch.uint8)).sum().item())
46
+
47
+
48
+ def time_ms(fn) -> float:
49
+ starter = torch.cuda.Event(enable_timing=True)
50
+ ender = torch.cuda.Event(enable_timing=True)
51
+ for _ in range(2):
52
+ fn()
53
+ torch.cuda.synchronize()
54
+ samples = []
55
+ for _ in range(REPEATS):
56
+ starter.record()
57
+ fn()
58
+ ender.record()
59
+ torch.cuda.synchronize()
60
+ samples.append(starter.elapsed_time(ender))
61
+ return min(samples)
62
+
63
+
64
+ def main() -> int:
65
+ load_extension(verbose=False)
66
+ device = torch.device("cuda")
67
+ torch.manual_seed(26081228)
68
+ x = torch.randn(ROWS, K, device=device, dtype=torch.bfloat16)
69
+ weight = torch.randn(2 * N, K, device=device, dtype=torch.bfloat16) * 0.02
70
+ full = fc1_paired_store(x, weight, product=False)
71
+ prod = fc1_paired_store(x, weight, product=True)
72
+ eager = eager_act(full)
73
+ two_q, two_s, two_g = swiglu_nvfp4_dynamic(full)
74
+ prod_q, prod_s, prod_g = bf16_nvfp4_dynamic(prod)
75
+ ref_q, ref_s, ref_g = eager_pack(eager)
76
+ payload = {
77
+ "identity": (
78
+ "paired-N MMA accumulates gate and up together; "
79
+ "product epilogue stores eager round(silu(round(g))*round(u)); "
80
+ "same mainloop as the [gate|up] store"
81
+ ),
82
+ "rows": ROWS,
83
+ "k": K,
84
+ "n": N,
85
+ "device": torch.cuda.get_device_name(device),
86
+ "product_vs_eager_full_mismatches": byte_diff(prod, eager),
87
+ "from_product_vs_twopass_q": byte_diff(prod_q, two_q),
88
+ "from_product_vs_twopass_s": byte_diff(prod_s, two_s),
89
+ "from_product_vs_twopass_scale_exact": bool(torch.equal(prod_g, two_g)),
90
+ "from_product_vs_eager_q": byte_diff(prod_q, ref_q),
91
+ "from_product_vs_eager_s": byte_diff(prod_s, ref_s),
92
+ "from_product_vs_eager_scale_exact": bool(torch.equal(prod_g, ref_g)),
93
+ "full_store_min_ms": round(
94
+ time_ms(lambda: fc1_paired_store(x, weight, product=False)), 4
95
+ ),
96
+ "product_store_min_ms": round(
97
+ time_ms(lambda: fc1_paired_store(x, weight, product=True)), 4
98
+ ),
99
+ "twopass_min_ms": round(time_ms(lambda: swiglu_nvfp4_dynamic(full)), 4),
100
+ "from_product_min_ms": round(time_ms(lambda: bf16_nvfp4_dynamic(prod)), 4),
101
+ }
102
+ payload["pass"] = (
103
+ payload["product_vs_eager_full_mismatches"] == 0
104
+ and payload["from_product_vs_twopass_q"] == 0
105
+ and payload["from_product_vs_twopass_s"] == 0
106
+ and payload["from_product_vs_twopass_scale_exact"]
107
+ and payload["from_product_vs_eager_q"] == 0
108
+ and payload["from_product_vs_eager_s"] == 0
109
+ and payload["from_product_vs_eager_scale_exact"]
110
+ )
111
+ if payload["pass"]:
112
+ payload["store_delta_ms"] = round(
113
+ payload["full_store_min_ms"] - payload["product_store_min_ms"], 4
114
+ )
115
+ payload["pack_side_saved_ms"] = round(
116
+ payload["twopass_min_ms"] - payload["from_product_min_ms"], 4
117
+ )
118
+ text = json.dumps(payload, indent=2, sort_keys=True)
119
+ Path(__file__).with_name("gate_fc1_paired_20423.json").write_text(text + "\n")
120
+ print(text)
121
+ return 0 if payload["pass"] else 2
122
+
123
+
124
+ if __name__ == "__main__":
125
+ raise SystemExit(main())