|
8 | 8 | pytest.skip("MXFP8 TMA GEMV requires SM100 or SM103", allow_module_level=True) |
9 | 9 |
|
10 | 10 | try: |
11 | | - from transformer_nuggets.cute import mxfp8_tma_gemv |
| 11 | + from transformer_nuggets.cute import ( |
| 12 | + MXFP8_TMA_PROFILE_TAGS, |
| 13 | + get_mxfp8_tma_gemv, |
| 14 | + mxfp8_tma_gemv, |
| 15 | + ) |
| 16 | + from transformer_nuggets.cute.profiler import profile_session |
| 17 | + from transformer_nuggets.cute.profiler.host import decode_events |
12 | 18 | except ImportError: |
13 | 19 | pytest.skip("CuTe DSL not available", allow_module_level=True) |
14 | 20 |
|
@@ -95,13 +101,47 @@ def test_mxfp8_tma_gemv_cuda_graph_replay(): |
95 | 101 | torch.testing.assert_close(output, expected, atol=1.0, rtol=0.05) |
96 | 102 |
|
97 | 103 |
|
98 | | -def test_mxfp8_tma_gemv_combines_cancelling_scales(): |
| 104 | +def test_mxfp8_tma_gemv_profiles_labeled_regions(): |
| 105 | + """Record each compile-time-enabled region with static event slots.""" |
| 106 | + k = 2048 |
| 107 | + q_input, input_scale = quantize_mxfp8(torch.randn((1, k), dtype=torch.bfloat16, device="cuda")) |
| 108 | + weight, weight_scale = quantize_mxfp8( |
| 109 | + torch.randn((128, k), dtype=torch.bfloat16, device="cuda") |
| 110 | + ) |
| 111 | + op = get_mxfp8_tma_gemv(128, k, 4, enable_profiling=True) |
| 112 | + |
| 113 | + with profile_session( |
| 114 | + max_events_per_unit=op.max_profile_events_per_cta, |
| 115 | + num_units=(op.num_profile_units, "CTA"), |
| 116 | + tag_names=list(MXFP8_TMA_PROFILE_TAGS), |
| 117 | + device=q_input.device, |
| 118 | + ) as (prof, tags): |
| 119 | + actual = op.interface( |
| 120 | + q_input, |
| 121 | + weight, |
| 122 | + input_scale, |
| 123 | + weight_scale, |
| 124 | + profile_buffer=prof.tensor, |
| 125 | + ) |
| 126 | + |
| 127 | + expected = ( |
| 128 | + dequantize_mxfp8(q_input, input_scale) @ dequantize_mxfp8(weight, weight_scale).T |
| 129 | + ).bfloat16() |
| 130 | + torch.testing.assert_close(actual, expected, atol=1.0, rtol=0.05) |
| 131 | + events = decode_events(prof, tags) |
| 132 | + assert len(events) == op.num_profile_units * (3 * op.num_k_tiles + 1) |
| 133 | + assert {event.tag_name for event in events} == set(MXFP8_TMA_PROFILE_TAGS) |
| 134 | + assert {event.unit_id for event in events} == set(range(op.num_profile_units)) |
| 135 | + |
| 136 | + |
| 137 | +@pytest.mark.parametrize(("input_byte", "weight_byte"), [(254, 0), (0, 254)]) |
| 138 | +def test_mxfp8_tma_gemv_combines_cancelling_scales(input_byte, weight_byte): |
99 | 139 | """Avoid an infinite intermediate when E8M0 scale exponents cancel.""" |
100 | 140 | k = 2048 |
101 | 141 | q_input = torch.ones((1, k), dtype=torch.float8_e4m3fn, device="cuda") |
102 | 142 | weight = torch.ones((128, k), dtype=torch.float8_e4m3fn, device="cuda") |
103 | | - input_scale = torch.full((1, k // 32), 254, dtype=torch.uint8, device="cuda") |
104 | | - weight_scale = torch.zeros((128, k // 32), dtype=torch.uint8, device="cuda") |
| 143 | + input_scale = torch.full((1, k // 32), input_byte, dtype=torch.uint8, device="cuda") |
| 144 | + weight_scale = torch.full((128, k // 32), weight_byte, dtype=torch.uint8, device="cuda") |
105 | 145 |
|
106 | 146 | actual = mxfp8_tma_gemv( |
107 | 147 | q_input, |
|
0 commit comments