已合并
aot_autograd_pass_fo_FA #30156
aot_autograd_pass_fo_FA #30156
已合并
Lu_G创建于 1月28日
3 个文件变更+102-1
@@ -0,0 +1,77 @@
1+import torch
2+import torch.fx as fx
3+from torch.fx.passes.shape_prop import ShapeProp
4+from torch.testing._internal.common_utils import run_tests, parametrize, instantiate_parametrized_tests
5+from testutils import TestUtils
6+import torch_npu
7+import torch_npu._inductor
8+ 
9+ 
10+class FusionAttentionUnchangeModel(torch.nn.Module):
11+ def forward(self, primals_1, primals_2, primals_3):
12+ npu_fusion_attention = torch.ops.npu.npu_fusion_attention.default(primals_1, primals_2, primals_3, 8, 'BNSD', None, None, None, 0.125, 0.9)
13+ getitem = npu_fusion_attention[0]
14+ getitem_1 = npu_fusion_attention[1]
15+ getitem_2 = npu_fusion_attention[2]
16+ getitem_3 = npu_fusion_attention[3]
17+ getitem_4 = npu_fusion_attention[4]
18+ getitem_5 = npu_fusion_attention[5]
19+ return {"getitem": getitem, "getitem_1": getitem_1, "getitem_2": getitem_2, "getitem_3": getitem_3, "getitem_4": getitem_4, "getitem_5": getitem_5}
20+ 
21+ 
22+class TestFusionAttentionUnchangePass(TestUtils):
23+ def op_calc(self, primals_1, primals_2, primals_3):
24+ npu_fusion_attention_v3 = torch.ops.npu.npu_fusion_attention_v3.default(primals_1, primals_2, primals_3, 8, 'BNSD', None, None, None, 0.125, 0.9)
25+ getitem = npu_fusion_attention_v3[0]
26+ getitem_1 = npu_fusion_attention_v3[1]
27+ getitem_2 = npu_fusion_attention_v3[2]
28+ getitem_3 = npu_fusion_attention_v3[3]
29+ getitem_4 = npu_fusion_attention_v3[4]
30+ getitem_5 = npu_fusion_attention_v3[5]
31+ return {"getitem": getitem, "getitem_1": getitem_1, "getitem_2": getitem_2, "getitem_3": getitem_3, "getitem_4": getitem_4, "getitem_5": getitem_5}
32+ 
33+ 
34+ 
35+ def test_compile_cases(self):
36+ primals_1 = torch.randn(2, 8, 16, 64, dtype=torch.float32, device="npu")
37+ primals_2 = torch.randn(2, 8, 16, 64, dtype=torch.float32, device="npu")
38+ primals_3 = torch.randn(2, 8, 16, 64, dtype=torch.float32, device="npu")
39+ 
40+ state = torch.npu.get_rng_state()
41+ std_result = self.op_calc(primals_1, primals_2, primals_3)
42+ torch.npu.set_rng_state(state)
43+ compiled_op_calc = torch.compile(self.op_calc, backend="inductor")
44+ inductor_result = compiled_op_calc(primals_1, primals_2, primals_3)
45+ self.assertIsInstance(inductor_result["getitem_4"], torch.Tensor, "The output parameter 'seed' of the npu_fusion_attention_v3 should be Tensor")
46+ self.assertIsInstance(inductor_result["getitem_5"], torch.Tensor, "The output parameter 'offset' of the npu_fusion_attention_v3 should be Tensor")
47+ self.assertEqual(std_result, inductor_result, atol=1e-3, rtol=1e-3)
48+
49+
50+ def test_ut_cases(self):
51+ primals_1 = torch.randn(2, 8, 16, 64, dtype=torch.float32, device="npu")
52+ primals_2 = torch.randn(2, 8, 16, 64, dtype=torch.float32, device="npu")
53+ primals_3 = torch.randn(2, 8, 16, 64, dtype=torch.float32, device="npu")
54+ model = FusionAttentionUnchangeModel()
55+ graph_module = fx.symbolic_trace(model)
56+ ShapeProp(graph_module).propagate(primals_1, primals_2, primals_3)
57+
58+ # 应用优化 Pass
59+ from torch_npu._inductor.fx_passes.ascend_custom_passes.ascend_graph_pass import fusion_attention_v3_pass
60+ fusion_attention_v3_pass(graph_module.graph)
61+ graph_module.recompile()
62+ 
63+ # 验证输出是否一致
64+ state = torch.npu.get_rng_state()
65+ std_result = model(primals_1, primals_2, primals_3)
66+ torch.npu.set_rng_state(state)
67+ inductor_result = graph_module(primals_1, primals_2, primals_3)
68+ self.assertIsInstance(inductor_result["getitem_4"], torch.Tensor, "After the pass, the output parameter 'seed' of the npu_fusion_attention should be Tensor")
69+ self.assertIsInstance(inductor_result["getitem_5"], torch.Tensor, "After the pass, the output parameter 'offset' of the npu_fusion_attention should be Tensor")
70+ self.assertEqual(std_result, inductor_result, atol=1e-3, rtol=1e-3)
71+ 
72+ 
73+instantiate_parametrized_tests(TestFusionAttentionUnchangePass)
74+ 
75+ 
76+if __name__ == "__main__":
77+ run_tests()
@@ -17,7 +17,12 @@ def run_register_pre_custom_passes(gm):
17 for fn in ASCEND_CUSTOME_PASS_REGISTER[PassType.PRE][level]:17 for fn in ASCEND_CUSTOME_PASS_REGISTER[PassType.PRE][level]:
18 fn(gm)18 fn(gm)
19 19 
20- log.debug(f"after pre_grad graph optimizer pass, graph is: {gm}")20+ for level in sorted(FxPassLevel):
21+ for fn in ASCEND_CUSTOME_PASS_REGISTER[PassType.PRE][level]:
22+ if fn.__name__ == "fusion_attention_v3_pass":
23+ fn(gm)
24+ 
25+ log.debug(f"after pre_grad graph optimizer pass, graph is: {gm}")
D
Ddezheng8892月3日
 log.debug(f"after pre_grad graph optimizer pass, graph is: {gm}") 日志提出来 只保留一个吧
likedislike
21 26
22 27 
23def run_register_post_custom_passes(gm):28def run_register_post_custom_passes(gm):
@@ -805,6 +805,25 @@ def unfold_dual_reduction_pass(graph: torch.fx.Graph) -> None:
805 eliminate_dead_code(graph, changed, unfold_dual_reduction_pass.__name__)805 eliminate_dead_code(graph, changed, unfold_dual_reduction_pass.__name__)
806 806 
807 807 
808+@register_custom_pass(PassType.PRE)
809+def fusion_attention_v3_pass(graph: torch.fx.Graph) -> None:
810+ changed = False
811+ for node in list(graph.nodes): # 使用list避免迭代时修改图结构
812+ if node.op == 'call_function' and node.target == torch.ops.npu.npu_fusion_attention.default:
813+ # 创建新节点调用v3版本
814+ with graph.inserting_before(node):
815+ new_node = graph.call_function(
816+ torch.ops.npu.npu_fusion_attention_v3.default,
817+ args=node.args,
818+ kwargs=node.kwargs
819+ )
820+ new_node.meta.update(node.meta)
821+ node.replace_all_uses_with(new_node)
D
Ddezheng8892月3日

最好是有个ut 作为测试用例

likedislike
Lu_G
2月10日 评论:
822+ graph.erase_node(node)
823+ changed = True
824+ eliminate_dead_code(graph, changed, fusion_attention_v3_pass.__name__, False)
825+ 
826+ 
808def eliminate_dead_code(graph, changed, fn_name, POST=True):827def eliminate_dead_code(graph, changed, fn_name, POST=True):
809 if changed:828 if changed:
810 if POST:829 if POST: