已合并
新增ut 测试 #5394
L1919_snow创建于 7月6日
新增ut 测试 #5394
已合并
L1919_snow创建于 7月6日
2 个文件变更+227-0
Atest/test_base_ops/test_drop_path.py+51-0
@@ -0,0 +1,51 @@
1import torch
2import torch_npu
3import unittest
4from torch.testing._internal.common_utils import TestCase, run_tests
5from torch_npu.contrib.module import NpuDropPath
6 
7 
8class 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()}")
atomgit-botatomgit-bot
atomgit-botatomgit-bot7月6日

🟡 Medium Priority

test_drop_path.pytest_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 语句或用日志替代。

likedislike
atomgit-botatomgit-bot7月6日

🟡 Medium Priority

test_train_eval_mode (line 35-47) 声称测试"训练模式 vs 评估模式",但仅对评估模式做了断言 (self.assertTrue(torch.allclose(eval_output, x))),训练模式下的 has_zero_train 仅被 print 输出,未做任何断言。若 NpuDropPath 在训练模式下存在 bug(例如即使 drop_prob=0.5 也从不丢弃),该测试仍会通过,无法起到回归保护作用。

对于一个形状为 (68, 5) = 340 元素的张量,drop_prob=0.5 时没有任何元素被丢弃的概率为 (0.5)^340 ≈ 10⁻¹⁰²,实际不可能发生。因此可以安全地添加断言,例如 self.assertTrue(has_zero_train.item(), "training mode should drop elements")self.assertFalse(torch.allclose(train_output, x))

建议:在 test_train_eval_mode 中对训练模式的行为添加断言。推荐方案:检查 has_zero_train 为 True(训练模式下应有元素被置零),或检查 train_outputx 不 allclose(标准 DropPath 在训练时会对保留值做 scale,因此不可能与输入完全一致)。同时移除或保留 print 语句均可,但断言是必须的。

likedislike
48 
49 
50if __name__ == '__main__':
51 run_tests()
Atest/test_base_ops/test_npu_renorm_backward.py+176-0
@@ -0,0 +1,176 @@
1import torch
2import torch_npu
3import unittest
4from torch.testing._internal.common_utils import TestCase, run_tests
5 
6 
7class 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 
175if __name__ == '__main__':
176 run_tests()