|
8 | 8 | from flag_gems.fused.DSA.bin_topk import ( |
9 | 9 | bucket_sort_topk, # Replace with actual module name |
10 | 10 | ) |
| 11 | +from flag_gems.fused.DSA.bin_topk import HAS_TLE |
11 | 12 |
|
12 | 13 |
|
13 | 14 | def assert_set_similar(actual, expected, dtype, equal_nan=False): |
@@ -134,6 +135,37 @@ def debug_topk_results(actual, expected, inputs, test_name=""): |
134 | 135 | print(f" Expected top values: {np.sort(expected_values)[-m:][::-1]}") |
135 | 136 |
|
136 | 137 |
|
| 138 | +@pytest.mark.skipif(not torch.cuda.is_available(), reason="CUDA device required") |
| 139 | +@pytest.mark.skipif(not HAS_TLE, reason="TLE bucket_sort_topk is unavailable") |
| 140 | +@pytest.mark.bucket_sort_topk |
| 141 | +@pytest.mark.parametrize( |
| 142 | + ("starts_list", "ends_list"), |
| 143 | + [ |
| 144 | + ([0, 0, 0], [512, 768, 1024]), |
| 145 | + ([7, 31, 63], [700, 900, 1024]), |
| 146 | + ], |
| 147 | +) |
| 148 | +def test_bucket_sort_topk_public_entrypoint_matches_torch_topk(starts_list, ends_list): |
| 149 | + batch_size = len(starts_list) |
| 150 | + seq_len = 1024 |
| 151 | + topk = 32 |
| 152 | + dtype = torch.float32 |
| 153 | + |
| 154 | + init_seed(2026) |
| 155 | + inputs = torch.randn((batch_size, seq_len), dtype=dtype, device=device) |
| 156 | + starts = torch.tensor(starts_list, dtype=torch.int32, device=device) |
| 157 | + ends = torch.tensor(ends_list, dtype=torch.int32, device=device) |
| 158 | + |
| 159 | + ref_indices = reference_topk_implementation( |
| 160 | + to_reference(inputs), to_reference(starts), to_reference(ends), topk |
| 161 | + ) |
| 162 | + actual_indices = bucket_sort_topk(inputs, starts, ends, topk) |
| 163 | + |
| 164 | + assert actual_indices.shape == (batch_size, topk) |
| 165 | + assert actual_indices.dtype == torch.int32 |
| 166 | + assert_set_similar(actual_indices, ref_indices, dtype) |
| 167 | + |
| 168 | + |
137 | 169 | @pytest.mark.skip( |
138 | 170 | "RuntimeError: Cannot call @triton.jit'd outside of the scope of a kernel" |
139 | 171 | ) |
|
0 commit comments