已关闭
[feat] Add test cases for verifying torch.jit.ScriptModule hook API on NPU #34324
考试请神请到孔子发现考的是英语创建于 4月24日关闭于 5月11日
[feat] Add test cases for verifying torch.jit.ScriptModule hook API on NPU #34324
已关闭
考试请神请到孔子发现考的是英语创建于 4月24日关闭于 5月11日
1 个文件变更+484-0
@@ -6,9 +6,15 @@ Add validation cases for torch.jit APIs:
6torch.jit.onednn_fusion_enabled6torch.jit.onednn_fusion_enabled
7torch.jit.enable_onednn_fusion7torch.jit.enable_onednn_fusion
8(extendable)8(extendable)
9+torch.jit.ScriptModule.register_full_backward_pre_hook,
10+torch.jit.ScriptModule.register_load_state_dict_pre_hook,
11+torch.jit.ScriptModule.register_load_state_dict_post_hook,
12+torch.jit.ScriptModule.register_state_dict_pre_hook,
13+torch.jit.ScriptModule.register_state_dict_post_hook
9"""14"""
10 15 
11import torch16import torch
17+import torch.nn as nn
12from torch.testing._internal.common_utils import run_tests, TestCase18from torch.testing._internal.common_utils import run_tests, TestCase
13 19 
14 20 
@@ -33,5 +39,483 @@ class TestOneDNNJitAPI(TestCase):
33 self.assertEqual(torch.jit.onednn_fusion_enabled(), False)39 self.assertEqual(torch.jit.onednn_fusion_enabled(), False)
34 40 
35 41 
42+class TestScriptModuleHooks(TestCase):
43+ # register_full_backward_hook: not working for ScriptModule, should raise error
44+ 
45+ def test_register_full_backward_hook_raises(self):
46+ class M(torch.jit.ScriptModule):
47+ def __init__(self):
48+ super().__init__()
49+ self.linear = nn.Linear(2, 2)
50+ 
51+ def forward(self, x):
52+ return self.linear(x)
53+ 
54+ model = M()
55+ with self.assertRaises(RuntimeError):
56+ model.register_full_backward_hook(
57+ lambda module, grad_input, grad_output: grad_input
58+ )
59+ 
60+ # register_full_backward_pre_hook
61+ 
62+ def test_register_full_backward_pre_hook_called(self):
63+ class M(torch.jit.ScriptModule):
64+ def __init__(self):
65+ super().__init__()
66+ self.linear = nn.Linear(2, 2)
67+ 
68+ def forward(self, x):
69+ return self.linear(x)
70+ 
71+ model = M()
72+ called = []
73+ handle = model.register_full_backward_pre_hook(
74+ lambda module, grad_output: (called.append(True), grad_output)[1]
75+ )
76+ x = torch.randn(2, 2, requires_grad=True)
77+ model(x).sum().backward()
78+ self.assertTrue(called)
79+ handle.remove()
80+ 
81+ def test_register_full_backward_pre_hook_modify_grad(self):
82+ class M(torch.jit.ScriptModule):
83+ def __init__(self):
84+ super().__init__()
85+ self.linear = nn.Linear(2, 2)
86+ 
87+ def forward(self, x):
88+ return self.linear(x)
89+ 
90+ model = M()
91+ model.register_full_backward_pre_hook(
92+ lambda module, grad_output: (grad_output[0] * 0,)
93+ )
94+ x = torch.ones(2, requires_grad=True)
95+ model(x).sum().backward()
96+ self.assertEqual(x.grad, torch.zeros(2))
97+ 
98+ def test_register_full_backward_pre_hook_prepend(self):
99+ class M(torch.jit.ScriptModule):
100+ def __init__(self):
101+ super().__init__()
102+ self.linear = nn.Linear(2, 2)
103+ 
104+ def forward(self, x):
105+ return self.linear(x)
106+ 
107+ model = M()
108+ order = []
109+ model.register_full_backward_pre_hook(
110+ lambda module, grad_output: (order.append(1), grad_output)[1]
111+ )
112+ model.register_full_backward_pre_hook(
113+ lambda module, grad_output: (order.append(2), grad_output)[1],
114+ prepend=True,
115+ )
116+ x = torch.randn(2, 2, requires_grad=True)
117+ model(x).sum().backward()
118+ self.assertEqual(order, [2, 1])
119+ 
120+ def test_register_full_backward_pre_hook_remove(self):
121+ class M(torch.jit.ScriptModule):
122+ def __init__(self):
123+ super().__init__()
124+ self.linear = nn.Linear(2, 2)
125+ 
126+ def forward(self, x):
127+ return self.linear(x)
128+ 
129+ model = M()
130+ called = []
131+ handle = model.register_full_backward_pre_hook(
132+ lambda module, grad_output: (called.append(True), grad_output)[1]
133+ )
134+ x = torch.randn(2, 2, requires_grad=True)
135+ model(x).sum().backward()
136+ self.assertEqual(len(called), 1)
137+ handle.remove()
138+ model(x).sum().backward()
139+ self.assertEqual(len(called), 1)
140+ 
141+ # register_load_state_dict_pre_hook & register_load_state_dict_post_hook
142+ 
143+ def test_load_state_dict_pre_hook_fires_before_module_and_post_hook(self):
144+ class M(torch.jit.ScriptModule):
145+ def __init__(self):
146+ super().__init__()
147+ self.linear = nn.Linear(2, 2)
148+ 
149+ def forward(self, x):
150+ return self.linear(x)
151+ 
152+ order = []
153+ 
154+ def post_hook(module, incompatible_keys):
155+ order.append("post")
156+ 
157+ def pre_hook(
158+ module,
159+ state_dict,
160+ prefix,
161+ local_metadata,
162+ strict,
163+ missing_keys,
164+ unexpected_keys,
165+ error_msgs,
166+ ):
167+ order.append("pre")
168+ 
169+ model = M()
170+ model.register_load_state_dict_post_hook(post_hook)
171+ model.register_load_state_dict_pre_hook(pre_hook)
172+ model.load_state_dict(model.state_dict())
173+ self.assertEqual(order, ["pre", "post"])
174+ 
175+ order2 = []
176+ 
177+ def pre_hook_modify(
178+ module,
179+ state_dict,
180+ prefix,
181+ local_metadata,
182+ strict,
183+ missing_keys,
184+ unexpected_keys,
185+ error_msgs,
186+ ):
187+ order2.append("pre")
188+ for key in list(state_dict.keys()):
189+ state_dict[key] = torch.zeros_like(state_dict[key])
190+ 
191+ def post_hook_check(module, incompatible_keys):
192+ order2.append("post")
193+ self.assertEqual(
194+ module.linear.weight, torch.zeros_like(module.linear.weight)
195+ )
196+ 
197+ model2 = M()
198+ model2.register_load_state_dict_post_hook(post_hook_check)
199+ model2.register_load_state_dict_pre_hook(pre_hook_modify)
200+ model2.load_state_dict(model.state_dict())
201+ self.assertEqual(order2, ["pre", "post"])
202+ 
203+ def test_register_load_state_dict_pre_hook_called(self):
204+ class M(torch.jit.ScriptModule):
205+ def __init__(self):
206+ super().__init__()
207+ self.linear = nn.Linear(2, 2)
208+ 
209+ def forward(self, x):
210+ return self.linear(x)
211+ 
212+ model = M()
213+ called = []
214+ 
215+ def hook(
216+ module,
217+ state_dict,
218+ prefix,
219+ local_metadata,
220+ strict,
221+ missing_keys,
222+ unexpected_keys,
223+ error_msgs,
224+ ):
225+ called.append(prefix)
226+ 
227+ model.register_load_state_dict_pre_hook(hook)
228+ model.load_state_dict(model.state_dict())
229+ self.assertEqual(called, [""])
230+ 
231+ def test_register_load_state_dict_pre_hook_with_module(self):
232+ class M(torch.jit.ScriptModule):
233+ def __init__(self):
234+ super().__init__()
235+ self.linear = nn.Linear(2, 2)
236+ 
237+ def forward(self, x):
238+ return self.linear(x)
239+ 
240+ model = M()
241+ received_module = []
242+ 
243+ def hook(
244+ module,
245+ state_dict,
246+ prefix,
247+ local_metadata,
248+ strict,
249+ missing_keys,
250+ unexpected_keys,
251+ error_msgs,
252+ ):
253+ received_module.append(module)
254+ 
255+ model.register_load_state_dict_pre_hook(hook)
256+ model.load_state_dict(model.state_dict())
257+ self.assertIs(received_module[0], model)
258+ 
259+ def test_register_load_state_dict_pre_hook_remove(self):
260+ class M(torch.jit.ScriptModule):
261+ def __init__(self):
262+ super().__init__()
263+ self.linear = nn.Linear(2, 2)
264+ 
265+ def forward(self, x):
266+ return self.linear(x)
267+ 
268+ model = M()
269+ called = []
270+ 
271+ def hook(
272+ module,
273+ state_dict,
274+ prefix,
275+ local_metadata,
276+ strict,
277+ missing_keys,
278+ unexpected_keys,
279+ error_msgs,
280+ ):
281+ called.append(True)
282+ 
283+ handle = model.register_load_state_dict_pre_hook(hook)
284+ model.load_state_dict(model.state_dict())
285+ self.assertEqual(len(called), 1)
286+ handle.remove()
287+ model.load_state_dict(model.state_dict())
288+ self.assertEqual(len(called), 1)
289+ 
290+ # register_load_state_dict_post_hook
291+ 
292+ def test_register_load_state_dict_post_hook_called(self):
293+ class M(torch.jit.ScriptModule):
294+ def __init__(self):
295+ super().__init__()
296+ self.linear = nn.Linear(2, 2)
297+ 
298+ def forward(self, x):
299+ return self.linear(x)
300+ 
301+ model = M()
302+ called = []
303+ 
304+ def hook(module, incompatible_keys):
305+ called.append(True)
306+ 
307+ handle = model.register_load_state_dict_post_hook(hook)
308+ model.load_state_dict(model.state_dict())
309+ self.assertTrue(called)
310+ handle.remove()
311+ 
312+ def test_register_load_state_dict_post_hook_with_module(self):
313+ class M(torch.jit.ScriptModule):
314+ def __init__(self):
315+ super().__init__()
316+ self.linear = nn.Linear(2, 2)
317+ 
318+ def forward(self, x):
319+ return self.linear(x)
320+ 
321+ model = M()
322+ received_module = []
323+ 
324+ def hook(module, incompatible_keys):
325+ received_module.append(module)
326+ 
327+ handle = model.register_load_state_dict_post_hook(hook)
328+ model.load_state_dict(model.state_dict())
329+ self.assertIs(received_module[0], model)
330+ handle.remove()
331+ 
332+ def test_register_load_state_dict_post_hook_remove(self):
333+ class M(torch.jit.ScriptModule):
334+ def __init__(self):
335+ super().__init__()
336+ self.linear = nn.Linear(2, 2)
337+ 
338+ def forward(self, x):
339+ return self.linear(x)
340+ 
341+ model = M()
342+ called = []
343+ 
344+ def hook(module, incompatible_keys):
345+ called.append(True)
346+ 
347+ handle = model.register_load_state_dict_post_hook(hook)
348+ model.load_state_dict(model.state_dict())
349+ self.assertEqual(len(called), 1)
350+ handle.remove()
351+ model.load_state_dict(model.state_dict())
352+ self.assertEqual(len(called), 1)
353+ 
354+ # register_state_dict_pre_hook & register_state_dict_post_hook
355+ 
356+ def test_state_dict_pre_hook_fires_before_module_and_post_hook(self):
357+ class M(torch.jit.ScriptModule):
358+ def __init__(self):
359+ super().__init__()
360+ self.linear = nn.Linear(2, 2)
361+ 
362+ def forward(self, x):
363+ return self.linear(x)
364+ 
365+ order = []
366+ 
367+ def post_hook(module, state_dict, prefix, local_metadata):
368+ order.append("post")
369+ 
370+ def pre_hook(module, prefix, keep_vars):
371+ order.append("pre")
372+ 
373+ model = M()
374+ model.register_state_dict_post_hook(post_hook)
375+ model.register_state_dict_pre_hook(pre_hook)
376+ model.state_dict()
377+ self.assertEqual(order, ["pre", "post"])
378+ 
379+ order2 = []
380+ pre_hook_called = [False]
381+ 
382+ def pre_hook_flag(module, prefix, keep_vars):
383+ order2.append("pre")
384+ pre_hook_called[0] = True
385+ 
386+ def post_hook_check(module, state_dict, prefix, local_metadata):
387+ order2.append("post")
388+ self.assertTrue(pre_hook_called[0])
389+ self.assertTrue(len(state_dict) > 0)
390+ 
391+ model2 = M()
392+ model2.register_state_dict_post_hook(post_hook_check)
393+ model2.register_state_dict_pre_hook(pre_hook_flag)
394+ model2.state_dict()
395+ self.assertEqual(order2, ["pre", "post"])
396+ 
397+ def test_register_state_dict_pre_hook_called(self):
398+ class M(torch.jit.ScriptModule):
399+ def __init__(self):
400+ super().__init__()
401+ self.linear = nn.Linear(2, 2)
402+ 
403+ def forward(self, x):
404+ return self.linear(x)
405+ 
406+ model = M()
407+ called = []
408+ 
409+ def hook(module, prefix, keep_vars):
410+ called.append(prefix)
411+ 
412+ model.register_state_dict_pre_hook(hook)
413+ model.state_dict()
414+ self.assertEqual(called, [""])
415+ 
416+ def test_register_state_dict_pre_hook_with_module(self):
417+ class M(torch.jit.ScriptModule):
418+ def __init__(self):
419+ super().__init__()
420+ self.linear = nn.Linear(2, 2)
421+ 
422+ def forward(self, x):
423+ return self.linear(x)
424+ 
425+ model = M()
426+ received_module = []
427+ 
428+ def hook(module, prefix, keep_vars):
429+ received_module.append(module)
430+ 
431+ model.register_state_dict_pre_hook(hook)
432+ model.state_dict()
433+ self.assertIs(received_module[0], model)
434+ 
435+ def test_register_state_dict_pre_hook_remove(self):
436+ class M(torch.jit.ScriptModule):
437+ def __init__(self):
438+ super().__init__()
439+ self.linear = nn.Linear(2, 2)
440+ 
441+ def forward(self, x):
442+ return self.linear(x)
443+ 
444+ model = M()
445+ called = []
446+ 
447+ def hook(module, prefix, keep_vars):
448+ called.append(True)
449+ 
450+ handle = model.register_state_dict_pre_hook(hook)
451+ model.state_dict()
452+ self.assertEqual(len(called), 1)
453+ handle.remove()
454+ model.state_dict()
455+ self.assertEqual(len(called), 1)
456+ 
457+ # register_state_dict_post_hook
458+ 
459+ def test_register_state_dict_post_hook_called(self):
460+ class M(torch.jit.ScriptModule):
461+ def __init__(self):
462+ super().__init__()
463+ self.linear = nn.Linear(2, 2)
464+ 
465+ def forward(self, x):
466+ return self.linear(x)
467+ 
468+ model = M()
469+ called = []
470+ 
471+ def hook(module, state_dict, prefix, local_metadata):
472+ called.append(prefix)
473+ 
474+ model.register_state_dict_post_hook(hook)
475+ model.state_dict()
476+ self.assertEqual(called, [""])
477+ 
478+ def test_register_state_dict_post_hook_with_module(self):
479+ class M(torch.jit.ScriptModule):
480+ def __init__(self):
481+ super().__init__()
482+ self.linear = nn.Linear(2, 2)
483+ 
484+ def forward(self, x):
485+ return self.linear(x)
486+ 
487+ model = M()
488+ received_module = []
489+ 
490+ def hook(module, state_dict, prefix, local_metadata):
491+ received_module.append(module)
492+ 
493+ model.register_state_dict_post_hook(hook)
494+ model.state_dict()
495+ self.assertIs(received_module[0], model)
496+ 
497+ def test_register_state_dict_post_hook_remove(self):
498+ class M(torch.jit.ScriptModule):
499+ def __init__(self):
500+ super().__init__()
501+ self.linear = nn.Linear(2, 2)
502+ 
503+ def forward(self, x):
504+ return self.linear(x)
505+ 
506+ model = M()
507+ called = []
508+ 
509+ def hook(module, state_dict, prefix, local_metadata):
510+ called.append(True)
511+ 
512+ handle = model.register_state_dict_post_hook(hook)
513+ model.state_dict()
514+ self.assertEqual(len(called), 1)
515+ handle.remove()
516+ model.state_dict()
517+ self.assertEqual(len(called), 1)
518+ 
519+ 
36if __name__ == "__main__":520if __name__ == "__main__":
37 run_tests()521 run_tests()