已合并
新增ut 测试 #5394
L1919_snow创建于 7月6日
新增ut 测试 #5394
已合并
共 2 个文件变更+227-0
| @@ -0,0 +1,51 @@ | |||
| 1 | import torch | ||
| 2 | import torch_npu | ||
| 3 | import unittest | ||
| 4 | from torch.testing._internal.common_utils import TestCase, run_tests | ||
| 5 | from torch_npu.contrib.module import NpuDropPath | ||
| 6 | |||
| 7 | |||
| 8 | class TestNpuDropPath(TestCase): | ||
| 9 | |||
| 10 | def test_basic_forward(self): | ||
| 11 | """基础前向传播""" | ||
| 12 | drop_path = NpuDropPath(0).npu() | ||
| 13 | x = torch.randn(68, 5, device='npu') | ||
| 14 | output = drop_path(x) | ||
| 15 | self.assertEqual(output.shape, x.shape) | ||
| 16 | self.assertEqual(output.device, x.device) | ||
| 17 | |||
| 18 | def test_drop_prob_0(self): | ||
| 19 | """drop_prob=0 时输出等于输入""" | ||
| 20 | drop_path = NpuDropPath(0).npu() | ||
| 21 | x = torch.randn(68, 5, device='npu') | ||
| 22 | output = drop_path(x) | ||
| 23 | self.assertTrue(torch.allclose(output, x)) | ||
| 24 | |||
| 25 | def test_backward(self): | ||
| 26 | """反向传播:autograd 示例""" | ||
| 27 | drop_path = NpuDropPath(0).npu() | ||
| 28 | input1 = torch.randn(68, 5, device='npu', requires_grad=True) | ||
| 29 | input2 = torch.randn(68, 5, device='npu', requires_grad=True) | ||
| 30 | output = input1 + drop_path(input2) | ||
| 31 | output.sum().backward() | ||
| 32 | self.assertIsNotNone(input1.grad) | ||
| 33 | self.assertIsNotNone(input2.grad) | ||
| 34 | |||
| 35 | def test_train_eval_mode(self): | ||
| 36 | """训练模式 vs 评估模式""" | ||
| 37 | drop_path = NpuDropPath(0.5).npu() | ||
| 38 | x = torch.randn(68, 5, device='npu') | ||
| 39 | # 训练模式:有随机丢弃 | ||
| 40 | drop_path.train() | ||
| 41 | train_output = drop_path(x) | ||
| 42 | has_zero_train = (train_output == 0).any() | ||
| 43 | # 评估模式:不丢弃 | ||
| 44 | drop_path.eval() | ||
| 45 | eval_output = drop_path(x) | ||
| 46 | self.assertTrue(torch.allclose(eval_output, x)) | ||
| 47 | print(f"训练模式是否有丢弃: {has_zero_train.item()}") | ||
🟡 Medium Priority
对于一个形状为 (68, 5) = 340 元素的张量, 建议:在 ![]() ![]() | |||
| 48 | |||
| 49 | |||
| 50 | if __name__ == '__main__': | ||
| 51 | run_tests() | ||
| @@ -0,0 +1,176 @@ | |||
| 1 | import torch | ||
| 2 | import torch_npu | ||
| 3 | import unittest | ||
| 4 | from torch.testing._internal.common_utils import TestCase, run_tests | ||
| 5 | |||
| 6 | |||
| 7 | class TestNPURenormBackward(TestCase): | ||
| 8 | |||
| 9 | def test_basic_forward(self): | ||
| 10 | """基础功能:直接调用 npu_renorm_backward""" | ||
| 11 | x = torch.randn(4, 8, device='npu', requires_grad=True) | ||
| 12 | grad = torch.randn(4, 8, device='npu') | ||
| 13 | result = torch_npu.npu_renorm_backward(grad, x, 2.0, 0, 1.0) | ||
| 14 | self.assertEqual(result.shape, x.shape) | ||
| 15 | self.assertEqual(result.device, x.device) | ||
| 16 | self.assertEqual(result.dtype, x.dtype) | ||
| 17 | |||
| 18 | def test_compare_with_autograd_p_2(self): | ||
| 19 | """对比自动微分:p=2""" | ||
| 20 | x = torch.randn(4, 8, device='npu', requires_grad=True) | ||
| 21 | grad = torch.randn(4, 8, device='npu') | ||
| 22 | y = torch.renorm(x, 2.0, 0, 1.0) | ||
| 23 | y.backward(grad) | ||
| 24 | grad_auto = x.grad.clone() | ||
| 25 | x.grad.zero_() | ||
| 26 | grad_custom = torch_npu.npu_renorm_backward(grad, x, 2.0, 0, 1.0) | ||
| 27 | self.assertTrue(torch.allclose(grad_auto, grad_custom, atol=1e-5, rtol=1e-5)) | ||
| 28 | |||
| 29 | def test_compare_with_autograd_p_1(self): | ||
| 30 | """对比自动微分:p=1""" | ||
| 31 | x = torch.randn(4, 8, device='npu', requires_grad=True) | ||
| 32 | grad = torch.randn(4, 8, device='npu') | ||
| 33 | y = torch.renorm(x, 1.0, 0, 1.0) | ||
| 34 | y.backward(grad) | ||
| 35 | grad_auto = x.grad.clone() | ||
| 36 | x.grad.zero_() | ||
| 37 | grad_custom = torch_npu.npu_renorm_backward(grad, x, 1.0, 0, 1.0) | ||
| 38 | self.assertTrue(torch.allclose(grad_auto, grad_custom, atol=1e-5, rtol=1e-5)) | ||
| 39 | |||
| 40 | def test_compare_with_autograd_p_3(self): | ||
| 41 | """对比自动微分:p>2""" | ||
| 42 | x = torch.randn(4, 8, device='npu', requires_grad=True) | ||
| 43 | grad = torch.randn(4, 8, device='npu') | ||
| 44 | y = torch.renorm(x, 3.0, 0, 1.0) | ||
| 45 | y.backward(grad) | ||
| 46 | grad_auto = x.grad.clone() | ||
| 47 | x.grad.zero_() | ||
| 48 | grad_custom = torch_npu.npu_renorm_backward(grad, x, 3.0, 0, 1.0) | ||
| 49 | self.assertTrue(torch.allclose(grad_auto, grad_custom, atol=1e-5, rtol=1e-5)) | ||
| 50 | |||
| 51 | def test_compare_with_autograd_p_0_5(self): | ||
| 52 | """对比自动微分:p<1""" | ||
| 53 | x = torch.randn(4, 8, device='npu', requires_grad=True) | ||
| 54 | grad = torch.randn(4, 8, device='npu') | ||
| 55 | y = torch.renorm(x, 0.5, 0, 1.0) | ||
| 56 | y.backward(grad) | ||
| 57 | grad_auto = x.grad.clone() | ||
| 58 | x.grad.zero_() | ||
| 59 | grad_custom = torch_npu.npu_renorm_backward(grad, x, 0.5, 0, 1.0) | ||
| 60 | self.assertTrue(torch.allclose(grad_auto, grad_custom, atol=1e-5, rtol=1e-5)) | ||
| 61 | |||
| 62 | def test_compare_with_autograd_p_1_5(self): | ||
| 63 | """对比自动微分:1<p<2""" | ||
| 64 | x = torch.randn(4, 8, device='npu', requires_grad=True) | ||
| 65 | grad = torch.randn(4, 8, device='npu') | ||
| 66 | y = torch.renorm(x, 1.5, 0, 1.0) | ||
| 67 | y.backward(grad) | ||
| 68 | grad_auto = x.grad.clone() | ||
| 69 | x.grad.zero_() | ||
| 70 | grad_custom = torch_npu.npu_renorm_backward(grad, x, 1.5, 0, 1.0) | ||
| 71 | self.assertTrue(torch.allclose(grad_auto, grad_custom, atol=1e-5, rtol=1e-5)) | ||
| 72 | |||
| 73 | def test_compare_with_autograd_3d(self): | ||
| 74 | """3D 张量测试""" | ||
| 75 | x = torch.randn(3, 4, 5, device='npu', requires_grad=True) | ||
| 76 | grad = torch.randn(3, 4, 5, device='npu') | ||
| 77 | y = torch.renorm(x, 2.0, 1, 0.8) | ||
| 78 | y.backward(grad) | ||
| 79 | grad_auto = x.grad.clone() | ||
| 80 | x.grad.zero_() | ||
| 81 | grad_custom = torch_npu.npu_renorm_backward(grad, x, 2.0, 1, 0.8) | ||
| 82 | self.assertTrue(torch.allclose(grad_auto, grad_custom, atol=1e-5, rtol=1e-5)) | ||
| 83 | |||
| 84 | def test_compare_with_autograd_4d(self): | ||
| 85 | """4D 张量测试""" | ||
| 86 | x = torch.randn(2, 3, 4, 5, device='npu', requires_grad=True) | ||
| 87 | grad = torch.randn(2, 3, 4, 5, device='npu') | ||
| 88 | y = torch.renorm(x, 2.0, 2, 0.8) | ||
| 89 | y.backward(grad) | ||
| 90 | grad_auto = x.grad.clone() | ||
| 91 | x.grad.zero_() | ||
| 92 | grad_custom = torch_npu.npu_renorm_backward(grad, x, 2.0, 2, 0.8) | ||
| 93 | self.assertTrue(torch.allclose(grad_auto, grad_custom, atol=1e-5, rtol=1e-5)) | ||
| 94 | |||
| 95 | def test_compare_with_autograd_negative_dim(self): | ||
| 96 | """负数 dim 测试""" | ||
| 97 | x = torch.randn(4, 8, device='npu', requires_grad=True) | ||
| 98 | grad = torch.randn(4, 8, device='npu') | ||
| 99 | y = torch.renorm(x, 2.0, -1, 1.0) | ||
| 100 | y.backward(grad) | ||
| 101 | grad_auto = x.grad.clone() | ||
| 102 | x.grad.zero_() | ||
| 103 | grad_custom = torch_npu.npu_renorm_backward(grad, x, 2.0, -1, 1.0) | ||
| 104 | self.assertTrue(torch.allclose(grad_auto, grad_custom, atol=1e-5, rtol=1e-5)) | ||
| 105 | |||
| 106 | def test_compare_with_autograd_different_maxnorm(self): | ||
| 107 | """不同 maxnorm 值测试""" | ||
| 108 | for maxnorm in [0.5, 1.0, 2.0, 5.0]: | ||
| 109 | x = torch.randn(4, 8, device='npu', requires_grad=True) | ||
| 110 | grad = torch.randn(4, 8, device='npu') | ||
| 111 | y = torch.renorm(x, 2.0, 0, maxnorm) | ||
| 112 | y.backward(grad) | ||
| 113 | grad_auto = x.grad.clone() | ||
| 114 | x.grad.zero_() | ||
| 115 | grad_custom = torch_npu.npu_renorm_backward(grad, x, 2.0, 0, maxnorm) | ||
| 116 | self.assertTrue(torch.allclose(grad_auto, grad_custom, atol=1e-5, rtol=1e-5)) | ||
| 117 | |||
| 118 | def test_compare_with_autograd_float16(self): | ||
| 119 | """float16 精度测试""" | ||
| 120 | x = torch.randn(4, 8, device='npu', dtype=torch.float16, requires_grad=True) | ||
| 121 | grad = torch.randn(4, 8, device='npu', dtype=torch.float16) | ||
| 122 | y = torch.renorm(x.float(), 2.0, 0, 1.0).to(torch.float16) | ||
| 123 | y.backward(grad) | ||
| 124 | grad_auto = x.grad.clone() | ||
| 125 | x.grad.zero_() | ||
| 126 | grad_custom = torch_npu.npu_renorm_backward(grad, x, 2.0, 0, 1.0) | ||
| 127 | self.assertTrue(torch.allclose(grad_auto, grad_custom, atol=1e-3, rtol=1e-3)) | ||
| 128 | |||
| 129 | def test_compare_with_autograd_bfloat16(self): | ||
| 130 | """bfloat16 精度测试""" | ||
| 131 | x = torch.randn(4, 8, device='npu', dtype=torch.bfloat16, requires_grad=True) | ||
| 132 | grad = torch.randn(4, 8, device='npu', dtype=torch.bfloat16) | ||
| 133 | y = torch.renorm(x.float(), 2.0, 0, 1.0).to(torch.bfloat16) | ||
| 134 | y.backward(grad) | ||
| 135 | grad_auto = x.grad.clone() | ||
| 136 | x.grad.zero_() | ||
| 137 | grad_custom = torch_npu.npu_renorm_backward(grad, x, 2.0, 0, 1.0) | ||
| 138 | self.assertTrue(torch.allclose(grad_auto, grad_custom, atol=1e-2, rtol=1e-2)) | ||
| 139 | |||
| 140 | def test_no_scale_when_norm_less_than_maxnorm(self): | ||
| 141 | """norm < maxnorm 时,梯度应等于输入梯度(不缩放)""" | ||
| 142 | x = torch.randn(4, 8, device='npu', requires_grad=True) | ||
| 143 | grad = torch.randn(4, 8, device='npu') | ||
| 144 | maxnorm = 10.0 | ||
| 145 | y = torch.renorm(x, 2.0, 0, maxnorm) | ||
| 146 | y.backward(grad) | ||
| 147 | grad_auto = x.grad.clone() | ||
| 148 | x.grad.zero_() | ||
| 149 | grad_custom = torch_npu.npu_renorm_backward(grad, x, 2.0, 0, maxnorm) | ||
| 150 | self.assertTrue(torch.allclose(grad_auto, grad_custom, atol=1e-5, rtol=1e-5)) | ||
| 151 | |||
| 152 | def test_zero_tensor(self): | ||
| 153 | """全零输入测试""" | ||
| 154 | x = torch.zeros(4, 8, device='npu', requires_grad=True) | ||
| 155 | grad = torch.randn(4, 8, device='npu') | ||
| 156 | y = torch.renorm(x, 2.0, 0, 1.0) | ||
| 157 | y.backward(grad) | ||
| 158 | grad_auto = x.grad.clone() | ||
| 159 | x.grad.zero_() | ||
| 160 | grad_custom = torch_npu.npu_renorm_backward(grad, x, 2.0, 0, 1.0) | ||
| 161 | self.assertTrue(torch.allclose(grad_auto, grad_custom, atol=1e-5, rtol=1e-5)) | ||
| 162 | |||
| 163 | def test_large_tensor(self): | ||
| 164 | """大张量测试""" | ||
| 165 | x = torch.randn(100, 100, device='npu', requires_grad=True) | ||
| 166 | grad = torch.randn(100, 100, device='npu') | ||
| 167 | y = torch.renorm(x, 2.0, 0, 1.0) | ||
| 168 | y.backward(grad) | ||
| 169 | grad_auto = x.grad.clone() | ||
| 170 | x.grad.zero_() | ||
| 171 | grad_custom = torch_npu.npu_renorm_backward(grad, x, 2.0, 0, 1.0) | ||
| 172 | self.assertTrue(torch.allclose(grad_auto, grad_custom, atol=1e-5, rtol=1e-5)) | ||
| 173 | |||
| 174 | |||
| 175 | if __name__ == '__main__': | ||
| 176 | run_tests() | ||


🟡 Medium Priority
在
test_drop_path.py的test_train_eval_mode方法中(第 41-47 行),has_zero_train = (train_output == 0).any()计算了训练模式下输出中是否存在被丢弃(置零)的元素,但该变量仅在print中使用,从未通过assertTrue或其他断言进行验证。测试仅对 eval 模式的输出做了断言(第 46 行),而对训练模式的丢弃行为没有任何断言。这意味着如果训练模式存在 bug 导致完全不丢弃(与 eval 模式行为一致),该测试仍会通过,无法起到验证训练模式正确性的作用。建议:对
has_zero_train增加断言,例如self.assertTrue(has_zero_train.item(), "训练模式下应有丢弃行为");或使用更严格的检查(如确认丢弃比例在合理范围内)。同时移除print语句或用日志替代。