已合并
feat(dvm): support A5 and optimizations #34725
SorryNaCN创建于 4月29日
feat(dvm): support A5 and optimizations #34725
已合并
SorryNaCN创建于 4月29日
10 个文件变更+47-35
@@ -24,4 +24,4 @@
24[submodule "third_party/dvm/dvm"]24[submodule "third_party/dvm/dvm"]
25 path = third_party/dvm/dvm25 path = third_party/dvm/dvm
26 url = https://gitcode.com/mindspore/dvm.git26 url = https://gitcode.com/mindspore/dvm.git
27- branch = r2.927+ branch = r2.10
@@ -1,7 +1,11 @@
1set(DVM_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/dvm)1set(DVM_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/dvm)
2set(DVM_LIB ${DVM_ROOT}/libdvm.a)2set(DVM_LIB ${DVM_ROOT}/libdvm.a)
3 3 
4-set(DVM_MAKE_ARGS_STR "PRE_ASCEND=1")4+set(ACL_INC_ROOT "${TORCHNPU_THIRD_PARTY_ROOT}/acl/inc")
5+set(DVM_MAKE_ARGS
6+ PRE_ASCEND=1
7+ DVM_CUSTOM_FLAGS=-I${ACL_INC_ROOT}
8+)
5 9 
6file(GLOB DVM_DEPENDS10file(GLOB DVM_DEPENDS
7 CONFIGURE_DEPENDS11 CONFIGURE_DEPENDS
@@ -12,19 +16,9 @@ file(GLOB DVM_DEPENDS
12 "${DVM_ROOT}/include/*.h"16 "${DVM_ROOT}/include/*.h"
13)17)
14 18 
15-set(ACL_INC_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/../acl/inc)
16-if (EXISTS "${ACL_INC_ROOT}")
17- file(GLOB ACL_INC_DIRS LIST_DIRECTORIES true "${ACL_INC_ROOT}/*")
18- foreach(acl_inc_dir IN LISTS ACL_INC_DIRS)
19- if (IS_DIRECTORY "${acl_inc_dir}")
20- file(COPY "${acl_inc_dir}" DESTINATION "${DVM_ROOT}/include")
21- endif()
22- endforeach()
23-endif()
24- 
25add_custom_command(19add_custom_command(
26 OUTPUT ${DVM_LIB}20 OUTPUT ${DVM_LIB}
27- COMMAND make -C ${DVM_ROOT} ${DVM_MAKE_ARGS_STR} libdvm.a21+ COMMAND make -C ${DVM_ROOT} ${DVM_MAKE_ARGS} libdvm.a
28 WORKING_DIRECTORY ${DVM_ROOT}22 WORKING_DIRECTORY ${DVM_ROOT}
29 DEPENDS ${DVM_DEPENDS}23 DEPENDS ${DVM_DEPENDS}
30 COMMENT "Building DVM static library"24 COMMENT "Building DVM static library"
@@ -1 +1 @@
1-Subproject commit fe91de40ccbb3d9fbb2077423ee0f109760fb2f61+Subproject commit d59888fdc684320445b92addaa4fd37eb1943902
@@ -11,6 +11,7 @@ from torch_npu._C.dvm import (
11 NDObject,11 NDObject,
12 TorchKernel as Kernel,12 TorchKernel as Kernel,
13)13)
14+from torch_npu.npu._backends import get_soc_version
14 15 
15from .fx_test import _accuracy_check_run16from .fx_test import _accuracy_check_run
16 17 
@@ -24,6 +25,12 @@ float32 = DataType.float32
24int32 = DataType.int3225int32 = DataType.int32
25int64 = DataType.int6426int64 = DataType.int64
26 27 
28+Ascend910B1 = 220
29+Ascend310B1 = 240
30+Ascend910_9391 = 250
31+Ascend950 = 260
32+is_ascend950 = get_soc_version() >= Ascend950
33+ 
27KERNEL_FACTORY = {34KERNEL_FACTORY = {
28 ("mix", True): partial(DynKernel, Kernel.K_MIX, Kernel.F_DYN),35 ("mix", True): partial(DynKernel, Kernel.K_MIX, Kernel.F_DYN),
29 ("mix", False): partial(Kernel, Kernel.K_MIX, 0),36 ("mix", False): partial(Kernel, Kernel.K_MIX, 0),
@@ -39,9 +46,8 @@ KERNEL_FACTORY = {
39def kernel(46def kernel(
40 ktype: str = "split",47 ktype: str = "split",
41 dyn_shape: bool = False,48 dyn_shape: bool = False,
42- mfusion: bool = False,
43):49):
44- r"""kernel(ktype="split", dyn_shape=False, mfusion=False)50+ r"""kernel(ktype="split", dyn_shape=False)
45 51 
46 Return a decorator that builds and executes a DVM kernel.52 Return a decorator that builds and executes a DVM kernel.
47 53 
@@ -188,4 +194,5 @@ def _install_bf16_promote():
188 setattr(Kernel, name, _promote_bf16(op_fn))194 setattr(Kernel, name, _promote_bf16(op_fn))
189 195 
190 196 
191-_install_bf16_promote()197+if not is_ascend950:
198+ _install_bf16_promote()
@@ -33,7 +33,6 @@ class DvmCodegenInterpreter(torch.fx.Interpreter):
33 ):33 ):
34 super().__init__(gm)34 super().__init__(gm)
35 self.gm = gm35 self.gm = gm
36- self.is_mfusion = bool(getattr(gm, "_mfusion", False))
37 self.ktype = ktype36 self.ktype = ktype
38 self.is_mix_kernel = annotate_mm_transpose_flags(gm)37 self.is_mix_kernel = annotate_mm_transpose_flags(gm)
39 if is_dynamic is None:38 if is_dynamic is None:
@@ -53,8 +52,7 @@ class DvmCodegenInterpreter(torch.fx.Interpreter):
53 self.ktype = "spec"52 self.ktype = "spec"
54 self.code.splice(f'\n"""\n{self.gm.print_readable(print_output=False)}\n"""')53 self.code.splice(f'\n"""\n{self.gm.print_readable(print_output=False)}\n"""')
55 decorator = (54 decorator = (
56- f"{chr(64)}dvm.kernel(ktype={self.ktype!r}, dyn_shape={self.is_dynamic}, "55+ f"{chr(64)}dvm.kernel(ktype={self.ktype!r}, dyn_shape={self.is_dynamic})"
57- f"mfusion={self.is_mfusion!r})"
58 )56 )
59 self.code.splice(decorator)57 self.code.splice(decorator)
60 self.code.splice(f"def {self.KERNEL_NAME_PLACEHOLDER}(k):")58 self.code.splice(f"def {self.KERNEL_NAME_PLACEHOLDER}(k):")
@@ -76,7 +76,8 @@ anir_config.GENERATE_LIST = [
76 aten.scalar_tensor,76 aten.scalar_tensor,
77 aten.unsqueeze,77 aten.unsqueeze,
78 aten.squeeze,78 aten.squeeze,
79- aten.clone,79+ # aten.reshape,
80+ # aten.clone,
80]81]
81 82 
82 83 
@@ -262,7 +263,6 @@ def _dvm_can_fuse_horizontal(self, node1, node2):
262def _patch_lowering_type_checks():263def _patch_lowering_type_checks():
263 import torch._inductor.graph as inductor_graph264 import torch._inductor.graph as inductor_graph
264 import torch._inductor.lowering as inductor_lowering265 import torch._inductor.lowering as inductor_lowering
265- import torch._inductor.pattern_matcher as pattern_matcher
266 266 
267 import torch_npu._inductor.ascend_npu_ir.ascend_npu_ir.npu.inductor_patch.lowering as npu_lowering_mod267 import torch_npu._inductor.ascend_npu_ir.ascend_npu_ir.npu.inductor_patch.lowering as npu_lowering_mod
268 268 
@@ -281,7 +281,7 @@ def _patch_lowering_type_checks():
281 if not isinstance(meta, torch._subclasses.FakeTensor):281 if not isinstance(meta, torch._subclasses.FakeTensor):
282 continue282 continue
283 283 
284- if meta.is_cpu:284+ if meta.is_cpu and config.disable_cpp_codegen:
285 return True285 return True
286 286 
287 if node.target in DVM_OP_REGISTRY:287 if node.target in DVM_OP_REGISTRY:
@@ -292,9 +292,6 @@ def _patch_lowering_type_checks():
292 inductor_lowering.fallback_node_due_to_unsupported_type = (292 inductor_lowering.fallback_node_due_to_unsupported_type = (
293 _fallback_node_due_to_unsupported_type293 _fallback_node_due_to_unsupported_type
294 )294 )
295- pattern_matcher.fallback_node_due_to_unsupported_type = (
296- _fallback_node_due_to_unsupported_type
297- )
298 npu_lowering_mod.fallback_node_due_to_unsupported_type = (295 npu_lowering_mod.fallback_node_due_to_unsupported_type = (
299 _fallback_node_due_to_unsupported_type296 _fallback_node_due_to_unsupported_type
300 )297 )
@@ -2,6 +2,8 @@ import torch
2import torch.fx2import torch.fx
3import torch.utils._pytree as pytree3import torch.utils._pytree as pytree
4 4 
5+from . import is_ascend950
6+ 
5 7 
6aten = torch.ops.aten8aten = torch.ops.aten
7prims = torch.ops.prims9prims = torch.ops.prims
@@ -43,7 +45,7 @@ def to_dvm_dtype(dtype):
43 return dtype45 return dtype
44 46 
45 47 
46-def _check_dtype(inputs, supported_dtypes):48+def _check_dtype(inputs, supported_dtypes, allow_cpu=False):
47 for inp in inputs:49 for inp in inputs:
48 if not isinstance(inp, torch.fx.Node):50 if not isinstance(inp, torch.fx.Node):
49 continue51 continue
@@ -55,7 +57,7 @@ def _check_dtype(inputs, supported_dtypes):
55 continue57 continue
56 if meta.dtype not in supported_dtypes:58 if meta.dtype not in supported_dtypes:
57 return False59 return False
58- if meta.is_cpu:60+ if meta.is_cpu and not allow_cpu:
59 return False61 return False
60 return True62 return True
61 63 
@@ -67,7 +69,7 @@ def common_rule(node: torch.fx.Node):
67 69 
68 70 
69def full_rule(node: torch.fx.Node):71def full_rule(node: torch.fx.Node):
70- return _check_dtype([node], supported_dtypes=DVM_SUPPORT_TYPE)72+ return _check_dtype([node], supported_dtypes=DVM_SUPPORT_TYPE, allow_cpu=True)
71 73 
72 74 
73def cast_rule(node: torch.fx.Node):75def cast_rule(node: torch.fx.Node):
@@ -114,11 +116,14 @@ def mm_rule(node: torch.fx.Node):
114 116 
115 def check(input_node):117 def check(input_node):
116 t = input_node.meta["val"]118 t = input_node.meta["val"]
119+ if t.dim() > 4 or t.dim() < 2:
120+ return False
117 inner_axis = inner_axis_length(t)121 inner_axis = inner_axis_length(t)
118- if isinstance(inner_axis, torch.SymInt):122+ if not is_ascend950:
119- return False123+ if isinstance(inner_axis, torch.SymInt):
120- if t.dim() > 4 or t.dim() < 2 or inner_axis > MAX_INNER:124+ return False
121- return False125+ if inner_axis > MAX_INNER:
126+ return False
122 return True127 return True
123 128 
124 def check_output(output_node):129 def check_output(output_node):
@@ -105,10 +105,10 @@ with MFusionPatch():
105 105 
106启用 MFusion 后,`torch.compile` 会生成融合后的 kernel 代码。如需查看融合算子的详细信息,可通过设置环境变量 export TORCH_COMPILE_DEBUG=1 开启调试模式,相关信息会输出到torch_compile_debug目录下的output_code.py 文件中。106启用 MFusion 后,`torch.compile` 会生成融合后的 kernel 代码。如需查看融合算子的详细信息,可通过设置环境变量 export TORCH_COMPILE_DEBUG=1 开启调试模式,相关信息会输出到torch_compile_debug目录下的output_code.py 文件中。
107 107 
108-融合 kernel 通过 `@dvm.kernel(..., mfusion=True)` 装饰器标识108+kernel 会生成 `mfusion_dvm_*` 命名的 DVM kernel
109 109 
110```Python110```Python
111-@dvm.kernel(ktype='vector', dyn_shape=False, mfusion=True)111+@dvm.kernel(ktype='vector', dyn_shape=False)
112def mfusion_dvm_0(k):112def mfusion_dvm_0(k):
113 arg0 = k.load([32], dvm.float32)113 arg0 = k.load([32], dvm.float32)
114 arg1 = k.load([32], dvm.float32)114 arg1 = k.load([32], dvm.float32)
@@ -206,6 +206,16 @@ py::object TorchKernelPy::Store(py::object obj, DataTypePy type)
206 return ObjToPy(stores_.emplace_back(op));206 return ObjToPy(stores_.emplace_back(op));
207}207}
208 208 
209+py::object TorchKernelPy::ViewStore(py::object obj, py::object stride, DataTypePy type)
210+{
211+ auto in_obj = PyToObj(obj);
212+ if (type != kDataTypeEnd) {
213+ in_obj = kernel_.Cast(in_obj, type);
214+ }
215+ auto op = kernel_.Store(nullptr, in_obj, GetShapeRef(stride));
216+ return ObjToPy(stores_.emplace_back(op));
217+}
218+ 
209void TorchKernelPy::Setup()219void TorchKernelPy::Setup()
210{220{
211 SetupRelocs();221 SetupRelocs();
@@ -64,6 +64,7 @@ public:
64 py::object Load(py::object shape, DataTypePy type) override;64 py::object Load(py::object shape, DataTypePy type) override;
65 py::object ViewLoad(py::object shape, py::object stride, DataTypePy type) override;65 py::object ViewLoad(py::object shape, py::object stride, DataTypePy type) override;
66 py::object Store(py::object obj, DataTypePy type) override;66 py::object Store(py::object obj, DataTypePy type) override;
67+ py::object ViewStore(py::object obj, py::object stride, DataTypePy type) override;
67 IntArrayRef* GetShapeRef(py::object shape) override;68 IntArrayRef* GetShapeRef(py::object shape) override;
68 69 
69 void SetKernelInfo(const std::string& op_name, const std::string& op_fullname,70 void SetKernelInfo(const std::string& op_name, const std::string& op_fullname,