|
21 | 21 |
|
22 | 22 |
|
23 | 23 | class TestRefImplementations(unittest.TestCase): |
| 24 | + def test_sdpa_bitwise_ring_mask_matches_visible_slots(self) -> None: |
| 25 | + for dtype in (torch.int32, torch.int64): |
| 26 | + for capacity in (8, 16, 24, 2048, 4096): |
| 27 | + positions = torch.tensor( |
| 28 | + [0, 1, 7, 8, capacity - 1, capacity, 3 * capacity + 5], |
| 29 | + dtype=dtype, |
| 30 | + ) |
| 31 | + for window in (1, min(9, capacity), capacity): |
| 32 | + with self.subTest(dtype=dtype, capacity=capacity, window=window): |
| 33 | + expected = torch.full( |
| 34 | + (positions.numel(), capacity // 8), 255, dtype=torch.uint8 |
| 35 | + ) |
| 36 | + for row, position in enumerate(positions.tolist()): |
| 37 | + for key in range( |
| 38 | + max(0, position - window + 1), position + 1 |
| 39 | + ): |
| 40 | + slot = key % capacity |
| 41 | + expected[row, slot // 8] &= 255 ^ (1 << (slot % 8)) |
| 42 | + actual = torch.ops.cadence.sdpa_bitwise_ring_mask_gen.default( |
| 43 | + positions, window, capacity |
| 44 | + ) |
| 45 | + torch.testing.assert_close(actual, expected, rtol=0, atol=0) |
| 46 | + meta = torch.ops.cadence.sdpa_bitwise_ring_mask_gen.default( |
| 47 | + positions.to("meta"), window, capacity |
| 48 | + ) |
| 49 | + self.assertEqual(meta.shape, expected.shape) |
| 50 | + self.assertEqual(meta.dtype, torch.uint8) |
| 51 | + |
| 52 | + def test_sdpa_bitwise_ring_mask_empty_and_large_positions(self) -> None: |
| 53 | + empty = torch.ops.cadence.sdpa_bitwise_ring_mask_gen.default( |
| 54 | + torch.empty(0, dtype=torch.int64), 4, 16 |
| 55 | + ) |
| 56 | + self.assertEqual(tuple(empty.shape), (0, 2)) |
| 57 | + actual = torch.ops.cadence.sdpa_bitwise_ring_mask_gen.default( |
| 58 | + torch.tensor([torch.iinfo(torch.int64).max]), 4, 16 |
| 59 | + ) |
| 60 | + torch.testing.assert_close( |
| 61 | + actual, torch.tensor([[255, 15]], dtype=torch.uint8), rtol=0, atol=0 |
| 62 | + ) |
| 63 | + |
| 64 | + def test_sdpa_bitwise_ring_mask_rejects_invalid_inputs(self) -> None: |
| 65 | + for device in ("cpu", "meta"): |
| 66 | + cases = [ |
| 67 | + (torch.zeros(1, dtype=torch.float32, device=device), 4, 16), |
| 68 | + (torch.zeros((1, 1), dtype=torch.int64, device=device), 4, 16), |
| 69 | + (torch.zeros(1, dtype=torch.int64, device=device), 0, 16), |
| 70 | + (torch.zeros(1, dtype=torch.int64, device=device), 17, 16), |
| 71 | + (torch.zeros(1, dtype=torch.int64, device=device), 4, 0), |
| 72 | + (torch.zeros(1, dtype=torch.int64, device=device), 4, 15), |
| 73 | + ] |
| 74 | + for positions, window, capacity in cases: |
| 75 | + with self.subTest(device=device, window=window, capacity=capacity): |
| 76 | + with self.assertRaises((AssertionError, RuntimeError)): |
| 77 | + torch.ops.cadence.sdpa_bitwise_ring_mask_gen.default( |
| 78 | + positions, window, capacity |
| 79 | + ) |
| 80 | + with self.assertRaises(AssertionError): |
| 81 | + torch.ops.cadence.sdpa_bitwise_ring_mask_gen.default( |
| 82 | + torch.tensor([-1], dtype=torch.int64), 4, 16 |
| 83 | + ) |
| 84 | + |
24 | 85 | @expand( |
25 | 86 | [ |
26 | 87 | ("basic_int8", 0.42, -1.0, 2.0, -7, 7, torch.int8, 0), |
|
0 commit comments