已合并
Add test_matmul_cuda ut for npu #8349
wang-guangbin创建于 2023年12月13日
Add test_matmul_cuda ut for npu #8349
已合并
从refs/pull/8349/head合入到master
共 2 个文件变更+184-0
| @@ -0,0 +1,169 @@ | |||
| 1 | +# Owner(s): ["module: linear algebra"] | ||
| 2 | + | ||
| 3 | +import unittest | ||
| 4 | +from functools import partial | ||
| 5 | + | ||
| 6 | +import torch | ||
| 7 | +from torch.testing import make_tensor | ||
| 8 | +import torch_npu | ||
| 9 | +import torch_npu.testing | ||
| 10 | +from torch.testing._internal.common_device_type import ( | ||
| 11 | + dtypes, | ||
| 12 | + instantiate_device_type_tests, | ||
| 13 | + tol as xtol, | ||
| 14 | + toleranceOverride, | ||
| 15 | +) | ||
| 16 | + | ||
| 17 | +from torch.testing._internal.common_utils import ( | ||
| 18 | + IS_JETSON, | ||
| 19 | + parametrize, | ||
| 20 | + run_tests, | ||
| 21 | + skipIfRocmVersionLessThan, | ||
| 22 | + TEST_WITH_ROCM, | ||
| 23 | + TestCase, | ||
| 24 | +) | ||
| 25 | + | ||
| 26 | +# Protects against includes accidentally setting the default dtype | ||
| 27 | +# NOTE: jit_metaprogramming_utils sets the default dtype to double! | ||
| 28 | +torch.set_default_dtype(torch.float32) | ||
| 29 | +if torch.get_default_dtype() is not torch.float32: | ||
| 30 | + raise RuntimeError("The torch default dtype is not float32!") | ||
| 31 | + | ||
| 32 | + | ||
| 33 | +class TestMatmul(TestCase): | ||
| 34 | + def setUp(self): | ||
| 35 | + super(self.__class__, self).setUp() | ||
| 36 | + | ||
| 37 | + def tearDown(self): | ||
| 38 | + super(self.__class__, self).tearDown() | ||
| 39 | + | ||
| 40 | + | ||
| 41 | + # imported 'tol' as 'xtol' to avoid aliasing in code above | ||
| 42 | + | ||
| 43 | + torch.bfloat16: xtol(atol=1e-1, rtol=1e-1), | ||
| 44 | + torch.float32: xtol(atol=1e-1, rtol=1e-1)}) | ||
| 45 | + | ||
| 46 | + | ||
| 47 | + def test_addmm(self, size: int, dtype: torch.dtype): | ||
W | |||
| 48 | + # | ||
| 49 | + # Check for catastrophic cuBLAS inaccuracy by measuring the deviation between | ||
| 50 | + # results from the NPU invocation of torch.addmm and the CPU invocation | ||
| 51 | + # (which does not use NPU backend). | ||
| 52 | + # | ||
| 53 | + # Get dims | ||
| 54 | + n, m, p = (size + 1, size, size + 2) | ||
| 55 | + # Make random tensors on CPU (seed set on common_utils.py import) | ||
| 56 | + # (Not using numpy because it does not support bfloat16) | ||
| 57 | + make_arg = partial(make_tensor, dtype=dtype, device="cpu") | ||
| 58 | + m_beta = make_arg(1) | ||
| 59 | + m_input = make_arg((n, p)) | ||
| 60 | + m_1 = make_arg((n, m)) | ||
| 61 | + m_2 = make_arg((m, p)) | ||
| 62 | + # *(B)FLOAT16 Special Handling* | ||
| 63 | + # Backend does not tensorize float16 on CPU, | ||
| 64 | + # and bloat16 may present accuracy issues, | ||
| 65 | + # so convert to float32 for these cases | ||
| 66 | + # (but keep same for other types, e.g. float32 and int*) | ||
| 67 | + if dtype == torch.float16 or dtype == torch.bfloat16: | ||
| 68 | + m_beta = m_beta.to(dtype=torch.float32) | ||
| 69 | + m_input = m_input.to(dtype=torch.float32) | ||
| 70 | + m_1 = m_1.to(dtype=torch.float32) | ||
| 71 | + m_2 = m_2.to(dtype=torch.float32) | ||
| 72 | + # Get CPU result | ||
| 73 | + res_cpu = torch.addmm(m_input, m_1, m_2, beta=m_beta.item()) | ||
| 74 | + # *(B)FLOAT16 Special Handling*`` | ||
| 75 | + # Convert back to (b)float16 | ||
| 76 | + if dtype == torch.float16 or dtype == torch.bfloat16: | ||
| 77 | + m_beta = m_beta.to(dtype=dtype) | ||
| 78 | + m_input = m_input.to(dtype=dtype) | ||
| 79 | + m_1 = m_1.to(dtype=dtype) | ||
| 80 | + m_2 = m_2.to(dtype=dtype) | ||
| 81 | + res_cpu = res_cpu.to(dtype=dtype) | ||
| 82 | + # Move arg tensors to NPU | ||
| 83 | + m_beta = m_beta.to("npu") | ||
| 84 | + m_input = m_input.to("npu") | ||
| 85 | + m_1 = m_1.to("npu") | ||
| 86 | + m_2 = m_2.to("npu") | ||
| 87 | + # Get NPU result | ||
| 88 | + res_npu = torch.addmm(m_input, m_1, m_2, beta=m_beta.item()) | ||
| 89 | + # Move to CPU for comparison | ||
| 90 | + res_npu = res_npu.to("cpu") | ||
| 91 | + # Compare | ||
| 92 | + self.assertEqual(res_cpu, res_npu) | ||
| 93 | + | ||
| 94 | + def test_addmm_alignment(self): | ||
| 95 | + dtype = torch.half | ||
| 96 | + device = 'npu' | ||
| 97 | + # perturb X, A, or B alignment | ||
| 98 | + for idx in range(0, 3): | ||
| 99 | + for offset in range(1, 3): | ||
| 100 | + offsets = [0, 0, 0] | ||
| 101 | + offsets[idx] = offset | ||
| 102 | + x_offset, a_offset, b_offset = offsets | ||
| 103 | + A = torch.rand((5120 * 2560 + a_offset), requires_grad=True, dtype=dtype, device=device) | ||
| 104 | + A = A[a_offset:].reshape(5120, 2560) | ||
| 105 | + X = torch.rand((26 * 2560 + x_offset), requires_grad=True, dtype=dtype, device=device) | ||
| 106 | + X = X[x_offset:].reshape(26, 1, 2560) | ||
| 107 | + B = torch.rand((5120 + b_offset), requires_grad=True, dtype=dtype, device=device) | ||
| 108 | + B = B[b_offset:].reshape(5120) | ||
| 109 | + out = torch.nn.functional.linear(X, A, B) | ||
| 110 | + self.assertEqual(out, torch.matmul(X, A.transpose(1, 0)) + B) | ||
| 111 | + | ||
| 112 | + | ||
| 113 | + | ||
| 114 | + | ||
| 115 | + | ||
| 116 | + "batch_size, N, M, P", | ||
| 117 | + [(2, 100, 100, 100), | ||
| 118 | + (2, 1000, 1000, 1000), | ||
| 119 | + (1, 10000, 1000, 10000), | ||
| 120 | + (1, 10000, 10000, 10000)], | ||
| 121 | + name_fn=lambda batch_size, N, M, P: f"{batch_size}_{N}_{M}_{P}", | ||
| 122 | + ) | ||
| 123 | + def test_baddbmm_large_input(self, device, batch_size, N, M, P, dtype): | ||
| 124 | + cpu_dtype = dtype | ||
| 125 | + if dtype == torch.float16 or dtype == torch.bfloat16: | ||
| 126 | + cpu_dtype = torch.float32 | ||
| 127 | + | ||
| 128 | + M1 = torch.rand((N, M), device=device, dtype=dtype) | ||
| 129 | + M2 = torch.rand((M, P), device=device, dtype=dtype) | ||
| 130 | + A = torch.rand((N, P), device=device, dtype=dtype) | ||
| 131 | + | ||
| 132 | + def _convert_to_cpu(t): | ||
| 133 | + return t.to(device='cpu', dtype=cpu_dtype) | ||
| 134 | + M1_cpu, M2_cpu, A_cpu = map(_convert_to_cpu, [M1, M2, A]) | ||
| 135 | + | ||
| 136 | + # linear | ||
| 137 | + out1_cpu = torch.nn.functional.linear(M1_cpu, M2_cpu.t(), A_cpu).to(dtype=dtype) | ||
| 138 | + out1_gpu = torch.nn.functional.linear(M1, M2.t(), A).cpu() | ||
| 139 | + self.assertEqual(out1_cpu, out1_gpu) | ||
| 140 | + # test multiply the identity matrix | ||
| 141 | + if N == M and M == P: | ||
| 142 | + M2_eye = torch.eye(N, device=device, dtype=dtype) | ||
| 143 | + out1_eye_gpu = torch.nn.functional.linear(M1, M2_eye.t(), torch.zeros_like(A)) | ||
| 144 | + self.assertEqual(M1_cpu.to(dtype=dtype), out1_eye_gpu.cpu()) | ||
| 145 | + | ||
| 146 | + # baddbmm | ||
| 147 | + def _expand_to_batch(t: torch.Tensor): | ||
| 148 | + return t.expand((batch_size, ) + t.size()) | ||
| 149 | + alpha, beta = 1.0, 1.0 | ||
| 150 | + M1, M2, A, M1_cpu, M2_cpu, A_cpu = map(_expand_to_batch, [M1, M2, A, M1_cpu, M2_cpu, A_cpu]) | ||
| 151 | + | ||
| 152 | + out2_cpu = torch.baddbmm(A_cpu, M1_cpu, M2_cpu, beta=beta, alpha=alpha).to(dtype=dtype) | ||
| 153 | + out2_gpu = torch.baddbmm(A, M1, M2, beta=beta, alpha=alpha).cpu() | ||
| 154 | + self.assertEqual(out2_cpu, out2_gpu) | ||
| 155 | + # test multiply the identity matrix | ||
| 156 | + if N == M and M == P: | ||
| 157 | + M2_eye = torch.eye(N, device=device, dtype=dtype).expand(batch_size, N, N) | ||
| 158 | + out2_eye_gpu = torch.baddbmm(torch.zeros_like(A), M1, M2_eye, beta=beta, alpha=alpha) | ||
| 159 | + self.assertEqual(M1_cpu.to(dtype=dtype), out2_eye_gpu.cpu()) | ||
| 160 | + | ||
| 161 | + # cross comparison | ||
| 162 | + self.assertEqual(out1_gpu, out2_gpu[0]) | ||
| 163 | + | ||
| 164 | + | ||
| 165 | +instantiate_device_type_tests(TestMatmul, globals(), only_for='privateuse1') | ||
| 166 | + | ||
| 167 | + | ||
| 168 | +if __name__ == '__main__': | ||
| 169 | + run_tests() | ||
| @@ -1203,6 +1203,20 @@ | |||
| 1203 | "test_repr_nn_ConvTranspose1d_npu_complex32 (__main__.TestModulePRIVATEUSE1)": ["", [""]], | 1203 | "test_repr_nn_ConvTranspose1d_npu_complex32 (__main__.TestModulePRIVATEUSE1)": ["", [""]], |
| 1204 | "test_repr_nn_ConvTranspose2d_npu_complex32 (__main__.TestModulePRIVATEUSE1)": ["", [""]], | 1204 | "test_repr_nn_ConvTranspose2d_npu_complex32 (__main__.TestModulePRIVATEUSE1)": ["", [""]], |
| 1205 | "test_repr_nn_ConvTranspose3d_npu_complex32 (__main__.TestModulePRIVATEUSE1)": ["", [""]], | 1205 | "test_repr_nn_ConvTranspose3d_npu_complex32 (__main__.TestModulePRIVATEUSE1)": ["", [""]], |
| 1206 | + "test_addmm_size_10000_npu_bfloat16 (main.TestMatmulPRIVATEUSE1)": ["", [""]], | ||
| 1207 | + "test_addmm_size_10000_npu_float32 (main.TestMatmulPRIVATEUSE1)": ["", [""]], | ||
| 1208 | + "test_addmm_size_1000_npu_bfloat16 (main.TestMatmulPRIVATEUSE1)": ["", [""]], | ||
| 1209 | + "test_addmm_size_1000_npu_float32 (main.TestMatmulPRIVATEUSE1)": ["", [""]], | ||
| 1210 | + "test_addmm_size_100_npu_bfloat16 (main.TestMatmulPRIVATEUSE1)": ["", [""]], | ||
| 1211 | + "test_addmm_size_100_npu_float32 (main.TestMatmulPRIVATEUSE1)": ["", [""]], | ||
| 1212 | + "test_baddbmm_large_input_1_10000_10000_10000_npu_bfloat16 (main.TestMatmulPRIVATEUSE1)": ["", [""]], | ||
| 1213 | + "test_baddbmm_large_input_1_10000_10000_10000_npu_float32 (main.TestMatmulPRIVATEUSE1)": ["", [""]], | ||
| 1214 | + "test_baddbmm_large_input_1_10000_1000_10000_npu_bfloat16 (main.TestMatmulPRIVATEUSE1)": ["", [""]], | ||
| 1215 | + "test_baddbmm_large_input_1_10000_1000_10000_npu_float32 (main.TestMatmulPRIVATEUSE1)": ["", [""]], | ||
| 1216 | + "test_baddbmm_large_input_2_1000_1000_1000_npu_bfloat16 (main.TestMatmulPRIVATEUSE1)": ["", [""]], | ||
| 1217 | + "test_baddbmm_large_input_2_1000_1000_1000_npu_float32 (main.TestMatmulPRIVATEUSE1)": ["", [""]], | ||
| 1218 | + "test_baddbmm_large_input_2_100_100_100_npu_bfloat16 (main.TestMatmulPRIVATEUSE1)": ["", [""]], | ||
| 1219 | + "test_baddbmm_large_input_2_100_100_100_npu_float32 (main.TestMatmulPRIVATEUSE1)": ["", [""]], | ||
| 1206 | "test_alpha_mismatch_npu (__main__.TestTypePromotionPRIVATEUSE1)": ["", [""]], | 1220 | "test_alpha_mismatch_npu (__main__.TestTypePromotionPRIVATEUSE1)": ["", [""]], |
| 1207 | "test_alternate_result_npu (__main__.TestTypePromotionPRIVATEUSE1)": ["", [""]], | 1221 | "test_alternate_result_npu (__main__.TestTypePromotionPRIVATEUSE1)": ["", [""]], |
| 1208 | "test_bfloat16_npu (__main__.TestTypePromotionPRIVATEUSE1)": ["", [""]], | 1222 | "test_bfloat16_npu (__main__.TestTypePromotionPRIVATEUSE1)": ["", [""]], |
| @@ -1433,6 +1447,7 @@ | |||
| 1433 | "test_unique_npu_int64 (__main__.TestSortAndSelectPRIVATEUSE1)": ["", [""]], | 1447 | "test_unique_npu_int64 (__main__.TestSortAndSelectPRIVATEUSE1)": ["", [""]], |
| 1434 | "test_unique_npu_int8 (__main__.TestSortAndSelectPRIVATEUSE1)": ["", [""]], | 1448 | "test_unique_npu_int8 (__main__.TestSortAndSelectPRIVATEUSE1)": ["", [""]], |
| 1435 | "test_unique_npu_uint8 (__main__.TestSortAndSelectPRIVATEUSE1)": ["", [""]], | 1449 | "test_unique_npu_uint8 (__main__.TestSortAndSelectPRIVATEUSE1)": ["", [""]], |
| 1450 | + "test_unique_dim_npu (__main__.TestSortAndSelectPRIVATEUSE1)": ["", [""]], | ||
| 1436 | "test_advancedindex_npu_float64 (__main__.TestIndexingPRIVATEUSE1)": ["", [""]], | 1451 | "test_advancedindex_npu_float64 (__main__.TestIndexingPRIVATEUSE1)": ["", [""]], |
| 1437 | "test_batchnorm_non_contig_cpu_SyncBatchNorm (__main__.TestNN)": ["", [""]], | 1452 | "test_batchnorm_non_contig_cpu_SyncBatchNorm (__main__.TestNN)": ["", [""]], |
| 1438 | "test_affine_grid (__main__.TestNN)": ["", [""]], | 1453 | "test_affine_grid (__main__.TestNN)": ["", [""]], |
已修改