已合并
fix: lintrunner --all-files --take NEWLINE -a #35871
Jingwei Huang创建于 5月17日
fix: lintrunner --all-files --take NEWLINE -a #35871
已合并
Jingwei Huang创建于 5月17日
89 个文件变更+16495-16512
MCMakeLists.txt+396-397
@@ -1,397 +1,396 @@
1cmake_minimum_required(VERSION 3.18 FATAL_ERROR)1cmake_minimum_required(VERSION 3.18 FATAL_ERROR)
2 2 
3find_program(CCACHE ccache)3find_program(CCACHE ccache)
4if(${CCACHE} STREQUAL "CCACHE-NOTFOUND")4if(${CCACHE} STREQUAL "CCACHE-NOTFOUND")
5 message(STATUS "Compile without ccache")5 message(STATUS "Compile without ccache")
6else()6else()
7 set(CMAKE_C_COMPILER_LAUNCHER ${CCACHE} CACHE PATH "cache Compiler")7 set(CMAKE_C_COMPILER_LAUNCHER ${CCACHE} CACHE PATH "cache Compiler")
8 set(CMAKE_CXX_COMPILER_LAUNCHER ${CCACHE} CACHE PATH "cache Compiler")8 set(CMAKE_CXX_COMPILER_LAUNCHER ${CCACHE} CACHE PATH "cache Compiler")
9 message(STATUS "CMAKE_C_COMPILER_LAUNCHER:${CMAKE_C_COMPILER_LAUNCHER}")9 message(STATUS "CMAKE_C_COMPILER_LAUNCHER:${CMAKE_C_COMPILER_LAUNCHER}")
10 message(STATUS "CMAKE_CXX_COMPILER_LAUNCHER:${CMAKE_CXX_COMPILER_LAUNCHER}")10 message(STATUS "CMAKE_CXX_COMPILER_LAUNCHER:${CMAKE_CXX_COMPILER_LAUNCHER}")
11endif()11endif()
12 12 
13project(TORCHNPU CXX C)13project(TORCHNPU CXX C)
14add_compile_options(-fmacro-prefix-map=${CMAKE_SOURCE_DIR}/=)14add_compile_options(-fmacro-prefix-map=${CMAKE_SOURCE_DIR}/=)
15 15 
16# GCC 11.2 (used in v2.7.1) does not support -fuse-ld=mold16# GCC 11.2 (used in v2.7.1) does not support -fuse-ld=mold
17find_program(MOLD_LINKER mold)17find_program(MOLD_LINKER mold)
18if(MOLD_LINKER)18if(MOLD_LINKER)
19 set(MOLD_WRAPPER_DIR "${CMAKE_BINARY_DIR}/mold-wrapper")19 set(MOLD_WRAPPER_DIR "${CMAKE_BINARY_DIR}/mold-wrapper")
20 file(MAKE_DIRECTORY "${MOLD_WRAPPER_DIR}")20 file(MAKE_DIRECTORY "${MOLD_WRAPPER_DIR}")
21 if(NOT EXISTS "${MOLD_WRAPPER_DIR}/ld")21 if(NOT EXISTS "${MOLD_WRAPPER_DIR}/ld")
22 file(CREATE_LINK "${MOLD_LINKER}" "${MOLD_WRAPPER_DIR}/ld" SYMBOLIC)22 file(CREATE_LINK "${MOLD_LINKER}" "${MOLD_WRAPPER_DIR}/ld" SYMBOLIC)
23 endif()23 endif()
24 add_link_options("-B${MOLD_WRAPPER_DIR}")24 add_link_options("-B${MOLD_WRAPPER_DIR}")
25 message(STATUS "Using mold linker via -B wrapper: ${MOLD_LINKER}")25 message(STATUS "Using mold linker via -B wrapper: ${MOLD_LINKER}")
26else()26else()
27 message(STATUS "mold linker not found, using default linker")27 message(STATUS "mold linker not found, using default linker")
28endif()28endif()
29 29 
30set(LINUX TRUE)30set(LINUX TRUE)
31set(CMAKE_INSTALL_MESSAGE NEVER)31set(CMAKE_INSTALL_MESSAGE NEVER)
32# set(CMAKE_VERBOSE_MAKEFILE ON)32# set(CMAKE_VERBOSE_MAKEFILE ON)
33set(CMAKE_EXPORT_COMPILE_COMMANDS ON)33set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
34 34 
35if(DEFINED TORCH_VERSION)35if(DEFINED TORCH_VERSION)
36 add_definitions(-DPYTORCH_NPU_VERSION="${TORCH_VERSION}")36 add_definitions(-DPYTORCH_NPU_VERSION="${TORCH_VERSION}")
37endif()37endif()
38 38 
39set(PLUGIN_NAME torch_npu)39set(PLUGIN_NAME torch_npu)
40 40 
41set(RPATH_VALUE $ORIGIN)41set(RPATH_VALUE $ORIGIN)
42set(CMAKE_SKIP_BUILD_RPATH FALSE)42set(CMAKE_SKIP_BUILD_RPATH FALSE)
43set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)43set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
44set(CMAKE_INSTALL_RPATH "${RPATH_VALUE}/lib/:${RPATH_VALUE}/")44set(CMAKE_INSTALL_RPATH "${RPATH_VALUE}/lib/:${RPATH_VALUE}/")
45set(CMAKE_INSTALL_RPATH_USE_LINK_PATH FALSE)45set(CMAKE_INSTALL_RPATH_USE_LINK_PATH FALSE)
46set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${TORCHNPU_INSTALL_LIBDIR})46set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${TORCHNPU_INSTALL_LIBDIR})
47SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -g")47SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -g")
48SET(CMAKE_CXX_FLAGS_RELEASE "-O2")48SET(CMAKE_CXX_FLAGS_RELEASE "-O2")
49SET(CMAKE_CXX_FLAGS_DEBUG "-O0 -g")49SET(CMAKE_CXX_FLAGS_DEBUG "-O0 -g")
50 50 
51option(USE_NPU "Use NPU" ON)51option(USE_NPU "Use NPU" ON)
52 52 
53# LTO&PGO optimization in compile option53# LTO&PGO optimization in compile option
54SET(IF_APPEND FALSE)54SET(IF_APPEND FALSE)
55if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")55if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
56 if(MOLD_LINKER)56 if(MOLD_LINKER)
57 SET(APPEND_FLAGS "-fGNU-compatibility -Wno-non-pod-varargs")57 SET(APPEND_FLAGS "-fGNU-compatibility -Wno-non-pod-varargs")
58 else()58 else()
59 SET(APPEND_FLAGS "-fGNU-compatibility -fuse-ld=lld -Wno-non-pod-varargs")59 SET(APPEND_FLAGS "-fGNU-compatibility -fuse-ld=lld -Wno-non-pod-varargs")
60 endif()60 endif()
61 if (DEFINED ENABLE_LTO)61 if (DEFINED ENABLE_LTO)
62 SET(IF_APPEND TRUE)62 SET(IF_APPEND TRUE)
63 SET(APPEND_FLAGS "${APPEND_FLAGS} -flto=thin")63 SET(APPEND_FLAGS "${APPEND_FLAGS} -flto=thin")
64 endif()64 endif()
65 if (DEFINED PGO_MODE)65 if (DEFINED PGO_MODE)
66 SET(IF_APPEND TRUE)66 SET(IF_APPEND TRUE)
67 if (PGO_MODE EQUAL 1)67 if (PGO_MODE EQUAL 1)
68 SET(APPEND_FLAGS "${APPEND_FLAGS} -fprofile-generate")68 SET(APPEND_FLAGS "${APPEND_FLAGS} -fprofile-generate")
69 elseif (PGO_MODE EQUAL 2)69 elseif (PGO_MODE EQUAL 2)
70 SET(APPEND_FLAGS "${APPEND_FLAGS} -fprofile-use=${CMAKE_CURRENT_SOURCE_DIR}/default.profdata")70 SET(APPEND_FLAGS "${APPEND_FLAGS} -fprofile-use=${CMAKE_CURRENT_SOURCE_DIR}/default.profdata")
71 endif()71 endif()
72 endif()72 endif()
73else()73else()
74 if (DEFINED ENABLE_LTO)74 if (DEFINED ENABLE_LTO)
75 message(FATAL_ERROR "Currently, LTO auto build is not supported in ${CMAKE_CXX_COMPILER_ID}")75 message(FATAL_ERROR "Currently, LTO auto build is not supported in ${CMAKE_CXX_COMPILER_ID}")
76 endif()76 endif()
77 if (DEFINED PGO_MODE)77 if (DEFINED PGO_MODE)
78 message(FATAL_ERROR "Currently, PGO auto build is not supported in ${CMAKE_CXX_COMPILER_ID}")78 message(FATAL_ERROR "Currently, PGO auto build is not supported in ${CMAKE_CXX_COMPILER_ID}")
79 endif()79 endif()
80endif()80endif()
81if (IF_APPEND)81if (IF_APPEND)
82 SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${APPEND_FLAGS}")82 SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${APPEND_FLAGS}")
83endif()83endif()
84 84 
85# check and set CMAKE_CXX_STANDARD85# check and set CMAKE_CXX_STANDARD
86string(FIND "${CMAKE_CXX_FLAGS}" "-std=c++" env_cxx_standard)86string(FIND "${CMAKE_CXX_FLAGS}" "-std=c++" env_cxx_standard)
87if(env_cxx_standard GREATER -1)87if(env_cxx_standard GREATER -1)
88 message(88 message(
89 WARNING "C++ standard version definition detected in environment variable."89 WARNING "C++ standard version definition detected in environment variable."
90 "PyTorch requires -std=c++17. Please remove -std=c++ settings in your environment.")90 "PyTorch requires -std=c++17. Please remove -std=c++ settings in your environment.")
91endif()91endif()
92set(CMAKE_CXX_STANDARD 17)92set(CMAKE_CXX_STANDARD 17)
93set(CMAKE_C_STANDARD 11)93set(CMAKE_C_STANDARD 11)
94set(CMAKE_CXX_EXTENSIONS OFF)94set(CMAKE_CXX_EXTENSIONS OFF)
95 95 
96set(TORCHNPU_ROOT "${PROJECT_SOURCE_DIR}/torch_npu/csrc")96set(TORCHNPU_ROOT "${PROJECT_SOURCE_DIR}/torch_npu/csrc")
97set(TORCHNPU_THIRD_PARTY_ROOT "${PROJECT_SOURCE_DIR}/third_party")97set(TORCHNPU_THIRD_PARTY_ROOT "${PROJECT_SOURCE_DIR}/third_party")
98 98 
99set(Torch_DIR ${PYTORCH_INSTALL_DIR}/share/cmake/Torch)99set(Torch_DIR ${PYTORCH_INSTALL_DIR}/share/cmake/Torch)
100FIND_PACKAGE(Torch REQUIRED)100FIND_PACKAGE(Torch REQUIRED)
101 101 
102set(LINUX TRUE)102set(LINUX TRUE)
103set(CMAKE_INSTALL_MESSAGE NEVER)103set(CMAKE_INSTALL_MESSAGE NEVER)
104#set(CMAKE_VERBOSE_MAKEFILE ON)104#set(CMAKE_VERBOSE_MAKEFILE ON)
105set(CMAKE_EXPORT_COMPILE_COMMANDS ON)105set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
106 106 
107# Define build type107# Define build type
108IF(CMAKE_BUILD_TYPE MATCHES Debug)108IF(CMAKE_BUILD_TYPE MATCHES Debug)
109 message("Debug build.")109 message("Debug build.")
110 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_DEBUG")110 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_DEBUG")
111ELSEIF(CMAKE_BUILD_TYPE MATCHES RelWithDebInfo)111ELSEIF(CMAKE_BUILD_TYPE MATCHES RelWithDebInfo)
112 message("RelWithDebInfo build")112 message("RelWithDebInfo build")
113 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DNDEBUG")113 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DNDEBUG")
114ELSE()114ELSE()
115 message("Release build.")115 message("Release build.")
116 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DNDEBUG")116 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DNDEBUG")
117ENDIF()117ENDIF()
118 118 
119if(USE_NPU)119if(USE_NPU)
120 string(APPEND CMAKE_CXX_FLAGS " -DUSE_NPU")120 string(APPEND CMAKE_CXX_FLAGS " -DUSE_NPU")
121endif()121endif()
122 122 
123set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC")123set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC")
124set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-narrowing")124set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-narrowing")
125# Eigen fails to build with some versions, so convert this to a warning125# Eigen fails to build with some versions, so convert this to a warning
126set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")126set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
127set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wextra")127set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wextra")
128set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-missing-field-initializers")128set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-missing-field-initializers")
129set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-type-limits")129set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-type-limits")
130set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-array-bounds")130set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-array-bounds")
131set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unknown-pragmas")131set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unknown-pragmas")
132set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-sign-compare")132set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-sign-compare")
133set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unused-parameter")133set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unused-parameter")
134set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unused-variable")134set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unused-variable")
135set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unused-function")135set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unused-function")
136set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unused-result")136set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unused-result")
137set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-strict-overflow")137set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-strict-overflow")
138set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-strict-aliasing")138set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-strict-aliasing")
139set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-error=deprecated-declarations")139set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-error=deprecated-declarations")
140set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-ignored-qualifiers")140set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-ignored-qualifiers")
141if (CMAKE_COMPILER_IS_GNUCXX AND NOT (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 7.0.0))141if (CMAKE_COMPILER_IS_GNUCXX AND NOT (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 7.0.0))
142 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-stringop-overflow")142 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-stringop-overflow")
143endif()143endif()
144set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-error=pedantic")144set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-error=pedantic")
145set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-error=redundant-decls")145set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-error=redundant-decls")
146set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-error=old-style-cast")146set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-error=old-style-cast")
147 147 
148# These flags are not available in GCC-4.8.5. Set only when using clang.148# These flags are not available in GCC-4.8.5. Set only when using clang.
149if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")149if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
150 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-invalid-partial-specialization")150 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-invalid-partial-specialization")
151 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-typedef-redefinition")151 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-typedef-redefinition")
152 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unknown-warning-option")152 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unknown-warning-option")
153 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unused-private-field")153 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unused-private-field")
154 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-inconsistent-missing-override")154 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-inconsistent-missing-override")
155 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-aligned-allocation-unavailable")155 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-aligned-allocation-unavailable")
156 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-c++17-extensions")156 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-c++17-extensions")
157 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-constexpr-not-const")157 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-constexpr-not-const")
158 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-missing-braces")158 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-missing-braces")
159 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Qunused-arguments")159 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Qunused-arguments")
160 if (${COLORIZE_OUTPUT})160 if (${COLORIZE_OUTPUT})
161 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fcolor-diagnostics")161 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fcolor-diagnostics")
162 endif()162 endif()
163endif()163endif()
164if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 4.9)164if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 4.9)
165 if (${COLORIZE_OUTPUT})165 if (${COLORIZE_OUTPUT})
166 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fdiagnostics-color=always")166 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fdiagnostics-color=always")
167 endif()167 endif()
168endif()168endif()
169if ((APPLE AND (NOT ("${CLANG_VERSION_STRING}" VERSION_LESS "9.0")))169if ((APPLE AND (NOT ("${CLANG_VERSION_STRING}" VERSION_LESS "9.0")))
170 OR (CMAKE_COMPILER_IS_GNUCXX170 OR (CMAKE_COMPILER_IS_GNUCXX
171 AND (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 7.0 AND NOT APPLE)))171 AND (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 7.0 AND NOT APPLE)))
172 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -faligned-new")172 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -faligned-new")
173endif()173endif()
174if (WERROR)174if (WERROR)
175 check_cxx_compiler_flag("-Werror" COMPILER_SUPPORT_WERROR)175 check_cxx_compiler_flag("-Werror" COMPILER_SUPPORT_WERROR)
176 if (NOT COMPILER_SUPPORT_WERROR)176 if (NOT COMPILER_SUPPORT_WERROR)
177 set(WERROR FALSE)177 set(WERROR FALSE)
178 else()178 else()
179 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror")179 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror")
180 endif()180 endif()
181endif(WERROR)181endif(WERROR)
182if (NOT APPLE)182if (NOT APPLE)
183 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unused-but-set-variable")183 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unused-but-set-variable")
184 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-uninitialized")184 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-uninitialized")
185endif()185endif()
186set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fno-omit-frame-pointer -O0")186set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fno-omit-frame-pointer -O0")
187set(CMAKE_LINKER_FLAGS_DEBUG "${CMAKE_STATIC_LINKER_FLAGS_DEBUG} -fno-omit-frame-pointer -O0")187set(CMAKE_LINKER_FLAGS_DEBUG "${CMAKE_STATIC_LINKER_FLAGS_DEBUG} -fno-omit-frame-pointer -O0")
188set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-math-errno")188set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-math-errno")
189set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-trapping-math")189set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-trapping-math")
190set(CMAKE_CXX_COVERAGE $ENV{CALCULATE_CXX_COVERAGE})190set(CMAKE_CXX_COVERAGE $ENV{CALCULATE_CXX_COVERAGE})
191 191 
192if (CMAKE_BUILD_TYPE MATCHES Debug)192if (CMAKE_BUILD_TYPE MATCHES Debug)
193 set(CMAKE_C_FLAGS "-fstack-protector-all -Wl,-z,relro,-z,now,-z,noexecstack -fPIE -pie ${CMAKE_C_FLAGS}")193 set(CMAKE_C_FLAGS "-fstack-protector-all -Wl,-z,relro,-z,now,-z,noexecstack -fPIE -pie ${CMAKE_C_FLAGS}")
194 set(CMAKE_CXX_FLAGS "-fstack-protector-all -Wl,-z,relro,-z,now,-z,noexecstack -fPIE -pie ${CMAKE_CXX_FLAGS}")194 set(CMAKE_CXX_FLAGS "-fstack-protector-all -Wl,-z,relro,-z,now,-z,noexecstack -fPIE -pie ${CMAKE_CXX_FLAGS}")
195 set(CXXFLAGS "-fstack-protector-all -Wl,-z,relro,-z,now,-z,noexecstack -fPIE -pie ${CXXFLAGS}")195 set(CXXFLAGS "-fstack-protector-all -Wl,-z,relro,-z,now,-z,noexecstack -fPIE -pie ${CXXFLAGS}")
196elseif (CMAKE_CXX_COVERAGE STREQUAL "1")196elseif (CMAKE_CXX_COVERAGE STREQUAL "1")
197 set(CMAKE_C_FLAGS "-fstack-protector-all -Wl,-z,relro,-z,now,-z,noexecstack -fprofile-arcs -ftest-coverage -fPIE -pie ${CMAKE_C_FLAGS}")197 set(CMAKE_C_FLAGS "-fstack-protector-all -Wl,-z,relro,-z,now,-z,noexecstack -fprofile-arcs -ftest-coverage -fPIE -pie ${CMAKE_C_FLAGS}")
198 set(CMAKE_CXX_FLAGS "-fstack-protector-all -Wl,-z,relro,-z,now,-z,noexecstack -fprofile-arcs -ftest-coverage -fPIE -pie ${CMAKE_CXX_FLAGS}")198 set(CMAKE_CXX_FLAGS "-fstack-protector-all -Wl,-z,relro,-z,now,-z,noexecstack -fprofile-arcs -ftest-coverage -fPIE -pie ${CMAKE_CXX_FLAGS}")
199 set(CXXFLAGS "-fstack-protector-all -Wl,-z,relro,-z,now,-z,noexecstack -fprofile-arcs -ftest-coverage -fPIE -pie ${CXXFLAGS}")199 set(CXXFLAGS "-fstack-protector-all -Wl,-z,relro,-z,now,-z,noexecstack -fprofile-arcs -ftest-coverage -fPIE -pie ${CXXFLAGS}")
200else()200else()
201 set(CMAKE_C_FLAGS "-fstack-protector-all -Wl,-z,relro,-z,now,-z,noexecstack -fPIE -pie ${CMAKE_C_FLAGS}")201 set(CMAKE_C_FLAGS "-fstack-protector-all -Wl,-z,relro,-z,now,-z,noexecstack -fPIE -pie ${CMAKE_C_FLAGS}")
202 set(CMAKE_CXX_FLAGS "-fstack-protector-all -Wl,-z,relro,-z,now,-z,noexecstack -fPIE -pie ${CMAKE_CXX_FLAGS}")202 set(CMAKE_CXX_FLAGS "-fstack-protector-all -Wl,-z,relro,-z,now,-z,noexecstack -fPIE -pie ${CMAKE_CXX_FLAGS}")
203 set(CXXFLAGS "-fstack-protector-all -Wl,-z,relro,-z,now,-z,noexecstack -fPIE -pie ${CXXFLAGS}")203 set(CXXFLAGS "-fstack-protector-all -Wl,-z,relro,-z,now,-z,noexecstack -fPIE -pie ${CXXFLAGS}")
204endif()204endif()
205 205 
206if (NOT DEFINED GLIBCXX_USE_CXX11_ABI)206if (NOT DEFINED GLIBCXX_USE_CXX11_ABI)
207 set(GLIBCXX_USE_CXX11_ABI 0)207 set(GLIBCXX_USE_CXX11_ABI 0)
208endif()208endif()
209message(STATUS "Determined _GLIBCXX_USE_CXX11_ABI=${GLIBCXX_USE_CXX11_ABI}")209message(STATUS "Determined _GLIBCXX_USE_CXX11_ABI=${GLIBCXX_USE_CXX11_ABI}")
210set(_GLIBCXX_USE_CXX11_ABI ${GLIBCXX_USE_CXX11_ABI})210set(_GLIBCXX_USE_CXX11_ABI ${GLIBCXX_USE_CXX11_ABI})
211set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_GLIBCXX_USE_CXX11_ABI=${GLIBCXX_USE_CXX11_ABI}")211set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_GLIBCXX_USE_CXX11_ABI=${GLIBCXX_USE_CXX11_ABI}")
212if (${GLIBCXX_USE_CXX11_ABI} EQUAL 0)212if (${GLIBCXX_USE_CXX11_ABI} EQUAL 0)
213 set(CMAKE_CXX_FLAGS "-fabi-version=11 ${CMAKE_CXX_FLAGS}")213 set(CMAKE_CXX_FLAGS "-fabi-version=11 ${CMAKE_CXX_FLAGS}")
214else()214else()
215 set(CXX_STANDARD_REQUIRED ON)215 set(CXX_STANDARD_REQUIRED ON)
216 if (DEFINED ABI_VERSION)216 if (DEFINED ABI_VERSION)
217 set(CMAKE_CXX_FLAGS "-fabi-version=${ABI_VERSION} ${CMAKE_CXX_FLAGS}")217 set(CMAKE_CXX_FLAGS "-fabi-version=${ABI_VERSION} ${CMAKE_CXX_FLAGS}")
218 endif()218 endif()
219endif()219endif()
220 220 
221 221 
222if (DEFINED BUILD_LIBTORCH)222if (DEFINED BUILD_LIBTORCH)
223 add_compile_definitions(BUILD_LIBTORCH)223 add_compile_definitions(BUILD_LIBTORCH)
224endif()224endif()
225 225 
226 226 
227include_directories(${PROJECT_SOURCE_DIR})227include_directories(${PROJECT_SOURCE_DIR})
228include_directories(${PROJECT_SOURCE_DIR}/torch_npu/csrc/aten)228include_directories(${PROJECT_SOURCE_DIR}/torch_npu/csrc/aten)
229include_directories(${PROJECT_SOURCE_DIR}/torch_npu/csrc/inductor)229include_directories(${PROJECT_SOURCE_DIR}/torch_npu/csrc/inductor)
230include_directories(${PROJECT_SOURCE_DIR}/third_party/hccl/inc)230include_directories(${PROJECT_SOURCE_DIR}/third_party/hccl/inc)
231include_directories(${PROJECT_SOURCE_DIR}/third_party/acl/inc)231include_directories(${PROJECT_SOURCE_DIR}/third_party/acl/inc)
232include_directories(${PROJECT_SOURCE_DIR}/third_party/Tensorpipe)232include_directories(${PROJECT_SOURCE_DIR}/third_party/Tensorpipe)
233include_directories(${PROJECT_SOURCE_DIR}/third_party/nlohmann/include)233include_directories(${PROJECT_SOURCE_DIR}/third_party/nlohmann/include)
234 234 
235# Set installed PyTorch dir235# Set installed PyTorch dir
236if(DEFINED PYTORCH_INSTALL_DIR)236if(DEFINED PYTORCH_INSTALL_DIR)
237 include_directories(${PYTORCH_INSTALL_DIR}/include)237 include_directories(${PYTORCH_INSTALL_DIR}/include)
238 include_directories(${PYTORCH_INSTALL_DIR}/include/torch/csrc/api/include)238 include_directories(${PYTORCH_INSTALL_DIR}/include/torch/csrc/api/include)
239 include_directories(${PYTORCH_INSTALL_DIR}/include/torch/csrc/distributed)239 include_directories(${PYTORCH_INSTALL_DIR}/include/torch/csrc/distributed)
240else()240else()
241 message(FATAL_ERROR "Cannot find installed PyTorch directory")241 message(FATAL_ERROR "Cannot find installed PyTorch directory")
242endif()242endif()
243 243 
244# Set Python include dir244# Set Python include dir
245if(DEFINED PYTHON_INCLUDE_DIR)245if(DEFINED PYTHON_INCLUDE_DIR)
246 include_directories(${PYTHON_INCLUDE_DIR})246 include_directories(${PYTHON_INCLUDE_DIR})
247else()247else()
248 message(FATAL_ERROR "Cannot find installed Python head file directory")248 message(FATAL_ERROR "Cannot find installed Python head file directory")
249endif()249endif()
250 250 
251# sources251# sources
252set(ATEN_SRCS)252set(ATEN_SRCS)
253set(CORE_SRCS)253set(CORE_SRCS)
254set(FRAMEWORK_SRCS)254set(FRAMEWORK_SRCS)
255set(LOGGING_SRCS)255set(LOGGING_SRCS)
256set(INDUCTOR_SRCS)256set(INDUCTOR_SRCS)
257set(DIST_SRCS)257set(DIST_SRCS)
258 258 
259if (NOT DEFINED BUILD_LIBTORCH)259if (NOT DEFINED BUILD_LIBTORCH)
260 set(FLOP_SRCS)260 set(FLOP_SRCS)
261 set(NPU_SRCS)261 set(NPU_SRCS)
262 set(PROF_SRCS)262 set(PROF_SRCS)
263 set(IPC_SRCS)263 set(IPC_SRCS)
264 set(UTILS_SRCS)264 set(UTILS_SRCS)
265 set(SAN_SRCS)265 set(SAN_SRCS)
266 set(AFD_SRCS)266 set(AFD_SRCS)
267endif()267endif()
268 268 
269if (DEFINED BUILD_LIBTORCH)269if (DEFINED BUILD_LIBTORCH)
270 set(NPU_CPP_LIBS_SRCS)270 set(NPU_CPP_LIBS_SRCS)
271endif()271endif()
272 272 
273add_subdirectory(${TORCHNPU_ROOT}/aten)273add_subdirectory(${TORCHNPU_ROOT}/aten)
274add_subdirectory(${TORCHNPU_ROOT}/core)274add_subdirectory(${TORCHNPU_ROOT}/core)
275add_subdirectory(${TORCHNPU_ROOT}/framework)275add_subdirectory(${TORCHNPU_ROOT}/framework)
276add_subdirectory(${TORCHNPU_ROOT}/flopcount)276add_subdirectory(${TORCHNPU_ROOT}/flopcount)
277add_subdirectory(${TORCHNPU_ROOT}/logging)277add_subdirectory(${TORCHNPU_ROOT}/logging)
278add_subdirectory(${TORCHNPU_ROOT}/custom_dtype)278add_subdirectory(${TORCHNPU_ROOT}/custom_dtype)
279add_subdirectory(${TORCHNPU_ROOT}/inductor)279add_subdirectory(${TORCHNPU_ROOT}/inductor)
280add_subdirectory(${TORCHNPU_ROOT}/distributed)280add_subdirectory(${TORCHNPU_ROOT}/distributed)
281 281 
282if (NOT DEFINED BUILD_LIBTORCH)282if (NOT DEFINED BUILD_LIBTORCH)
283 add_subdirectory(${TORCHNPU_ROOT}/npu)283 add_subdirectory(${TORCHNPU_ROOT}/npu)
284 add_subdirectory(${TORCHNPU_ROOT}/profiler)284 add_subdirectory(${TORCHNPU_ROOT}/profiler)
285 add_subdirectory(${TORCHNPU_ROOT}/ipc)285 add_subdirectory(${TORCHNPU_ROOT}/ipc)
286 add_subdirectory(${TORCHNPU_ROOT}/utils)286 add_subdirectory(${TORCHNPU_ROOT}/utils)
287 add_subdirectory(${TORCHNPU_ROOT}/sanitizer)287 add_subdirectory(${TORCHNPU_ROOT}/sanitizer)
288 add_subdirectory(${TORCHNPU_ROOT}/afd)288 add_subdirectory(${TORCHNPU_ROOT}/afd)
289endif()289endif()
290 290 
291if (DEFINED BUILD_LIBTORCH)291if (DEFINED BUILD_LIBTORCH)
292 add_subdirectory(${TORCHNPU_ROOT}/libs)292 add_subdirectory(${TORCHNPU_ROOT}/libs)
293endif()293endif()
294 294 
295set(OPS_PLUGIN_SRCS)295set(OPS_PLUGIN_SRCS)
296# Add subdirectory of op-plugin296# Add subdirectory of op-plugin
297include_directories(${PROJECT_SOURCE_DIR}/third_party/op-plugin)297include_directories(${PROJECT_SOURCE_DIR}/third_party/op-plugin)
298add_subdirectory(${PROJECT_SOURCE_DIR}/third_party/op-plugin/op_plugin)298add_subdirectory(${PROJECT_SOURCE_DIR}/third_party/op-plugin/op_plugin)
299 299 
300if (DEFINED BUILD_TENSORPIPE)300if (DEFINED BUILD_TENSORPIPE)
301 add_definitions(-DUSE_RPC_FRAMEWORK)301 add_definitions(-DUSE_RPC_FRAMEWORK)
302 set(BUILD_SHARED_LIBS ON)302 set(BUILD_SHARED_LIBS ON)
303 add_subdirectory(${PROJECT_SOURCE_DIR}/third_party/Tensorpipe)303 add_subdirectory(${PROJECT_SOURCE_DIR}/third_party/Tensorpipe)
304 set(BUILD_SHARED_LIBS OFF)304 set(BUILD_SHARED_LIBS OFF)
305endif()305endif()
306 306 
307if (DEFINED BUILD_LIBTORCH)307if (DEFINED BUILD_LIBTORCH)
308 set(CPP_SRCS ${ATEN_SRCS} ${INDUCTOR_SRCS} ${CORE_SRCS} ${OPS_PLUGIN_SRCS} ${DIST_SRCS} ${FLOP_SRCS} ${CUS_DTYPE_SRCS} ${FRAMEWORK_SRCS} ${LOGGING_SRCS} ${NPU_CPP_LIBS_SRCS} )308 set(CPP_SRCS ${ATEN_SRCS} ${INDUCTOR_SRCS} ${CORE_SRCS} ${OPS_PLUGIN_SRCS} ${DIST_SRCS} ${FLOP_SRCS} ${CUS_DTYPE_SRCS} ${FRAMEWORK_SRCS} ${LOGGING_SRCS} ${NPU_CPP_LIBS_SRCS} )
309else()309else()
310# Compile code with pybind11310# Compile code with pybind11
311 set(CPP_SRCS ${ATEN_SRCS} ${INDUCTOR_SRCS} ${CORE_SRCS} ${OPS_PLUGIN_SRCS} ${DIST_SRCS} ${FLOP_SRCS} ${CUS_DTYPE_SRCS} ${LOGGING_SRCS} ${FRAMEWORK_SRCS} ${NPU_SRCS} ${PROF_SRCS} ${IPC_SRCS} ${UTILS_SRCS} ${SAN_SRCS} ${AFD_SRCS})311 set(CPP_SRCS ${ATEN_SRCS} ${INDUCTOR_SRCS} ${CORE_SRCS} ${OPS_PLUGIN_SRCS} ${DIST_SRCS} ${FLOP_SRCS} ${CUS_DTYPE_SRCS} ${LOGGING_SRCS} ${FRAMEWORK_SRCS} ${NPU_SRCS} ${PROF_SRCS} ${IPC_SRCS} ${UTILS_SRCS} ${SAN_SRCS} ${AFD_SRCS})
312endif()312endif()
313 313 
314add_library(${PLUGIN_NAME} SHARED ${CPP_SRCS})314add_library(${PLUGIN_NAME} SHARED ${CPP_SRCS})
315include(CheckCXXCompilerFlag)315include(CheckCXXCompilerFlag)
316check_cxx_compiler_flag("-fvisibility=hidden" COMPILER_SUPPORTS_HIDDEN_VISIBILITY)316check_cxx_compiler_flag("-fvisibility=hidden" COMPILER_SUPPORTS_HIDDEN_VISIBILITY)
317if(${COMPILER_SUPPORTS_HIDDEN_VISIBILITY})317if(${COMPILER_SUPPORTS_HIDDEN_VISIBILITY})
318 target_compile_options(${PLUGIN_NAME} PRIVATE "-fvisibility=hidden")318 target_compile_options(${PLUGIN_NAME} PRIVATE "-fvisibility=hidden")
319endif()319endif()
320 320 
321target_link_options(${PLUGIN_NAME} PRIVATE "-Wl,-Bsymbolic-functions,--no-as-needed")321target_link_options(${PLUGIN_NAME} PRIVATE "-Wl,-Bsymbolic-functions,--no-as-needed")
322 322 
323if (DEFINED BUILD_TORCHAIR)323if (DEFINED BUILD_TORCHAIR)
324 add_subdirectory(${TORCHNPU_THIRD_PARTY_ROOT}/torchair)324 add_subdirectory(${TORCHNPU_THIRD_PARTY_ROOT}/torchair)
325 add_dependencies(${PLUGIN_NAME} copy_torchair_pyfiles)325 add_dependencies(${PLUGIN_NAME} copy_torchair_pyfiles)
326endif()326endif()
327 327 
328add_subdirectory(${TORCHNPU_THIRD_PARTY_ROOT}/fmt EXCLUDE_FROM_ALL)328add_subdirectory(${TORCHNPU_THIRD_PARTY_ROOT}/fmt EXCLUDE_FROM_ALL)
329 329 
330add_subdirectory(${PROJECT_SOURCE_DIR}/third_party/dvm)330add_subdirectory(${PROJECT_SOURCE_DIR}/third_party/dvm)
331add_dependencies(${PLUGIN_NAME} dvm_build)331add_dependencies(${PLUGIN_NAME} dvm_build)
332target_link_libraries(${PLUGIN_NAME} PRIVATE ${PROJECT_SOURCE_DIR}/third_party/dvm/dvm/libdvm.a)332target_link_libraries(${PLUGIN_NAME} PRIVATE ${PROJECT_SOURCE_DIR}/third_party/dvm/dvm/libdvm.a)
333 333 
334link_directories(${PYTORCH_INSTALL_DIR}/lib)334link_directories(${PYTORCH_INSTALL_DIR}/lib)
335link_directories(${TORCHNPU_THIRD_PARTY_ROOT}/acl/libs)335link_directories(${TORCHNPU_THIRD_PARTY_ROOT}/acl/libs)
336 336 
337target_link_libraries(${PLUGIN_NAME} PUBLIC ${TORCHNPU_THIRD_PARTY_ROOT}/acl/libs/libhccl.so)337target_link_libraries(${PLUGIN_NAME} PUBLIC ${TORCHNPU_THIRD_PARTY_ROOT}/acl/libs/libhccl.so)
338 338 
339if (NOT DEFINED BUILD_LIBTORCH)339if (NOT DEFINED BUILD_LIBTORCH)
340 target_link_libraries(${PLUGIN_NAME} PUBLIC ${PYTORCH_INSTALL_DIR}/lib/libtorch_python.so)340 target_link_libraries(${PLUGIN_NAME} PUBLIC ${PYTORCH_INSTALL_DIR}/lib/libtorch_python.so)
341endif()341endif()
342 342 
343target_link_libraries(${PLUGIN_NAME} PUBLIC ${TORCHNPU_THIRD_PARTY_ROOT}/acl/libs/libascendcl.so)343target_link_libraries(${PLUGIN_NAME} PUBLIC ${TORCHNPU_THIRD_PARTY_ROOT}/acl/libs/libascendcl.so)
344target_link_libraries(${PLUGIN_NAME} PUBLIC ${TORCHNPU_THIRD_PARTY_ROOT}/acl/libs/libacl_op_compiler.so)344target_link_libraries(${PLUGIN_NAME} PUBLIC ${TORCHNPU_THIRD_PARTY_ROOT}/acl/libs/libacl_op_compiler.so)
345target_link_libraries(${PLUGIN_NAME} PUBLIC ${TORCHNPU_THIRD_PARTY_ROOT}/acl/libs/libge_runner.so)345target_link_libraries(${PLUGIN_NAME} PUBLIC ${TORCHNPU_THIRD_PARTY_ROOT}/acl/libs/libge_runner.so)
346target_link_libraries(${PLUGIN_NAME} PUBLIC ${TORCHNPU_THIRD_PARTY_ROOT}/acl/libs/libgraph.so)346target_link_libraries(${PLUGIN_NAME} PUBLIC ${TORCHNPU_THIRD_PARTY_ROOT}/acl/libs/libgraph.so)
347 347 
348if (DEFINED BUILD_TENSORPIPE)348if (DEFINED BUILD_TENSORPIPE)
349 target_link_libraries(${PLUGIN_NAME} PUBLIC ${PROJECT_SOURCE_DIR}/build/packages/torch_npu/lib/libtensorpipe.so)349 target_link_libraries(${PLUGIN_NAME} PUBLIC ${PROJECT_SOURCE_DIR}/build/packages/torch_npu/lib/libtensorpipe.so)
350endif()350endif()
351 351 
352target_link_libraries(${PLUGIN_NAME} PUBLIC torch torch_cpu c10 fmt::fmt-header-only)352target_link_libraries(${PLUGIN_NAME} PUBLIC torch torch_cpu c10 fmt::fmt-header-only)
353 353 
354if (NOT DEFINED BUILD_LIBTORCH)354if (NOT DEFINED BUILD_LIBTORCH)
355 set(ATEN_THREADING "OMP" CACHE STRING "ATen parallel backend")355 set(ATEN_THREADING "OMP" CACHE STRING "ATen parallel backend")
356 message(STATUS "Using ATen parallel backend: ${ATEN_THREADING}")356 message(STATUS "Using ATen parallel backend: ${ATEN_THREADING}")
357 if ("${ATEN_THREADING}" STREQUAL "OMP")357 if ("${ATEN_THREADING}" STREQUAL "OMP")
358 target_compile_definitions(${PLUGIN_NAME} PUBLIC "-DAT_PARALLEL_OPENMP=1")358 target_compile_definitions(${PLUGIN_NAME} PUBLIC "-DAT_PARALLEL_OPENMP=1")
359 elseif ("${ATEN_THREADING}" STREQUAL "NATIVE")359 elseif ("${ATEN_THREADING}" STREQUAL "NATIVE")
360 target_compile_definitions(${PLUGIN_NAME} PUBLIC "-DAT_PARALLEL_NATIVE=1")360 target_compile_definitions(${PLUGIN_NAME} PUBLIC "-DAT_PARALLEL_NATIVE=1")
361 elseif ("${ATEN_THREADING}" STREQUAL "TBB")361 elseif ("${ATEN_THREADING}" STREQUAL "TBB")
362 target_compile_definitions(${PLUGIN_NAME} PUBLIC "-DAT_PARALLEL_NATIVE_TBB=1")362 target_compile_definitions(${PLUGIN_NAME} PUBLIC "-DAT_PARALLEL_NATIVE_TBB=1")
363 else()363 else()
364 message(FATAL_ERROR "Unknown ATen parallel backend: ${ATEN_THREADING}")364 message(FATAL_ERROR "Unknown ATen parallel backend: ${ATEN_THREADING}")
365 endif()365 endif()
366 366 
367 include(GNUInstallDirs)367 include(GNUInstallDirs)
368 target_compile_options(${PLUGIN_NAME} PRIVATE "-DC10_BUILD_MAIN_LIB")368 target_compile_options(${PLUGIN_NAME} PRIVATE "-DC10_BUILD_MAIN_LIB")
369 install(TARGETS ${PLUGIN_NAME} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})369 install(TARGETS ${PLUGIN_NAME} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})
370endif()370endif()
371 371 
372if (NOT DEFINED BUILD_LIBTORCH)372if (NOT DEFINED BUILD_LIBTORCH)
373 add_subdirectory(${TORCHNPU_ROOT}/toolkit)373 add_subdirectory(${TORCHNPU_ROOT}/toolkit)
374 target_link_libraries(${PLUGIN_NAME} PUBLIC npu_profiler)374 target_link_libraries(${PLUGIN_NAME} PUBLIC npu_profiler)
375endif()375endif()
376 376 
377if (DEFINED BUILD_GTEST)377if (DEFINED BUILD_GTEST)
378 enable_testing()378 enable_testing()
379 SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/build/gtest)379 SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/build/gtest)
380 add_subdirectory(${PROJECT_SOURCE_DIR}/third_party/googletest)380 add_subdirectory(${PROJECT_SOURCE_DIR}/third_party/googletest)
381 include_directories(${PROJECT_SOURCE_DIR}/third_party/googletest/googletest/include)381 include_directories(${PROJECT_SOURCE_DIR}/third_party/googletest/googletest/include)
382 382 
383 set(TORCH_API_TEST_SOURCES)383 set(TORCH_API_TEST_SOURCES)
384 add_subdirectory(${PROJECT_SOURCE_DIR}/test/cpp/api)384 add_subdirectory(${PROJECT_SOURCE_DIR}/test/cpp/api)
385 add_executable(test_api ${TORCH_API_TEST_SOURCES})385 add_executable(test_api ${TORCH_API_TEST_SOURCES})
386 386 
387 target_link_libraries(test_api PUBLIC torch_npu)387 target_link_libraries(test_api PUBLIC torch_npu)
388 target_link_libraries(test_api PUBLIC gtest_main gtest)388 target_link_libraries(test_api PUBLIC gtest_main gtest)
389endif()389endif()
390 390 
391if (DEFINED BUILD_LIBTORCH)391if (DEFINED BUILD_LIBTORCH)
392 configure_file(392 configure_file(
393 ${PROJECT_SOURCE_DIR}/cmake/Torch_npuConfig.cmake.in393 ${PROJECT_SOURCE_DIR}/cmake/Torch_npuConfig.cmake.in
394 ${PROJECT_SOURCE_DIR}/build/Torch_npuConfig.cmake394 ${PROJECT_SOURCE_DIR}/build/Torch_npuConfig.cmake
395 @ONLY)395 @ONLY)
396endif()396endif()
397 
MThird_Party_Open_Source_Software_Notice+190-190
@@ -1,190 +1,190 @@
1OPEN SOURCE SOFTWARE NOTICE1OPEN SOURCE SOFTWARE NOTICE
2Please note we provide an open source software notice along with this product and/or this product firmware (in the following just "this product"). The open source software licenses are granted by the respective right holders. And the open source licenses prevail all other license information with regard to the respective open source software contained in the product, including but not limited to End User Software Licensing Agreement. This notice is provided on behalf of Huawei Technologies Co. Ltd. and any of its local subsidiaries which may have provided this product to you in your local country.2Please note we provide an open source software notice along with this product and/or this product firmware (in the following just "this product"). The open source software licenses are granted by the respective right holders. And the open source licenses prevail all other license information with regard to the respective open source software contained in the product, including but not limited to End User Software Licensing Agreement. This notice is provided on behalf of Huawei Technologies Co. Ltd. and any of its local subsidiaries which may have provided this product to you in your local country.
3 3 
4Warranty Disclaimer4Warranty Disclaimer
5THE OPEN SOURCE SOFTWARE IN THIS PRODUCT IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL, BUT WITHOUT ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. SEE THE APPLICABLE LICENSES FOR MORE DETAILS.5THE OPEN SOURCE SOFTWARE IN THIS PRODUCT IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL, BUT WITHOUT ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. SEE THE APPLICABLE LICENSES FOR MORE DETAILS.
6 6 
7Copyright Notice and License Texts7Copyright Notice and License Texts
8Software: pytorch v2.6.08Software: pytorch v2.6.0
9Copyright notice:9Copyright notice:
10Copyright (c) Advanced Micro Devices, Inc.10Copyright (c) Advanced Micro Devices, Inc.
11 11 
12Copyright (c) Microsoft Corporation12Copyright (c) Microsoft Corporation
13 13 
14Copyright (c) Bjorn Fahller14Copyright (c) Bjorn Fahller
15 15 
16Copyright (c) 2001-2014 Python Software Foundation All Rights Reserved16Copyright (c) 2001-2014 Python Software Foundation All Rights Reserved
17 17 
18Copyright (c) 2011-2013 NYU18Copyright (c) 2011-2013 NYU
19 19 
20Copyright (c) 1995-2011 by Fredrik Lundh20Copyright (c) 1995-2011 by Fredrik Lundh
21 21 
22Copyright (c) Edward Z. Yang ezyang@mit.edu22Copyright (c) Edward Z. Yang ezyang@mit.edu
23 23 
24Copyright (c) 2014- Facebook, Inc24Copyright (c) 2014- Facebook, Inc
25 25 
26Copyright (c) 2017 The Android Open Source Project26Copyright (c) 2017 The Android Open Source Project
27 27 
28Copyright Python Software Foundation28Copyright Python Software Foundation
29 29 
30Copyright (c) 2012 Massachusetts Institute of Technology30Copyright (c) 2012 Massachusetts Institute of Technology
31 31 
32Copyright (c) 2018 Alex Rogozhnikov32Copyright (c) 2018 Alex Rogozhnikov
33 33 
34Copyright (c) 2007-2009 Scientific Computing and Imaging Institute, University of Utah34Copyright (c) 2007-2009 Scientific Computing and Imaging Institute, University of Utah
35 35 
36Copyright (c) 2006 Idiap Research Institute36Copyright (c) 2006 Idiap Research Institute
37 37 
38Copyright (c) 2011-2021, NVIDIA CORPORATION. All rights reserved38Copyright (c) 2011-2021, NVIDIA CORPORATION. All rights reserved
39 39 
40Copyright (c) 2015 Yangqing Jia All rights reserved40Copyright (c) 2015 Yangqing Jia All rights reserved
41 41 
42Copyright (c) Meta Platforms, Inc.42Copyright (c) Meta Platforms, Inc.
43 43 
44Copyright 2023-present Facebook. All Rights Reserved44Copyright 2023-present Facebook. All Rights Reserved
45 45 
46Copyright (c) 2022 Apple Inc.46Copyright (c) 2022 Apple Inc.
47 47 
48Copyright (c) 2005-2017, NumPy Developers. All rights reserved48Copyright (c) 2005-2017, NumPy Developers. All rights reserved
49 49 
50Copyright (c) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura, All rights reserved50Copyright (c) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura, All rights reserved
51 51 
52Copyright (c) 2014, The Regents52Copyright (c) 2014, The Regents
53 53 
54Copyright (c) 2005-2010 ActiveState Software Inc.54Copyright (c) 2005-2010 ActiveState Software Inc.
55 55 
56Copyright Malte Skarupke 201756Copyright Malte Skarupke 2017
57 57 
58Copyright (c) 2006-2010 NEC Laboratories America (Ronan Collobert, Leon Bottou, Iain Melvin, Jason Weston)58Copyright (c) 2006-2010 NEC Laboratories America (Ronan Collobert, Leon Bottou, Iain Melvin, Jason Weston)
59 59 
60Copyright 2005, Google Inc. All rights reserved60Copyright 2005, Google Inc. All rights reserved
61 61 
62Copyright (c) Meta Platforms, Inc. and affiliates62Copyright (c) Meta Platforms, Inc. and affiliates
63 63 
64Copyright (c) 2023, Advanced Micro Devices, Inc.64Copyright (c) 2023, Advanced Micro Devices, Inc.
65 65 
66Copyright (c) 2022, Tri Dao66Copyright (c) 2022, Tri Dao
67 67 
68Copyright (c) 2005-2023 NVIDIA Corporation Built68Copyright (c) 2005-2023 NVIDIA Corporation Built
69 69 
70Copyright (c) 2001-2002 Enthought, Inc. 2003-2019, SciPy Developers. All rights reserved70Copyright (c) 2001-2002 Enthought, Inc. 2003-2019, SciPy Developers. All rights reserved
71 71 
72Copyright 2008 Google Inc. All rights reserved72Copyright 2008 Google Inc. All rights reserved
73 73 
74Copyright (c) 2021, 2023-2024 Arm Limited74Copyright (c) 2021, 2023-2024 Arm Limited
75 75 
76Copyright (c) 2003-2017 Josef Weidendorfer. All rights reserved76Copyright (c) 2003-2017 Josef Weidendorfer. All rights reserved
77 77 
78Copyright (c) 1997-2011 by Secret Labs AB78Copyright (c) 1997-2011 by Secret Labs AB
79 79 
80Copyright (c) 2016- Facebook, Inc80Copyright (c) 2016- Facebook, Inc
81 81 
82Copyright (c) 2014 Matthew Rocklin82Copyright (c) 2014 Matthew Rocklin
83 83 
84Copyright (c) 2005-2022 NVIDIA Corporation Built84Copyright (c) 2005-2022 NVIDIA Corporation Built
85 85 
86Copyright (c) Facebook, Inc.86Copyright (c) Facebook, Inc.
87 87 
88Copyright 2019-2020 Kakao Brain88Copyright 2019-2020 Kakao Brain
89 89 
90Copyright (c) 2000-2017 Julian Seward. All rights reserved90Copyright (c) 2000-2017 Julian Seward. All rights reserved
91 91 
92Copyright (c) 2005-2020 Rich Felker92Copyright (c) 2005-2020 Rich Felker
93 93 
94Copyright (c) 2008 - 2009 NVIDIA Corporation. All rights reserved94Copyright (c) 2008 - 2009 NVIDIA Corporation. All rights reserved
95 95 
96Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC96Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC
97 97 
98Copyright (c) 2016 Facebook Inc.98Copyright (c) 2016 Facebook Inc.
99 99 
100Copyright (c) 2001-2004 Idiap Research Institute (Ronan Collobert, Samy Bengio, Johnny Mariethoz)100Copyright (c) 2001-2004 Idiap Research Institute (Ronan Collobert, Samy Bengio, Johnny Mariethoz)
101 101 
102Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC All Rights Reserved102Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC All Rights Reserved
103 103 
104Copyright (c) 2012-2014 Deepmind Technologies104Copyright (c) 2012-2014 Deepmind Technologies
105 105 
106Copyright (c) 2012 Giovanni Garberoglio Interdisciplinary Laboratory106Copyright (c) 2012 Giovanni Garberoglio Interdisciplinary Laboratory
107 107 
108Copyright (c) 2024, Tri Dao108Copyright (c) 2024, Tri Dao
109 109 
110Copyright (c) Donald Stufft and individual contributors. All rights reserved110Copyright (c) Donald Stufft and individual contributors. All rights reserved
111 111 
112Copyright (c) 2018, Steven Moshier All rights reserved112Copyright (c) 2018, Steven Moshier All rights reserved
113 113 
114Copyright (c) 2015 Google Inc. All rights reserved114Copyright (c) 2015 Google Inc. All rights reserved
115 115 
116Copyright (c) 2015-2016 Advanced Micro Devices, Inc. All rights reserved116Copyright (c) 2015-2016 Advanced Micro Devices, Inc. All rights reserved
117 117 
118Copyright (c) 2010-2022 by Alex Clark and contributors118Copyright (c) 2010-2022 by Alex Clark and contributors
119 119 
120Copyright 2015 Google Inc. All Rights Reserved120Copyright 2015 Google Inc. All Rights Reserved
121 121 
122Copyright (c) 2017 - 2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved122Copyright (c) 2017 - 2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved
123 123 
124Copyright (c) 2020-2023, NVIDIA CORPORATION. All rights reserved124Copyright (c) 2020-2023, NVIDIA CORPORATION. All rights reserved
125 125 
126Copyright (c) 2016 manylinux126Copyright (c) 2016 manylinux
127 127 
128Copyright (c) 2017 - 2022 NVIDIA CORPORATION & AFFILIATES. All rights reserved128Copyright (c) 2017 - 2022 NVIDIA CORPORATION & AFFILIATES. All rights reserved
129 129 
130Copyright (c) 2011-2012 NEC Laboratories America (Koray Kavukcuoglu)130Copyright (c) 2011-2012 NEC Laboratories America (Koray Kavukcuoglu)
131 131 
132Copyright 2013-2014 RAD Game132Copyright 2013-2014 RAD Game
133 133 
134Copyright (c) 2011-2019 Stephan Brumme. All rights reserved134Copyright (c) 2011-2019 Stephan Brumme. All rights reserved
135 135 
136Copyright (c) 2018 MathInf GmbH, Thomas Viehmann136Copyright (c) 2018 MathInf GmbH, Thomas Viehmann
137 137 
138Copyright (c) 2013 Eddy Petrisor138Copyright (c) 2013 Eddy Petrisor
139 139 
140Copyright (c) 2023-2024 The ggml140Copyright (c) 2023-2024 The ggml
141 141 
142Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020 Python Software Foundation All Rights Reserved142Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020 Python Software Foundation All Rights Reserved
143 143 
144Copyright 2004-present Facebook. All Rights Reserved144Copyright 2004-present Facebook. All Rights Reserved
145 145 
146Copyright (c) 2010 ActiveState Software Inc.146Copyright (c) 2010 ActiveState Software Inc.
147 147 
148Copyright (c) 2006 The Android Open Source Project148Copyright (c) 2006 The Android Open Source Project
149 149 
150(c) Meta Platforms, Inc. and affiliates. All rights reserved150(c) Meta Platforms, Inc. and affiliates. All rights reserved
151 151 
152Copyright (c) 2023 Apple Inc.152Copyright (c) 2023 Apple Inc.
153 153 
154Copyright (c) Microsoft Corporation. All rights reserved154Copyright (c) Microsoft Corporation. All rights reserved
155 155 
156Copyright 2015 The TensorFlow Authors. All Rights Reserved156Copyright 2015 The TensorFlow Authors. All Rights Reserved
157 157 
158Copyright (c) 2023, Tri Dao158Copyright (c) 2023, Tri Dao
159 159 
160Copyright 2022 Cruise LLC160Copyright 2022 Cruise LLC
161 161 
162Copyright (c) Meta Platforms, Inc. and affiliates. All rights reserved162Copyright (c) Meta Platforms, Inc. and affiliates. All rights reserved
163 163 
164Copyright (c) 2022 Cruise LLC. All rights reserved164Copyright (c) 2022 Cruise LLC. All rights reserved
165 165 
166Copyright (c) 2016-present, Facebook, Inc.166Copyright (c) 2016-present, Facebook, Inc.
167 167 
168(c) Copyright John Maddock 2006168(c) Copyright John Maddock 2006
169 169 
170Copyright (c) 2011-2014 Idiap Research Institute170Copyright (c) 2011-2014 Idiap Research Institute
171 171 
172Copyright (c) 2014 Indiana University All rights reserved172Copyright (c) 2014 Indiana University All rights reserved
173 173 
174copyright 2019 The TensorFlow Authors174copyright 2019 The TensorFlow Authors
175 175 
176Copyright (c) 2016-present, Facebook Inc. All rights reserved176Copyright (c) 2016-present, Facebook Inc. All rights reserved
177 177 
178License: BSD 3-Clause License178License: BSD 3-Clause License
179Copyright (c) ,179Copyright (c) ,
180All rights reserved.180All rights reserved.
181 181 
1821. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:1821. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
183 183 
1842. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.1842. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
185 185 
1863. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.1863. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
187 187 
188Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.188Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
189 189 
190THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.190THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Mrequirements.txt+7-7
@@ -1,7 +1,7 @@
1--extra-index-url https://download.pytorch.org/whl/cpu1--extra-index-url https://download.pytorch.org/whl/cpu
2 2 
3pyyaml3pyyaml
4setuptools4setuptools
5auditwheel5auditwheel
6 6 
7torch==2.7.17torch==2.7.1
Msetup.py+782-782
@@ -1,782 +1,782 @@
1import glob1import glob
2import multiprocessing2import multiprocessing
3import multiprocessing.pool3import multiprocessing.pool
4import os4import os
5import re5import re
6import shutil6import shutil
7import stat7import stat
8import subprocess8import subprocess
9import sys9import sys
10import traceback10import traceback
11import platform11import platform
12import time12import time
13import sysconfig13import sysconfig
14from sysconfig import get_paths14from sysconfig import get_paths
15from pathlib import Path15from pathlib import Path
16from typing import Union16from typing import Union
17 17 
18import distutils.ccompiler18import distutils.ccompiler
19import distutils.command.clean19import distutils.command.clean
20from distutils.version import LooseVersion20from distutils.version import LooseVersion
21from distutils.command.build_py import build_py21from distutils.command.build_py import build_py
22from setuptools import setup, distutils, Extension, find_packages22from setuptools import setup, distutils, Extension, find_packages
23from setuptools.command.build_clib import build_clib23from setuptools.command.build_clib import build_clib
24from setuptools.command.build_ext import build_ext24from setuptools.command.build_ext import build_ext
25from setuptools.command.egg_info import egg_info25from setuptools.command.egg_info import egg_info
26from setuptools.command.install import install26from setuptools.command.install import install
27from wheel.bdist_wheel import bdist_wheel27from wheel.bdist_wheel import bdist_wheel
28 28 
29# Disable autoloading before running 'import torch' to avoid circular dependencies29# Disable autoloading before running 'import torch' to avoid circular dependencies
30os.environ["TORCH_DEVICE_BACKEND_AUTOLOAD"] = "0"30os.environ["TORCH_DEVICE_BACKEND_AUTOLOAD"] = "0"
31 31 
32from torchnpugen.utils import PathManager32from torchnpugen.utils import PathManager
33 33 
34BASE_DIR = os.path.dirname(os.path.realpath(__file__))34BASE_DIR = os.path.dirname(os.path.realpath(__file__))
35THIRD_PARTY_PATH = os.path.join(BASE_DIR, "third_party")35THIRD_PARTY_PATH = os.path.join(BASE_DIR, "third_party")
36PathManager.check_directory_path_readable(os.path.join(BASE_DIR, "version.txt"))36PathManager.check_directory_path_readable(os.path.join(BASE_DIR, "version.txt"))
37with open(os.path.join(BASE_DIR, "version.txt")) as version_f:37with open(os.path.join(BASE_DIR, "version.txt")) as version_f:
38 VERSION = version_f.read().strip()38 VERSION = version_f.read().strip()
39UNKNOWN = "Unknown"39UNKNOWN = "Unknown"
40BUILD_PERMISSION = stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR | stat.S_IRGRP | stat.S_IXGRP40BUILD_PERMISSION = stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR | stat.S_IRGRP | stat.S_IXGRP
41 41 
42DISABLE_TORCHAIR = "FALSE"42DISABLE_TORCHAIR = "FALSE"
43if os.environ.get("DISABLE_INSTALL_TORCHAIR") is not None:43if os.environ.get("DISABLE_INSTALL_TORCHAIR") is not None:
44 DISABLE_TORCHAIR = os.environ.get("DISABLE_INSTALL_TORCHAIR")44 DISABLE_TORCHAIR = os.environ.get("DISABLE_INSTALL_TORCHAIR")
45DISABLE_RPC = "FALSE"45DISABLE_RPC = "FALSE"
46if os.environ.get("DISABLE_RPC_FRAMEWORK") is not None:46if os.environ.get("DISABLE_RPC_FRAMEWORK") is not None:
47 DISABLE_RPC = os.environ.get("DISABLE_RPC_FRAMEWORK")47 DISABLE_RPC = os.environ.get("DISABLE_RPC_FRAMEWORK")
48ENABLE_LTO = "FALSE"48ENABLE_LTO = "FALSE"
49if os.environ.get("ENABLE_LTO") is not None:49if os.environ.get("ENABLE_LTO") is not None:
50 ENABLE_LTO = os.environ.get("ENABLE_LTO")50 ENABLE_LTO = os.environ.get("ENABLE_LTO")
51PGO_MODE = 051PGO_MODE = 0
52if os.environ.get("PGO_MODE") is not None:52if os.environ.get("PGO_MODE") is not None:
53 PGO_MODE = int(os.environ.get("PGO_MODE"))53 PGO_MODE = int(os.environ.get("PGO_MODE"))
54 54 
55# change to use cxx11.abi in default since 2.755# change to use cxx11.abi in default since 2.7
56USE_CXX11_ABI = True56USE_CXX11_ABI = True
57if os.environ.get("_GLIBCXX_USE_CXX11_ABI") is not None and os.environ.get("_GLIBCXX_USE_CXX11_ABI") == "0":57if os.environ.get("_GLIBCXX_USE_CXX11_ABI") is not None and os.environ.get("_GLIBCXX_USE_CXX11_ABI") == "0":
58 USE_CXX11_ABI = False58 USE_CXX11_ABI = False
59 59 
60 60 
61def get_submodule_folders():61def get_submodule_folders():
62 git_modules_path = os.path.join(BASE_DIR, ".gitmodules")62 git_modules_path = os.path.join(BASE_DIR, ".gitmodules")
63 default_modules_path = [63 default_modules_path = [
64 os.path.join(THIRD_PARTY_PATH, name)64 os.path.join(THIRD_PARTY_PATH, name)
65 for name in [65 for name in [
66 "op-plugin",66 "op-plugin",
67 ]67 ]
68 ]68 ]
69 if not os.path.exists(git_modules_path):69 if not os.path.exists(git_modules_path):
70 return default_modules_path70 return default_modules_path
71 with open(git_modules_path) as f:71 with open(git_modules_path) as f:
72 return [72 return [
73 os.path.join(BASE_DIR, line.split("=", 1)[1].strip())73 os.path.join(BASE_DIR, line.split("=", 1)[1].strip())
74 for line in f.readlines()74 for line in f.readlines()
75 if line.strip().startswith("path")75 if line.strip().startswith("path")
76 ]76 ]
77 77 
78 78 
79def check_submodules():79def check_submodules():
80 def not_exists_or_empty(folder):80 def not_exists_or_empty(folder):
81 return not os.path.exists(folder) or (81 return not os.path.exists(folder) or (
82 os.path.isdir(folder) and len(os.listdir(folder)) == 082 os.path.isdir(folder) and len(os.listdir(folder)) == 0
83 )83 )
84 84 
85 folders = get_submodule_folders()85 folders = get_submodule_folders()
86 # If none of the submodule folders exists, try to initialize them86 # If none of the submodule folders exists, try to initialize them
87 if all(not_exists_or_empty(folder) for folder in folders):87 if all(not_exists_or_empty(folder) for folder in folders):
88 try:88 try:
89 print(" --- Trying to initialize submodules")89 print(" --- Trying to initialize submodules")
90 start = time.time()90 start = time.time()
91 subprocess.check_call(["git", "submodule", "update", "--init", "--recursive"], cwd=BASE_DIR) # Compliant91 subprocess.check_call(["git", "submodule", "update", "--init", "--recursive"], cwd=BASE_DIR) # Compliant
92 end = time.time()92 end = time.time()
93 print(f" --- Submodule initialization took {end - start:.2f} sec")93 print(f" --- Submodule initialization took {end - start:.2f} sec")
94 except Exception:94 except Exception:
95 print(" --- Submodule initalization failed")95 print(" --- Submodule initalization failed")
96 print("Please run:\n\tgit submodule init && git submodule update")96 print("Please run:\n\tgit submodule init && git submodule update")
97 sys.exit(1)97 sys.exit(1)
98 98 
99 99 
100check_submodules()100check_submodules()
101 101 
102 102 
103def get_sha(pytorch_root: Union[str, Path]) -> str:103def get_sha(pytorch_root: Union[str, Path]) -> str:
104 try:104 try:
105 return (105 return (
106 subprocess.check_output(["git", "rev-parse", "HEAD"], cwd=pytorch_root) # Compliant106 subprocess.check_output(["git", "rev-parse", "HEAD"], cwd=pytorch_root) # Compliant
107 .decode("ascii")107 .decode("ascii")
108 .strip()108 .strip()
109 )109 )
110 except Exception:110 except Exception:
111 return UNKNOWN111 return UNKNOWN
112 112 
113 113 
114def generate_torch_npu_version():114def generate_torch_npu_version():
115 torch_npu_root = Path(__file__).parent115 torch_npu_root = Path(__file__).parent
116 version_path = torch_npu_root / "torch_npu" / "version.py"116 version_path = torch_npu_root / "torch_npu" / "version.py"
117 if version_path.exists():117 if version_path.exists():
118 version_path.unlink()118 version_path.unlink()
119 flags = os.O_WRONLY | os.O_CREAT | os.O_EXCL119 flags = os.O_WRONLY | os.O_CREAT | os.O_EXCL
120 modes = stat.S_IWUSR | stat.S_IRUSR120 modes = stat.S_IWUSR | stat.S_IRUSR
121 sha = get_sha(torch_npu_root)121 sha = get_sha(torch_npu_root)
122 if os.getenv("BUILD_WITHOUT_SHA") is None:122 if os.getenv("BUILD_WITHOUT_SHA") is None:
123 global VERSION123 global VERSION
124 VERSION += "+git" + sha[:7]124 VERSION += "+git" + sha[:7]
125 with os.fdopen(os.open(version_path, flags, modes), 'w') as f:125 with os.fdopen(os.open(version_path, flags, modes), 'w') as f:
126 f.write("__version__ = '{version}'\n".format(version=VERSION))126 f.write("__version__ = '{version}'\n".format(version=VERSION))
127 f.write("git_version = {}\n".format(repr(sha)))127 f.write("git_version = {}\n".format(repr(sha)))
128 os.chmod(version_path, mode=stat.S_IRUSR | stat.S_IEXEC | stat.S_IRGRP | stat.S_IXGRP)128 os.chmod(version_path, mode=stat.S_IRUSR | stat.S_IEXEC | stat.S_IRGRP | stat.S_IXGRP)
129 129 
130 130 
131generate_torch_npu_version()131generate_torch_npu_version()
132 132 
133 133 
134def which(thefile):134def which(thefile):
135 path = os.environ.get("PATH", os.defpath).split(os.pathsep)135 path = os.environ.get("PATH", os.defpath).split(os.pathsep)
136 for d in path:136 for d in path:
137 fname = os.path.join(d, thefile)137 fname = os.path.join(d, thefile)
138 fnames = [fname]138 fnames = [fname]
139 if sys.platform == 'win32':139 if sys.platform == 'win32':
140 exts = os.environ.get('PATHEXT', '').split(os.pathsep)140 exts = os.environ.get('PATHEXT', '').split(os.pathsep)
141 fnames += [fname + ext for ext in exts]141 fnames += [fname + ext for ext in exts]
142 for name in fnames:142 for name in fnames:
143 if os.access(name, os.F_OK | os.X_OK) and not os.path.isdir(name):143 if os.access(name, os.F_OK | os.X_OK) and not os.path.isdir(name):
144 return name144 return name
145 return None145 return None
146 146 
147 147 
148def get_cmake_command():148def get_cmake_command():
149 def _get_version(cmd):149 def _get_version(cmd):
150 for line in subprocess.check_output([cmd, '--version']).decode('utf-8').split('\n'):150 for line in subprocess.check_output([cmd, '--version']).decode('utf-8').split('\n'):
151 if 'version' in line:151 if 'version' in line:
152 return LooseVersion(line.strip().split(' ')[2])152 return LooseVersion(line.strip().split(' ')[2])
153 raise RuntimeError('no version found')153 raise RuntimeError('no version found')
154 "Returns cmake command."154 "Returns cmake command."
155 cmake_command = 'cmake'155 cmake_command = 'cmake'
156 if platform.system() == 'Windows':156 if platform.system() == 'Windows':
157 return cmake_command157 return cmake_command
158 cmake3 = which('cmake3')158 cmake3 = which('cmake3')
159 cmake = which('cmake')159 cmake = which('cmake')
160 if cmake3 is not None and _get_version(cmake3) >= LooseVersion("3.18.0"):160 if cmake3 is not None and _get_version(cmake3) >= LooseVersion("3.18.0"):
161 cmake_command = 'cmake3'161 cmake_command = 'cmake3'
162 return cmake_command162 return cmake_command
163 elif cmake is not None and _get_version(cmake) >= LooseVersion("3.18.0"):163 elif cmake is not None and _get_version(cmake) >= LooseVersion("3.18.0"):
164 return cmake_command164 return cmake_command
165 else:165 else:
166 raise RuntimeError('no cmake or cmake3 with version >= 3.18.0 found')166 raise RuntimeError('no cmake or cmake3 with version >= 3.18.0 found')
167 167 
168 168 
169def get_build_type():169def get_build_type():
170 build_type = 'Release'170 build_type = 'Release'
171 if os.getenv('DEBUG', default='0').upper() in ['ON', '1', 'YES', 'TRUE', 'Y']:171 if os.getenv('DEBUG', default='0').upper() in ['ON', '1', 'YES', 'TRUE', 'Y']:
172 build_type = 'Debug'172 build_type = 'Debug'
173 173 
174 if os.getenv('REL_WITH_DEB_INFO', default='0').upper() in ['ON', '1', 'YES', 'TRUE', 'Y']:174 if os.getenv('REL_WITH_DEB_INFO', default='0').upper() in ['ON', '1', 'YES', 'TRUE', 'Y']:
175 build_type = 'RelWithDebInfo'175 build_type = 'RelWithDebInfo'
176 176 
177 return build_type177 return build_type
178 178 
179 179 
180def _get_build_mode():180def _get_build_mode():
181 for i in range(1, len(sys.argv)):181 for i in range(1, len(sys.argv)):
182 if not sys.argv[i].startswith('-'):182 if not sys.argv[i].startswith('-'):
183 return sys.argv[i]183 return sys.argv[i]
184 184 
185 raise RuntimeError("Run setup.py without build mode.")185 raise RuntimeError("Run setup.py without build mode.")
186 186 
187 187 
188def get_pytorch_dir():188def get_pytorch_dir():
189 try:189 try:
190 import torch190 import torch
191 return os.path.dirname(os.path.realpath(torch.__file__))191 return os.path.dirname(os.path.realpath(torch.__file__))
192 except Exception:192 except Exception:
193 _, _, exc_traceback = sys.exc_info()193 _, _, exc_traceback = sys.exc_info()
194 frame_summary = traceback.extract_tb(exc_traceback)[-1]194 frame_summary = traceback.extract_tb(exc_traceback)[-1]
195 return os.path.dirname(frame_summary.filename)195 return os.path.dirname(frame_summary.filename)
196 196 
197 197 
198def generate_bindings_code(base_dir):198def generate_bindings_code(base_dir):
199 python_execute = sys.executable199 python_execute = sys.executable
200 generate_code_cmd = ["bash", os.path.join(base_dir, 'generate_code.sh'), python_execute, VERSION]200 generate_code_cmd = ["bash", os.path.join(base_dir, 'generate_code.sh'), python_execute, VERSION]
201 if subprocess.call(generate_code_cmd) != 0: # Compliant201 if subprocess.call(generate_code_cmd) != 0: # Compliant
202 print(202 print(
203 'Failed to generate ATEN bindings: {}'.format(generate_code_cmd),203 'Failed to generate ATEN bindings: {}'.format(generate_code_cmd),
204 file=sys.stderr)204 file=sys.stderr)
205 sys.exit(1)205 sys.exit(1)
206 206 
207 207 
208def build_stub(base_dir):208def build_stub(base_dir):
209 build_stub_cmd = ["sh", os.path.join(base_dir, 'third_party/acl/libs/build_stub.sh')]209 build_stub_cmd = ["sh", os.path.join(base_dir, 'third_party/acl/libs/build_stub.sh')]
210 if subprocess.call(build_stub_cmd) != 0:210 if subprocess.call(build_stub_cmd) != 0:
211 print(211 print(
212 'Failed to build stub: {}'.format(build_stub_cmd),212 'Failed to build stub: {}'.format(build_stub_cmd),
213 file=sys.stderr)213 file=sys.stderr)
214 sys.exit(1)214 sys.exit(1)
215 215 
216 216 
217def check_torchair_valid(base_dir):217def check_torchair_valid(base_dir):
218 # build with submodule of torchair, if path of torchair is valid218 # build with submodule of torchair, if path of torchair is valid
219 torchair_path = os.path.join(base_dir, 'third_party/torchair/torchair')219 torchair_path = os.path.join(base_dir, 'third_party/torchair/torchair')
220 return os.path.exists(torchair_path) and (220 return os.path.exists(torchair_path) and (
221 os.path.isdir(torchair_path) and len(os.listdir(torchair_path)) != 0221 os.path.isdir(torchair_path) and len(os.listdir(torchair_path)) != 0
222 )222 )
223 223 
224 224 
225def check_tensorpipe_valid(base_dir):225def check_tensorpipe_valid(base_dir):
226 tensorpipe_path = os.path.join(base_dir, 'third_party/Tensorpipe/tensorpipe')226 tensorpipe_path = os.path.join(base_dir, 'third_party/Tensorpipe/tensorpipe')
227 return os.path.exists(tensorpipe_path)227 return os.path.exists(tensorpipe_path)
228 228 
229 229 
230def generate_dbg_files_and_strip():230def generate_dbg_files_and_strip():
231 library_dir = Path(BASE_DIR).joinpath("build/packages/torch_npu")231 library_dir = Path(BASE_DIR).joinpath("build/packages/torch_npu")
232 dbg_dir = Path(BASE_DIR).joinpath("build/dbg")232 dbg_dir = Path(BASE_DIR).joinpath("build/dbg")
233 os.makedirs(dbg_dir, exist_ok=True)233 os.makedirs(dbg_dir, exist_ok=True)
234 library_files = [Path(i) for i in library_dir.rglob('*.so')]234 library_files = [Path(i) for i in library_dir.rglob('*.so')]
235 for library_file in library_files:235 for library_file in library_files:
236 subprocess.check_call(["eu-strip", library_file, "-f",236 subprocess.check_call(["eu-strip", library_file, "-f",
237 str(dbg_dir.joinpath(library_file.name)) + ".debug"], cwd=BASE_DIR) # Compliant237 str(dbg_dir.joinpath(library_file.name)) + ".debug"], cwd=BASE_DIR) # Compliant
238 238 
239 239 
240def patchelf_dynamic_library():240def patchelf_dynamic_library():
241 # Process all .so files in lib directory241 # Process all .so files in lib directory
242 lib_dir = Path(BASE_DIR).joinpath("build/packages/torch_npu/lib")242 lib_dir = Path(BASE_DIR).joinpath("build/packages/torch_npu/lib")
243 lib_files = [str(i) for i in lib_dir.rglob('*.so')]243 lib_files = [str(i) for i in lib_dir.rglob('*.so')]
244 244 
245 for library_file in lib_files:245 for library_file in lib_files:
246 subprocess.check_call(["patchelf", "--remove-needed", "libgomp.so.1", library_file], cwd=BASE_DIR) # Compliant246 subprocess.check_call(["patchelf", "--remove-needed", "libgomp.so.1", library_file], cwd=BASE_DIR) # Compliant
247 247 
248 248 
249def CppExtension(name, sources, *args, **kwargs):249def CppExtension(name, sources, *args, **kwargs):
250 r'''250 r'''
251 Creates a :class:`setuptools.Extension` for C++.251 Creates a :class:`setuptools.Extension` for C++.
252 '''252 '''
253 pytorch_dir = get_pytorch_dir()253 pytorch_dir = get_pytorch_dir()
254 temp_include_dirs = kwargs.get('include_dirs', [])254 temp_include_dirs = kwargs.get('include_dirs', [])
255 temp_include_dirs.append(os.path.join(pytorch_dir, 'include'))255 temp_include_dirs.append(os.path.join(pytorch_dir, 'include'))
256 temp_include_dirs.append(os.path.join(pytorch_dir, 'include/torch/csrc/api/include'))256 temp_include_dirs.append(os.path.join(pytorch_dir, 'include/torch/csrc/api/include'))
257 kwargs['include_dirs'] = temp_include_dirs257 kwargs['include_dirs'] = temp_include_dirs
258 258 
259 temp_library_dirs = kwargs.get('library_dirs', [])259 temp_library_dirs = kwargs.get('library_dirs', [])
260 temp_library_dirs.append(os.path.join(pytorch_dir, 'lib'))260 temp_library_dirs.append(os.path.join(pytorch_dir, 'lib'))
261 temp_library_dirs.append(os.path.join(BASE_DIR, "third_party/acl/libs"))261 temp_library_dirs.append(os.path.join(BASE_DIR, "third_party/acl/libs"))
262 kwargs['library_dirs'] = temp_library_dirs262 kwargs['library_dirs'] = temp_library_dirs
263 263 
264 libraries = kwargs.get('libraries', [])264 libraries = kwargs.get('libraries', [])
265 libraries.append('c10')265 libraries.append('c10')
266 libraries.append('torch')266 libraries.append('torch')
267 libraries.append('torch_cpu')267 libraries.append('torch_cpu')
268 libraries.append('torch_python')268 libraries.append('torch_python')
269 libraries.append('hccl')269 libraries.append('hccl')
270 kwargs['libraries'] = libraries270 kwargs['libraries'] = libraries
271 kwargs['language'] = 'c++'271 kwargs['language'] = 'c++'
272 return Extension(name, sources, *args, **kwargs)272 return Extension(name, sources, *args, **kwargs)
273 273 
274 274 
275class Clean(distutils.command.clean.clean):275class Clean(distutils.command.clean.clean):
276 276 
277 def run(self):277 def run(self):
278 f_ignore = open('.gitignore', 'r')278 f_ignore = open('.gitignore', 'r')
279 ignores = f_ignore.read()279 ignores = f_ignore.read()
280 pat = re.compile(r'^#( BEGIN NOT-CLEAN-FILES )?')280 pat = re.compile(r'^#( BEGIN NOT-CLEAN-FILES )?')
281 for wildcard in filter(None, ignores.split('\n')):281 for wildcard in filter(None, ignores.split('\n')):
282 match = pat.match(wildcard)282 match = pat.match(wildcard)
283 if match:283 if match:
284 if match.group(1):284 if match.group(1):
285 # Marker is found and stop reading .gitignore.285 # Marker is found and stop reading .gitignore.
286 break286 break
287 # Ignore lines which begin with '#'.287 # Ignore lines which begin with '#'.
288 else:288 else:
289 for filename in glob.glob(wildcard):289 for filename in glob.glob(wildcard):
290 if os.path.islink(filename):290 if os.path.islink(filename):
291 raise RuntimeError(f"Failed to remove path: {filename}")291 raise RuntimeError(f"Failed to remove path: {filename}")
292 if os.path.exists(filename):292 if os.path.exists(filename):
293 try:293 try:
294 shutil.rmtree(filename, ignore_errors=True)294 shutil.rmtree(filename, ignore_errors=True)
295 except Exception as err:295 except Exception as err:
296 raise RuntimeError(f"Failed to remove path: {filename}") from err296 raise RuntimeError(f"Failed to remove path: {filename}") from err
297 f_ignore.close()297 f_ignore.close()
298 298 
299 # It's an old-style class in Python 2.7...299 # It's an old-style class in Python 2.7...
300 distutils.command.clean.clean.run(self)300 distutils.command.clean.clean.run(self)
301 301 
302 remove_files = [302 remove_files = [
303 'torch_npu/csrc/aten/RegisterCPU.cpp',303 'torch_npu/csrc/aten/RegisterCPU.cpp',
304 'torch_npu/csrc/aten/RegisterNPU.cpp',304 'torch_npu/csrc/aten/RegisterNPU.cpp',
305 'torch_npu/csrc/aten/RegisterAutogradNPU.cpp',305 'torch_npu/csrc/aten/RegisterAutogradNPU.cpp',
306 'torch_npu/csrc/aten/NPUNativeFunctions.h',306 'torch_npu/csrc/aten/NPUNativeFunctions.h',
307 'torch_npu/csrc/aten/CustomRegisterSchema.cpp',307 'torch_npu/csrc/aten/CustomRegisterSchema.cpp',
308 'torch_npu/csrc/aten/ForeachRegister.cpp',308 'torch_npu/csrc/aten/ForeachRegister.cpp',
309 'torch_npu/utils/custom_ops.py',309 'torch_npu/utils/custom_ops.py',
310 'torch_npu/version.py',310 'torch_npu/version.py',
311 ]311 ]
312 for remove_file in remove_files:312 for remove_file in remove_files:
313 file_path = os.path.join(BASE_DIR, remove_file)313 file_path = os.path.join(BASE_DIR, remove_file)
314 if os.path.exists(file_path):314 if os.path.exists(file_path):
315 os.remove(file_path)315 os.remove(file_path)
316 316 
317USE_NINJA = os.environ["CMAKE_GENERATOR"].lower() == "ninja" if "CMAKE_GENERATOR" in os.environ else shutil.which("ninja")317USE_NINJA = os.environ["CMAKE_GENERATOR"].lower() == "ninja" if "CMAKE_GENERATOR" in os.environ else shutil.which("ninja")
318 318 
319class CPPLibBuild(build_clib, object):319class CPPLibBuild(build_clib, object):
320 def run(self):320 def run(self):
321 cmake = get_cmake_command()321 cmake = get_cmake_command()
322 322 
323 if cmake is None:323 if cmake is None:
324 raise RuntimeError(324 raise RuntimeError(
325 "CMake must be installed to build the following extensions: " +325 "CMake must be installed to build the following extensions: " +
326 ", ".join(e.name for e in self.extensions))326 ", ".join(e.name for e in self.extensions))
327 self.cmake = cmake327 self.cmake = cmake
328 328 
329 build_dir = os.path.join(BASE_DIR, "build")329 build_dir = os.path.join(BASE_DIR, "build")
330 build_type_dir = os.path.join(build_dir)330 build_type_dir = os.path.join(build_dir)
331 output_lib_path = os.path.join(build_type_dir, "packages/torch_npu/lib")331 output_lib_path = os.path.join(build_type_dir, "packages/torch_npu/lib")
332 os.makedirs(build_type_dir, exist_ok=True)332 os.makedirs(build_type_dir, exist_ok=True)
333 os.chmod(build_type_dir, mode=BUILD_PERMISSION)333 os.chmod(build_type_dir, mode=BUILD_PERMISSION)
334 os.makedirs(output_lib_path, exist_ok=True)334 os.makedirs(output_lib_path, exist_ok=True)
335 self.build_lib = os.path.relpath(os.path.join(build_dir, "packages/torch_npu"))335 self.build_lib = os.path.relpath(os.path.join(build_dir, "packages/torch_npu"))
336 self.build_temp = os.path.relpath(build_type_dir)336 self.build_temp = os.path.relpath(build_type_dir)
337 337 
338 cmake_args = [338 cmake_args = [
339 '-DCMAKE_BUILD_TYPE=' + get_build_type(),339 '-DCMAKE_BUILD_TYPE=' + get_build_type(),
340 '-DCMAKE_INSTALL_PREFIX=' + os.path.realpath(output_lib_path),340 '-DCMAKE_INSTALL_PREFIX=' + os.path.realpath(output_lib_path),
341 '-DCMAKE_LIBRARY_OUTPUT_DIRECTORY=' + os.path.realpath(output_lib_path),341 '-DCMAKE_LIBRARY_OUTPUT_DIRECTORY=' + os.path.realpath(output_lib_path),
342 '-DCMAKE_ARCHIVE_OUTPUT_DIRECTORY=' + os.path.realpath(output_lib_path),342 '-DCMAKE_ARCHIVE_OUTPUT_DIRECTORY=' + os.path.realpath(output_lib_path),
343 '-DTORCHNPU_INSTALL_LIBDIR=' + os.path.realpath(output_lib_path),343 '-DTORCHNPU_INSTALL_LIBDIR=' + os.path.realpath(output_lib_path),
344 '-DPYTHON_INCLUDE_DIR=' + get_paths().get('include'),344 '-DPYTHON_INCLUDE_DIR=' + get_paths().get('include'),
345 '-DTORCH_VERSION=' + VERSION,345 '-DTORCH_VERSION=' + VERSION,
346 '-DPYTORCH_INSTALL_DIR=' + get_pytorch_dir()]346 '-DPYTORCH_INSTALL_DIR=' + get_pytorch_dir()]
347 347 
348 if DISABLE_TORCHAIR == 'FALSE':348 if DISABLE_TORCHAIR == 'FALSE':
349 if check_torchair_valid(BASE_DIR):349 if check_torchair_valid(BASE_DIR):
350 cmake_args.append('-DBUILD_TORCHAIR=on')350 cmake_args.append('-DBUILD_TORCHAIR=on')
351 torchair_install_prefix = os.path.join(build_type_dir, "packages/torch_npu/dynamo/torchair")351 torchair_install_prefix = os.path.join(build_type_dir, "packages/torch_npu/dynamo/torchair")
352 cmake_args.append(f'-DTORCHAIR_INSTALL_PREFIX={torchair_install_prefix}')352 cmake_args.append(f'-DTORCHAIR_INSTALL_PREFIX={torchair_install_prefix}')
353 cmake_args.append(f'-DTORCHAIR_TARGET_PYTHON={sys.executable}')353 cmake_args.append(f'-DTORCHAIR_TARGET_PYTHON={sys.executable}')
354 354 
355 if DISABLE_RPC == 'FALSE':355 if DISABLE_RPC == 'FALSE':
356 if check_tensorpipe_valid(BASE_DIR):356 if check_tensorpipe_valid(BASE_DIR):
357 cmake_args.append('-DBUILD_TENSORPIPE=on')357 cmake_args.append('-DBUILD_TENSORPIPE=on')
358 358 
359 if ENABLE_LTO == "TRUE":359 if ENABLE_LTO == "TRUE":
360 cmake_args.append('-DENABLE_LTO=on')360 cmake_args.append('-DENABLE_LTO=on')
361 if PGO_MODE != 0:361 if PGO_MODE != 0:
362 cmake_args.append('-DPGO_MODE=' + str(PGO_MODE))362 cmake_args.append('-DPGO_MODE=' + str(PGO_MODE))
363 363 
364 if USE_CXX11_ABI:364 if USE_CXX11_ABI:
365 cmake_args.append('-DGLIBCXX_USE_CXX11_ABI=1')365 cmake_args.append('-DGLIBCXX_USE_CXX11_ABI=1')
366 366 
367 if os.getenv('_ABI_VERSION') is not None:367 if os.getenv('_ABI_VERSION') is not None:
368 cmake_args.append('-DABI_VERSION=' + os.getenv('_ABI_VERSION'))368 cmake_args.append('-DABI_VERSION=' + os.getenv('_ABI_VERSION'))
369 369 
370 if USE_NINJA:370 if USE_NINJA:
371 cmake_args.append("-GNinja")371 cmake_args.append("-GNinja")
372 372 
373 max_jobs = os.getenv("MAX_JOBS")373 max_jobs = os.getenv("MAX_JOBS")
374 if max_jobs is not None or not USE_NINJA:374 if max_jobs is not None or not USE_NINJA:
375 max_jobs = max_jobs or str(multiprocessing.cpu_count())375 max_jobs = max_jobs or str(multiprocessing.cpu_count())
376 build_args = ['-j', max_jobs]376 build_args = ['-j', max_jobs]
377 else:377 else:
378 build_args = []378 build_args = []
379 379 
380 subprocess.check_call([self.cmake, BASE_DIR] + cmake_args, cwd=build_type_dir, env=os.environ)380 subprocess.check_call([self.cmake, BASE_DIR] + cmake_args, cwd=build_type_dir, env=os.environ)
381 for base_dir, dirs, files in os.walk(build_type_dir):381 for base_dir, dirs, files in os.walk(build_type_dir):
382 for dir_name in dirs:382 for dir_name in dirs:
383 dir_path = os.path.join(base_dir, dir_name)383 dir_path = os.path.join(base_dir, dir_name)
384 os.chmod(dir_path, mode=BUILD_PERMISSION)384 os.chmod(dir_path, mode=BUILD_PERMISSION)
385 for file_name in files:385 for file_name in files:
386 file_path = os.path.join(base_dir, file_name)386 file_path = os.path.join(base_dir, file_name)
387 os.chmod(file_path, mode=BUILD_PERMISSION)387 os.chmod(file_path, mode=BUILD_PERMISSION)
388 388 
389 if USE_NINJA:389 if USE_NINJA:
390 subprocess.check_call(['ninja'] + build_args, cwd=build_type_dir, env=os.environ)390 subprocess.check_call(['ninja'] + build_args, cwd=build_type_dir, env=os.environ)
391 else:391 else:
392 subprocess.check_call(['make'] + build_args, cwd=build_type_dir, env=os.environ)392 subprocess.check_call(['make'] + build_args, cwd=build_type_dir, env=os.environ)
393 393 
394 394 
395class Build(build_ext, object):395class Build(build_ext, object):
396 396 
397 def run(self):397 def run(self):
398 self.run_command('build_clib')398 self.run_command('build_clib')
399 self.run_command('build_py')399 self.run_command('build_py')
400 # proceed with the normal build_ext process400 # proceed with the normal build_ext process
401 self.build_lib = os.path.relpath(os.path.join(BASE_DIR, "build/packages"))401 self.build_lib = os.path.relpath(os.path.join(BASE_DIR, "build/packages"))
402 self.build_temp = os.path.relpath(os.path.join(BASE_DIR, "build/temp"))402 self.build_temp = os.path.relpath(os.path.join(BASE_DIR, "build/temp"))
403 self.library_dirs.append(403 self.library_dirs.append(
404 os.path.relpath(os.path.join(BASE_DIR, "build/packages/torch_npu/lib"))404 os.path.relpath(os.path.join(BASE_DIR, "build/packages/torch_npu/lib"))
405 )405 )
406 super(Build, self).run()406 super(Build, self).run()
407 407 
408 408 
409class InstallCmd(install):409class InstallCmd(install):
410 410 
411 def finalize_options(self) -> None:411 def finalize_options(self) -> None:
412 self.build_lib = os.path.relpath(os.path.join(BASE_DIR, "build/packages"))412 self.build_lib = os.path.relpath(os.path.join(BASE_DIR, "build/packages"))
413 return super(InstallCmd, self).finalize_options()413 return super(InstallCmd, self).finalize_options()
414 414 
415 415 
416def add_ops_files(base_dir, file_list):416def add_ops_files(base_dir, file_list):
417 # add ops header files417 # add ops header files
418 plugin_path = os.path.join(base_dir, 'third_party/op-plugin/op_plugin/include')418 plugin_path = os.path.join(base_dir, 'third_party/op-plugin/op_plugin/include')
419 if os.path.exists(plugin_path):419 if os.path.exists(plugin_path):
420 file_list.append('third_party/op-plugin/op_plugin/include/*.h')420 file_list.append('third_party/op-plugin/op_plugin/include/*.h')
421 plugin_utils_path = os.path.join(base_dir, 'third_party/op-plugin/op_plugin/utils')421 plugin_utils_path = os.path.join(base_dir, 'third_party/op-plugin/op_plugin/utils')
422 if os.path.exists(plugin_utils_path):422 if os.path.exists(plugin_utils_path):
423 file_list.append('third_party/op-plugin/op_plugin/utils/*.h')423 file_list.append('third_party/op-plugin/op_plugin/utils/*.h')
424 return424 return
425 425 
426 426 
427def add_ops_python_files(ret_list):427def add_ops_python_files(ret_list):
428 # add ops python files428 # add ops python files
429 opplugin_path = os.path.join(BASE_DIR, 'third_party/op-plugin/op_plugin/python')429 opplugin_path = os.path.join(BASE_DIR, 'third_party/op-plugin/op_plugin/python')
430 430 
431 if os.path.exists(opplugin_path):431 if os.path.exists(opplugin_path):
432 ops_python_files = glob.glob(os.path.join(opplugin_path, '**/*.py'), recursive=True)432 ops_python_files = glob.glob(os.path.join(opplugin_path, '**/*.py'), recursive=True)
433 for src in ops_python_files:433 for src in ops_python_files:
434 dst = os.path.join(434 dst = os.path.join(
435 os.path.join(BASE_DIR, "build/packages/torch_npu/op_plugin"),435 os.path.join(BASE_DIR, "build/packages/torch_npu/op_plugin"),
436 os.path.relpath(src, opplugin_path))436 os.path.relpath(src, opplugin_path))
437 os.makedirs(os.path.dirname(dst), exist_ok=True)437 os.makedirs(os.path.dirname(dst), exist_ok=True)
438 ret_list.append((src, dst))438 ret_list.append((src, dst))
439 return439 return
440 440 
441 441
442def get_src_py_and_dst():442def get_src_py_and_dst():
443 ret = []443 ret = []
444 generated_python_files = glob.glob(444 generated_python_files = glob.glob(
445 os.path.join(BASE_DIR, "torch_npu", '**/*.py'),445 os.path.join(BASE_DIR, "torch_npu", '**/*.py'),
446 recursive=True) + glob.glob(446 recursive=True) + glob.glob(
447 os.path.join(BASE_DIR, "torch_npu", '**/*.yaml'),447 os.path.join(BASE_DIR, "torch_npu", '**/*.yaml'),
448 recursive=True) + glob.glob(448 recursive=True) + glob.glob(
449 os.path.join(BASE_DIR, "torch_npu", 'acl*.json'),449 os.path.join(BASE_DIR, "torch_npu", 'acl*.json'),
450 recursive=True) + glob.glob(450 recursive=True) + glob.glob(
451 os.path.join(BASE_DIR, "torch_npu", 'contrib/apis_config.json'),451 os.path.join(BASE_DIR, "torch_npu", 'contrib/apis_config.json'),
452 recursive=True)452 recursive=True)
453 for src in generated_python_files:453 for src in generated_python_files:
454 dst = os.path.join(454 dst = os.path.join(
455 os.path.join(BASE_DIR, "build/packages/torch_npu"),455 os.path.join(BASE_DIR, "build/packages/torch_npu"),
456 os.path.relpath(src, os.path.join(BASE_DIR, "torch_npu")))456 os.path.relpath(src, os.path.join(BASE_DIR, "torch_npu")))
457 os.makedirs(os.path.dirname(dst), exist_ok=True)457 os.makedirs(os.path.dirname(dst), exist_ok=True)
458 ret.append((src, dst))458 ret.append((src, dst))
459 459 
460 add_ops_python_files(ret)460 add_ops_python_files(ret)
461 461 
462 header_files = [462 header_files = [
463 "torch_npu/csrc/*.h",463 "torch_npu/csrc/*.h",
464 "torch_npu/csrc/*/*.h",464 "torch_npu/csrc/*/*.h",
465 "torch_npu/csrc/*/*.hpp",465 "torch_npu/csrc/*/*.hpp",
466 "torch_npu/csrc/*/*/*.h",466 "torch_npu/csrc/*/*/*.h",
467 "torch_npu/csrc/*/*/*/*.h",467 "torch_npu/csrc/*/*/*/*.h",
468 "torch_npu/csrc/*/*/*/*/*.h",468 "torch_npu/csrc/*/*/*/*/*.h",
469 "third_party/acl/inc/*/*.h",469 "third_party/acl/inc/*/*.h",
470 "third_party/hccl/inc/*/*.h",470 "third_party/hccl/inc/*/*.h",
471 "third_party/acl/inc/*/*/*.h",471 "third_party/acl/inc/*/*/*.h",
472 "torch_npu/csrc/distributed/HCCLUtils.hpp",472 "torch_npu/csrc/distributed/HCCLUtils.hpp",
473 "torch_npu/csrc/distributed/ProcessGroupHCCL.hpp"473 "torch_npu/csrc/distributed/ProcessGroupHCCL.hpp"
474 ]474 ]
475 add_ops_files(BASE_DIR, header_files)475 add_ops_files(BASE_DIR, header_files)
476 glob_header_files = []476 glob_header_files = []
477 for regex_pattern in header_files:477 for regex_pattern in header_files:
478 glob_header_files += glob.glob(os.path.join(BASE_DIR, regex_pattern), recursive=True)478 glob_header_files += glob.glob(os.path.join(BASE_DIR, regex_pattern), recursive=True)
479 479 
480 for src in glob_header_files:480 for src in glob_header_files:
481 dst = os.path.join(481 dst = os.path.join(
482 os.path.join(BASE_DIR, "build/packages/torch_npu/include/torch_npu"),482 os.path.join(BASE_DIR, "build/packages/torch_npu/include/torch_npu"),
483 os.path.relpath(src, os.path.join(BASE_DIR, "torch_npu")))483 os.path.relpath(src, os.path.join(BASE_DIR, "torch_npu")))
484 os.makedirs(os.path.dirname(dst), exist_ok=True)484 os.makedirs(os.path.dirname(dst), exist_ok=True)
485 ret.append((src, dst))485 ret.append((src, dst))
486 486 
487 torch_header_files = [487 torch_header_files = [
488 "*/*.h",488 "*/*.h",
489 "*/*/*.h",489 "*/*/*.h",
490 "*/*/*/*.h",490 "*/*/*/*.h",
491 "*/*/*/*/*.h",491 "*/*/*/*/*.h",
492 "*/*/*/*/*/*.h"492 "*/*/*/*/*/*.h"
493 ]493 ]
494 torch_glob_header_files = []494 torch_glob_header_files = []
495 for regex_pattern in torch_header_files:495 for regex_pattern in torch_header_files:
496 torch_glob_header_files += glob.glob(os.path.join(BASE_DIR, "patch/include", regex_pattern), recursive=True)496 torch_glob_header_files += glob.glob(os.path.join(BASE_DIR, "patch/include", regex_pattern), recursive=True)
497 497 
498 for src in torch_glob_header_files:498 for src in torch_glob_header_files:
499 dst = os.path.join(499 dst = os.path.join(
500 os.path.join(BASE_DIR, "build/packages/torch_npu/include"),500 os.path.join(BASE_DIR, "build/packages/torch_npu/include"),
501 os.path.relpath(src, os.path.join(BASE_DIR, "patch/include")))501 os.path.relpath(src, os.path.join(BASE_DIR, "patch/include")))
502 os.makedirs(os.path.dirname(dst), exist_ok=True)502 os.makedirs(os.path.dirname(dst), exist_ok=True)
503 ret.append((src, dst))503 ret.append((src, dst))
504 504 
505 aot_inductor_files = [505 aot_inductor_files = [
506 # Follow torch v2.6.0.506 # Follow torch v2.6.0.
507 # These aoti_runtime/*.cpp don't compile to libtorch_npu,507 # These aoti_runtime/*.cpp don't compile to libtorch_npu,
508 # but act like header files when generate cppwrapper in aot-inductor.508 # but act like header files when generate cppwrapper in aot-inductor.
509 "torch_npu/_inductor/codegen/aoti_runtime/*.cpp"509 "torch_npu/_inductor/codegen/aoti_runtime/*.cpp"
510 ]510 ]
511 glob_aoti_files = []511 glob_aoti_files = []
512 for regex_pattern in aot_inductor_files:512 for regex_pattern in aot_inductor_files:
513 glob_aoti_files += glob.glob(513 glob_aoti_files += glob.glob(
514 os.path.join(BASE_DIR, regex_pattern), recursive=True514 os.path.join(BASE_DIR, regex_pattern), recursive=True
515 )515 )
516 516 
517 for src in glob_aoti_files:517 for src in glob_aoti_files:
518 # Dst: torch_npu/_inductor/codegen/aoti_runtime/*.cpp518 # Dst: torch_npu/_inductor/codegen/aoti_runtime/*.cpp
519 dst = os.path.join(519 dst = os.path.join(
520 os.path.join(BASE_DIR, "build/packages/torch_npu/"),520 os.path.join(BASE_DIR, "build/packages/torch_npu/"),
521 os.path.relpath(src, os.path.join(BASE_DIR, "torch_npu")),521 os.path.relpath(src, os.path.join(BASE_DIR, "torch_npu")),
522 )522 )
523 os.makedirs(os.path.dirname(dst), exist_ok=True)523 os.makedirs(os.path.dirname(dst), exist_ok=True)
524 ret.append((src, dst))524 ret.append((src, dst))
525 525 
526 def add_torch_npu_codegen(codegen_src_dir, codegen_dst_dir, exclude_root_init=None):526 def add_torch_npu_codegen(codegen_src_dir, codegen_dst_dir, exclude_root_init=None):
527 """527 """
528 复制codegen目录下的文件到目标路径528 复制codegen目录下的文件到目标路径
529 :param codegen_src_dir: 源codegen目录529 :param codegen_src_dir: 源codegen目录
530 :param codegen_dst_dir: 目标目录530 :param codegen_dst_dir: 目标目录
531 :param exclude_root_init: 需要排除根目录__init__.py的源目录(仅过滤该目录下的__init__.py)531 :param exclude_root_init: 需要排除根目录__init__.py的源目录(仅过滤该目录下的__init__.py)
532 """532 """
533 # 匹配需要复制的文件类型533 # 匹配需要复制的文件类型
534 codegen_files = glob.glob(534 codegen_files = glob.glob(
535 os.path.join(codegen_src_dir, '**/*.py'), recursive=True535 os.path.join(codegen_src_dir, '**/*.py'), recursive=True
536 ) + glob.glob(536 ) + glob.glob(
537 os.path.join(codegen_src_dir, '**/*.yaml'), recursive=True537 os.path.join(codegen_src_dir, '**/*.yaml'), recursive=True
538 ) + glob.glob(538 ) + glob.glob(
539 os.path.join(codegen_src_dir, '**/*.json'), recursive=True539 os.path.join(codegen_src_dir, '**/*.json'), recursive=True
540 ) + glob.glob(540 ) + glob.glob(
541 os.path.join(codegen_src_dir, '**/*.cpp'), recursive=True541 os.path.join(codegen_src_dir, '**/*.cpp'), recursive=True
542 ) + glob.glob(542 ) + glob.glob(
543 os.path.join(codegen_src_dir, '**/*.h'), recursive=True543 os.path.join(codegen_src_dir, '**/*.h'), recursive=True
544 )544 )
545 545 
546 # 按原目录结构复制到目标路径546 # 按原目录结构复制到目标路径
547 for src in codegen_files:547 for src in codegen_files:
548 # 仅过滤指定目录下的根级__init__.py548 # 仅过滤指定目录下的根级__init__.py
549 if (exclude_root_init is not None and 549 if (exclude_root_init is not None and
550 os.path.basename(src) == '__init__.py' and 550 os.path.basename(src) == '__init__.py' and
551 os.path.dirname(src) == exclude_root_init):551 os.path.dirname(src) == exclude_root_init):
552 continue # 跳过op-plugin/codegen根目录的__init__.py552 continue # 跳过op-plugin/codegen根目录的__init__.py
553 553
554 # 计算目标路径(保留原目录层级)554 # 计算目标路径(保留原目录层级)
555 dst = os.path.join(555 dst = os.path.join(
556 codegen_dst_dir,556 codegen_dst_dir,
557 os.path.relpath(src, codegen_src_dir) # 保留torchnpugen内部的目录层级557 os.path.relpath(src, codegen_src_dir) # 保留torchnpugen内部的目录层级
558 )558 )
559 print(os.path.relpath(src, codegen_src_dir))559 print(os.path.relpath(src, codegen_src_dir))
560 # 确保目标目录存在560 # 确保目标目录存在
561 os.makedirs(os.path.dirname(dst), exist_ok=True)561 os.makedirs(os.path.dirname(dst), exist_ok=True)
562 # 加入文件复制列表562 # 加入文件复制列表
563 ret.append((src, dst))563 ret.append((src, dst))
564 564 
565 # 新增:提前创建 torchnpugen 根目录565 # 新增:提前创建 torchnpugen 根目录
566 torchnpugen_root = os.path.join(BASE_DIR, "build/packages/torchnpugen")566 torchnpugen_root = os.path.join(BASE_DIR, "build/packages/torchnpugen")
567 os.makedirs(torchnpugen_root, exist_ok=True)567 os.makedirs(torchnpugen_root, exist_ok=True)
568 # 将codegen复制到package路径568 # 将codegen复制到package路径
569 codegen_src_dir = os.path.join(BASE_DIR, "torchnpugen")569 codegen_src_dir = os.path.join(BASE_DIR, "torchnpugen")
570 codegen_dst_dir = os.path.join(BASE_DIR, "build/packages/torchnpugen")570 codegen_dst_dir = os.path.join(BASE_DIR, "build/packages/torchnpugen")
571 # 复制torch_npu的torchnpugen571 # 复制torch_npu的torchnpugen
572 add_torch_npu_codegen(codegen_src_dir, codegen_dst_dir)572 add_torch_npu_codegen(codegen_src_dir, codegen_dst_dir)
573 # 复制op-plugin的torchnpugen(仅过滤其根目录的__init__.py)573 # 复制op-plugin的torchnpugen(仅过滤其根目录的__init__.py)
574 op_plugin_codegen_src = os.path.join(BASE_DIR, "third_party/op-plugin/torchnpugen")574 op_plugin_codegen_src = os.path.join(BASE_DIR, "third_party/op-plugin/torchnpugen")
575 add_torch_npu_codegen(575 add_torch_npu_codegen(
576 op_plugin_codegen_src,576 op_plugin_codegen_src,
577 codegen_dst_dir,577 codegen_dst_dir,
578 exclude_root_init=op_plugin_codegen_src # 指定要过滤根目录__init__.py的源目录578 exclude_root_init=op_plugin_codegen_src # 指定要过滤根目录__init__.py的源目录
579 )579 )
580 580 
581 return ret581 return ret
582 582 
583 583 
584class EggInfoBuild(egg_info, object):584class EggInfoBuild(egg_info, object):
585 def finalize_options(self):585 def finalize_options(self):
586 self.egg_base = os.path.relpath(os.path.join(BASE_DIR, "build/packages"))586 self.egg_base = os.path.relpath(os.path.join(BASE_DIR, "build/packages"))
587 ret = get_src_py_and_dst()587 ret = get_src_py_and_dst()
588 for src, dst in ret:588 for src, dst in ret:
589 self.copy_file(src, dst)589 self.copy_file(src, dst)
590 super(EggInfoBuild, self).finalize_options()590 super(EggInfoBuild, self).finalize_options()
591 591 
592 592 
593class PythonPackageBuild(build_py, object):593class PythonPackageBuild(build_py, object):
594 def run(self) -> None:594 def run(self) -> None:
595 ret = get_src_py_and_dst()595 ret = get_src_py_and_dst()
596 for src, dst in ret:596 for src, dst in ret:
597 self.copy_file(src, dst)597 self.copy_file(src, dst)
598 super(PythonPackageBuild, self).finalize_options()598 super(PythonPackageBuild, self).finalize_options()
599 599 
600 600 
601class BdistWheelBuild(bdist_wheel):601class BdistWheelBuild(bdist_wheel):
602 def run(self):602 def run(self):
603 if which('patchelf') is not None:603 if which('patchelf') is not None:
604 patchelf_dynamic_library()604 patchelf_dynamic_library()
605 605 
606 if not DEBUG and which('eu-strip') is not None:606 if not DEBUG and which('eu-strip') is not None:
607 generate_dbg_files_and_strip()607 generate_dbg_files_and_strip()
608 608 
609 torch_dependencies = ["libc10.so", "libtorch.so", "libtorch_cpu.so", "libtorch_python.so"]609 torch_dependencies = ["libc10.so", "libtorch.so", "libtorch_cpu.so", "libtorch_python.so"]
610 cann_dependencies = ["libhccl.so", "libascendcl.so", "libacl_op_compiler.so", "libge_runner.so",610 cann_dependencies = ["libhccl.so", "libascendcl.so", "libacl_op_compiler.so", "libge_runner.so",
611 "libgraph.so", "libacl_tdt_channel.so", "libfmk_parser.so", "libascend_protobuf.so",611 "libgraph.so", "libacl_tdt_channel.so", "libfmk_parser.so", "libascend_protobuf.so",
612 "libascend_ml.so"]612 "libascend_ml.so"]
613 other_dependencies = ["libtorch_npu.so", "libnpu_profiler.so", "libgomp.so.1", "libatb.so"]613 other_dependencies = ["libtorch_npu.so", "libnpu_profiler.so", "libgomp.so.1", "libatb.so"]
614 614 
615 dependencies = torch_dependencies + cann_dependencies + other_dependencies615 dependencies = torch_dependencies + cann_dependencies + other_dependencies
616 616 
617 bdist_wheel.run(self)617 bdist_wheel.run(self)
618 618 
619 if is_manylinux:619 if is_manylinux:
620 file = glob.glob(os.path.join(self.dist_dir, "*linux*.whl"))[0]620 file = glob.glob(os.path.join(self.dist_dir, "*linux*.whl"))[0]
621 621 
622 auditwheel_cmd = ["auditwheel", "-v", "repair", "-w", self.dist_dir, file]622 auditwheel_cmd = ["auditwheel", "-v", "repair", "-w", self.dist_dir, file]
623 for i in dependencies:623 for i in dependencies:
624 auditwheel_cmd += ["--exclude", i]624 auditwheel_cmd += ["--exclude", i]
625 625 
626 try:626 try:
627 subprocess.run(auditwheel_cmd, check=True, stdout=subprocess.PIPE)627 subprocess.run(auditwheel_cmd, check=True, stdout=subprocess.PIPE)
628 finally:628 finally:
629 os.remove(file)629 os.remove(file)
630 630 
631 631 
632build_mode = _get_build_mode()632build_mode = _get_build_mode()
633if build_mode not in ['clean']:633if build_mode not in ['clean']:
634 # Generate bindings code, including RegisterNPU.cpp & NPUNativeFunctions.h.634 # Generate bindings code, including RegisterNPU.cpp & NPUNativeFunctions.h.
635 generate_bindings_code(BASE_DIR)635 generate_bindings_code(BASE_DIR)
636 if Path(BASE_DIR).joinpath("third_party/Tensorpipe/third_party/acl/libs").exists():636 if Path(BASE_DIR).joinpath("third_party/Tensorpipe/third_party/acl/libs").exists():
637 build_stub(Path(BASE_DIR).joinpath("third_party/Tensorpipe"))637 build_stub(Path(BASE_DIR).joinpath("third_party/Tensorpipe"))
638 build_stub(BASE_DIR)638 build_stub(BASE_DIR)
639 639 
640# Setup include directories folders.640# Setup include directories folders.
641include_directories = [641include_directories = [
642 BASE_DIR,642 BASE_DIR,
643 os.path.join(BASE_DIR, 'patch/include'),643 os.path.join(BASE_DIR, 'patch/include'),
644 os.path.join(BASE_DIR, 'third_party/hccl/inc'),644 os.path.join(BASE_DIR, 'third_party/hccl/inc'),
645 os.path.join(BASE_DIR, 'third_party/acl/inc')645 os.path.join(BASE_DIR, 'third_party/acl/inc')
646]646]
647 647 
648extra_link_args = []648extra_link_args = []
649 649 
650DEBUG = (os.getenv('DEBUG', default='').upper() in ['ON', '1', 'YES', 'TRUE', 'Y'])650DEBUG = (os.getenv('DEBUG', default='').upper() in ['ON', '1', 'YES', 'TRUE', 'Y'])
651 651 
652extra_compile_args = [652extra_compile_args = [
653 '-std=c++17',653 '-std=c++17',
654 '-Wno-sign-compare',654 '-Wno-sign-compare',
655 '-Wno-deprecated-declarations',655 '-Wno-deprecated-declarations',
656 '-Wno-return-type'656 '-Wno-return-type'
657]657]
658 658 
659if re.match(r'clang', os.getenv('CC', '')):659if re.match(r'clang', os.getenv('CC', '')):
660 extra_compile_args += [660 extra_compile_args += [
661 '-Wno-macro-redefined',661 '-Wno-macro-redefined',
662 '-Wno-return-std-move',662 '-Wno-return-std-move',
663 ]663 ]
664 664 
665if DEBUG:665if DEBUG:
666 extra_compile_args += ['-O0', '-g']666 extra_compile_args += ['-O0', '-g']
667 extra_link_args += ['-O0', '-g', '-Wl,-z,now']667 extra_link_args += ['-O0', '-g', '-Wl,-z,now']
668else:668else:
669 extra_compile_args += ['-DNDEBUG']669 extra_compile_args += ['-DNDEBUG']
670 extra_link_args += ['-Wl,-z,now']670 extra_link_args += ['-Wl,-z,now']
671 671 
672# valid manylinux tags672# valid manylinux tags
673manylinux_tags = [673manylinux_tags = [
674 "manylinux1_x86_64",674 "manylinux1_x86_64",
675 "manylinux2010_x86_64",675 "manylinux2010_x86_64",
676 "manylinux2014_x86_64",676 "manylinux2014_x86_64",
677 "manylinux2014_aarch64",677 "manylinux2014_aarch64",
678 "manylinux_2_5_x86_64",678 "manylinux_2_5_x86_64",
679 "manylinux_2_12_x86_64",679 "manylinux_2_12_x86_64",
680 "manylinux_2_17_x86_64",680 "manylinux_2_17_x86_64",
681 "manylinux_2_17_aarch64",681 "manylinux_2_17_aarch64",
682 "manylinux_2_24_x86_64",682 "manylinux_2_24_x86_64",
683 "manylinux_2_24_aarch64",683 "manylinux_2_24_aarch64",
684 "manylinux_2_27_x86_64",684 "manylinux_2_27_x86_64",
685 "manylinux_2_27_aarch64",685 "manylinux_2_27_aarch64",
686 "manylinux_2_28_x86_64",686 "manylinux_2_28_x86_64",
687 "manylinux_2_28_aarch64",687 "manylinux_2_28_aarch64",
688 "manylinux_2_31_x86_64",688 "manylinux_2_31_x86_64",
689 "manylinux_2_31_aarch64",689 "manylinux_2_31_aarch64",
690 "manylinux_2_34_x86_64",690 "manylinux_2_34_x86_64",
691 "manylinux_2_34_aarch64",691 "manylinux_2_34_aarch64",
692 "manylinux_2_35_x86_64"692 "manylinux_2_35_x86_64"
693 "manylinux_2_35_aarch64",693 "manylinux_2_35_aarch64",
694]694]
695is_manylinux = os.environ.get("AUDITWHEEL_PLAT", None) in manylinux_tags695is_manylinux = os.environ.get("AUDITWHEEL_PLAT", None) in manylinux_tags
696 696 
697readme = os.path.join(BASE_DIR, "README.md")697readme = os.path.join(BASE_DIR, "README.md")
698if not os.path.exists(readme):698if not os.path.exists(readme):
699 raise FileNotFoundError("Unable to find 'README.md'")699 raise FileNotFoundError("Unable to find 'README.md'")
700with open(readme, encoding="utf-8") as fdesc:700with open(readme, encoding="utf-8") as fdesc:
701 long_description = fdesc.read()701 long_description = fdesc.read()
702 702 
703classifiers = [703classifiers = [
704 "Development Status :: 5 - Production/Stable",704 "Development Status :: 5 - Production/Stable",
705 "Intended Audience :: Developers",705 "Intended Audience :: Developers",
706 "License :: OSI Approved :: BSD License",706 "License :: OSI Approved :: BSD License",
707 "Operating System :: POSIX :: Linux",707 "Operating System :: POSIX :: Linux",
708 "Topic :: Scientific/Engineering",708 "Topic :: Scientific/Engineering",
709 "Topic :: Scientific/Engineering :: Mathematics",709 "Topic :: Scientific/Engineering :: Mathematics",
710 "Topic :: Scientific/Engineering :: Artificial Intelligence",710 "Topic :: Scientific/Engineering :: Artificial Intelligence",
711 "Topic :: Software Development",711 "Topic :: Software Development",
712 "Topic :: Software Development :: Libraries",712 "Topic :: Software Development :: Libraries",
713 "Topic :: Software Development :: Libraries :: Python Modules",713 "Topic :: Software Development :: Libraries :: Python Modules",
714 "Programming Language :: Python",714 "Programming Language :: Python",
715 "Programming Language :: Python :: 3 :: Only",715 "Programming Language :: Python :: 3 :: Only",
716 "Programming Language :: Python :: 3.8",716 "Programming Language :: Python :: 3.8",
717 "Programming Language :: Python :: 3.9",717 "Programming Language :: Python :: 3.9",
718 "Programming Language :: Python :: 3.10",718 "Programming Language :: Python :: 3.10",
719 "Programming Language :: Python :: 3.11",719 "Programming Language :: Python :: 3.11",
720]720]
721 721 
722requirements = ['torch==2.7.1+cpu' if platform.machine() == 'x86_64' else 'torch==2.7.1']722requirements = ['torch==2.7.1+cpu' if platform.machine() == 'x86_64' else 'torch==2.7.1']
723 723 
724ext_modules = [CppExtension(724ext_modules = [CppExtension(
725 'torch_npu._C',725 'torch_npu._C',
726 sources=["torch_npu/csrc/InitNpuBindings.cpp"],726 sources=["torch_npu/csrc/InitNpuBindings.cpp"],
727 libraries=["torch_npu"],727 libraries=["torch_npu"],
728 include_dirs=include_directories,728 include_dirs=include_directories,
729 extra_compile_args=extra_compile_args + ['-fstack-protector-all'] + [729 extra_compile_args=extra_compile_args + ['-fstack-protector-all'] + [
730 '-D__FILENAME__=\"InitNpuBindings.cpp\"'],730 '-D__FILENAME__=\"InitNpuBindings.cpp\"'],
731 library_dirs=["lib"],731 library_dirs=["lib"],
732 extra_link_args=extra_link_args + ['-Wl,-rpath,$ORIGIN/lib', '-Wl,-Bsymbolic-functions'],732 extra_link_args=extra_link_args + ['-Wl,-rpath,$ORIGIN/lib', '-Wl,-Bsymbolic-functions'],
733 define_macros=[('_GLIBCXX_USE_CXX11_ABI', '1' if USE_CXX11_ABI else '0'),733 define_macros=[('_GLIBCXX_USE_CXX11_ABI', '1' if USE_CXX11_ABI else '0'),
734 ('GLIBCXX_USE_CXX11_ABI', '1' if USE_CXX11_ABI else '0')]734 ('GLIBCXX_USE_CXX11_ABI', '1' if USE_CXX11_ABI else '0')]
735 )]735 )]
736 736 
737setup(737setup(
738 name=os.environ.get('TORCH_NPU_PACKAGE_NAME', 'torch_npu'),738 name=os.environ.get('TORCH_NPU_PACKAGE_NAME', 'torch_npu'),
739 version=VERSION,739 version=VERSION,
740 description='NPU bridge for PyTorch',740 description='NPU bridge for PyTorch',
741 long_description=long_description,741 long_description=long_description,
742 long_description_content_type="text/markdown",742 long_description_content_type="text/markdown",
743 license="BSD License",743 license="BSD License",
744 classifiers=classifiers,744 classifiers=classifiers,
745 packages=["torch_npu", "torchnpugen"],745 packages=["torch_npu", "torchnpugen"],
746 libraries=[('torch_npu', {'sources': list()})],746 libraries=[('torch_npu', {'sources': list()})],
747 package_dir={'': os.path.relpath(os.path.join(BASE_DIR, "build/packages"))},747 package_dir={'': os.path.relpath(os.path.join(BASE_DIR, "build/packages"))},
748 ext_modules=ext_modules,748 ext_modules=ext_modules,
749 install_requires=requirements,749 install_requires=requirements,
750 750 
751 extras_require={751 extras_require={
752 },752 },
753 package_data={753 package_data={
754 'torch_npu': [754 'torch_npu': [
755 '*.so',755 '*.so',
756 'lib/*.so*',756 'lib/*.so*',
757 ],757 ],
758 'torchnpugen': [758 'torchnpugen': [
759 '*.py', '**/*.py',759 '*.py', '**/*.py',
760 '*.yaml', '**/*.yaml',760 '*.yaml', '**/*.yaml',
761 '*.json', '**/*.json',761 '*.json', '**/*.json',
762 '*.cpp', '**/*.cpp',762 '*.cpp', '**/*.cpp',
763 '*.h', '**/*.h',763 '*.h', '**/*.h',
764 ],764 ],
765 },765 },
766 cmdclass={766 cmdclass={
767 'build_clib': CPPLibBuild,767 'build_clib': CPPLibBuild,
768 'build_ext': Build,768 'build_ext': Build,
769 'build_py': PythonPackageBuild,769 'build_py': PythonPackageBuild,
770 'bdist_wheel': BdistWheelBuild,770 'bdist_wheel': BdistWheelBuild,
771 'install': InstallCmd,771 'install': InstallCmd,
772 'clean': Clean772 'clean': Clean
773 },773 },
774 entry_points={774 entry_points={
775 'console_scripts': [775 'console_scripts': [
776 'torch_npu_run = torch_npu.distributed.run:_main',776 'torch_npu_run = torch_npu.distributed.run:_main',
777 ],777 ],
778 'torch.backends': [778 'torch.backends': [
779 'torch_npu = torch_npu:_autoload',779 'torch_npu = torch_npu:_autoload',
780 ],780 ],
781 }781 }
782)782)
Mtest/_inductor/test_empty.py+0-1
@@ -42,4 +42,3 @@ instantiate_parametrized_tests(TestEmpty)
42 42 
43if __name__ == "__main__":43if __name__ == "__main__":
44 run_tests()44 run_tests()
45 
Mtest/_inductor/test_exp.py+0-1
@@ -25,4 +25,3 @@ instantiate_parametrized_tests(TestExp)
25 25 
26if __name__ == "__main__":26if __name__ == "__main__":
27 run_tests()27 run_tests()
28 
Mtest/_inductor/test_fxpass_level.py+91-91
@@ -1,92 +1,92 @@
1import torch1import torch
2import torch.fx as fx2import torch.fx as fx
3from torch.fx.passes.shape_prop import ShapeProp3from torch.fx.passes.shape_prop import ShapeProp
4from torch.testing._internal.common_utils import run_tests, parametrize, instantiate_parametrized_tests4from torch.testing._internal.common_utils import run_tests, parametrize, instantiate_parametrized_tests
5from testutils import TestUtils5from testutils import TestUtils
6import torch_npu6import torch_npu
7import torch_npu._inductor7import torch_npu._inductor
8from torch_npu._inductor.fx_passes.utils.fx_pass_level import FxPassLevel8from torch_npu._inductor.fx_passes.utils.fx_pass_level import FxPassLevel
9from torch_npu._inductor.fx_passes.utils.fx_pass_level import PassType9from torch_npu._inductor.fx_passes.utils.fx_pass_level import PassType
10 10 
11 11 
12class TestFxPassLevel(TestUtils):12class TestFxPassLevel(TestUtils):
13 13 
14 def test_comparison_between_members(self):14 def test_comparison_between_members(self):
15 """枚举成员之间的大小比较"""15 """枚举成员之间的大小比较"""
16 assert FxPassLevel.LEVEL1 < FxPassLevel.LEVEL216 assert FxPassLevel.LEVEL1 < FxPassLevel.LEVEL2
17 assert FxPassLevel.LEVEL1 <= FxPassLevel.LEVEL217 assert FxPassLevel.LEVEL1 <= FxPassLevel.LEVEL2
18 assert FxPassLevel.LEVEL2 > FxPassLevel.LEVEL118 assert FxPassLevel.LEVEL2 > FxPassLevel.LEVEL1
19 assert FxPassLevel.LEVEL2 >= FxPassLevel.LEVEL119 assert FxPassLevel.LEVEL2 >= FxPassLevel.LEVEL1
20 assert FxPassLevel.LEVEL2 == FxPassLevel.LEVEL220 assert FxPassLevel.LEVEL2 == FxPassLevel.LEVEL2
21 assert FxPassLevel.LEVEL1 != FxPassLevel.LEVEL321 assert FxPassLevel.LEVEL1 != FxPassLevel.LEVEL3
22 22 
23 # 严格顺序23 # 严格顺序
24 assert FxPassLevel.LEVEL1 < FxPassLevel.LEVEL2 < FxPassLevel.LEVEL324 assert FxPassLevel.LEVEL1 < FxPassLevel.LEVEL2 < FxPassLevel.LEVEL3
25 25 
26 26 
27 def test_sorting_and_min_max(self):27 def test_sorting_and_min_max(self):
28 """支持排序、min、max 等操作"""28 """支持排序、min、max 等操作"""
29 levels = [FxPassLevel.LEVEL3, FxPassLevel.LEVEL1, FxPassLevel.LEVEL2]29 levels = [FxPassLevel.LEVEL3, FxPassLevel.LEVEL1, FxPassLevel.LEVEL2]
30 sorted_levels = sorted(levels)30 sorted_levels = sorted(levels)
31 assert sorted_levels == [FxPassLevel.LEVEL1, FxPassLevel.LEVEL2, FxPassLevel.LEVEL3]31 assert sorted_levels == [FxPassLevel.LEVEL1, FxPassLevel.LEVEL2, FxPassLevel.LEVEL3]
32 32 
33 assert min(levels) == FxPassLevel.LEVEL133 assert min(levels) == FxPassLevel.LEVEL1
34 assert max(levels) == FxPassLevel.LEVEL334 assert max(levels) == FxPassLevel.LEVEL3
35 35 
36 36 
37 def test_hash_consistency(self):37 def test_hash_consistency(self):
38 """哈希值一致性"""38 """哈希值一致性"""
39 assert hash(FxPassLevel.LEVEL1) == hash(1)39 assert hash(FxPassLevel.LEVEL1) == hash(1)
40 assert hash(FxPassLevel.LEVEL2) == hash(2)40 assert hash(FxPassLevel.LEVEL2) == hash(2)
41 assert hash(FxPassLevel.LEVEL3) == hash(3)41 assert hash(FxPassLevel.LEVEL3) == hash(3)
42 42 
43 # 相同值哈希相同43 # 相同值哈希相同
44 assert hash(FxPassLevel.LEVEL1) == hash(FxPassLevel.LEVEL1)44 assert hash(FxPassLevel.LEVEL1) == hash(FxPassLevel.LEVEL1)
45 45 
46 # 不同值哈希不同46 # 不同值哈希不同
47 assert hash(FxPassLevel.LEVEL1) != hash(FxPassLevel.LEVEL2)47 assert hash(FxPassLevel.LEVEL1) != hash(FxPassLevel.LEVEL2)
48 48 
49 # 可用于集合49 # 可用于集合
50 s = {FxPassLevel.LEVEL1, FxPassLevel.LEVEL2}50 s = {FxPassLevel.LEVEL1, FxPassLevel.LEVEL2}
51 assert FxPassLevel.LEVEL1 in s51 assert FxPassLevel.LEVEL1 in s
52 assert FxPassLevel.LEVEL3 not in s52 assert FxPassLevel.LEVEL3 not in s
53 53 
54 54 
55class TestPassType(TestUtils):55class TestPassType(TestUtils):
56 56 
57 def test_comparison_between_members(self):57 def test_comparison_between_members(self):
58 """枚举成员之间的大小比较"""58 """枚举成员之间的大小比较"""
59 assert PassType.PRE < PassType.POST59 assert PassType.PRE < PassType.POST
60 assert PassType.PRE <= PassType.POST60 assert PassType.PRE <= PassType.POST
61 assert PassType.POST > PassType.PRE61 assert PassType.POST > PassType.PRE
62 assert PassType.POST >= PassType.PRE62 assert PassType.POST >= PassType.PRE
63 assert PassType.PRE == PassType.PRE63 assert PassType.PRE == PassType.PRE
64 assert PassType.PRE != PassType.POST64 assert PassType.PRE != PassType.POST
65 65 
66 66 
67 def test_sorting_and_min_max(self):67 def test_sorting_and_min_max(self):
68 """支持排序、min、max"""68 """支持排序、min、max"""
69 types = [PassType.POST, PassType.PRE]69 types = [PassType.POST, PassType.PRE]
70 sorted_types = sorted(types)70 sorted_types = sorted(types)
71 assert sorted_types == [PassType.PRE, PassType.POST]71 assert sorted_types == [PassType.PRE, PassType.POST]
72 72 
73 assert min(types) == PassType.PRE73 assert min(types) == PassType.PRE
74 assert max(types) == PassType.POST74 assert max(types) == PassType.POST
75 75 
76 76 
77 def test_hash_consistency(self):77 def test_hash_consistency(self):
78 """哈希值一致性"""78 """哈希值一致性"""
79 assert hash(PassType.PRE) == hash(1)79 assert hash(PassType.PRE) == hash(1)
80 assert hash(PassType.POST) == hash(2)80 assert hash(PassType.POST) == hash(2)
81 81 
82 s = {PassType.PRE, PassType.POST}82 s = {PassType.PRE, PassType.POST}
83 assert PassType.PRE in s83 assert PassType.PRE in s
84 assert PassType.PRE in s # 重复添加不影响84 assert PassType.PRE in s # 重复添加不影响
85 85 
86 86 
87instantiate_parametrized_tests(TestFxPassLevel)87instantiate_parametrized_tests(TestFxPassLevel)
88instantiate_parametrized_tests(TestPassType)88instantiate_parametrized_tests(TestPassType)
89 89 
90 90 
91if __name__ == "__main__":91if __name__ == "__main__":
92 run_tests()92 run_tests()
Mtest/_inductor/test_gt.py+0-1
@@ -29,4 +29,3 @@ instantiate_parametrized_tests(TestGt)
29 29 
30if __name__ == "__main__":30if __name__ == "__main__":
31 run_tests()31 run_tests()
32 
Mtest/_inductor/test_shape_handling.py+815-815
@@ -1,816 +1,816 @@
1import unittest1import unittest
2from unittest import mock2from unittest import mock
3 3 
4import torch4import torch
5from torch.nn.parallel import scatter_gather5from torch.nn.parallel import scatter_gather
6from torch.testing._internal.common_utils import (6from torch.testing._internal.common_utils import (
7 IS_JETSON,7 IS_JETSON,
8 IS_REMOTE_GPU,8 IS_REMOTE_GPU,
9 IS_SANDCASTLE,9 IS_SANDCASTLE,
10 NoTest,10 NoTest,
11 TEST_PRIVATEUSE1,11 TEST_PRIVATEUSE1,
12 TestCase,12 TestCase,
13 instantiate_parametrized_tests,13 instantiate_parametrized_tests,
14 run_tests,14 run_tests,
15 skipCUDANonDefaultStreamIf,15 skipCUDANonDefaultStreamIf,
16 skipIfRocm,16 skipIfRocm,
17)17)
18import torch_npu18import torch_npu
19import torch_npu._inductor19import torch_npu._inductor
20import torch_npu.testing20import torch_npu.testing
21from torch_npu.testing.common_utils import get_cycles_per_ms21from torch_npu.testing.common_utils import get_cycles_per_ms
22from torch_npu._inductor.shape_handling import unified_copy22from torch_npu._inductor.shape_handling import unified_copy
23import torch_npu._inductor.shape_handling as shape_handling_module23import torch_npu._inductor.shape_handling as shape_handling_module
24 24 
25torch._dynamo.config.cache_size_limit = 12825torch._dynamo.config.cache_size_limit = 128
26 26 
27if not torch.npu.is_available():27if not torch.npu.is_available():
28 raise unittest.SkipTest("NPU is not available")28 raise unittest.SkipTest("NPU is not available")
29 29 
30device = "npu"30device = "npu"
31 31 
32 32 
33def model_fn(A, B): 33def model_fn(A, B):
34 return A + B34 return A + B
35 35 
36shape_options = {36shape_options = {
37 "enable_shape_handling": True,37 "enable_shape_handling": True,
38 "shape_handling_configs": [38 "shape_handling_configs": [
39 {39 {
40 "type": "BATCHSIZE", # 处理的维度类型(Required)40 "type": "BATCHSIZE", # 处理的维度类型(Required)
41 "dimensions": 0, # 该维度在tensor中的下标(BATCHSIZE默认为0)(Optional)41 "dimensions": 0, # 该维度在tensor中的下标(BATCHSIZE默认为0)(Optional)
42 # "indices": [0, 1], # 需要处理的tensor下标(默认为所有tensor)(Optional)42 # "indices": [0, 1], # 需要处理的tensor下标(默认为所有tensor)(Optional)
43 "value": 0.0, # padding时填充的值, 默认为0.0(Optional)43 "value": 0.0, # padding时填充的值, 默认为0.0(Optional)
44 "gears": [], # 自定义档位信息(Optional)44 "gears": [], # 自定义档位信息(Optional)
45 "min_size": 1, # 该维度的最小大小(档位), 默认为1(Optional) 45 "min_size": 1, # 该维度的最小大小(档位), 默认为1(Optional)
46 "max_size": 1024, # 该维度的最大大小(档位), 默认为1024(Optional)46 "max_size": 1024, # 该维度的最大大小(档位), 默认为1024(Optional)
47 "policy": "TIMES", # 依据min_size, max_size自动生成gears的策略, 默认为TIMES, 表示生成范围内2的整数幂档位(Optional) 47 "policy": "TIMES", # 依据min_size, max_size自动生成gears的策略, 默认为TIMES, 表示生成范围内2的整数幂档位(Optional)
48 },48 },
49 {49 {
50 "type": "SEQLEN", # 处理的维度类型(Required)50 "type": "SEQLEN", # 处理的维度类型(Required)
51 "dimensions": [1, 1], # 该维度在tensor中的下标, 与indices一一对应, 也可以接收dimension表示所有tensor使用相同的dimension index, 优先接收dimension(SEQLEN默认为1)(Optional)51 "dimensions": [1, 1], # 该维度在tensor中的下标, 与indices一一对应, 也可以接收dimension表示所有tensor使用相同的dimension index, 优先接收dimension(SEQLEN默认为1)(Optional)
52 # "indices": [0, 1], # 需要处理的tensor下标(默认为所有tensor)(Optional)52 # "indices": [0, 1], # 需要处理的tensor下标(默认为所有tensor)(Optional)
53 "value": 0.0, # padding时填充的值, 默认为0.0(Optional)53 "value": 0.0, # padding时填充的值, 默认为0.0(Optional)
54 "gears": [], # 自定义档位信息(Optional)54 "gears": [], # 自定义档位信息(Optional)
55 "min_size": 1, # 该维度的最小大小(档位), 默认为1(Optional) 55 "min_size": 1, # 该维度的最小大小(档位), 默认为1(Optional)
56 "max_size": 1024, # 该维度的最大大小(档位), 默认为1024(Optional)56 "max_size": 1024, # 该维度的最大大小(档位), 默认为1024(Optional)
57 "policy": "TIMES", # 依据min_size, max_size自动生成gears的策略, 默认为TIMES, 表示生成范围内2的整数幂档位(Optional) 57 "policy": "TIMES", # 依据min_size, max_size自动生成gears的策略, 默认为TIMES, 表示生成范围内2的整数幂档位(Optional)
58 }58 }
59 ]59 ]
60}60}
61 61 
62 62 
63class TestShapeHandling(TestCase):63class TestShapeHandling(TestCase):
64 def test_init_no_input(self):64 def test_init_no_input(self):
65 shape_handling = torch_npu._inductor.NPUShapeHandling()65 shape_handling = torch_npu._inductor.NPUShapeHandling()
66 self.assertNotEqual(shape_handling, None)66 self.assertNotEqual(shape_handling, None)
67 67
68 def test_init_with_empty_conifg(self):68 def test_init_with_empty_conifg(self):
69 configs = []69 configs = []
70 shape_handling = torch_npu._inductor.NPUShapeHandling(configs)70 shape_handling = torch_npu._inductor.NPUShapeHandling(configs)
71 self.assertNotEqual(shape_handling, None)71 self.assertNotEqual(shape_handling, None)
72 72
73 def test_init_with_gears(self):73 def test_init_with_gears(self):
74 configs = [74 configs = [
75 {75 {
76 "type": "BATCHSIZE",76 "type": "BATCHSIZE",
77 "gears": [16, 32, 64]77 "gears": [16, 32, 64]
78 },78 },
79 {79 {
80 "type": "SEQLEN",80 "type": "SEQLEN",
81 "gears": [16, 32, 64]81 "gears": [16, 32, 64]
82 }82 }
83 ]83 ]
84 shape_handling = torch_npu._inductor.NPUShapeHandling(configs)84 shape_handling = torch_npu._inductor.NPUShapeHandling(configs)
85 self.assertNotEqual(shape_handling, None)85 self.assertNotEqual(shape_handling, None)
86 86
87 def test_init_with_policy(self):87 def test_init_with_policy(self):
88 configs = [88 configs = [
89 {89 {
90 "type": "BATCHSIZE",90 "type": "BATCHSIZE",
91 "min_size": 2,91 "min_size": 2,
92 "max_size": 8,92 "max_size": 8,
93 "policy": "TIMES"93 "policy": "TIMES"
94 },94 },
95 {95 {
96 "type": "SEQLEN",96 "type": "SEQLEN",
97 "min_size": 2,97 "min_size": 2,
98 "max_size": 8,98 "max_size": 8,
99 "policy": "TIMES"99 "policy": "TIMES"
100 }100 }
101 ]101 ]
102 shape_handling = torch_npu._inductor.NPUShapeHandling(configs)102 shape_handling = torch_npu._inductor.NPUShapeHandling(configs)
103 self.assertNotEqual(shape_handling, None)103 self.assertNotEqual(shape_handling, None)
104 104
105 def test_transform_no_operation(self):105 def test_transform_no_operation(self):
106 configs = [106 configs = [
107 {107 {
108 "type": "BATCHSIZE",108 "type": "BATCHSIZE",
109 "gears": [32],109 "gears": [32],
110 "dimensions": 0110 "dimensions": 0
111 },111 },
112 {112 {
113 "type": "SEQLEN",113 "type": "SEQLEN",
114 "gears": [128],114 "gears": [128],
115 "dimensions": [1]115 "dimensions": [1]
116 }116 }
117 ]117 ]
118 shape_handling = torch_npu._inductor.NPUShapeHandling(configs)118 shape_handling = torch_npu._inductor.NPUShapeHandling(configs)
119 input_tensor = torch.randn(32, 128)119 input_tensor = torch.randn(32, 128)
120 outputs = shape_handling.transform([input_tensor])120 outputs = shape_handling.transform([input_tensor])
121 self.assertEqual(outputs[0][0].shape, input_tensor.shape)121 self.assertEqual(outputs[0][0].shape, input_tensor.shape)
122 122
123 def test_transform_padding(self):123 def test_transform_padding(self):
124 configs = [124 configs = [
125 {125 {
126 "type": "BATCHSIZE",126 "type": "BATCHSIZE",
127 "min_size": 16,127 "min_size": 16,
128 "max_size": 256,128 "max_size": 256,
129 "policy": "TIMES",129 "policy": "TIMES",
130 "dimensions": 0130 "dimensions": 0
131 },131 },
132 {132 {
133 "type": "SEQLEN",133 "type": "SEQLEN",
134 "min_size": 16,134 "min_size": 16,
135 "max_size": 256,135 "max_size": 256,
136 "policy": "TIMES",136 "policy": "TIMES",
137 "dimensions": [1]137 "dimensions": [1]
138 }138 }
139 ]139 ]
140 shape_handling = torch_npu._inductor.NPUShapeHandling(configs)140 shape_handling = torch_npu._inductor.NPUShapeHandling(configs)
141 input_tensor = torch.randn(48, 96)141 input_tensor = torch.randn(48, 96)
142 outputs = shape_handling.transform([input_tensor])142 outputs = shape_handling.transform([input_tensor])
143 self.assertEqual(outputs[0][0].shape, (64, 128))143 self.assertEqual(outputs[0][0].shape, (64, 128))
144 144
145 def test_transform_padding_with_indices(self):145 def test_transform_padding_with_indices(self):
146 configs = [146 configs = [
147 {147 {
148 "type": "BATCHSIZE",148 "type": "BATCHSIZE",
149 "min_size": 16,149 "min_size": 16,
150 "max_size": 256,150 "max_size": 256,
151 "policy": "TIMES",151 "policy": "TIMES",
152 "dimensions": 0,152 "dimensions": 0,
153 "indices": [0]153 "indices": [0]
154 },154 },
155 {155 {
156 "type": "SEQLEN",156 "type": "SEQLEN",
157 "min_size": 16,157 "min_size": 16,
158 "max_size": 256,158 "max_size": 256,
159 "policy": "TIMES",159 "policy": "TIMES",
160 "dimensions": [1],160 "dimensions": [1],
161 "indices": [0]161 "indices": [0]
162 }162 }
163 ]163 ]
164 shape_handling = torch_npu._inductor.NPUShapeHandling(configs)164 shape_handling = torch_npu._inductor.NPUShapeHandling(configs)
165 input_tensor1 = torch.randn(48, 96)165 input_tensor1 = torch.randn(48, 96)
166 input_tensor2 = torch.randn(48, 96) 166 input_tensor2 = torch.randn(48, 96)
167 outputs = shape_handling.transform([input_tensor1, input_tensor2])167 outputs = shape_handling.transform([input_tensor1, input_tensor2])
168 self.assertEqual(outputs[0][0].shape, (64, 128))168 self.assertEqual(outputs[0][0].shape, (64, 128))
169 self.assertEqual(outputs[0][1].shape, (48, 96))169 self.assertEqual(outputs[0][1].shape, (48, 96))
170 170
171 def test_transform_split(self):171 def test_transform_split(self):
172 """测试分割操作"""172 """测试分割操作"""
173 # 设置max_size为128,那么超过128的会被分割173 # 设置max_size为128,那么超过128的会被分割
174 configs = [174 configs = [
175 {175 {
176 "type": "BATCHSIZE",176 "type": "BATCHSIZE",
177 "gears": [64, 128],177 "gears": [64, 128],
178 "dimensions": 0178 "dimensions": 0
179 },179 },
180 {180 {
181 "type": "SEQLEN",181 "type": "SEQLEN",
182 "gears": [64, 128],182 "gears": [64, 128],
183 "dimensions": [1]183 "dimensions": [1]
184 }184 }
185 ]185 ]
186 shape_handling = torch_npu._inductor.NPUShapeHandling(configs)186 shape_handling = torch_npu._inductor.NPUShapeHandling(configs)
187 input_tensor = torch.randn(200, 96) # 超过max_size187 input_tensor = torch.randn(200, 96) # 超过max_size
188 outputs = shape_handling.transform([input_tensor])188 outputs = shape_handling.transform([input_tensor])
189 # 验证分割结果:分割为两个组,第一段128,第二段72,再填充为128189 # 验证分割结果:分割为两个组,第一段128,第二段72,再填充为128
190 self.assertEqual(len(outputs), 2) # 分割为两个组190 self.assertEqual(len(outputs), 2) # 分割为两个组
191 self.assertEqual(outputs[0][0].shape, (128, 128)) # 第一段191 self.assertEqual(outputs[0][0].shape, (128, 128)) # 第一段
192 self.assertEqual(outputs[1][0].shape, (128, 128)) # 第二段192 self.assertEqual(outputs[1][0].shape, (128, 128)) # 第二段
193 193
194 def test_recover_padding(self):194 def test_recover_padding(self):
195 """测试恢复填充的张量"""195 """测试恢复填充的张量"""
196 configs = [196 configs = [
197 {197 {
198 "type": "BATCHSIZE",198 "type": "BATCHSIZE",
199 "min_size": 16,199 "min_size": 16,
200 "max_size": 256,200 "max_size": 256,
201 "policy": "TIMES",201 "policy": "TIMES",
202 "dimensions": 0,202 "dimensions": 0,
203 "indices": [0]203 "indices": [0]
204 },204 },
205 {205 {
206 "type": "SEQLEN",206 "type": "SEQLEN",
207 "min_size": 16,207 "min_size": 16,
208 "max_size": 256,208 "max_size": 256,
209 "policy": "TIMES",209 "policy": "TIMES",
210 "dimensions": [1],210 "dimensions": [1],
211 "indices": [0]211 "indices": [0]
212 }212 }
213 ]213 ]
214 shape_handling = torch_npu._inductor.NPUShapeHandling(configs)214 shape_handling = torch_npu._inductor.NPUShapeHandling(configs)
215 orig_tensor = torch.randn(48, 128)215 orig_tensor = torch.randn(48, 128)
216 padded_group = shape_handling.transform([orig_tensor])216 padded_group = shape_handling.transform([orig_tensor])
217 # 执行恢复217 # 执行恢复
218 recovered = shape_handling.recover(padded_group)218 recovered = shape_handling.recover(padded_group)
219 # 验证尺寸还原219 # 验证尺寸还原
220 self.assertEqual(recovered[0].shape, orig_tensor.shape)220 self.assertEqual(recovered[0].shape, orig_tensor.shape)
221 # 验证数据一致性221 # 验证数据一致性
222 self.assertTrue(torch.allclose(recovered[0], orig_tensor))222 self.assertTrue(torch.allclose(recovered[0], orig_tensor))
223 223
224 def test_recover_split(self):224 def test_recover_split(self):
225 """测试恢复分割的张量组"""225 """测试恢复分割的张量组"""
226 configs = [226 configs = [
227 {227 {
228 "type": "BATCHSIZE",228 "type": "BATCHSIZE",
229 "min_size": 16,229 "min_size": 16,
230 "max_size": 128,230 "max_size": 128,
231 "policy": "TIMES",231 "policy": "TIMES",
232 "dimensions": 0,232 "dimensions": 0,
233 "indices": [0]233 "indices": [0]
234 },234 },
235 {235 {
236 "type": "SEQLEN",236 "type": "SEQLEN",
237 "min_size": 16,237 "min_size": 16,
238 "max_size": 256,238 "max_size": 256,
239 "policy": "TIMES",239 "policy": "TIMES",
240 "dimensions": [1],240 "dimensions": [1],
241 "indices": [0]241 "indices": [0]
242 }242 }
243 ]243 ]
244 shape_handling = torch_npu._inductor.NPUShapeHandling(configs)244 shape_handling = torch_npu._inductor.NPUShapeHandling(configs)
245 orig_tensor = torch.randn(200, 128)245 orig_tensor = torch.randn(200, 128)
246 split_groups = shape_handling.transform([orig_tensor])246 split_groups = shape_handling.transform([orig_tensor])
247 # 执行恢复247 # 执行恢复
248 recovered = shape_handling.recover(split_groups)248 recovered = shape_handling.recover(split_groups)
249 # 验证拼接还原249 # 验证拼接还原
250 self.assertEqual(recovered[0].shape, orig_tensor.shape)250 self.assertEqual(recovered[0].shape, orig_tensor.shape)
251 self.assertTrue(torch.allclose(recovered[0], orig_tensor))251 self.assertTrue(torch.allclose(recovered[0], orig_tensor))
252 252
253 def test_invalid_dim(self):253 def test_invalid_dim(self):
254 """测试无效维度异常"""254 """测试无效维度异常"""
255 configs = [255 configs = [
256 {256 {
257 "type": "BATCHSIZE",257 "type": "BATCHSIZE",
258 "min_size": 16,258 "min_size": 16,
259 "max_size": 128,259 "max_size": 128,
260 "policy": "TIMES",260 "policy": "TIMES",
261 "dimensions": 3,261 "dimensions": 3,
262 "indices": [0]262 "indices": [0]
263 }263 }
264 ]264 ]
265 shape_handling = torch_npu._inductor.NPUShapeHandling(configs)265 shape_handling = torch_npu._inductor.NPUShapeHandling(configs)
266 input_tensor = torch.randn(32, 128)266 input_tensor = torch.randn(32, 128)
267 # 验证越界维度触发异常267 # 验证越界维度触发异常
268 with self.assertRaises(RuntimeError):268 with self.assertRaises(RuntimeError):
269 shape_handling.transform([input_tensor]) # 有效维度应为0或1269 shape_handling.transform([input_tensor]) # 有效维度应为0或1
270 270 
271 def test_register_custom_strategy(self):271 def test_register_custom_strategy(self):
272 """测试注册自定义策略"""272 """测试注册自定义策略"""
273 # 创建自定义策略类273 # 创建自定义策略类
274 class CustomBsShapeOp(torch_npu._C._BSShapeOpStrategy):274 class CustomBsShapeOp(torch_npu._C._BSShapeOpStrategy):
275 def __init__(self):275 def __init__(self):
276 super().__init__()276 super().__init__()
277 self.transform_called = False277 self.transform_called = False
278 self.recover_called = False278 self.recover_called = False
279 279 
280 def Transform(self, inputs, outputs):280 def Transform(self, inputs, outputs):
281 self.transform_called = True281 self.transform_called = True
282 # 简单实现:直接复制输入到输出282 # 简单实现:直接复制输入到输出
283 if inputs:283 if inputs:
284 outputs.append([tensor.clone() for tensor in inputs])284 outputs.append([tensor.clone() for tensor in inputs])
285 285 
286 def Recover(self, inputs, outputs):286 def Recover(self, inputs, outputs):
287 self.recover_called = True287 self.recover_called = True
288 # 简单实现:直接复制第一个组的第一个张量288 # 简单实现:直接复制第一个组的第一个张量
289 if inputs and inputs[0]:289 if inputs and inputs[0]:
290 outputs.append(inputs[0][0].clone())290 outputs.append(inputs[0][0].clone())
291 291
292 class CustomSeqShapeOp(torch_npu._C._SeqShapeOpStrategy):292 class CustomSeqShapeOp(torch_npu._C._SeqShapeOpStrategy):
293 def __init__(self):293 def __init__(self):
294 super().__init__()294 super().__init__()
295 self.transform_called = False295 self.transform_called = False
296 self.recover_called = False296 self.recover_called = False
297 297 
298 def Transform(self, inputs, outputs):298 def Transform(self, inputs, outputs):
299 self.transform_called = True299 self.transform_called = True
300 # 简单实现:直接复制输入到输出300 # 简单实现:直接复制输入到输出
301 if inputs:301 if inputs:
302 outputs.append([tensor.clone() for tensor in inputs])302 outputs.append([tensor.clone() for tensor in inputs])
303 303
304 configs = [304 configs = [
305 {305 {
306 "type": "BATCHSIZE",306 "type": "BATCHSIZE",
307 "min_size": 16,307 "min_size": 16,
308 "max_size": 128,308 "max_size": 128,
309 "policy": "TIMES",309 "policy": "TIMES",
310 "dimensions": 0,310 "dimensions": 0,
311 "indices": [0]311 "indices": [0]
312 },312 },
313 {313 {
314 "type": "SEQLEN",314 "type": "SEQLEN",
315 "min_size": 16,315 "min_size": 16,
316 "max_size": 256,316 "max_size": 256,
317 "policy": "TIMES",317 "policy": "TIMES",
318 "dimensions": [1],318 "dimensions": [1],
319 "indices": [0]319 "indices": [0]
320 }320 }
321 ]321 ]
322 shape_handling = torch_npu._inductor.NPUShapeHandling(configs)322 shape_handling = torch_npu._inductor.NPUShapeHandling(configs)
323 custom_bs_strategy = CustomBsShapeOp()323 custom_bs_strategy = CustomBsShapeOp()
324 custom_seq_strategy = CustomSeqShapeOp()324 custom_seq_strategy = CustomSeqShapeOp()
325 325 
326 # 注册自定义策略326 # 注册自定义策略
327 shape_handling.register_batch_size_strategy(custom_bs_strategy)327 shape_handling.register_batch_size_strategy(custom_bs_strategy)
328 shape_handling.register_sequence_strategy(custom_seq_strategy)328 shape_handling.register_sequence_strategy(custom_seq_strategy)
329 329 
330 # 验证自定义策略被调用330 # 验证自定义策略被调用
331 input_tensor = torch.randn(32, 128)331 input_tensor = torch.randn(32, 128)
332 shape_handling.transform([input_tensor])332 shape_handling.transform([input_tensor])
333 333 
334 self.assertTrue(custom_bs_strategy.transform_called)334 self.assertTrue(custom_bs_strategy.transform_called)
335 self.assertTrue(custom_seq_strategy.transform_called)335 self.assertTrue(custom_seq_strategy.transform_called)
336 336 
337 337 
338 338
339class TestShapeHandlingBranchCoverage(TestCase):339class TestShapeHandlingBranchCoverage(TestCase):
340 def test_validate_configs_error_branches(self):340 def test_validate_configs_error_branches(self):
341 shape_handling = torch_npu._inductor.NPUShapeHandling()341 shape_handling = torch_npu._inductor.NPUShapeHandling()
342 342 
343 with self.assertRaises(ValueError):343 with self.assertRaises(ValueError):
344 shape_handling._validate_configs([{}])344 shape_handling._validate_configs([{}])
345 345 
346 with self.assertRaises(ValueError):346 with self.assertRaises(ValueError):
347 shape_handling._validate_configs([{"type": 1}])347 shape_handling._validate_configs([{"type": 1}])
348 348 
349 with self.assertRaises(ValueError):349 with self.assertRaises(ValueError):
350 shape_handling._validate_configs([{"type": "UNKNOWN"}])350 shape_handling._validate_configs([{"type": "UNKNOWN"}])
351 351 
352 with self.assertRaises(ValueError):352 with self.assertRaises(ValueError):
353 shape_handling._validate_configs([{"type": "BATCHSIZE", "dimensions": "0"}])353 shape_handling._validate_configs([{"type": "BATCHSIZE", "dimensions": "0"}])
354 354 
355 with self.assertRaises(ValueError):355 with self.assertRaises(ValueError):
356 shape_handling._validate_configs([{"type": "BATCHSIZE", "dimensions": [0, "1"]}])356 shape_handling._validate_configs([{"type": "BATCHSIZE", "dimensions": [0, "1"]}])
357 357 
358 with self.assertRaises(ValueError):358 with self.assertRaises(ValueError):
359 shape_handling._validate_configs([{"type": "BATCHSIZE", "min_size": 1.5}])359 shape_handling._validate_configs([{"type": "BATCHSIZE", "min_size": 1.5}])
360 360 
361 with self.assertRaises(ValueError):361 with self.assertRaises(ValueError):
362 shape_handling._validate_configs([{"type": "BATCHSIZE", "value": "bad"}])362 shape_handling._validate_configs([{"type": "BATCHSIZE", "value": "bad"}])
363 363 
364 with self.assertRaises(ValueError):364 with self.assertRaises(ValueError):
365 shape_handling._validate_configs([{"type": "BATCHSIZE", "policy": 1}])365 shape_handling._validate_configs([{"type": "BATCHSIZE", "policy": 1}])
366 366 
367 with self.assertRaises(ValueError):367 with self.assertRaises(ValueError):
368 shape_handling._validate_configs([{"type": "BATCHSIZE", "policy": "BAD"}])368 shape_handling._validate_configs([{"type": "BATCHSIZE", "policy": "BAD"}])
369 369 
370 with self.assertRaises(ValueError):370 with self.assertRaises(ValueError):
371 shape_handling._validate_configs([{"type": "BATCHSIZE"}, {"type": "BATCHSIZE"}])371 shape_handling._validate_configs([{"type": "BATCHSIZE"}, {"type": "BATCHSIZE"}])
372 372 
373 with self.assertRaises(ValueError):373 with self.assertRaises(ValueError):
374 shape_handling._validate_configs(374 shape_handling._validate_configs(
375 [{"type": "BATCHSIZE"}, {"type": "SEQLEN"}, {"type": "BATCHSIZE"}]375 [{"type": "BATCHSIZE"}, {"type": "SEQLEN"}, {"type": "BATCHSIZE"}]
376 )376 )
377 377 
378 def test_construct_indices_branches(self):378 def test_construct_indices_branches(self):
379 shape_handling = torch_npu._inductor.NPUShapeHandling()379 shape_handling = torch_npu._inductor.NPUShapeHandling()
380 tensors = [torch.randn(2, 3), torch.randn(2)]380 tensors = [torch.randn(2, 3), torch.randn(2)]
381 381 
382 bs_indices = shape_handling._construct_indices(tensors, [], "BATCHSIZE")382 bs_indices = shape_handling._construct_indices(tensors, [], "BATCHSIZE")
383 self.assertEqual(bs_indices, [0, 1])383 self.assertEqual(bs_indices, [0, 1])
384 384 
385 seq_indices_default = shape_handling._construct_indices(tensors, [], "SEQLEN")385 seq_indices_default = shape_handling._construct_indices(tensors, [], "SEQLEN")
386 self.assertEqual(seq_indices_default, [0])386 self.assertEqual(seq_indices_default, [0])
387 387 
388 seq_indices_dim0 = shape_handling._construct_indices(tensors, [0], "SEQLEN")388 seq_indices_dim0 = shape_handling._construct_indices(tensors, [0], "SEQLEN")
389 self.assertEqual(seq_indices_dim0, [0, 1])389 self.assertEqual(seq_indices_dim0, [0, 1])
390 390 
391 def test_delay_initialize_builds_missing_indices(self):391 def test_delay_initialize_builds_missing_indices(self):
392 configs = [392 configs = [
393 {393 {
394 "type": "BATCHSIZE",394 "type": "BATCHSIZE",
395 "dimensions": [0],395 "dimensions": [0],
396 "indices": [],396 "indices": [],
397 "gears": [8]397 "gears": [8]
398 },398 },
399 {399 {
400 "type": "SEQLEN",400 "type": "SEQLEN",
401 "dimensions": [1],401 "dimensions": [1],
402 "indices": [0],402 "indices": [0],
403 "gears": [8]403 "gears": [8]
404 }404 }
405 ]405 ]
406 shape_handling = torch_npu._inductor.NPUShapeHandling(configs)406 shape_handling = torch_npu._inductor.NPUShapeHandling(configs)
407 self.assertTrue(shape_handling.delay_init)407 self.assertTrue(shape_handling.delay_init)
408 408 
409 shape_handling.delay_initialize([torch.randn(4, 5)])409 shape_handling.delay_initialize([torch.randn(4, 5)])
410 self.assertEqual(shape_handling.configs[0]["indices"], [0])410 self.assertEqual(shape_handling.configs[0]["indices"], [0])
411 self.assertEqual(shape_handling.configs[1]["indices"], [0])411 self.assertEqual(shape_handling.configs[1]["indices"], [0])
412 self.assertFalse(shape_handling.delay_init)412 self.assertFalse(shape_handling.delay_init)
413 413 
414 def test_flatten_and_unflatten_with_and_without_tensor(self):414 def test_flatten_and_unflatten_with_and_without_tensor(self):
415 shape_handling = torch_npu._inductor.NPUShapeHandling()415 shape_handling = torch_npu._inductor.NPUShapeHandling()
416 416 
417 tensors, indices, leaves, spec = shape_handling.flatten_to_tensors({"a": 1, "b": "x"})417 tensors, indices, leaves, spec = shape_handling.flatten_to_tensors({"a": 1, "b": "x"})
418 self.assertEqual(list(tensors), [])418 self.assertEqual(list(tensors), [])
419 self.assertEqual(list(indices), [])419 self.assertEqual(list(indices), [])
420 self.assertEqual(len(leaves), 2)420 self.assertEqual(len(leaves), 2)
421 self.assertIsNotNone(spec)421 self.assertIsNotNone(spec)
422 422 
423 structure = ((torch.tensor([1.0]), "k"), {"v": torch.tensor([2.0])})423 structure = ((torch.tensor([1.0]), "k"), {"v": torch.tensor([2.0])})
424 tensors, indices, leaves, spec = shape_handling.flatten_to_tensors(structure)424 tensors, indices, leaves, spec = shape_handling.flatten_to_tensors(structure)
425 rebuilt = shape_handling.unflatten_from_tensors(425 rebuilt = shape_handling.unflatten_from_tensors(
426 [torch.tensor([10.0]), torch.tensor([20.0])], indices, leaves, spec426 [torch.tensor([10.0]), torch.tensor([20.0])], indices, leaves, spec
427 )427 )
428 self.assertEqual(rebuilt[0][1], "k")428 self.assertEqual(rebuilt[0][1], "k")
429 self.assertTrue(torch.equal(rebuilt[0][0], torch.tensor([10.0])))429 self.assertTrue(torch.equal(rebuilt[0][0], torch.tensor([10.0])))
430 self.assertTrue(torch.equal(rebuilt[1]["v"], torch.tensor([20.0])))430 self.assertTrue(torch.equal(rebuilt[1]["v"], torch.tensor([20.0])))
431 431 
432 def test_transform_hook_default_and_custom_paths(self):432 def test_transform_hook_default_and_custom_paths(self):
433 shape_handling = torch_npu._inductor.NPUShapeHandling()433 shape_handling = torch_npu._inductor.NPUShapeHandling()
434 input_a = torch.tensor([1.0])434 input_a = torch.tensor([1.0])
435 input_b = torch.tensor([2.0])435 input_b = torch.tensor([2.0])
436 transform_res = [436 transform_res = [
437 [torch.tensor([3.0]), torch.tensor([4.0])],437 [torch.tensor([3.0]), torch.tensor([4.0])],
438 [torch.tensor([5.0]), torch.tensor([6.0])]438 [torch.tensor([5.0]), torch.tensor([6.0])]
439 ]439 ]
440 440 
441 with mock.patch.object(441 with mock.patch.object(
442 torch_npu._inductor.NPUShapeHandling, "transform", return_value=transform_res442 torch_npu._inductor.NPUShapeHandling, "transform", return_value=transform_res
443 ):443 ):
444 args_list, kwargs_list = shape_handling.transform_hook(input_a, extra=input_b)444 args_list, kwargs_list = shape_handling.transform_hook(input_a, extra=input_b)
445 self.assertEqual(len(args_list), 2)445 self.assertEqual(len(args_list), 2)
446 self.assertEqual(len(kwargs_list), 2)446 self.assertEqual(len(kwargs_list), 2)
447 self.assertTrue(torch.equal(args_list[0][0], torch.tensor([3.0])))447 self.assertTrue(torch.equal(args_list[0][0], torch.tensor([3.0])))
448 self.assertTrue(torch.equal(kwargs_list[1]["extra"], torch.tensor([6.0])))448 self.assertTrue(torch.equal(kwargs_list[1]["extra"], torch.tensor([6.0])))
449 449 
450 recorded = {}450 recorded = {}
451 451 
452 def pre_fn(*args, **kwargs):452 def pre_fn(*args, **kwargs):
453 recorded["pre"] = (args, kwargs)453 recorded["pre"] = (args, kwargs)
454 return [args[0]]454 return [args[0]]
455 455 
456 def post_fn(outputs):456 def post_fn(outputs):
457 recorded["post"] = outputs457 recorded["post"] = outputs
458 return [("ok",)], [{"done": True}]458 return [("ok",)], [{"done": True}]
459 459 
460 shape_handling_custom = torch_npu._inductor.NPUShapeHandling(460 shape_handling_custom = torch_npu._inductor.NPUShapeHandling(
461 transform_pre_fn=pre_fn,461 transform_pre_fn=pre_fn,
462 transform_post_fn=post_fn,462 transform_post_fn=post_fn,
463 )463 )
464 with mock.patch.object(464 with mock.patch.object(
465 torch_npu._inductor.NPUShapeHandling, "transform", return_value=[[torch.tensor([9.0])]]465 torch_npu._inductor.NPUShapeHandling, "transform", return_value=[[torch.tensor([9.0])]]
466 ):466 ):
467 out_args, out_kwargs = shape_handling_custom.transform_hook(torch.tensor([7.0]))467 out_args, out_kwargs = shape_handling_custom.transform_hook(torch.tensor([7.0]))
468 self.assertIn("pre", recorded)468 self.assertIn("pre", recorded)
469 self.assertIn("post", recorded)469 self.assertIn("post", recorded)
470 self.assertEqual(out_args, [("ok",)])470 self.assertEqual(out_args, [("ok",)])
471 self.assertEqual(out_kwargs, [{"done": True}])471 self.assertEqual(out_kwargs, [{"done": True}])
472 472 
473 shape_handling_none = torch_npu._inductor.NPUShapeHandling(transform_post_fn=lambda _: None)473 shape_handling_none = torch_npu._inductor.NPUShapeHandling(transform_post_fn=lambda _: None)
474 with mock.patch.object(474 with mock.patch.object(
475 torch_npu._inductor.NPUShapeHandling, "transform", return_value=[[torch.tensor([1.0])]]475 torch_npu._inductor.NPUShapeHandling, "transform", return_value=[[torch.tensor([1.0])]]
476 ):476 ):
477 self.assertIsNone(shape_handling_none.transform_hook(torch.tensor([1.0])))477 self.assertIsNone(shape_handling_none.transform_hook(torch.tensor([1.0])))
478 478 
479 def test_recover_hook_default_and_custom_paths(self):479 def test_recover_hook_default_and_custom_paths(self):
480 shape_handling = torch_npu._inductor.NPUShapeHandling()480 shape_handling = torch_npu._inductor.NPUShapeHandling()
481 groups = [481 groups = [
482 ((torch.tensor([1.0]), "x"), {"y": torch.tensor([2.0])})482 ((torch.tensor([1.0]), "x"), {"y": torch.tensor([2.0])})
483 ]483 ]
484 484 
485 with mock.patch.object(485 with mock.patch.object(
486 torch_npu._inductor.NPUShapeHandling,486 torch_npu._inductor.NPUShapeHandling,
487 "recover",487 "recover",
488 side_effect=lambda tensor_groups: list(tensor_groups[0]),488 side_effect=lambda tensor_groups: list(tensor_groups[0]),
489 ):489 ):
490 outputs = shape_handling.recover_hook(groups)490 outputs = shape_handling.recover_hook(groups)
491 self.assertEqual(outputs[0][1], "x")491 self.assertEqual(outputs[0][1], "x")
492 self.assertTrue(torch.equal(outputs[0][0], torch.tensor([1.0])))492 self.assertTrue(torch.equal(outputs[0][0], torch.tensor([1.0])))
493 self.assertTrue(torch.equal(outputs[1]["y"], torch.tensor([2.0])))493 self.assertTrue(torch.equal(outputs[1]["y"], torch.tensor([2.0])))
494 494 
495 custom = torch_npu._inductor.NPUShapeHandling(495 custom = torch_npu._inductor.NPUShapeHandling(
496 recover_pre_fn=lambda groups: [[torch.tensor([5.0])]],496 recover_pre_fn=lambda groups: [[torch.tensor([5.0])]],
497 recover_post_fn=lambda recover_res: {"result": recover_res},497 recover_post_fn=lambda recover_res: {"result": recover_res},
498 )498 )
499 with mock.patch.object(499 with mock.patch.object(
500 torch_npu._inductor.NPUShapeHandling, "recover", return_value=[torch.tensor([8.0])]500 torch_npu._inductor.NPUShapeHandling, "recover", return_value=[torch.tensor([8.0])]
501 ):501 ):
502 outputs = custom.recover_hook(groups)502 outputs = custom.recover_hook(groups)
503 self.assertEqual(list(outputs.keys()), ["result"])503 self.assertEqual(list(outputs.keys()), ["result"])
504 self.assertTrue(torch.equal(outputs["result"][0], torch.tensor([8.0])))504 self.assertTrue(torch.equal(outputs["result"][0], torch.tensor([8.0])))
505 505 
506 def test_get_shape_safe_and_patch_shape_handling(self):506 def test_get_shape_safe_and_patch_shape_handling(self):
507 shape_handling = torch_npu._inductor.NPUShapeHandling()507 shape_handling = torch_npu._inductor.NPUShapeHandling()
508 shape_info = shape_handling.get_shape_safe((torch.randn(2, 3), [torch.randn(1)]))508 shape_info = shape_handling.get_shape_safe((torch.randn(2, 3), [torch.randn(1)]))
509 self.assertEqual(shape_info[0], [2, 3])509 self.assertEqual(shape_info[0], [2, 3])
510 self.assertEqual(shape_info[1][0], [1])510 self.assertEqual(shape_info[1][0], [1])
511 self.assertIs(shape_handling.get_shape_safe(1), int)511 self.assertIs(shape_handling.get_shape_safe(1), int)
512 512 
513 if hasattr(shape_handling_module.patch_shape_handling, "_is_patched"):513 if hasattr(shape_handling_module.patch_shape_handling, "_is_patched"):
514 delattr(shape_handling_module.patch_shape_handling, "_is_patched")514 delattr(shape_handling_module.patch_shape_handling, "_is_patched")
515 called = []515 called = []
516 with mock.patch.object(shape_handling_module, "patch_dynamo_context", side_effect=lambda: called.append(1)):516 with mock.patch.object(shape_handling_module, "patch_dynamo_context", side_effect=lambda: called.append(1)):
517 shape_handling_module.patch_shape_handling()517 shape_handling_module.patch_shape_handling()
518 shape_handling_module.patch_shape_handling()518 shape_handling_module.patch_shape_handling()
519 self.assertEqual(len(called), 1)519 self.assertEqual(len(called), 1)
520 if hasattr(shape_handling_module.patch_shape_handling, "_is_patched"):520 if hasattr(shape_handling_module.patch_shape_handling, "_is_patched"):
521 delattr(shape_handling_module.patch_shape_handling, "_is_patched")521 delattr(shape_handling_module.patch_shape_handling, "_is_patched")
522 522 
523 523 
524class TestDynamicShapeCompile(TestCase):524class TestDynamicShapeCompile(TestCase):
525 def test_npu_dynamic_shape_reuse_with_no_bucket(self):525 def test_npu_dynamic_shape_reuse_with_no_bucket(self):
526 526
527 compiled_fn = torch.compile(527 compiled_fn = torch.compile(
528 model_fn, 528 model_fn,
529 backend='inductor', 529 backend='inductor',
530 dynamic=False,530 dynamic=False,
531 )531 )
532 532 
533 # 运行不同形状,验证是否只触发 4 次编译533 # 运行不同形状,验证是否只触发 4 次编译
534 test_shapes = [(3, 20), (4, 20), (5, 20), (6, 20)]534 test_shapes = [(3, 20), (4, 20), (5, 20), (6, 20)]
535 535
536 536 
537 if hasattr(torch._inductor.metrics.generated_kernel_count, 'reset'):537 if hasattr(torch._inductor.metrics.generated_kernel_count, 'reset'):
538 torch._inductor.metrics.generated_kernel_count.reset()538 torch._inductor.metrics.generated_kernel_count.reset()
539 else:539 else:
540 torch._inductor.metrics.generated_kernel_count = 0540 torch._inductor.metrics.generated_kernel_count = 0
541 541 
542 for shape in test_shapes:542 for shape in test_shapes:
543 A = torch.randn(shape, device=device)543 A = torch.randn(shape, device=device)
544 B = torch.randn(shape, device=device)544 B = torch.randn(shape, device=device)
545 out = compiled_fn(A, B)545 out = compiled_fn(A, B)
546 self.assertTrue(torch.allclose(out, A + B))546 self.assertTrue(torch.allclose(out, A + B))
547 547 
548 548 
549 compile_count = torch._inductor.metrics.generated_kernel_count549 compile_count = torch._inductor.metrics.generated_kernel_count
550 550 
551 # 获取 Inductor 编译的总次数(生成的 kernel 数量相关)551 # 获取 Inductor 编译的总次数(生成的 kernel 数量相关)
552 print(f"\n[结果] Inductor 编译次数 (generated_kernel_count): {compile_count}")552 print(f"\n[结果] Inductor 编译次数 (generated_kernel_count): {compile_count}")
553 553 
554 # 如果动态形状分档不生效,编译次数应为 4554 # 如果动态形状分档不生效,编译次数应为 4
555 self.assertEqual(compile_count, 4)555 self.assertEqual(compile_count, 4)
556 556 
557 def test_npu_dynamic_shape_reuse_with_bucket(self):557 def test_npu_dynamic_shape_reuse_with_bucket(self):
558 558
559 compiled_fn = torch.compile(559 compiled_fn = torch.compile(
560 model_fn, 560 model_fn,
561 backend='inductor', 561 backend='inductor',
562 dynamic=False,562 dynamic=False,
563 options=shape_options563 options=shape_options
564 )564 )
565 565 
566 # 运行不同形状,验证是否只触发 2 次编译566 # 运行不同形状,验证是否只触发 2 次编译
567 test_shapes = [(3, 32), (4, 32), (5, 32), (6, 32)]567 test_shapes = [(3, 32), (4, 32), (5, 32), (6, 32)]
568 if hasattr(torch._inductor.metrics.generated_kernel_count, 'reset'):568 if hasattr(torch._inductor.metrics.generated_kernel_count, 'reset'):
569 torch._inductor.metrics.generated_kernel_count.reset()569 torch._inductor.metrics.generated_kernel_count.reset()
570 else:570 else:
571 torch._inductor.metrics.generated_kernel_count = 0571 torch._inductor.metrics.generated_kernel_count = 0
572 572 
573 for shape in test_shapes:573 for shape in test_shapes:
574 A = torch.randn(shape, device=device)574 A = torch.randn(shape, device=device)
575 B = torch.randn(shape, device=device)575 B = torch.randn(shape, device=device)
576 out = compiled_fn(A, B)576 out = compiled_fn(A, B)
577 self.assertTrue(torch.allclose(out, A + B))577 self.assertTrue(torch.allclose(out, A + B))
578 578
579 579 
580 compile_count = torch._inductor.metrics.generated_kernel_count580 compile_count = torch._inductor.metrics.generated_kernel_count
581 581
582 # 获取 Inductor 编译的总次数(生成的 kernel 数量相关)582 # 获取 Inductor 编译的总次数(生成的 kernel 数量相关)
583 print(f"\n[结果] Inductor 编译次数 (generated_kernel_count): {compile_count}")583 print(f"\n[结果] Inductor 编译次数 (generated_kernel_count): {compile_count}")
584 584 
585 # 如果动态形状分档生效,编译次数应为 2585 # 如果动态形状分档生效,编译次数应为 2
586 self.assertEqual(compile_count, 2)586 self.assertEqual(compile_count, 2)
587 587 
588 def test_npu_dynamic_shape_reuse_with_symbolic_shape(self):588 def test_npu_dynamic_shape_reuse_with_symbolic_shape(self):
589 589
590 compiled_fn = torch.compile(590 compiled_fn = torch.compile(
591 model_fn, 591 model_fn,
592 backend='inductor', 592 backend='inductor',
593 dynamic=True,593 dynamic=True,
594 )594 )
595 595 
596 # 运行不同形状,验证是否只触发 1 次编译596 # 运行不同形状,验证是否只触发 1 次编译
597 test_shapes = [(3, 32), (4, 32), (5, 32), (6, 32)]597 test_shapes = [(3, 32), (4, 32), (5, 32), (6, 32)]
598 598
599 if hasattr(torch._inductor.metrics.generated_kernel_count, 'reset'):599 if hasattr(torch._inductor.metrics.generated_kernel_count, 'reset'):
600 torch._inductor.metrics.generated_kernel_count.reset()600 torch._inductor.metrics.generated_kernel_count.reset()
601 else:601 else:
602 torch._inductor.metrics.generated_kernel_count = 0602 torch._inductor.metrics.generated_kernel_count = 0
603 603 
604 for shape in test_shapes:604 for shape in test_shapes:
605 A = torch.randn(shape, device=device)605 A = torch.randn(shape, device=device)
606 B = torch.randn(shape, device=device)606 B = torch.randn(shape, device=device)
607 out = compiled_fn(A, B)607 out = compiled_fn(A, B)
608 self.assertTrue(torch.allclose(out, A + B))608 self.assertTrue(torch.allclose(out, A + B))
609 609 
610 compile_count = torch._inductor.metrics.generated_kernel_count610 compile_count = torch._inductor.metrics.generated_kernel_count
611 611 
612 612 
613 613 
614 # 获取 Inductor 编译的总次数(生成的 kernel 数量相关)614 # 获取 Inductor 编译的总次数(生成的 kernel 数量相关)
615 print(f"\n[结果] Inductor 编译次数 (generated_kernel_count): {compile_count}")615 print(f"\n[结果] Inductor 编译次数 (generated_kernel_count): {compile_count}")
616 616 
617 # 如果动态形状符号化生效,编译次数应为 1617 # 如果动态形状符号化生效,编译次数应为 1
618 self.assertEqual(compile_count, 1)618 self.assertEqual(compile_count, 1)
619 619
620 def test_npu_dynamic_shape_reuse_with_symbolic_shape_and_bucket(self):620 def test_npu_dynamic_shape_reuse_with_symbolic_shape_and_bucket(self):
621 621
622 compiled_fn = torch.compile(622 compiled_fn = torch.compile(
623 model_fn, 623 model_fn,
624 backend='inductor', 624 backend='inductor',
625 dynamic=True,625 dynamic=True,
626 options=shape_options626 options=shape_options
627 )627 )
628 628 
629 # 运行不同形状,验证是否只触发 1 次编译629 # 运行不同形状,验证是否只触发 1 次编译
630 test_shapes = [(3, 32), (4, 32), (5, 32), (6, 32)]630 test_shapes = [(3, 32), (4, 32), (5, 32), (6, 32)]
631 631
632 if hasattr(torch._inductor.metrics.generated_kernel_count, 'reset'):632 if hasattr(torch._inductor.metrics.generated_kernel_count, 'reset'):
633 torch._inductor.metrics.generated_kernel_count.reset()633 torch._inductor.metrics.generated_kernel_count.reset()
634 else:634 else:
635 torch._inductor.metrics.generated_kernel_count = 0635 torch._inductor.metrics.generated_kernel_count = 0
636 636 
637 for shape in test_shapes:637 for shape in test_shapes:
638 A = torch.randn(shape, device=device)638 A = torch.randn(shape, device=device)
639 B = torch.randn(shape, device=device)639 B = torch.randn(shape, device=device)
640 out = compiled_fn(A, B)640 out = compiled_fn(A, B)
641 self.assertTrue(torch.allclose(out, A + B))641 self.assertTrue(torch.allclose(out, A + B))
642 642 
643 compile_count = torch._inductor.metrics.generated_kernel_count643 compile_count = torch._inductor.metrics.generated_kernel_count
644 644 
645 645
646 # 获取 Inductor 编译的总次数(生成的 kernel 数量相关)646 # 获取 Inductor 编译的总次数(生成的 kernel 数量相关)
647 print(f"\n[结果] Inductor 编译次数 (generated_kernel_count): {compile_count}")647 print(f"\n[结果] Inductor 编译次数 (generated_kernel_count): {compile_count}")
648 648 
649 # 如果动态形状符号化生效,编译次数应为 1649 # 如果动态形状符号化生效,编译次数应为 1
650 self.assertEqual(compile_count, 1)650 self.assertEqual(compile_count, 1)
651 651
652 def test_npu_invalid_shape_options_key_error(self):652 def test_npu_invalid_shape_options_key_error(self):
653 653 
654 # 构造一个非法的配置:最小尺寸大于最大尺寸654 # 构造一个非法的配置:最小尺寸大于最大尺寸
655 invalid_shape_options = {655 invalid_shape_options = {
656 "enable_shape_handling": True,656 "enable_shape_handling": True,
657 "shape_handling_configs": [657 "shape_handling_configs": [
658 {658 {
659 "type": "BATCHSIZE",659 "type": "BATCHSIZE",
660 "min_size": 1024, # 错误:min > max660 "min_size": 1024, # 错误:min > max
661 "max_size": 1,661 "max_size": 1,
662 "policy": "TIMES",662 "policy": "TIMES",
663 }663 }
664 ]664 ]
665 }665 }
666 666 
667 # 尝试编译,预期抛出 ValueError 或相关配置错误667 # 尝试编译,预期抛出 ValueError 或相关配置错误
668 # 注意:有些错误可能在编译阶段 (compile) 触发,有些可能在首次运行 (call) 时触发668 # 注意:有些错误可能在编译阶段 (compile) 触发,有些可能在首次运行 (call) 时触发
669 try:669 try:
670 compiled_fn = torch.compile(670 compiled_fn = torch.compile(
671 model_fn, 671 model_fn,
672 backend='inductor', 672 backend='inductor',
673 dynamic=False,673 dynamic=False,
674 options=invalid_shape_options674 options=invalid_shape_options
675 )675 )
676 676
677 # 准备输入数据触发编译677 # 准备输入数据触发编译
678 A = torch.randn((2, 32), device=device)678 A = torch.randn((2, 32), device=device)
679 B = torch.randn((2, 32), device=device)679 B = torch.randn((2, 32), device=device)
680 680
681 with self.assertRaises((ValueError, RuntimeError, TypeError)) as cm:681 with self.assertRaises((ValueError, RuntimeError, TypeError)) as cm:
682 compiled_fn(A, B)682 compiled_fn(A, B)
683 683
684 print(f"\n[成功捕获异常]: {cm.exception}")684 print(f"\n[成功捕获异常]: {cm.exception}")
685 685
686 except Exception as e:686 except Exception as e:
687 # 如果在 torch.compile 阶段就直接崩溃,也算捕获成功687 # 如果在 torch.compile 阶段就直接崩溃,也算捕获成功
688 print(f"\n[编译阶段直接报错]: {e}")688 print(f"\n[编译阶段直接报错]: {e}")
689 self.assertIsInstance(e, (ValueError, RuntimeError, TypeError))689 self.assertIsInstance(e, (ValueError, RuntimeError, TypeError))
690 690 
691 def test_npu_malformed_option_type(self):691 def test_npu_malformed_option_type(self):
692 692
693 # 构造格式完全错误的 options693 # 构造格式完全错误的 options
694 malformed_options = {694 malformed_options = {
695 "shape_handling_configs": "this should be a list, not a string"695 "shape_handling_configs": "this should be a list, not a string"
696 }696 }
697 697 
698 with self.assertRaises(Exception):698 with self.assertRaises(Exception):
699 compiled_fn = torch.compile(model_fn, options=malformed_options)699 compiled_fn = torch.compile(model_fn, options=malformed_options)
700 compiled_fn(torch.randn(2, device="npu"), torch.randn(2, device="npu"))700 compiled_fn(torch.randn(2, device="npu"), torch.randn(2, device="npu"))
701 701 
702 def test_npu_shape_options_with_handling_disabled(self):702 def test_npu_shape_options_with_handling_disabled(self):
703 # enable_shape_handling 设置为False, 同时保留主流的配置选项,测试是否会存在选项异常报错703 # enable_shape_handling 设置为False, 同时保留主流的配置选项,测试是否会存在选项异常报错
704 704
705 705 
706 shape_options_off = {706 shape_options_off = {
707 "enable_shape_handling": False,707 "enable_shape_handling": False,
708 "shape_handling_configs": [708 "shape_handling_configs": [
709 {709 {
710 "type": "BATCHSIZE",710 "type": "BATCHSIZE",
711 "min_size": 1,711 "min_size": 1,
712 "max_size": 1024,712 "max_size": 1024,
713 "policy": "TIMES",713 "policy": "TIMES",
714 }714 }
715 ]715 ]
716 }716 }
717 717 
718 # 尝试编译,预期可正确处理此类配置,则通过测试718 # 尝试编译,预期可正确处理此类配置,则通过测试
719 try:719 try:
720 compiled_fn = torch.compile(720 compiled_fn = torch.compile(
721 model_fn, 721 model_fn,
722 backend='inductor', 722 backend='inductor',
723 dynamic=False,723 dynamic=False,
724 options=shape_options_off724 options=shape_options_off
725 )725 )
726 726
727 # 准备输入数据触发编译727 # 准备输入数据触发编译
728 A = torch.randn((2, 32), device=device)728 A = torch.randn((2, 32), device=device)
729 B = torch.randn((2, 32), device=device)729 B = torch.randn((2, 32), device=device)
730 compiled_fn(A, B)730 compiled_fn(A, B)
731 731 
732 except Exception as e:732 except Exception as e:
733 self.fail(f"torch.compile raised {type(e).__name__} unexpectedly: {e}")733 self.fail(f"torch.compile raised {type(e).__name__} unexpectedly: {e}")
734 734 
735 def test_npu_shape_handling_whit_mutil_compile(self):735 def test_npu_shape_handling_whit_mutil_compile(self):
736 # 多次编译同一个函数,验证 shape handling 是否正常工作736 # 多次编译同一个函数,验证 shape handling 是否正常工作
737 # 1. 首次编译触发 shape handling737 # 1. 首次编译触发 shape handling
738 # 2. 后续编译复用已有的 shape handling 逻辑738 # 2. 后续编译复用已有的 shape handling 逻辑
739 try:739 try:
740 compiled_fn = torch.compile(740 compiled_fn = torch.compile(
741 model_fn, 741 model_fn,
742 backend='inductor', 742 backend='inductor',
743 dynamic=False, 743 dynamic=False,
744 options=shape_options744 options=shape_options
745 )745 )
746 # 第一次spilt746 # 第一次spilt
747 compiled_fn(torch.randn((1025, 32), device=device), torch.randn((1025, 32), device=device))747 compiled_fn(torch.randn((1025, 32), device=device), torch.randn((1025, 32), device=device))
748 748 
749 # 第二次spilt749 # 第二次spilt
750 compiled_fn(torch.randn((2048, 32), device=device), torch.randn((2048, 32), device=device))750 compiled_fn(torch.randn((2048, 32), device=device), torch.randn((2048, 32), device=device))
751 751 
752 # 第三次spilt752 # 第三次spilt
753 compiled_fn(torch.randn((10240, 32), device=device), torch.randn((10240, 32), device=device))753 compiled_fn(torch.randn((10240, 32), device=device), torch.randn((10240, 32), device=device))
754 except Exception as e:754 except Exception as e:
755 self.fail(f"torch.compile raised {type(e).__name__} unexpectedly: ")755 self.fail(f"torch.compile raised {type(e).__name__} unexpectedly: ")
756 756 
757 757 
758class TestUnifiedCopy(TestCase):758class TestUnifiedCopy(TestCase):
759 def test_none_and_simple_types(self):759 def test_none_and_simple_types(self):
760 """Test unified_copy with None, list, dict, and tuple."""760 """Test unified_copy with None, list, dict, and tuple."""
761 # None761 # None
762 self.assertIsNone(unified_copy(None))762 self.assertIsNone(unified_copy(None))
763 763 
764 # list764 # list
765 lst = [1, 2, 3]765 lst = [1, 2, 3]
766 copied_lst = unified_copy(lst)766 copied_lst = unified_copy(lst)
767 self.assertEqual(lst, copied_lst)767 self.assertEqual(lst, copied_lst)
768 self.assertIsNot(lst, copied_lst)768 self.assertIsNot(lst, copied_lst)
769 769 
770 # dict770 # dict
771 d = {"a": 1, "b": [2, 3]}771 d = {"a": 1, "b": [2, 3]}
772 copied_d = unified_copy(d)772 copied_d = unified_copy(d)
773 self.assertEqual(d, copied_d)773 self.assertEqual(d, copied_d)
774 self.assertIsNot(d, copied_d)774 self.assertIsNot(d, copied_d)
775 775 
776 # tuple776 # tuple
777 t = (1, [2, 3])777 t = (1, [2, 3])
778 copied_t = unified_copy(t)778 copied_t = unified_copy(t)
779 self.assertEqual(t, copied_t)779 self.assertEqual(t, copied_t)
780 self.assertIsInstance(copied_t, tuple)780 self.assertIsInstance(copied_t, tuple)
781 781 
782 def test_nested_structure_with_tensor(self):782 def test_nested_structure_with_tensor(self):
783 """Test nested structure containing NPU tensor."""783 """Test nested structure containing NPU tensor."""
784 original = {784 original = {
785 "data": [torch.tensor([1.0, 2.0]), 42],785 "data": [torch.tensor([1.0, 2.0]), 42],
786 "meta": {"shape": (2,)}786 "meta": {"shape": (2,)}
787 }787 }
788 copied = unified_copy(original)788 copied = unified_copy(original)
789 789 
790 # 结构和值一致790 # 结构和值一致
791 self.assertEqual(original["meta"], copied["meta"])791 self.assertEqual(original["meta"], copied["meta"])
792 self.assertTrue(torch.equal(original["data"][0], copied["data"][0]))792 self.assertTrue(torch.equal(original["data"][0], copied["data"][0]))
793 self.assertEqual(original["data"][1], copied["data"][1])793 self.assertEqual(original["data"][1], copied["data"][1])
794 794 
795 # 验证独立副本795 # 验证独立副本
796 original["data"][0][0] = 888.0796 original["data"][0][0] = 888.0
797 self.assertNotEqual(copied["data"][0][0].item(), 888.0)797 self.assertNotEqual(copied["data"][0][0].item(), 888.0)
798 798 
799 799 
800 def test_deepcopy_failure_returns_original(self):800 def test_deepcopy_failure_returns_original(self):
801 class NonCopyable:801 class NonCopyable:
802 def __deepcopy__(self, memo):802 def __deepcopy__(self, memo):
803 raise TypeError("deepcopy not supported")803 raise TypeError("deepcopy not supported")
804 804 
805 obj = NonCopyable()805 obj = NonCopyable()
806 copied = unified_copy(obj)806 copied = unified_copy(obj)
807 self.assertIs(copied, obj)807 self.assertIs(copied, obj)
808 808 
809 809 
810instantiate_parametrized_tests(TestShapeHandling)810instantiate_parametrized_tests(TestShapeHandling)
811instantiate_parametrized_tests(TestShapeHandlingBranchCoverage)811instantiate_parametrized_tests(TestShapeHandlingBranchCoverage)
812instantiate_parametrized_tests(TestUnifiedCopy)812instantiate_parametrized_tests(TestUnifiedCopy)
813instantiate_parametrized_tests(TestDynamicShapeCompile)813instantiate_parametrized_tests(TestDynamicShapeCompile)
814 814
815if __name__ == '__main__':815if __name__ == '__main__':
816 run_tests()816 run_tests()
Mtest/_inductor/test_tile_generator_32b_alignment.py+96-96
@@ -1,97 +1,97 @@
1import torch1import torch
2from torch.testing._internal.common_utils import run_tests2from torch.testing._internal.common_utils import run_tests
3from testutils import TestUtils3from testutils import TestUtils
4 4 
5from torch_npu._inductor.codegen.tile_generator import TileGenerator, aligned_numel_32byte5from torch_npu._inductor.codegen.tile_generator import TileGenerator, aligned_numel_32byte
6from torch_npu._inductor.codegen.triton_utils import NPUKernelType6from torch_npu._inductor.codegen.triton_utils import NPUKernelType
7 7 
8 8 
9class TestTileGenerator32ByteAlignment(TestUtils):9class TestTileGenerator32ByteAlignment(TestUtils):
10 """10 """
11 Test class for TileGenerator 32Byte alignment functionality11 Test class for TileGenerator 32Byte alignment functionality
12 """12 """
13 13 
14 def test_32byte_alignment(self):14 def test_32byte_alignment(self):
15 """15 """
16 Test that block_size and sub_block_size are 32Byte aligned16 Test that block_size and sub_block_size are 32Byte aligned
17 """17 """
18 # Test with different data types18 # Test with different data types
19 dtypes = [torch.float32, torch.float16, torch.bfloat16, torch.int32]19 dtypes = [torch.float32, torch.float16, torch.bfloat16, torch.int32]
20 test_cases = [20 test_cases = [
21 # (numels, axis_names, tiling_axis, no_loop_axis, split_axis, low_dims)21 # (numels, axis_names, tiling_axis, no_loop_axis, split_axis, low_dims)
22 ((1024, 512), ["h", "w"], [0, 1], [], [0, 1], []),22 ((1024, 512), ["h", "w"], [0, 1], [], [0, 1], []),
23 ((2048, 2048), ["h", "w"], [0, 1], [], [0, 1], []),23 ((2048, 2048), ["h", "w"], [0, 1], [], [0, 1], []),
24 ((100, 200), ["h", "w"], [0, 1], [], [0, 1], []), # Non-power-of-2 sizes24 ((100, 200), ["h", "w"], [0, 1], [], [0, 1], []), # Non-power-of-2 sizes
25 ]25 ]
26 26 
27 for dtype in dtypes:27 for dtype in dtypes:
28 for numels, axis_names, tiling_axis, no_loop_axis, split_axis, low_dims in test_cases:28 for numels, axis_names, tiling_axis, no_loop_axis, split_axis, low_dims in test_cases:
29 # Create TileGenerator instance29 # Create TileGenerator instance
30 tile_gen = TileGenerator(30 tile_gen = TileGenerator(
31 numels=numels,31 numels=numels,
32 axis_names=axis_names,32 axis_names=axis_names,
33 tiling_axis=tiling_axis,33 tiling_axis=tiling_axis,
34 no_loop_axis=no_loop_axis,34 no_loop_axis=no_loop_axis,
35 split_axis=split_axis,35 split_axis=split_axis,
36 low_dims=low_dims,36 low_dims=low_dims,
37 persistent_reduction=False,37 persistent_reduction=False,
38 dtype=dtype,38 dtype=dtype,
39 npu_kernel_type=NPUKernelType.SIMD39 npu_kernel_type=NPUKernelType.SIMD
40 )40 )
41 41 
42 # Generate configs42 # Generate configs
43 configs = tile_gen.descend_split_tiling()43 configs = tile_gen.descend_split_tiling()
44 44 
45 # Check each config for 32Byte alignment45 # Check each config for 32Byte alignment
46 for cfg in configs:46 for cfg in configs:
47 kwargs = cfg.kwargs47 kwargs = cfg.kwargs
48 dtype_bytes = torch.tensor([], dtype=dtype).element_size()48 dtype_bytes = torch.tensor([], dtype=dtype).element_size()
49 min_numel = 32 // dtype_bytes49 min_numel = 32 // dtype_bytes
50 50 
51 # Check split axis block sizes51 # Check split axis block sizes
52 for axis in split_axis:52 for axis in split_axis:
53 block_name = f"{axis_names[axis].upper()}BLOCK"53 block_name = f"{axis_names[axis].upper()}BLOCK"
54 if block_name in kwargs:54 if block_name in kwargs:
55 block_size = kwargs[block_name]55 block_size = kwargs[block_name]
56 if block_size > min_numel:56 if block_size > min_numel:
57 self.assertEqual(block_size % min_numel, 0, 57 self.assertEqual(block_size % min_numel, 0,
58 msg=f"Block size {block_size} for {block_name} "58 msg=f"Block size {block_size} for {block_name} "
59 f"with dtype {dtype} is not 32Byte aligned")59 f"with dtype {dtype} is not 32Byte aligned")
60 60 
61 # Check tiling axis sub-block sizes61 # Check tiling axis sub-block sizes
62 for axis in tiling_axis:62 for axis in tiling_axis:
63 sub_block_name = f"{axis_names[axis].upper()}BLOCK_SUB"63 sub_block_name = f"{axis_names[axis].upper()}BLOCK_SUB"
64 if sub_block_name in kwargs:64 if sub_block_name in kwargs:
65 sub_block_size = kwargs[sub_block_name]65 sub_block_size = kwargs[sub_block_name]
66 if sub_block_size > min_numel:66 if sub_block_size > min_numel:
67 self.assertEqual(sub_block_size % min_numel, 0, 67 self.assertEqual(sub_block_size % min_numel, 0,
68 msg=f"Sub-block size {sub_block_size} for {sub_block_name} "68 msg=f"Sub-block size {sub_block_size} for {sub_block_name} "
69 f"with dtype {dtype} is not 32Byte aligned")69 f"with dtype {dtype} is not 32Byte aligned")
70 70 
71 def test_aligned_numel_method(self):71 def test_aligned_numel_method(self):
72 """72 """
73 Test the aligned_numel_32byte method directly73 Test the aligned_numel_32byte method directly
74 """74 """
75 # Test with different data types75 # Test with different data types
76 test_cases = [76 test_cases = [
77 (torch.float32, 32, 32), # 32 elements = 128 bytes, already aligned77 (torch.float32, 32, 32), # 32 elements = 128 bytes, already aligned
78 (torch.float32, 33, 40), # 33 elements = 132 bytes, should align to 40 elements (160 bytes)78 (torch.float32, 33, 40), # 33 elements = 132 bytes, should align to 40 elements (160 bytes)
79 (torch.float16, 32, 32), # 32 elements = 64 bytes, already aligned79 (torch.float16, 32, 32), # 32 elements = 64 bytes, already aligned
80 (torch.float16, 33, 48), # 33 elements = 66 bytes, should align to 48 elements (96 bytes)80 (torch.float16, 33, 48), # 33 elements = 66 bytes, should align to 48 elements (96 bytes)
81 (torch.bfloat16, 32, 32), # 32 elements = 64 bytes, already aligned81 (torch.bfloat16, 32, 32), # 32 elements = 64 bytes, already aligned
82 (torch.bfloat16, 33, 48), # 33 elements = 66 bytes, should align to 48 elements (96 bytes)82 (torch.bfloat16, 33, 48), # 33 elements = 66 bytes, should align to 48 elements (96 bytes)
83 (torch.int32, 32, 32), # 32 elements = 128 bytes, already aligned83 (torch.int32, 32, 32), # 32 elements = 128 bytes, already aligned
84 (torch.int32, 33, 40), # 33 elements = 132 bytes, should align to 40 elements (160 bytes)84 (torch.int32, 33, 40), # 33 elements = 132 bytes, should align to 40 elements (160 bytes)
85 ]85 ]
86 86 
87 for dtype, input_numel, expected_numel in test_cases:87 for dtype, input_numel, expected_numel in test_cases:
88 # Get dtype_bytes for the test88 # Get dtype_bytes for the test
89 dtype_bytes = torch.tensor([], dtype=dtype).element_size()89 dtype_bytes = torch.tensor([], dtype=dtype).element_size()
90 result = aligned_numel_32byte(input_numel, dtype_bytes)90 result = aligned_numel_32byte(input_numel, dtype_bytes)
91 self.assertEqual(result, expected_numel, 91 self.assertEqual(result, expected_numel,
92 msg=f"aligned_numel_32byte({input_numel}) for {dtype} "92 msg=f"aligned_numel_32byte({input_numel}) for {dtype} "
93 f"returned {result}, expected {expected_numel}")93 f"returned {result}, expected {expected_numel}")
94 94
95 95
96if __name__ == "__main__":96if __name__ == "__main__":
97 run_tests()97 run_tests()
Mtest/_inductor/test_upcast_codegen.py+34-34
@@ -1,35 +1,35 @@
1import unittest1import unittest
2import torch2import torch
3 3 
4from testutils import TestUtils4from testutils import TestUtils
5from torch.testing._internal.common_utils import run_tests, parametrize, instantiate_parametrized_tests5from torch.testing._internal.common_utils import run_tests, parametrize, instantiate_parametrized_tests
6from torch._inductor import config6from torch._inductor import config
7from torch._inductor.utils import run_and_get_code7from torch._inductor.utils import run_and_get_code
8 8 
9import torch_npu9import torch_npu
10import torch_npu._inductor10import torch_npu._inductor
11 11 
12DEVICE = "npu"12DEVICE = "npu"
13 13 
14 14 
15class TestCodegenUpcastToFP32(TestUtils):15class TestCodegenUpcastToFP32(TestUtils):
16 @parametrize("dtype", [torch.float16, torch.bfloat16])16 @parametrize("dtype", [torch.float16, torch.bfloat16])
17 @parametrize("upcast_flag", [True, False])17 @parametrize("upcast_flag", [True, False])
18 def test_codegen_upcast_to_fp32_emits_cast(self, dtype, upcast_flag):18 def test_codegen_upcast_to_fp32_emits_cast(self, dtype, upcast_flag):
19 @torch.compile(backend="inductor")19 @torch.compile(backend="inductor")
20 def func(x):20 def func(x):
21 return torch.abs(x)21 return torch.abs(x)
22 22 
23 x = torch.randn((1024, 1024), device=DEVICE, dtype=dtype)23 x = torch.randn((1024, 1024), device=DEVICE, dtype=dtype)
24 24 
25 with config.patch("triton.codegen_upcast_to_fp32", upcast_flag):25 with config.patch("triton.codegen_upcast_to_fp32", upcast_flag):
26 opt_func = torch._dynamo.optimize("inductor")(func)26 opt_func = torch._dynamo.optimize("inductor")(func)
27 out, code = run_and_get_code(opt_func, x)27 out, code = run_and_get_code(opt_func, x)
28 28 
29 self.assertTrue(".to(tl.float32)" in code[0])29 self.assertTrue(".to(tl.float32)" in code[0])
30 self.assertEqual(func(x), opt_func(x))30 self.assertEqual(func(x), opt_func(x))
31 31 
32instantiate_parametrized_tests(TestCodegenUpcastToFP32)32instantiate_parametrized_tests(TestCodegenUpcastToFP32)
33 33 
34if __name__ == "__main__":34if __name__ == "__main__":
35 run_tests()35 run_tests()
Mtest/_inductor/test_use_static_kernel.py+49-49
@@ -1,50 +1,50 @@
1import unittest1import unittest
2import torch2import torch
3import torch_npu3import torch_npu
4 4 
5from torch.testing._internal.common_utils import (5from torch.testing._internal.common_utils import (
6 run_tests,6 run_tests,
7 parametrize,7 parametrize,
8 instantiate_parametrized_tests,8 instantiate_parametrized_tests,
9)9)
10from testutils import TestUtils10from testutils import TestUtils
11 11 
12 12 
13class TestInductorStaticKernel(TestUtils):13class TestInductorStaticKernel(TestUtils):
14 14 
15 def simple_op(self, x):15 def simple_op(self, x):
16 return torch.neg(x)16 return torch.neg(x)
17 17 
18 @parametrize("shape", [(1024, 1024), (4096,)])18 @parametrize("shape", [(1024, 1024), (4096,)])
19 @parametrize("dtype", [torch.float16, torch.float32])19 @parametrize("dtype", [torch.float16, torch.float32])
20 def test_inductor_static_kernel(self, shape, dtype):20 def test_inductor_static_kernel(self, shape, dtype):
21 device = "npu"21 device = "npu"
22 22 
23 x = torch.randn(shape, dtype=dtype, device=device)23 x = torch.randn(shape, dtype=dtype, device=device)
24 24 
25 ref = self.simple_op(x)25 ref = self.simple_op(x)
26 26 
27 torch._inductor.config.triton.cudagraph_trees = False27 torch._inductor.config.triton.cudagraph_trees = False
28 torch_npu.npu.aclnn._use_static_aclnn_kernel = True28 torch_npu.npu.aclnn._use_static_aclnn_kernel = True
29 29 
30 compiled_fn = torch.compile(30 compiled_fn = torch.compile(
31 self.simple_op,31 self.simple_op,
32 backend="inductor",32 backend="inductor",
33 dynamic=False33 dynamic=False
34 )34 )
35 35 
36 for _ in range(3):36 for _ in range(3):
37 compiled_fn(x)37 compiled_fn(x)
38 38 
39 torch.npu.synchronize()39 torch.npu.synchronize()
40 40 
41 out = compiled_fn(x)41 out = compiled_fn(x)
42 torch.npu.synchronize()42 torch.npu.synchronize()
43 43 
44 self.assertEqual(ref, out)44 self.assertEqual(ref, out)
45 45 
46instantiate_parametrized_tests(TestInductorStaticKernel)46instantiate_parametrized_tests(TestInductorStaticKernel)
47 47 
48if __name__ == "__main__":48if __name__ == "__main__":
49 torch.npu.config.allow_internal_format = False49 torch.npu.config.allow_internal_format = False
50 run_tests()50 run_tests()
Mtest/_inductor/testutils.py+0-1
@@ -73,4 +73,3 @@ class BenchmarkTestUtils(TestCase):
73 writer.writeheader()73 writer.writeheader()
74 74 
75 writer.writerow(perf_info)75 writer.writerow(perf_info)
76 
Mtest/autograd/test_autograd_fallback.py+30-30
@@ -1,30 +1,30 @@
1import torch1import torch
2from torch.testing._internal.common_utils import (2from torch.testing._internal.common_utils import (
3 run_tests,3 run_tests,
4 TestCase,4 TestCase,
5)5)
6import torch_npu6import torch_npu
7 7 
8class TestAutogradFallback(TestCase):8class TestAutogradFallback(TestCase):
9 9 
10 def test_pad_backward_warn(self):10 def test_pad_backward_warn(self):
11 11 
12 def _exec_npu_pad():12 def _exec_npu_pad():
13 npu_input = torch.randn(2, 3).npu()13 npu_input = torch.randn(2, 3).npu()
14 npu_input.requires_grad = True14 npu_input.requires_grad = True
15 pads = (1, 1, 1, 1)15 pads = (1, 1, 1, 1)
16 output = torch_npu.npu_pad(npu_input, pads)16 output = torch_npu.npu_pad(npu_input, pads)
17 output.backward(torch.ones_like(output))17 output.backward(torch.ones_like(output))
18 18 
19 # When set to "nothing," calling the reverse function directly causes an error.19 # When set to "nothing," calling the reverse function directly causes an error.
20 torch._C._set_autograd_fallback_mode("nothing")20 torch._C._set_autograd_fallback_mode("nothing")
21 with self.assertRaisesRegex(RuntimeError, "does not require grad"):21 with self.assertRaisesRegex(RuntimeError, "does not require grad"):
22 _exec_npu_pad()22 _exec_npu_pad()
23 23 
24 # When set to "warn," calling the print function emits a warning.24 # When set to "warn," calling the print function emits a warning.
25 torch._C._set_autograd_fallback_mode("warn")25 torch._C._set_autograd_fallback_mode("warn")
26 _exec_npu_pad()26 _exec_npu_pad()
27 27 
28 28 
29if __name__ == "__main__":29if __name__ == "__main__":
30 run_tests()30 run_tests()
Mtest/custom_ops/test_fast_gelu.py+41-41
@@ -1,41 +1,41 @@
1import numpy as np1import numpy as np
2import torch2import torch
3 3 
4import torch_npu4import torch_npu
5from torch_npu.testing.testcase import TestCase, run_tests5from torch_npu.testing.testcase import TestCase, run_tests
6from torch_npu.testing.common_utils import create_common_tensor6from torch_npu.testing.common_utils import create_common_tensor
7 7 
8 8 
9class TestFastGelu(TestCase):9class TestFastGelu(TestCase):
10 10 
11 def supported_op_exec(self, input1):11 def supported_op_exec(self, input1):
12 attr = 1.70212 attr = 1.702
13 attr_half = attr / 213 attr_half = attr / 2
14 abs_input1 = torch.abs(input1)14 abs_input1 = torch.abs(input1)
15 numerator = input1 * torch.exp((attr_half * input1) * (input1 - abs_input1))15 numerator = input1 * torch.exp((attr_half * input1) * (input1 - abs_input1))
16 denominator = 1.0 + torch.exp(- attr * abs_input1)16 denominator = 1.0 + torch.exp(- attr * abs_input1)
17 output = numerator / denominator17 output = numerator / denominator
18 return output.cpu().detach()18 return output.cpu().detach()
19 19 
20 def custom_op_exec(self, input1):20 def custom_op_exec(self, input1):
21 output = torch_npu.fast_gelu(input1)21 output = torch_npu.fast_gelu(input1)
22 return output.cpu().detach()22 return output.cpu().detach()
23 23 
24 def test_fast_gelu(self, device="npu"):24 def test_fast_gelu(self, device="npu"):
25 item = [np.float32, 0, [3, 16, 32]]25 item = [np.float32, 0, [3, 16, 32]]
26 _, npu_input = create_common_tensor(item, 0, 100)26 _, npu_input = create_common_tensor(item, 0, 100)
27 27 
28 supported_output = self.supported_op_exec(npu_input)28 supported_output = self.supported_op_exec(npu_input)
29 custom_output = self.custom_op_exec(npu_input)29 custom_output = self.custom_op_exec(npu_input)
30 self.assertRtolEqual(supported_output, custom_output)30 self.assertRtolEqual(supported_output, custom_output)
31 31 
32 def test_fast_gelu_input_arg(self):32 def test_fast_gelu_input_arg(self):
33 item = [np.float32, 0, [3, 16, 32]]33 item = [np.float32, 0, [3, 16, 32]]
34 _, npu_input = create_common_tensor(item, 0, 100)34 _, npu_input = create_common_tensor(item, 0, 100)
35 supported_output = self.supported_op_exec(npu_input)35 supported_output = self.supported_op_exec(npu_input)
36 custom_output = torch_npu.fast_gelu(input=npu_input)36 custom_output = torch_npu.fast_gelu(input=npu_input)
37 self.assertRtolEqual(supported_output, custom_output)37 self.assertRtolEqual(supported_output, custom_output)
38 38 
39 39 
40if __name__ == "__main__":40if __name__ == "__main__":
41 run_tests()41 run_tests()
Mtest/custom_ops/test_npu_confusion_transpose.py+35-35
@@ -1,35 +1,35 @@
1import numpy as np1import numpy as np
2import torch2import torch
3 3 
4import torch_npu4import torch_npu
5from torch_npu.testing.testcase import TestCase, run_tests5from torch_npu.testing.testcase import TestCase, run_tests
6from torch_npu.testing.common_utils import create_common_tensor6from torch_npu.testing.common_utils import create_common_tensor
7 7 
8 8 
9class TestConfusionTranspose(TestCase):9class TestConfusionTranspose(TestCase):
10 10 
11 def supported_op_exec(self, input1, perm, shape, transpose_first):11 def supported_op_exec(self, input1, perm, shape, transpose_first):
12 if transpose_first:12 if transpose_first:
13 output = input1.permute(*perm).contiguous().view(shape)13 output = input1.permute(*perm).contiguous().view(shape)
14 else:14 else:
15 output = input1.view(shape).permute(*perm)15 output = input1.view(shape).permute(*perm)
16 return output.cpu().detach()16 return output.cpu().detach()
17 17 
18 def custom_op_exec(self, input1, perm, shape, transpose_first):18 def custom_op_exec(self, input1, perm, shape, transpose_first):
19 output = torch_npu.npu_confusion_transpose(input1, perm, shape, transpose_first)19 output = torch_npu.npu_confusion_transpose(input1, perm, shape, transpose_first)
20 return output.cpu().detach()20 return output.cpu().detach()
21 21 
22 def test_npu_confusion_transpose(self, device="npu"):22 def test_npu_confusion_transpose(self, device="npu"):
23 item = [np.float32, 0, [1, 576, 2560]]23 item = [np.float32, 0, [1, 576, 2560]]
24 _, npu_input = create_common_tensor(item, 0, 100)24 _, npu_input = create_common_tensor(item, 0, 100)
25 perm = (0, 2, 1, 3)25 perm = (0, 2, 1, 3)
26 shape = [1, 576, 32, 80]26 shape = [1, 576, 32, 80]
27 transpose_first = False27 transpose_first = False
28 28 
29 supported_output = self.supported_op_exec(npu_input, perm, shape, transpose_first)29 supported_output = self.supported_op_exec(npu_input, perm, shape, transpose_first)
30 custom_output = self.custom_op_exec(npu_input, perm, shape, transpose_first)30 custom_output = self.custom_op_exec(npu_input, perm, shape, transpose_first)
31 self.assertRtolEqual(supported_output, custom_output)31 self.assertRtolEqual(supported_output, custom_output)
32 32 
33 33 
34if __name__ == "__main__":34if __name__ == "__main__":
35 run_tests()35 run_tests()
Mtest/custom_ops/test_npu_convolution.py+52-52
@@ -1,52 +1,52 @@
1#1#
2 2 
3import numpy as np3import numpy as np
4import torch4import torch
5 5 
6import torch_npu6import torch_npu
7from torch_npu.testing.testcase import TestCase, run_tests7from torch_npu.testing.testcase import TestCase, run_tests
8from torch_npu.testing.common_utils import create_common_tensor8from torch_npu.testing.common_utils import create_common_tensor
9 9 
10 10 
11class TestConvolution(TestCase):11class TestConvolution(TestCase):
12 12 
13 def supported_op_exec(self, input1, weight, bias, stride, padding, dilation, groups):13 def supported_op_exec(self, input1, weight, bias, stride, padding, dilation, groups):
14 dim = input1.dim()14 dim = input1.dim()
15 if dim == 4:15 if dim == 4:
16 output = torch.nn.functional.conv2d(input1, weight, bias, stride, padding, dilation, groups)16 output = torch.nn.functional.conv2d(input1, weight, bias, stride, padding, dilation, groups)
17 if dim == 5:17 if dim == 5:
18 is_dilated = False18 is_dilated = False
19 for d in dilation:19 for d in dilation:
20 is_dilated |= (d != 1)20 is_dilated |= (d != 1)
21 if groups == 1 and not is_dilated:21 if groups == 1 and not is_dilated:
22 kernel_size = weight.size()[2]22 kernel_size = weight.size()[2]
23 output = torch._C._nn.slow_conv3d(input1, weight, kernel_size, bias, stride, padding)23 output = torch._C._nn.slow_conv3d(input1, weight, kernel_size, bias, stride, padding)
24 else:24 else:
25 output = torch.nn.functional.conv3d(input1, weight, bias, stride, padding, dilation, groups)25 output = torch.nn.functional.conv3d(input1, weight, bias, stride, padding, dilation, groups)
26 return output.cpu().detach()26 return output.cpu().detach()
27 27 
28 def custom_op_exec(self, input1, weight, bias, stride, padding, dilation, groups):28 def custom_op_exec(self, input1, weight, bias, stride, padding, dilation, groups):
29 output = torch_npu.npu_convolution(input1, weight, bias, stride, padding, dilation, groups)29 output = torch_npu.npu_convolution(input1, weight, bias, stride, padding, dilation, groups)
30 return output.cpu().detach()30 return output.cpu().detach()
31 31 
32 def test_npu_convolution(self, device="npu"):32 def test_npu_convolution(self, device="npu"):
33 items = [[[np.float32, 0, [16, 128, 112, 112]], [np.float32, 0, [256, 128, 3, 3]], [np.float32, 2, [256]],33 items = [[[np.float32, 0, [16, 128, 112, 112]], [np.float32, 0, [256, 128, 3, 3]], [np.float32, 2, [256]],
34 [1, 1], [1, 1], [1, 1], 1],34 [1, 1], [1, 1], [1, 1], 1],
35 [[np.float16, 30, [1, 128, 4, 14, 14]], [np.float16, 30, [1, 128, 3, 3, 3]], None,35 [[np.float16, 30, [1, 128, 4, 14, 14]], [np.float16, 30, [1, 128, 3, 3, 3]], None,
36 [1, 1, 1], [1, 1, 1], [1, 1, 1], 1]]36 [1, 1, 1], [1, 1, 1], [1, 1, 1], 1]]
37 for item in items:37 for item in items:
38 _, npu_input = create_common_tensor(item[0], -1, 1)38 _, npu_input = create_common_tensor(item[0], -1, 1)
39 _, weight = create_common_tensor(item[1], -1, 1)39 _, weight = create_common_tensor(item[1], -1, 1)
40 _, bias = create_common_tensor(item[2], -1, 1) if item[2] else _, None40 _, bias = create_common_tensor(item[2], -1, 1) if item[2] else _, None
41 stride = item[3]41 stride = item[3]
42 padding = item[4]42 padding = item[4]
43 dilation = item[5]43 dilation = item[5]
44 groups = item[6]44 groups = item[6]
45 45 
46 supported_output = self.supported_op_exec(npu_input, weight, bias, stride, padding, dilation, groups)46 supported_output = self.supported_op_exec(npu_input, weight, bias, stride, padding, dilation, groups)
47 custom_output = self.custom_op_exec(npu_input, weight, bias, stride, padding, dilation, groups)47 custom_output = self.custom_op_exec(npu_input, weight, bias, stride, padding, dilation, groups)
48 self.assertRtolEqual(supported_output, custom_output)48 self.assertRtolEqual(supported_output, custom_output)
49 49 
50 50 
51if __name__ == "__main__":51if __name__ == "__main__":
52 run_tests()52 run_tests()
Mtest/custom_ops/test_npu_dtype_cast.py+50-50
@@ -1,50 +1,50 @@
1import numpy as np1import numpy as np
2import torch2import torch
3 3 
4import torch_npu4import torch_npu
5from torch_npu.testing.testcase import TestCase, run_tests5from torch_npu.testing.testcase import TestCase, run_tests
6from torch_npu.testing.common_utils import create_common_tensor6from torch_npu.testing.common_utils import create_common_tensor
7from torch_npu.testing.common_utils import SupportedDevices7from torch_npu.testing.common_utils import SupportedDevices
8 8 
9 9 
10class TestDtypeCast(TestCase):10class TestDtypeCast(TestCase):
11 11 
12 def supported_op_exec(self, input1, dst_dtype):12 def supported_op_exec(self, input1, dst_dtype):
13 output = input1.to(dst_dtype)13 output = input1.to(dst_dtype)
14 return output.cpu().detach()14 return output.cpu().detach()
15 15 
16 def custom_op_exec(self, input1, dst_dtype):16 def custom_op_exec(self, input1, dst_dtype):
17 output = torch_npu.npu_dtype_cast(input1, dst_dtype)17 output = torch_npu.npu_dtype_cast(input1, dst_dtype)
18 return output.cpu().detach()18 return output.cpu().detach()
19 19 
20 def test_npu_dtype_cast(self):20 def test_npu_dtype_cast(self):
21 item = [np.float32, 0, (64, 10)]21 item = [np.float32, 0, (64, 10)]
22 _, npu_input = create_common_tensor(item, -1, 1)22 _, npu_input = create_common_tensor(item, -1, 1)
23 dst_dtype = torch.float1623 dst_dtype = torch.float16
24 24 
25 supported_output = self.supported_op_exec(npu_input, dst_dtype)25 supported_output = self.supported_op_exec(npu_input, dst_dtype)
26 custom_output = self.custom_op_exec(npu_input, dst_dtype)26 custom_output = self.custom_op_exec(npu_input, dst_dtype)
27 self.assertRtolEqual(supported_output, custom_output)27 self.assertRtolEqual(supported_output, custom_output)
28 28 
29 def test_npu_dtype_cast_double_backward(self):29 def test_npu_dtype_cast_double_backward(self):
30 x = torch.randn(3, 3, requires_grad=True).to("npu")30 x = torch.randn(3, 3, requires_grad=True).to("npu")
31 y = torch_npu.npu_dtype_cast(x, torch.half)31 y = torch_npu.npu_dtype_cast(x, torch.half)
32 z = torch.autograd.grad(outputs=y, inputs=x, grad_outputs=torch.ones_like(y))32 z = torch.autograd.grad(outputs=y, inputs=x, grad_outputs=torch.ones_like(y))
33 self.assertIsNone(z[0].grad_fn)33 self.assertIsNone(z[0].grad_fn)
34 z = torch.autograd.grad(outputs=y, inputs=x, grad_outputs=torch.ones_like(y), create_graph=True)34 z = torch.autograd.grad(outputs=y, inputs=x, grad_outputs=torch.ones_like(y), create_graph=True)
35 self.assertIsNotNone(z[0].grad_fn)35 self.assertIsNotNone(z[0].grad_fn)
36 36 
37 @SupportedDevices(['Ascend910B'])37 @SupportedDevices(['Ascend910B'])
38 def test_npu_dtype_cast_complex(self):38 def test_npu_dtype_cast_complex(self):
39 x = torch.empty([2, 3], dtype=torch.complex64, device="npu")39 x = torch.empty([2, 3], dtype=torch.complex64, device="npu")
40 x.requires_grad_()40 x.requires_grad_()
41 y = torch_npu.npu_dtype_cast(x, torch.complex128)41 y = torch_npu.npu_dtype_cast(x, torch.complex128)
42 grad_fn = str(y.grad_fn)42 grad_fn = str(y.grad_fn)
43 self.assertTrue("NpuDtypeCastBackward" in grad_fn)43 self.assertTrue("NpuDtypeCastBackward" in grad_fn)
44 44
45 with self.assertRaisesRegex(RuntimeError, r'grad can be implicitly created'):45 with self.assertRaisesRegex(RuntimeError, r'grad can be implicitly created'):
46 y.sum().backward()46 y.sum().backward()
47 47 
48 48 
49if __name__ == "__main__":49if __name__ == "__main__":
50 run_tests()50 run_tests()
Mtest/custom_ops/test_npu_format_cast.py+31-31
@@ -1,31 +1,31 @@
1import numpy as np1import numpy as np
2import torch2import torch
3 3 
4import torch_npu4import torch_npu
5from torch_npu.testing.testcase import TestCase, run_tests5from torch_npu.testing.testcase import TestCase, run_tests
6from torch_npu.testing.common_utils import create_common_tensor6from torch_npu.testing.common_utils import create_common_tensor
7 7 
8 8 
9class TestFormatCast(TestCase):9class TestFormatCast(TestCase):
10 10 
11 def supported_op_exec(self, input1):11 def supported_op_exec(self, input1):
12 m = torch.nn.Identity(54, unused_argument1=0.1, unused_argument2=False)12 m = torch.nn.Identity(54, unused_argument1=0.1, unused_argument2=False)
13 output = m(input1)13 output = m(input1)
14 return output.cpu().detach()14 return output.cpu().detach()
15 15 
16 def custom_op_exec(self, input1, acl_format):16 def custom_op_exec(self, input1, acl_format):
17 output = torch_npu.npu_format_cast(input1, acl_format)17 output = torch_npu.npu_format_cast(input1, acl_format)
18 return output.cpu().detach()18 return output.cpu().detach()
19 19 
20 def test_npu_format_cast(self, device="npu"):20 def test_npu_format_cast(self, device="npu"):
21 item = [np.float16, 0, (2, 2, 4, 4)]21 item = [np.float16, 0, (2, 2, 4, 4)]
22 _, npu_input = create_common_tensor(item, -1, 1)22 _, npu_input = create_common_tensor(item, -1, 1)
23 acl_format = 323 acl_format = 3
24 24 
25 supported_output = self.supported_op_exec(npu_input)25 supported_output = self.supported_op_exec(npu_input)
26 custom_output = self.custom_op_exec(npu_input, acl_format)26 custom_output = self.custom_op_exec(npu_input, acl_format)
27 self.assertRtolEqual(supported_output, custom_output)27 self.assertRtolEqual(supported_output, custom_output)
28 28 
29 29 
30if __name__ == "__main__":30if __name__ == "__main__":
31 run_tests()31 run_tests()
Mtest/custom_ops/test_npu_grid_assign_positive.py+44-44
@@ -1,44 +1,44 @@
1import torch1import torch
2 2 
3import torch_npu3import torch_npu
4from torch_npu.testing.testcase import TestCase, run_tests4from torch_npu.testing.testcase import TestCase, run_tests
5 5 
6 6 
7class TestGridAssignPositive(TestCase):7class TestGridAssignPositive(TestCase):
8 8 
9 def supported_op_exec(self, input1, box_responsible_flags, max_overlaps, argmax_overlaps, pos_iou_thr):9 def supported_op_exec(self, input1, box_responsible_flags, max_overlaps, argmax_overlaps, pos_iou_thr):
10 pos_inds = (max_overlaps > pos_iou_thr) & box_responsible_flags.type(torch.bool)10 pos_inds = (max_overlaps > pos_iou_thr) & box_responsible_flags.type(torch.bool)
11 argmax_overlaps = argmax_overlaps.to(input1.dtype)11 argmax_overlaps = argmax_overlaps.to(input1.dtype)
12 input1[pos_inds] = argmax_overlaps[pos_inds] + 112 input1[pos_inds] = argmax_overlaps[pos_inds] + 1
13 return input1.cpu().detach()13 return input1.cpu().detach()
14 14 
15 def custom_op_exec(self, input1, overlaps, box_responsible_flags, max_overlaps, argmax_overlaps,15 def custom_op_exec(self, input1, overlaps, box_responsible_flags, max_overlaps, argmax_overlaps,
16 gt_max_overlaps, gt_argmax_overlaps, num_gts, pos_iou_thr, min_pos_iou, gt_max_assign_all):16 gt_max_overlaps, gt_argmax_overlaps, num_gts, pos_iou_thr, min_pos_iou, gt_max_assign_all):
17 output = torch_npu.npu_grid_assign_positive(input1, overlaps, box_responsible_flags, max_overlaps,17 output = torch_npu.npu_grid_assign_positive(input1, overlaps, box_responsible_flags, max_overlaps,
18 argmax_overlaps, gt_max_overlaps, gt_argmax_overlaps, num_gts,18 argmax_overlaps, gt_max_overlaps, gt_argmax_overlaps, num_gts,
19 pos_iou_thr, min_pos_iou, gt_max_assign_all)19 pos_iou_thr, min_pos_iou, gt_max_assign_all)
20 return output.cpu().detach()20 return output.cpu().detach()
21 21 
22 def test_npu_grid_assign_positive(self):22 def test_npu_grid_assign_positive(self):
23 npu_input = torch.rand((4,), dtype=torch.float32).to("npu")23 npu_input = torch.rand((4,), dtype=torch.float32).to("npu")
24 overlaps = torch.rand((2, 4), dtype=torch.float32).to("npu")24 overlaps = torch.rand((2, 4), dtype=torch.float32).to("npu")
25 box_responsible_flags = torch.tensor([1, 1, 1, 0], dtype=torch.uint8).to("npu")25 box_responsible_flags = torch.tensor([1, 1, 1, 0], dtype=torch.uint8).to("npu")
26 max_overlaps = torch.rand((4,), dtype=torch.float32).to("npu")26 max_overlaps = torch.rand((4,), dtype=torch.float32).to("npu")
27 argmax_overlaps = torch.tensor([1, 0, 1, 0], dtype=torch.int32).to("npu")27 argmax_overlaps = torch.tensor([1, 0, 1, 0], dtype=torch.int32).to("npu")
28 gt_max_overlaps = torch.rand((2,), dtype=torch.float32).to("npu")28 gt_max_overlaps = torch.rand((2,), dtype=torch.float32).to("npu")
29 gt_argmax_overlaps = torch.tensor([1, 0], dtype=torch.int32).to("npu")29 gt_argmax_overlaps = torch.tensor([1, 0], dtype=torch.int32).to("npu")
30 num_gts = 12830 num_gts = 128
31 pos_iou_thr = .531 pos_iou_thr = .5
32 min_pos_iou = .032 min_pos_iou = .0
33 gt_max_assign_all = True33 gt_max_assign_all = True
34 34 
35 supported_output = self.supported_op_exec(npu_input, box_responsible_flags, max_overlaps,35 supported_output = self.supported_op_exec(npu_input, box_responsible_flags, max_overlaps,
36 argmax_overlaps, pos_iou_thr)36 argmax_overlaps, pos_iou_thr)
37 custom_output = self.custom_op_exec(npu_input, overlaps, box_responsible_flags, max_overlaps,37 custom_output = self.custom_op_exec(npu_input, overlaps, box_responsible_flags, max_overlaps,
38 argmax_overlaps, gt_max_overlaps, gt_argmax_overlaps, num_gts,38 argmax_overlaps, gt_max_overlaps, gt_argmax_overlaps, num_gts,
39 pos_iou_thr, min_pos_iou, gt_max_assign_all)39 pos_iou_thr, min_pos_iou, gt_max_assign_all)
40 self.assertRtolEqual(supported_output, custom_output)40 self.assertRtolEqual(supported_output, custom_output)
41 41 
42 42 
43if __name__ == "__main__":43if __name__ == "__main__":
44 run_tests()44 run_tests()
Mtest/custom_ops/test_npu_ps_roi_pooling.py+94-94
@@ -1,94 +1,94 @@
1import numpy as np1import numpy as np
2import torch2import torch
3 3 
4import torch_npu4import torch_npu
5from torch_npu.testing.testcase import TestCase, run_tests5from torch_npu.testing.testcase import TestCase, run_tests
6from torch_npu.testing.common_utils import create_common_tensor6from torch_npu.testing.common_utils import create_common_tensor
7 7 
8 8 
9class TestPSROIPooling(TestCase):9class TestPSROIPooling(TestCase):
10 10 
11 def cal_sum(self, hstart, hend, wstart, wend, image):11 def cal_sum(self, hstart, hend, wstart, wend, image):
12 out_sum = 0.012 out_sum = 0.0
13 for row in range(hstart, hend):13 for row in range(hstart, hend):
14 for col in range(wstart, wend):14 for col in range(wstart, wend):
15 out_sum += image[row][col]15 out_sum += image[row][col]
16 return out_sum16 return out_sum
17 17 
18 def supported_op_exec(self, input1, rois, spatial_scale, group_size, output_dim):18 def supported_op_exec(self, input1, rois, spatial_scale, group_size, output_dim):
19 dst_type = input1.dtype19 dst_type = input1.dtype
20 if dst_type != torch.float32:20 if dst_type != torch.float32:
21 input1 = input1.to(torch.float32)21 input1 = input1.to(torch.float32)
22 rois = rois.to(torch.float32)22 rois = rois.to(torch.float32)
23 23 
24 n, channels, height, width = input1.shape24 n, channels, height, width = input1.shape
25 tensor_height = torch.tensor([height]).npu()25 tensor_height = torch.tensor([height]).npu()
26 tensor_width = torch.tensor([width]).npu()26 tensor_width = torch.tensor([width]).npu()
27 tensor_zero = torch.tensor([0]).npu()27 tensor_zero = torch.tensor([0]).npu()
28 tensor_one_tenth = torch.tensor([0.1]).npu()28 tensor_one_tenth = torch.tensor([0.1]).npu()
29 29 
30 output_size = [rois.size(0) * rois.size(2), output_dim, group_size, group_size]30 output_size = [rois.size(0) * rois.size(2), output_dim, group_size, group_size]
31 rois = rois.transpose(2, 1)31 rois = rois.transpose(2, 1)
32 rois = torch.reshape(rois, (rois.shape[0] * rois.shape[1], rois.shape[2]))32 rois = torch.reshape(rois, (rois.shape[0] * rois.shape[1], rois.shape[2]))
33 output = torch.zeros(output_size).npu()33 output = torch.zeros(output_size).npu()
34 for out_n in range(output_size[0]):34 for out_n in range(output_size[0]):
35 for ctop in range(output_size[1]):35 for ctop in range(output_size[1]):
36 for ph in range(output_size[2]):36 for ph in range(output_size[2]):
37 for pw in range(output_size[3]):37 for pw in range(output_size[3]):
38 roi_batch_ind = rois[out_n][0].to(int)38 roi_batch_ind = rois[out_n][0].to(int)
39 roi_start_w = torch.round(rois[out_n][1]) * spatial_scale39 roi_start_w = torch.round(rois[out_n][1]) * spatial_scale
40 roi_start_h = torch.round(rois[out_n][2]) * spatial_scale40 roi_start_h = torch.round(rois[out_n][2]) * spatial_scale
41 roi_end_w = torch.round(rois[out_n][3] + 1.0) * spatial_scale41 roi_end_w = torch.round(rois[out_n][3] + 1.0) * spatial_scale
42 roi_end_h = torch.round(rois[out_n][4] + 1.0) * spatial_scale42 roi_end_h = torch.round(rois[out_n][4] + 1.0) * spatial_scale
43 # Force too small ROIs to be 1x143 # Force too small ROIs to be 1x1
44 roi_width = torch.max(roi_end_w - roi_start_w, tensor_one_tenth)44 roi_width = torch.max(roi_end_w - roi_start_w, tensor_one_tenth)
45 roi_height = torch.max(roi_end_h - roi_start_h, tensor_one_tenth)45 roi_height = torch.max(roi_end_h - roi_start_h, tensor_one_tenth)
46 # Compute w and h at bottom46 # Compute w and h at bottom
47 bin_size_h = roi_height / group_size47 bin_size_h = roi_height / group_size
48 bin_size_w = roi_width / group_size48 bin_size_w = roi_width / group_size
49 49 
50 # Add roi offsets and clip to input boundaries50 # Add roi offsets and clip to input boundaries
51 hstart = (ph * bin_size_h + roi_start_h).to(int)51 hstart = (ph * bin_size_h + roi_start_h).to(int)
52 wstart = torch.floor(pw * bin_size_w + roi_start_w).to(int)52 wstart = torch.floor(pw * bin_size_w + roi_start_w).to(int)
53 hend = torch.ceil((ph + 1) * bin_size_h + roi_start_h).to(int)53 hend = torch.ceil((ph + 1) * bin_size_h + roi_start_h).to(int)
54 wend = torch.ceil((pw + 1) * bin_size_w + roi_start_w).to(int)54 wend = torch.ceil((pw + 1) * bin_size_w + roi_start_w).to(int)
55 hstart = torch.min(torch.max(hstart, tensor_zero), tensor_height).to(int)55 hstart = torch.min(torch.max(hstart, tensor_zero), tensor_height).to(int)
56 hend = torch.min(torch.max(hend, tensor_zero), tensor_height).to(int)56 hend = torch.min(torch.max(hend, tensor_zero), tensor_height).to(int)
57 wstart = torch.min(torch.max(wstart, tensor_zero), tensor_width).to(int)57 wstart = torch.min(torch.max(wstart, tensor_zero), tensor_width).to(int)
58 wend = torch.min(torch.max(wend, tensor_zero), tensor_width).to(int)58 wend = torch.min(torch.max(wend, tensor_zero), tensor_width).to(int)
59 is_empty = ((hend <= hstart) or (wend <= wstart))59 is_empty = ((hend <= hstart) or (wend <= wstart))
60 c = (ctop * group_size + ph) * group_size + pw60 c = (ctop * group_size + ph) * group_size + pw
61 out_sum = self.cal_sum(hstart,61 out_sum = self.cal_sum(hstart,
62 hend,62 hend,
63 wstart,63 wstart,
64 wend,64 wend,
65 image=input1[roi_batch_ind][c])65 image=input1[roi_batch_ind][c])
66 bin_area = (hend - hstart) * (wend - wstart)66 bin_area = (hend - hstart) * (wend - wstart)
67 if is_empty:67 if is_empty:
68 output[out_n][ctop][ph][pw] = 0.068 output[out_n][ctop][ph][pw] = 0.0
69 else:69 else:
70 output[out_n][ctop][ph][pw] = out_sum / bin_area70 output[out_n][ctop][ph][pw] = out_sum / bin_area
71 71 
72 if dst_type != torch.float32:72 if dst_type != torch.float32:
73 output = output.to(dst_type)73 output = output.to(dst_type)
74 return output.cpu().detach()74 return output.cpu().detach()
75 75 
76 def custom_op_exec(self, input1, rois, spatial_scale, group_size, output_dim):76 def custom_op_exec(self, input1, rois, spatial_scale, group_size, output_dim):
77 output = torch_npu.npu_ps_roi_pooling(input1, rois, spatial_scale, group_size, output_dim)77 output = torch_npu.npu_ps_roi_pooling(input1, rois, spatial_scale, group_size, output_dim)
78 return output.cpu().detach()78 return output.cpu().detach()
79 79 
80 def test_npu_ps_roi_pooling(self, device="npu"):80 def test_npu_ps_roi_pooling(self, device="npu"):
81 item = [np.float32, 0, (2, 961, 127, 127)]81 item = [np.float32, 0, (2, 961, 127, 127)]
82 _, npu_input = create_common_tensor(item, 0.1, 1)82 _, npu_input = create_common_tensor(item, 0.1, 1)
83 rois = torch.tensor([[[0], [3], [2], [9], [9]], [[1], [1], [4], [9], [9]]], dtype=torch.float32).npu()83 rois = torch.tensor([[[0], [3], [2], [9], [9]], [[1], [1], [4], [9], [9]]], dtype=torch.float32).npu()
84 spatial_scale = 0.2584 spatial_scale = 0.25
85 group_size = 3185 group_size = 31
86 output_dim = 186 output_dim = 1
87 87 
88 supported_output = self.supported_op_exec(npu_input, rois, spatial_scale, group_size, output_dim)88 supported_output = self.supported_op_exec(npu_input, rois, spatial_scale, group_size, output_dim)
89 custom_output = self.custom_op_exec(npu_input, rois, spatial_scale, group_size, output_dim)89 custom_output = self.custom_op_exec(npu_input, rois, spatial_scale, group_size, output_dim)
90 self.assertRtolEqual(supported_output, custom_output)90 self.assertRtolEqual(supported_output, custom_output)
91 91 
92 92 
93if __name__ == "__main__":93if __name__ == "__main__":
94 run_tests()94 run_tests()
Mtest/custom_ops/test_npu_softmax_cross_entropy_with_logits.py+31-31
@@ -1,31 +1,31 @@
1import numpy as np1import numpy as np
2import torch2import torch
3 3 
4import torch_npu4import torch_npu
5from torch_npu.testing.testcase import TestCase, run_tests5from torch_npu.testing.testcase import TestCase, run_tests
6from torch_npu.testing.common_utils import create_common_tensor6from torch_npu.testing.common_utils import create_common_tensor
7 7 
8 8 
9class TestSoftmaxCrossEntropyWithLogits(TestCase):9class TestSoftmaxCrossEntropyWithLogits(TestCase):
10 10 
11 def supported_op_exec(self, input1, label):11 def supported_op_exec(self, input1, label):
12 softmax = torch.nn.functional.softmax(input1)12 softmax = torch.nn.functional.softmax(input1)
13 log_softmax = torch.log(softmax)13 log_softmax = torch.log(softmax)
14 loss = torch.sum(- label * log_softmax, dim=1)14 loss = torch.sum(- label * log_softmax, dim=1)
15 return loss.cpu().detach()15 return loss.cpu().detach()
16 16 
17 def custom_op_exec(self, input1, label):17 def custom_op_exec(self, input1, label):
18 output = torch_npu.npu_softmax_cross_entropy_with_logits(input1, label)18 output = torch_npu.npu_softmax_cross_entropy_with_logits(input1, label)
19 return output.cpu().detach()19 return output.cpu().detach()
20 20 
21 def test_npu_softmax_cross_entropy_with_logits(self, device="npu"):21 def test_npu_softmax_cross_entropy_with_logits(self, device="npu"):
22 item = [np.float32, 0, (64, 10)]22 item = [np.float32, 0, (64, 10)]
23 _, npu_input = create_common_tensor(item, -1, 1)23 _, npu_input = create_common_tensor(item, -1, 1)
24 _, label = create_common_tensor(item, 0, 1)24 _, label = create_common_tensor(item, 0, 1)
25 supported_output = self.supported_op_exec(npu_input, label)25 supported_output = self.supported_op_exec(npu_input, label)
26 custom_output = self.custom_op_exec(npu_input, label)26 custom_output = self.custom_op_exec(npu_input, label)
27 self.assertRtolEqual(supported_output, custom_output)27 self.assertRtolEqual(supported_output, custom_output)
28 28 
29 29 
30if __name__ == "__main__":30if __name__ == "__main__":
31 run_tests()31 run_tests()
Mtest/custom_ops/test_scatter_update.py+115-115
@@ -1,115 +1,115 @@
1import numpy as np1import numpy as np
2import torch2import torch
3 3 
4import torch_npu4import torch_npu
5from torch_npu.testing.testcase import TestCase, run_tests5from torch_npu.testing.testcase import TestCase, run_tests
6from torch_npu.testing.common_utils import create_common_tensor6from torch_npu.testing.common_utils import create_common_tensor
7 7 
8 8 
9class TestScatterUpdate(TestCase):9class TestScatterUpdate(TestCase):
10 10 
11 def supported_scatter_update_exec(self, var, updates, start, length, axis=-2):11 def supported_scatter_update_exec(self, var, updates, start, length, axis=-2):
12 var_input = var.clone()12 var_input = var.clone()
13 var_input[:, :, start: start + length, :] = updates13 var_input[:, :, start: start + length, :] = updates
14 return var_input14 return var_input
15 15 
16 def custom_scatter_update_exec(self, var, indices, updates, axis=-2):16 def custom_scatter_update_exec(self, var, indices, updates, axis=-2):
17 output = torch_npu.scatter_update(var, indices, updates, axis)17 output = torch_npu.scatter_update(var, indices, updates, axis)
18 return output.cpu().detach()18 return output.cpu().detach()
19 19 
20 20 
21 def supported_scatter_update__exec(self, var, updates, start, length, axis=-2):21 def supported_scatter_update__exec(self, var, updates, start, length, axis=-2):
22 var[:, :, start: start + length, :] = updates22 var[:, :, start: start + length, :] = updates
23 return var23 return var
24 24 
25 def custom_scatter_update__exec(self, var, indices, updates, axis=-2):25 def custom_scatter_update__exec(self, var, indices, updates, axis=-2):
26 torch_npu.scatter_update_(var, indices, updates, axis)26 torch_npu.scatter_update_(var, indices, updates, axis)
27 return var.cpu().detach()27 return var.cpu().detach()
28 28 
29 def custom_scatter_update__exec_return(self, var, indices, updates, axis=-2):29 def custom_scatter_update__exec_return(self, var, indices, updates, axis=-2):
30 result = torch_npu.scatter_update_(var, indices, updates, axis)30 result = torch_npu.scatter_update_(var, indices, updates, axis)
31 return result.cpu().detach()31 return result.cpu().detach()
32 32 
33 33 
34 def test_scatter_update(self, device="npu"):34 def test_scatter_update(self, device="npu"):
35 # input_dtype, slice_start, slice_length35 # input_dtype, slice_start, slice_length
36 items = [36 items = [
37 [torch.float16, 0, 1],37 [torch.float16, 0, 1],
38 [torch.float16, 2, 1],38 [torch.float16, 2, 1],
39 [torch.float16, 4, 8],39 [torch.float16, 4, 8],
40 [torch.float16, 0, 16],40 [torch.float16, 0, 16],
41 [torch.float32, 0, 1],41 [torch.float32, 0, 1],
42 [torch.float32, 2, 1],42 [torch.float32, 2, 1],
43 [torch.float32, 4, 8],43 [torch.float32, 4, 8],
44 [torch.float32, 0, 16],44 [torch.float32, 0, 16],
45 ]45 ]
46 46 
47 for item in items:47 for item in items:
48 in_self_cpu = torch.randn(4, 8, 16, 64, dtype=item[0])48 in_self_cpu = torch.randn(4, 8, 16, 64, dtype=item[0])
49 in_self_npu = in_self_cpu.npu()49 in_self_npu = in_self_cpu.npu()
50 in_update_cpu = torch.randn(4, 8, item[2], 64, dtype=item[0])50 in_update_cpu = torch.randn(4, 8, item[2], 64, dtype=item[0])
51 in_update_npu = in_update_cpu.npu()51 in_update_npu = in_update_cpu.npu()
52 in_indices_npu = torch.tensor([item[1], item[1], item[1], item[1]]).npu()52 in_indices_npu = torch.tensor([item[1], item[1], item[1], item[1]]).npu()
53 53 
54 supported_output = self.supported_scatter_update_exec(in_self_cpu, in_update_cpu, item[1], item[2])54 supported_output = self.supported_scatter_update_exec(in_self_cpu, in_update_cpu, item[1], item[2])
55 custom_output = self.custom_scatter_update_exec(in_self_npu, in_indices_npu, in_update_npu)55 custom_output = self.custom_scatter_update_exec(in_self_npu, in_indices_npu, in_update_npu)
56 self.assertRtolEqual(supported_output, custom_output)56 self.assertRtolEqual(supported_output, custom_output)
57 # check whether the custom operator modifies the input_self57 # check whether the custom operator modifies the input_self
58 self.assertRtolEqual(in_self_cpu, in_self_npu.cpu().detach())58 self.assertRtolEqual(in_self_cpu, in_self_npu.cpu().detach())
59 59 
60 60 
61 def test_scatter_update_(self, device="npu"):61 def test_scatter_update_(self, device="npu"):
62 # input_dtype, slice_start, slice_length62 # input_dtype, slice_start, slice_length
63 items = [63 items = [
64 [torch.float16, 0, 1],64 [torch.float16, 0, 1],
65 [torch.float16, 4, 1],65 [torch.float16, 4, 1],
66 [torch.float16, 8, 32],66 [torch.float16, 8, 32],
67 [torch.float16, 0, 64],67 [torch.float16, 0, 64],
68 [torch.float32, 0, 1],68 [torch.float32, 0, 1],
69 [torch.float32, 4, 1],69 [torch.float32, 4, 1],
70 [torch.float32, 8, 32],70 [torch.float32, 8, 32],
71 [torch.float32, 0, 64],71 [torch.float32, 0, 64],
72 ]72 ]
73 for item in items:73 for item in items:
74 in_self_cpu = torch.randn(4, 8, 64, 128, dtype=item[0])74 in_self_cpu = torch.randn(4, 8, 64, 128, dtype=item[0])
75 in_self_npu = in_self_cpu.npu()75 in_self_npu = in_self_cpu.npu()
76 in_update_cpu = torch.randn(4, 8, item[2], 128, dtype=item[0])76 in_update_cpu = torch.randn(4, 8, item[2], 128, dtype=item[0])
77 in_update_npu = in_update_cpu.npu()77 in_update_npu = in_update_cpu.npu()
78 in_indices_npu = torch.tensor([item[1], item[1], item[1], item[1]]).npu()78 in_indices_npu = torch.tensor([item[1], item[1], item[1], item[1]]).npu()
79 79 
80 supported_output = self.supported_scatter_update__exec(in_self_cpu, in_update_cpu, item[1], item[2])80 supported_output = self.supported_scatter_update__exec(in_self_cpu, in_update_cpu, item[1], item[2])
81 custom_output = self.custom_scatter_update__exec(in_self_npu, in_indices_npu, in_update_npu)81 custom_output = self.custom_scatter_update__exec(in_self_npu, in_indices_npu, in_update_npu)
82 self.assertRtolEqual(supported_output, custom_output)82 self.assertRtolEqual(supported_output, custom_output)
83 # check whether the custom operator modifies the input_self83 # check whether the custom operator modifies the input_self
84 self.assertRtolEqual(in_self_cpu, in_self_npu.cpu().detach())84 self.assertRtolEqual(in_self_cpu, in_self_npu.cpu().detach())
85 85 
86 86 
87 def test_scatter_update__return(self, device="npu"):87 def test_scatter_update__return(self, device="npu"):
88 # input_dtype, slice_start, slice_length88 # input_dtype, slice_start, slice_length
89 items = [89 items = [
90 [torch.float16, 0, 1],90 [torch.float16, 0, 1],
91 [torch.float16, 8, 1],91 [torch.float16, 8, 1],
92 [torch.float16, 16, 8],92 [torch.float16, 16, 8],
93 [torch.float16, 0, 32],93 [torch.float16, 0, 32],
94 [torch.float32, 0, 1],94 [torch.float32, 0, 1],
95 [torch.float32, 8, 1],95 [torch.float32, 8, 1],
96 [torch.float32, 16, 8],96 [torch.float32, 16, 8],
97 [torch.float32, 0, 32],97 [torch.float32, 0, 32],
98 ]98 ]
99 for item in items:99 for item in items:
100 in_self_cpu = torch.randn(12, 2, 64, 128, dtype=item[0])100 in_self_cpu = torch.randn(12, 2, 64, 128, dtype=item[0])
101 in_self_npu = in_self_cpu.npu()101 in_self_npu = in_self_cpu.npu()
102 in_update_cpu = torch.randn(12, 2, item[2], 128, dtype=item[0])102 in_update_cpu = torch.randn(12, 2, item[2], 128, dtype=item[0])
103 in_update_npu = in_update_cpu.npu()103 in_update_npu = in_update_cpu.npu()
104 in_indices_npu = torch.tensor([item[1], item[1], item[1], item[1], item[1], item[1],104 in_indices_npu = torch.tensor([item[1], item[1], item[1], item[1], item[1], item[1],
105 item[1], item[1], item[1], item[1], item[1], item[1]]).npu()105 item[1], item[1], item[1], item[1], item[1], item[1]]).npu()
106 106 
107 supported_output = self.supported_scatter_update__exec(in_self_cpu, in_update_cpu, item[1], item[2])107 supported_output = self.supported_scatter_update__exec(in_self_cpu, in_update_cpu, item[1], item[2])
108 custom_output = self.custom_scatter_update__exec(in_self_npu, in_indices_npu, in_update_npu)108 custom_output = self.custom_scatter_update__exec(in_self_npu, in_indices_npu, in_update_npu)
109 self.assertRtolEqual(supported_output, custom_output)109 self.assertRtolEqual(supported_output, custom_output)
110 # check whether the custom operator modifies the input_self110 # check whether the custom operator modifies the input_self
111 self.assertRtolEqual(in_self_cpu, in_self_npu.cpu().detach())111 self.assertRtolEqual(in_self_cpu, in_self_npu.cpu().detach())
112 112 
113 113 
114if __name__ == "__main__":114if __name__ == "__main__":
115 run_tests()115 run_tests()
Mtest/distributed/elastic/events/test_events_api.py+319-319
@@ -1,320 +1,320 @@
1"""1"""
2Add validation cases for torch.distributed.elastic.events.record API:2Add validation cases for torch.distributed.elastic.events.record API:
3 3 
41. PyTorch community lacks direct test cases for torch.distributed.elastic.events.record41. PyTorch community lacks direct test cases for torch.distributed.elastic.events.record
5 in the standard test suite, so this file is added.5 in the standard test suite, so this file is added.
6 6 
72. This file validates the following APIs:72. This file validates the following APIs:
8 torch.distributed.elastic.events.record (This is a pure Python-level event logging API with no hardware dependency.)8 torch.distributed.elastic.events.record (This is a pure Python-level event logging API with no hardware dependency.)
9 torch.distributed.elastic.events.api.EventMetadataValue (Type alias for metadata values)9 torch.distributed.elastic.events.api.EventMetadataValue (Type alias for metadata values)
10 (extendable)10 (extendable)
11"""11"""
12 12 
13import json13import json
14import time14import time
15from typing import Union, Optional, get_args, get_origin15from typing import Union, Optional, get_args, get_origin
16from unittest.mock import patch, MagicMock16from unittest.mock import patch, MagicMock
17 17 
18import torch18import torch
19from torch.distributed.elastic.events import record, get_logging_handler19from torch.distributed.elastic.events import record, get_logging_handler
20from torch.distributed.elastic.events.api import Event, EventSource, EventMetadataValue20from torch.distributed.elastic.events.api import Event, EventSource, EventMetadataValue
21from torch.testing._internal.common_utils import TestCase, run_tests21from torch.testing._internal.common_utils import TestCase, run_tests
22 22 
23 23 
24class TestEventsRecord(TestCase):24class TestEventsRecord(TestCase):
25 """Test torch.distributed.elastic.events.record method."""25 """Test torch.distributed.elastic.events.record method."""
26 26 
27 DESTINATION_NULL = "null"27 DESTINATION_NULL = "null"
28 DESTINATION_CONSOLE = "console"28 DESTINATION_CONSOLE = "console"
29 TEST_EVENT_PREFIX = "test_event_"29 TEST_EVENT_PREFIX = "test_event_"
30 30 
31 def tearDown(self):31 def tearDown(self):
32 """Clean up resources after each test case to ensure test isolation."""32 """Clean up resources after each test case to ensure test isolation."""
33 from torch.distributed.elastic.events import _events_loggers33 from torch.distributed.elastic.events import _events_loggers
34 _events_loggers.clear()34 _events_loggers.clear()
35 35 
36 if hasattr(get_logging_handler, "cache_clear"):36 if hasattr(get_logging_handler, "cache_clear"):
37 get_logging_handler.cache_clear()37 get_logging_handler.cache_clear()
38 38 
39 patch.stopall()39 patch.stopall()
40 super().tearDown()40 super().tearDown()
41 41 
42 def test_record_null_destination(self):42 def test_record_null_destination(self):
43 """Verify that record does not raise an exception when using the default null destination."""43 """Verify that record does not raise an exception when using the default null destination."""
44 event = Event(44 event = Event(
45 name=f"{self.TEST_EVENT_PREFIX}null",45 name=f"{self.TEST_EVENT_PREFIX}null",
46 source=EventSource.WORKER,46 source=EventSource.WORKER,
47 metadata={"key": "value"}47 metadata={"key": "value"}
48 )48 )
49 record(event)49 record(event)
50 50 
51 def test_record_console_destination(self):51 def test_record_console_destination(self):
52 """Verify that record does not raise an exception when using the console destination."""52 """Verify that record does not raise an exception when using the console destination."""
53 event = Event(53 event = Event(
54 name=f"{self.TEST_EVENT_PREFIX}console",54 name=f"{self.TEST_EVENT_PREFIX}console",
55 source=EventSource.AGENT,55 source=EventSource.AGENT,
56 metadata={"stage": "init"}56 metadata={"stage": "init"}
57 )57 )
58 record(event, destination=self.DESTINATION_CONSOLE)58 record(event, destination=self.DESTINATION_CONSOLE)
59 59 
60 def test_record_with_timestamp(self):60 def test_record_with_timestamp(self):
61 """Verify that record can correctly log an event with a custom or auto-generated timestamp."""61 """Verify that record can correctly log an event with a custom or auto-generated timestamp."""
62 custom_timestamp = int(time.time() * 1000)62 custom_timestamp = int(time.time() * 1000)
63 event = Event(63 event = Event(
64 name=f"{self.TEST_EVENT_PREFIX}timestamp_custom",64 name=f"{self.TEST_EVENT_PREFIX}timestamp_custom",
65 source=EventSource.WORKER,65 source=EventSource.WORKER,
66 timestamp=custom_timestamp,66 timestamp=custom_timestamp,
67 metadata={"ts": custom_timestamp}67 metadata={"ts": custom_timestamp}
68 )68 )
69 record(event, destination=self.DESTINATION_NULL)69 record(event, destination=self.DESTINATION_NULL)
70 self.assertEqual(event.timestamp, custom_timestamp)70 self.assertEqual(event.timestamp, custom_timestamp)
71 self.assertIsInstance(event.timestamp, int)71 self.assertIsInstance(event.timestamp, int)
72 self.assertGreaterEqual(event.timestamp, 0)72 self.assertGreaterEqual(event.timestamp, 0)
73 73 
74 event_with_auto_timestamp = Event(74 event_with_auto_timestamp = Event(
75 name=f"{self.TEST_EVENT_PREFIX}timestamp_auto",75 name=f"{self.TEST_EVENT_PREFIX}timestamp_auto",
76 source=EventSource.WORKER76 source=EventSource.WORKER
77 )77 )
78 record(event_with_auto_timestamp)78 record(event_with_auto_timestamp)
79 self.assertIsNotNone(event_with_auto_timestamp.timestamp)79 self.assertIsNotNone(event_with_auto_timestamp.timestamp)
80 self.assertIsInstance(event_with_auto_timestamp.timestamp, int)80 self.assertIsInstance(event_with_auto_timestamp.timestamp, int)
81 self.assertGreaterEqual(event_with_auto_timestamp.timestamp, 0)81 self.assertGreaterEqual(event_with_auto_timestamp.timestamp, 0)
82 82 
83 @patch("torch.distributed.elastic.events._get_or_create_logger")83 @patch("torch.distributed.elastic.events._get_or_create_logger")
84 def test_record_with_various_metadata_types(self, mock_get_logger):84 def test_record_with_various_metadata_types(self, mock_get_logger):
85 """Verify that record correctly passes various metadata types to the underlying logger."""85 """Verify that record correctly passes various metadata types to the underlying logger."""
86 mock_logger = MagicMock()86 mock_logger = MagicMock()
87 mock_get_logger.return_value = mock_logger87 mock_get_logger.return_value = mock_logger
88 88 
89 metadata = {89 metadata = {
90 "str_val": "hello",90 "str_val": "hello",
91 "int_val": 42,91 "int_val": 42,
92 "float_val": 3.14,92 "float_val": 3.14,
93 "bool_val": True,93 "bool_val": True,
94 "none_val": None,94 "none_val": None,
95 "list_val": [1, 2, 3],95 "list_val": [1, 2, 3],
96 "nested_dict": {"sub_key": "sub_val"}96 "nested_dict": {"sub_key": "sub_val"}
97 }97 }
98 event = Event(98 event = Event(
99 name=f"{self.TEST_EVENT_PREFIX}metadata_types",99 name=f"{self.TEST_EVENT_PREFIX}metadata_types",
100 source=EventSource.AGENT,100 source=EventSource.AGENT,
101 metadata=metadata101 metadata=metadata
102 )102 )
103 record(event, destination=self.DESTINATION_CONSOLE)103 record(event, destination=self.DESTINATION_CONSOLE)
104 104 
105 # Verify the internal call chain105 # Verify the internal call chain
106 mock_get_logger.assert_called_once_with(self.DESTINATION_CONSOLE)106 mock_get_logger.assert_called_once_with(self.DESTINATION_CONSOLE)
107 mock_logger.info.assert_called_once()107 mock_logger.info.assert_called_once()
108 108 
109 # Verify that the serialized metadata is correctly preserved109 # Verify that the serialized metadata is correctly preserved
110 logged_raw = mock_logger.info.call_args[0][0]110 logged_raw = mock_logger.info.call_args[0][0]
111 logged_data = json.loads(logged_raw)111 logged_data = json.loads(logged_raw)
112 self.assertEqual(logged_data["metadata"], metadata)112 self.assertEqual(logged_data["metadata"], metadata)
113 113 
114 def test_record_multiple_events(self):114 def test_record_multiple_events(self):
115 """Verify that consecutive calls to record do not interfere with each other."""115 """Verify that consecutive calls to record do not interfere with each other."""
116 event1 = Event(116 event1 = Event(
117 name=f"{self.TEST_EVENT_PREFIX}multiple_1",117 name=f"{self.TEST_EVENT_PREFIX}multiple_1",
118 source=EventSource.WORKER,118 source=EventSource.WORKER,
119 metadata={"seq": 1}119 metadata={"seq": 1}
120 )120 )
121 event2 = Event(121 event2 = Event(
122 name=f"{self.TEST_EVENT_PREFIX}multiple_2",122 name=f"{self.TEST_EVENT_PREFIX}multiple_2",
123 source=EventSource.WORKER,123 source=EventSource.WORKER,
124 metadata={"seq": 2}124 metadata={"seq": 2}
125 )125 )
126 126 
127 record(event1)127 record(event1)
128 record(event2)128 record(event2)
129 129 
130 self.assertIn("seq", event1.metadata)130 self.assertIn("seq", event1.metadata)
131 self.assertEqual(event1.metadata["seq"], 1)131 self.assertEqual(event1.metadata["seq"], 1)
132 self.assertIn("seq", event2.metadata)132 self.assertIn("seq", event2.metadata)
133 self.assertEqual(event2.metadata["seq"], 2)133 self.assertEqual(event2.metadata["seq"], 2)
134 134 
135 @patch("torch.distributed.elastic.events._get_or_create_logger")135 @patch("torch.distributed.elastic.events._get_or_create_logger")
136 def test_record_calls_get_or_create_logger(self, mock_get_logger):136 def test_record_calls_get_or_create_logger(self, mock_get_logger):
137 """137 """
138 Verify that record internally calls _get_or_create_logger to obtain the logger,138 Verify that record internally calls _get_or_create_logger to obtain the logger,
139 and then calls .info() on that logger with the serialized event.139 and then calls .info() on that logger with the serialized event.
140 """140 """
141 mock_logger = MagicMock()141 mock_logger = MagicMock()
142 mock_get_logger.return_value = mock_logger142 mock_get_logger.return_value = mock_logger
143 143 
144 event = Event(144 event = Event(
145 name=f"{self.TEST_EVENT_PREFIX}mock",145 name=f"{self.TEST_EVENT_PREFIX}mock",
146 source=EventSource.WORKER146 source=EventSource.WORKER
147 )147 )
148 record(event, destination=self.DESTINATION_CONSOLE)148 record(event, destination=self.DESTINATION_CONSOLE)
149 149 
150 mock_get_logger.assert_called_once_with(self.DESTINATION_CONSOLE)150 mock_get_logger.assert_called_once_with(self.DESTINATION_CONSOLE)
151 mock_logger.info.assert_called_once_with(event.serialize())151 mock_logger.info.assert_called_once_with(event.serialize())
152 152 
153 def test_record_event_name_empty(self):153 def test_record_event_name_empty(self):
154 """Verify that record does not raise an exception when the event name is an empty string."""154 """Verify that record does not raise an exception when the event name is an empty string."""
155 event = Event(name="", source=EventSource.WORKER)155 event = Event(name="", source=EventSource.WORKER)
156 record(event)156 record(event)
157 157 
158 def test_record_event_name_special_chars(self):158 def test_record_event_name_special_chars(self):
159 """Verify event names with special characters (spaces, symbols, unicode) are handled gracefully."""159 """Verify event names with special characters (spaces, symbols, unicode) are handled gracefully."""
160 special_names = ["test event", "test@event", "测试事件", "a" * 256]160 special_names = ["test event", "test@event", "测试事件", "a" * 256]
161 for name in special_names:161 for name in special_names:
162 with self.subTest(name=name):162 with self.subTest(name=name):
163 event = Event(name=name, source=EventSource.WORKER)163 event = Event(name=name, source=EventSource.WORKER)
164 record(event, destination=self.DESTINATION_NULL)164 record(event, destination=self.DESTINATION_NULL)
165 165 
166 def test_record_all_event_sources(self):166 def test_record_all_event_sources(self):
167 """Verify record compatibility with all EventSource enum values."""167 """Verify record compatibility with all EventSource enum values."""
168 for source in EventSource:168 for source in EventSource:
169 with self.subTest(source=source):169 with self.subTest(source=source):
170 event = Event(170 event = Event(
171 name=f"{self.TEST_EVENT_PREFIX}source_{source.name.lower()}",171 name=f"{self.TEST_EVENT_PREFIX}source_{source.name.lower()}",
172 source=source,172 source=source,
173 metadata={"source_type": source.name}173 metadata={"source_type": source.name}
174 )174 )
175 record(event)175 record(event)
176 self.assertEqual(event.source, source)176 self.assertEqual(event.source, source)
177 self.assertIn("source_type", event.metadata)177 self.assertIn("source_type", event.metadata)
178 self.assertEqual(event.metadata["source_type"], source.name)178 self.assertEqual(event.metadata["source_type"], source.name)
179 179 
180 180 
181class TestEventMetadataValue(TestCase):181class TestEventMetadataValue(TestCase):
182 """Test torch.distributed.elastic.events.api.EventMetadataValue type alias."""182 """Test torch.distributed.elastic.events.api.EventMetadataValue type alias."""
183 183 
184 def test_event_metadata_value_is_defined(self):184 def test_event_metadata_value_is_defined(self):
185 """Verify that EventMetadataValue is exported and defined."""185 """Verify that EventMetadataValue is exported and defined."""
186 self.assertIsNotNone(EventMetadataValue)186 self.assertIsNotNone(EventMetadataValue)
187 self.assertIs(get_origin(EventMetadataValue), Union)187 self.assertIs(get_origin(EventMetadataValue), Union)
188 188 
189 def test_event_metadata_value_type_structure(self):189 def test_event_metadata_value_type_structure(self):
190 """190 """
191 Verify that EventMetadataValue is a Union of str, int, float, bool, None.191 Verify that EventMetadataValue is a Union of str, int, float, bool, None.
192 Expected: Optional[Union[str, int, float, bool]]192 Expected: Optional[Union[str, int, float, bool]]
193 """193 """
194 origin = get_origin(EventMetadataValue)194 origin = get_origin(EventMetadataValue)
195 args = get_args(EventMetadataValue)195 args = get_args(EventMetadataValue)
196 196 
197 self.assertIs(origin, Union)197 self.assertIs(origin, Union)
198 self.assertIn(str, args)198 self.assertIn(str, args)
199 self.assertIn(int, args)199 self.assertIn(int, args)
200 self.assertIn(float, args)200 self.assertIn(float, args)
201 self.assertIn(bool, args)201 self.assertIn(bool, args)
202 self.assertIn(type(None), args)202 self.assertIn(type(None), args)
203 self.assertEqual(len(args), 5)203 self.assertEqual(len(args), 5)
204 204 
205 def test_event_metadata_value_legal_primitives(self):205 def test_event_metadata_value_legal_primitives(self):
206 """Verify that all legal primitive values are accepted by Event metadata."""206 """Verify that all legal primitive values are accepted by Event metadata."""
207 test_cases = [207 test_cases = [
208 ("string_val", "hello"),208 ("string_val", "hello"),
209 ("int_val", 42),209 ("int_val", 42),
210 ("int_val_neg", -7),210 ("int_val_neg", -7),
211 ("float_val", 3.14159),211 ("float_val", 3.14159),
212 ("float_val_zero", 0.0),212 ("float_val_zero", 0.0),
213 ("bool_true", True),213 ("bool_true", True),
214 ("bool_false", False),214 ("bool_false", False),
215 ("none_val", None),215 ("none_val", None),
216 ]216 ]
217 217 
218 for key, value in test_cases:218 for key, value in test_cases:
219 with self.subTest(key=key, value=value):219 with self.subTest(key=key, value=value):
220 event = Event(220 event = Event(
221 name=f"test_metadata_{key}",221 name=f"test_metadata_{key}",
222 source=EventSource.WORKER,222 source=EventSource.WORKER,
223 metadata={key: value}223 metadata={key: value}
224 )224 )
225 self.assertIn(key, event.metadata)225 self.assertIn(key, event.metadata)
226 self.assertEqual(event.metadata[key], value)226 self.assertEqual(event.metadata[key], value)
227 record(event, destination=TestEventsRecord.DESTINATION_NULL)227 record(event, destination=TestEventsRecord.DESTINATION_NULL)
228 228 
229 def test_event_metadata_value_none_explicit(self):229 def test_event_metadata_value_none_explicit(self):
230 """Verify that None is explicitly allowed as a metadata value."""230 """Verify that None is explicitly allowed as a metadata value."""
231 event = Event(231 event = Event(
232 name="test_metadata_none",232 name="test_metadata_none",
233 source=EventSource.AGENT,233 source=EventSource.AGENT,
234 metadata={"explicit_none": None}234 metadata={"explicit_none": None}
235 )235 )
236 self.assertIsNone(event.metadata["explicit_none"])236 self.assertIsNone(event.metadata["explicit_none"])
237 record(event, destination=TestEventsRecord.DESTINATION_NULL)237 record(event, destination=TestEventsRecord.DESTINATION_NULL)
238 238 
239 def test_event_metadata_value_mixed_dict(self):239 def test_event_metadata_value_mixed_dict(self):
240 """Verify that a metadata dict containing all legal types can be constructed and recorded."""240 """Verify that a metadata dict containing all legal types can be constructed and recorded."""
241 metadata = {241 metadata = {
242 "epoch": 10,242 "epoch": 10,
243 "loss": 0.1234,243 "loss": 0.1234,
244 "model_name": "resnet50",244 "model_name": "resnet50",
245 "is_training": True,245 "is_training": True,
246 "checkpoint_path": None,246 "checkpoint_path": None,
247 }247 }
248 event = Event(248 event = Event(
249 name="test_metadata_mixed",249 name="test_metadata_mixed",
250 source=EventSource.WORKER,250 source=EventSource.WORKER,
251 metadata=metadata251 metadata=metadata
252 )252 )
253 self.assertEqual(len(event.metadata), 5)253 self.assertEqual(len(event.metadata), 5)
254 record(event, destination=TestEventsRecord.DESTINATION_NULL)254 record(event, destination=TestEventsRecord.DESTINATION_NULL)
255 255 
256 def test_event_metadata_value_serialization_roundtrip(self):256 def test_event_metadata_value_serialization_roundtrip(self):
257 """257 """
258 Verify that metadata values survive the Event.serialize() roundtrip258 Verify that metadata values survive the Event.serialize() roundtrip
259 and remain as their original Python types.259 and remain as their original Python types.
260 """260 """
261 metadata = {261 metadata = {
262 "lr": 0.01,262 "lr": 0.01,
263 "step": 100,263 "step": 100,
264 "tag": "train",264 "tag": "train",
265 "enabled": False,265 "enabled": False,
266 "optional": None,266 "optional": None,
267 }267 }
268 event = Event(268 event = Event(
269 name="test_serialization",269 name="test_serialization",
270 source=EventSource.AGENT,270 source=EventSource.AGENT,
271 metadata=metadata271 metadata=metadata
272 )272 )
273 serialized = event.serialize()273 serialized = event.serialize()
274 274 
275 self.assertIsInstance(serialized, str)275 self.assertIsInstance(serialized, str)
276 data = json.loads(serialized)276 data = json.loads(serialized)
277 self.assertIn("metadata", data)277 self.assertIn("metadata", data)
278 278 
279 serialized_metadata = data["metadata"]279 serialized_metadata = data["metadata"]
280 self.assertEqual(serialized_metadata["lr"], 0.01)280 self.assertEqual(serialized_metadata["lr"], 0.01)
281 self.assertEqual(serialized_metadata["step"], 100)281 self.assertEqual(serialized_metadata["step"], 100)
282 self.assertEqual(serialized_metadata["tag"], "train")282 self.assertEqual(serialized_metadata["tag"], "train")
283 self.assertEqual(serialized_metadata["enabled"], False)283 self.assertEqual(serialized_metadata["enabled"], False)
284 self.assertIsNone(serialized_metadata["optional"])284 self.assertIsNone(serialized_metadata["optional"])
285 285 
286 def test_event_serialize_empty_metadata(self):286 def test_event_serialize_empty_metadata(self):
287 """Verify that empty metadata serializes correctly without data loss."""287 """Verify that empty metadata serializes correctly without data loss."""
288 event = Event(288 event = Event(
289 name="test_empty_metadata",289 name="test_empty_metadata",
290 source=EventSource.WORKER,290 source=EventSource.WORKER,
291 metadata={}291 metadata={}
292 )292 )
293 data = json.loads(event.serialize())293 data = json.loads(event.serialize())
294 self.assertEqual(data["metadata"], {})294 self.assertEqual(data["metadata"], {})
295 295 
296 def test_event_serialize_unsupported_metadata_type(self):296 def test_event_serialize_unsupported_metadata_type(self):
297 """297 """
298 Verify that unsupported metadata types (e.g. set, bytes) raise TypeError298 Verify that unsupported metadata types (e.g. set, bytes) raise TypeError
299 during serialization / record, since Event itself does not validate at construction time.299 during serialization / record, since Event itself does not validate at construction time.
300 """300 """
301 invalid_metadata_cases = [301 invalid_metadata_cases = [
302 ("set_val", {1, 2, 3}),302 ("set_val", {1, 2, 3}),
303 ("bytes_val", b"test"),303 ("bytes_val", b"test"),
304 ("object_val", MagicMock()),304 ("object_val", MagicMock()),
305 ]305 ]
306 306 
307 for key, value in invalid_metadata_cases:307 for key, value in invalid_metadata_cases:
308 with self.subTest(key=key):308 with self.subTest(key=key):
309 event = Event(309 event = Event(
310 name=f"test_invalid_{key}",310 name=f"test_invalid_{key}",
311 source=EventSource.WORKER,311 source=EventSource.WORKER,
312 metadata={key: value}312 metadata={key: value}
313 )313 )
314 # Event construction succeeds, but serialize/record should fail314 # Event construction succeeds, but serialize/record should fail
315 with self.assertRaises(TypeError):315 with self.assertRaises(TypeError):
316 event.serialize()316 event.serialize()
317 317 
318 318 
319if __name__ == "__main__":319if __name__ == "__main__":
320 run_tests()320 run_tests()
Mtest/distributed/rpc/multiprocessing/test_reduction_new.py+0-1
@@ -127,4 +127,3 @@ class TestReduction(TestCase):
127 127 
128if __name__ == "__main__":128if __name__ == "__main__":
129 run_tests()129 run_tests()
130 
Mtest/distributed/test_all_to_all_single.py+1-0
@@ -133,6 +133,7 @@ class HcclAlltoAllSingleTest(TestCase):
133 HcclAlltoAllSingleTest._test_alltoall_single_2p,133 HcclAlltoAllSingleTest._test_alltoall_single_2p,
134 HcclAlltoAllSingleTest._init_dist_hccl)134 HcclAlltoAllSingleTest._init_dist_hccl)
135 135 
136 @unittest.skip("Disabled during A1 to A2 chip transition")
136 @skipIfUnsupportMultiNPU(2)137 @skipIfUnsupportMultiNPU(2)
137 def test_alltoall_single_2p_size_dist(self):138 def test_alltoall_single_2p_size_dist(self):
138 self._test_multiprocess_2p(139 self._test_multiprocess_2p(
Mtest/distributed/test_device_mesh.py+1100-1100
@@ -1,1101 +1,1101 @@
1# Copyright (c) Meta Platforms, Inc. and affiliates1# Copyright (c) Meta Platforms, Inc. and affiliates
2# Owner(s): ["oncall: distributed"]2# Owner(s): ["oncall: distributed"]
3import os3import os
4 4 
5import torch5import torch
6import torch.distributed._functional_collectives as funcol6import torch.distributed._functional_collectives as funcol
7from torch.distributed._tensor import DTensor7from torch.distributed._tensor import DTensor
8from torch.distributed.device_mesh import _mesh_resources, DeviceMesh, init_device_mesh8from torch.distributed.device_mesh import _mesh_resources, DeviceMesh, init_device_mesh
9from torch.distributed.distributed_c10d import (9from torch.distributed.distributed_c10d import (
10 _get_default_group,10 _get_default_group,
11 _world,11 _world,
12 get_global_rank,12 get_global_rank,
13 get_world_size,13 get_world_size,
14 init_process_group,14 init_process_group,
15 is_initialized,15 is_initialized,
16 ProcessGroup,16 ProcessGroup,
17)17)
18from torch.distributed.tensor._collective_utils import (18from torch.distributed.tensor._collective_utils import (
19 mesh_broadcast,19 mesh_broadcast,
20 mesh_scatter,20 mesh_scatter,
21 unpad_tensor,21 unpad_tensor,
22)22)
23from torch.distributed.tensor.placement_types import _Partial, Shard23from torch.distributed.tensor.placement_types import _Partial, Shard
24from torch.testing._internal.distributed._tensor.common_dtensor import DTensorTestBase24from torch.testing._internal.distributed._tensor.common_dtensor import DTensorTestBase
25from torch.testing._internal.distributed.fake_pg import FakeStore25from torch.testing._internal.distributed.fake_pg import FakeStore
26 26 
27import torch_npu27import torch_npu
28from torch_npu.testing.common_distributed import with_comms, skipIfUnsupportMultiNPU28from torch_npu.testing.common_distributed import with_comms, skipIfUnsupportMultiNPU
29from torch_npu.testing.testcase import run_tests29from torch_npu.testing.testcase import run_tests
30 30 
31 31 
32def _get_device_type(world_size):32def _get_device_type(world_size):
33 if (33 if (
34 torch.npu.is_available()34 torch.npu.is_available()
35 and torch.npu.device_count() >= world_size35 and torch.npu.device_count() >= world_size
36 and torch.distributed.is_hccl_available()36 and torch.distributed.is_hccl_available()
37 ):37 ):
38 device_type = "npu"38 device_type = "npu"
39 else:39 else:
40 device_type = "cpu"40 device_type = "cpu"
41 return device_type41 return device_type
42 42 
43 43 
44def _set_env_var(addr="localhost", port="29500", world_size=1, rank=0):44def _set_env_var(addr="localhost", port="29500", world_size=1, rank=0):
45 os.environ["MASTER_ADDR"] = addr45 os.environ["MASTER_ADDR"] = addr
46 os.environ["MASTER_PORT"] = port46 os.environ["MASTER_PORT"] = port
47 os.environ["WORLD_SIZE"] = f"{world_size}"47 os.environ["WORLD_SIZE"] = f"{world_size}"
48 os.environ["RANK"] = f"{rank}"48 os.environ["RANK"] = f"{rank}"
49 49 
50 50 
51class DeviceMeshTest(DTensorTestBase):51class DeviceMeshTest(DTensorTestBase):
52 @property52 @property
53 def world_size(self):53 def world_size(self):
54 return 254 return 2
55 55 
56 @skipIfUnsupportMultiNPU(2)56 @skipIfUnsupportMultiNPU(2)
57 def test_init_process_group(self):57 def test_init_process_group(self):
58 device_type = _get_device_type(self.world_size)58 device_type = _get_device_type(self.world_size)
59 mesh_tensor = torch.arange(2).reshape(2, 1)59 mesh_tensor = torch.arange(2).reshape(2, 1)
60 self.assertTrue(not is_initialized())60 self.assertTrue(not is_initialized())
61 _set_env_var(world_size=self.world_size, rank=self.rank)61 _set_env_var(world_size=self.world_size, rank=self.rank)
62 DeviceMesh(device_type, mesh_tensor)62 DeviceMesh(device_type, mesh_tensor)
63 self.assertTrue(is_initialized())63 self.assertTrue(is_initialized())
64 self.destroy_pg()64 self.destroy_pg()
65 65 
66 @skipIfUnsupportMultiNPU(2)66 @skipIfUnsupportMultiNPU(2)
67 @with_comms67 @with_comms
68 def test_2d_mesh_non_eager_init_subgroup(self):68 def test_2d_mesh_non_eager_init_subgroup(self):
69 mesh_shape = (2, self.world_size // 2)69 mesh_shape = (2, self.world_size // 2)
70 mesh_2d = init_device_mesh(self.device_type, mesh_shape)70 mesh_2d = init_device_mesh(self.device_type, mesh_shape)
71 71 
72 self.assertEqual(mesh_2d.get_group(0).bound_device_id, None)72 self.assertEqual(mesh_2d.get_group(0).bound_device_id, None)
73 self.assertEqual(mesh_2d.get_group(1).bound_device_id, None)73 self.assertEqual(mesh_2d.get_group(1).bound_device_id, None)
74 74 
75 # need to refactor the other tests in this file to test both75 # need to refactor the other tests in this file to test both
76 # eager_init=True and eager_init=False scenarios.76 # eager_init=True and eager_init=False scenarios.
77 @skipIfUnsupportMultiNPU(2)77 @skipIfUnsupportMultiNPU(2)
78 @with_comms78 @with_comms
79 def test_2d_mesh_eager_init_subgroup(self):79 def test_2d_mesh_eager_init_subgroup(self):
80 # Test with eager_init=True80 # Test with eager_init=True
81 with self.subTest(eager_init=True):81 with self.subTest(eager_init=True):
82 mesh_shape = (2, self.world_size // 2)82 mesh_shape = (2, self.world_size // 2)
83 mesh_2d = init_device_mesh(self.device_type, mesh_shape)83 mesh_2d = init_device_mesh(self.device_type, mesh_shape)
84 84 
85 # when eager init is used, the subgroup is created from hccl comm split and85 # when eager init is used, the subgroup is created from hccl comm split and
86 # there would be bound_device_id immediately assigned for the subgroup.86 # there would be bound_device_id immediately assigned for the subgroup.
87 if self.backend == "hccl":87 if self.backend == "hccl":
88 curr_device = torch.npu.current_device()88 curr_device = torch.npu.current_device()
89 self.assertEqual(mesh_2d.get_group(0).bound_device_id.index, curr_device)89 self.assertEqual(mesh_2d.get_group(0).bound_device_id.index, curr_device)
90 self.assertEqual(mesh_2d.get_group(1).bound_device_id.index, curr_device)90 self.assertEqual(mesh_2d.get_group(1).bound_device_id.index, curr_device)
91 91 
92 # Test with eager_init=False92 # Test with eager_init=False
93 with self.subTest(eager_init=False):93 with self.subTest(eager_init=False):
94 mesh_shape = (2, self.world_size // 2)94 mesh_shape = (2, self.world_size // 2)
95 mesh_2d = init_device_mesh(self.device_type, mesh_shape)95 mesh_2d = init_device_mesh(self.device_type, mesh_shape)
96 96 
97 # when eager init is used, the subgroup is created from hccl comm split and97 # when eager init is used, the subgroup is created from hccl comm split and
98 # there would be bound_device_id immediately assigned for the subgroup.98 # there would be bound_device_id immediately assigned for the subgroup.
99 if self.backend == "hccl":99 if self.backend == "hccl":
100 curr_device = torch.npu.current_device()100 curr_device = torch.npu.current_device()
101 self.assertEqual(mesh_2d.get_group(0).bound_device_id.index, curr_device)101 self.assertEqual(mesh_2d.get_group(0).bound_device_id.index, curr_device)
102 self.assertEqual(mesh_2d.get_group(1).bound_device_id.index, curr_device)102 self.assertEqual(mesh_2d.get_group(1).bound_device_id.index, curr_device)
103 103 
104 @skipIfUnsupportMultiNPU(2)104 @skipIfUnsupportMultiNPU(2)
105 @with_comms105 @with_comms
106 def test_get_group_and_get_all_groups(self):106 def test_get_group_and_get_all_groups(self):
107 mesh_shape = (2, self.world_size // 2)107 mesh_shape = (2, self.world_size // 2)
108 mesh_2d = init_device_mesh(108 mesh_2d = init_device_mesh(
109 self.device_type, mesh_shape, mesh_dim_names=("dp", "tp")109 self.device_type, mesh_shape, mesh_dim_names=("dp", "tp")
110 )110 )
111 111 
112 tp_mesh = mesh_2d["tp"]112 tp_mesh = mesh_2d["tp"]
113 dp_mesh = mesh_2d["dp"]113 dp_mesh = mesh_2d["dp"]
114 114 
115 self.assertEqual(mesh_2d.get_group(0), mesh_2d.get_group("dp"))115 self.assertEqual(mesh_2d.get_group(0), mesh_2d.get_group("dp"))
116 self.assertEqual(mesh_2d.get_group(1), mesh_2d.get_group("tp"))116 self.assertEqual(mesh_2d.get_group(1), mesh_2d.get_group("tp"))
117 117 
118 self.assertEqual(mesh_2d.get_group("dp"), dp_mesh.get_group())118 self.assertEqual(mesh_2d.get_group("dp"), dp_mesh.get_group())
119 self.assertEqual(mesh_2d.get_group("tp"), tp_mesh.get_group())119 self.assertEqual(mesh_2d.get_group("tp"), tp_mesh.get_group())
120 120 
121 groups = mesh_2d.get_all_groups()121 groups = mesh_2d.get_all_groups()
122 self.assertEqual(len(groups), 2)122 self.assertEqual(len(groups), 2)
123 self.assertTrue(tp_mesh.get_group() in groups)123 self.assertTrue(tp_mesh.get_group() in groups)
124 self.assertTrue(dp_mesh.get_group() in groups)124 self.assertTrue(dp_mesh.get_group() in groups)
125 125 
126 @skipIfUnsupportMultiNPU(2)126 @skipIfUnsupportMultiNPU(2)
127 @with_comms127 @with_comms
128 def test_get_local_rank_raises_exception(self):128 def test_get_local_rank_raises_exception(self):
129 mesh_shape = (2, self.world_size // 2)129 mesh_shape = (2, self.world_size // 2)
130 mesh_2d = init_device_mesh(130 mesh_2d = init_device_mesh(
131 self.device_type, mesh_shape, mesh_dim_names=("dp", "tp")131 self.device_type, mesh_shape, mesh_dim_names=("dp", "tp")
132 )132 )
133 133 
134 with self.assertRaisesRegex(134 with self.assertRaisesRegex(
135 RuntimeError,135 RuntimeError,
136 "Optional kwarg `mesh_dim` needs to be specified when device_mesh.ndim > 1.",136 "Optional kwarg `mesh_dim` needs to be specified when device_mesh.ndim > 1.",
137 ):137 ):
138 mesh_2d.get_local_rank()138 mesh_2d.get_local_rank()
139 139 
140 @skipIfUnsupportMultiNPU(2)140 @skipIfUnsupportMultiNPU(2)
141 @with_comms141 @with_comms
142 def test_device_mesh_init_backend(self):142 def test_device_mesh_init_backend(self):
143 mesh = DeviceMesh(self.device_type, [1], _init_backend=False)143 mesh = DeviceMesh(self.device_type, [1], _init_backend=False)
144 144 
145 with self.assertRaisesRegex(RuntimeError, "process groups not initialized!"):145 with self.assertRaisesRegex(RuntimeError, "process groups not initialized!"):
146 mesh.get_group()146 mesh.get_group()
147 147 
148 # coordinates should always been populated when init_backend is False, as whenever148 # coordinates should always been populated when init_backend is False, as whenever
149 # we call init_backend we should make sure the default pg already created149 # we call init_backend we should make sure the default pg already created
150 mesh.get_coordinate()150 mesh.get_coordinate()
151 151 
152 @skipIfUnsupportMultiNPU(2)152 @skipIfUnsupportMultiNPU(2)
153 def test_fake_pg_device_mesh(self):153 def test_fake_pg_device_mesh(self):
154 fake_store = FakeStore()154 fake_store = FakeStore()
155 init_process_group("fake", store=fake_store, rank=0, world_size=self.world_size)155 init_process_group("fake", store=fake_store, rank=0, world_size=self.world_size)
156 device_type = "npu" if torch.npu.is_available() else "cpu"156 device_type = "npu" if torch.npu.is_available() else "cpu"
157 mesh = DeviceMesh(device_type, torch.arange(self.world_size))157 mesh = DeviceMesh(device_type, torch.arange(self.world_size))
158 158 
159 local_tensor = torch.randn(2, 8)159 local_tensor = torch.randn(2, 8)
160 global_tensor = funcol.all_gather_tensor(160 global_tensor = funcol.all_gather_tensor(
161 local_tensor, gather_dim=0, group=(mesh, 0)161 local_tensor, gather_dim=0, group=(mesh, 0)
162 )162 )
163 self.assertEqual(global_tensor.shape, (self.world_size * 2, 8))163 self.assertEqual(global_tensor.shape, (self.world_size * 2, 8))
164 164 
165 @skipIfUnsupportMultiNPU(2)165 @skipIfUnsupportMultiNPU(2)
166 @with_comms166 @with_comms
167 def test_from_group_with_global_pg(self):167 def test_from_group_with_global_pg(self):
168 # Simple test: check `from_group` from a mesh pg vs. directly168 # Simple test: check `from_group` from a mesh pg vs. directly
169 # initializing via `init_device_mesh`169 # initializing via `init_device_mesh`
170 ref_global_mesh = init_device_mesh(self.device_type, (self.world_size,))170 ref_global_mesh = init_device_mesh(self.device_type, (self.world_size,))
171 mesh_pg = ref_global_mesh.get_group()171 mesh_pg = ref_global_mesh.get_group()
172 global_mesh = DeviceMesh.from_group(mesh_pg, self.device_type)172 global_mesh = DeviceMesh.from_group(mesh_pg, self.device_type)
173 self.assertEqual(ref_global_mesh, global_mesh)173 self.assertEqual(ref_global_mesh, global_mesh)
174 self.assertEqual(ref_global_mesh._dim_group_infos, global_mesh._dim_group_infos)174 self.assertEqual(ref_global_mesh._dim_group_infos, global_mesh._dim_group_infos)
175 self.assertEqual(175 self.assertEqual(
176 ref_global_mesh._coordinate_on_dim, global_mesh._coordinate_on_dim176 ref_global_mesh._coordinate_on_dim, global_mesh._coordinate_on_dim
177 )177 )
178 # Check when `mesh` is passed as well178 # Check when `mesh` is passed as well
179 global_mesh = DeviceMesh.from_group(179 global_mesh = DeviceMesh.from_group(
180 mesh_pg, self.device_type, mesh=torch.arange(self.world_size)180 mesh_pg, self.device_type, mesh=torch.arange(self.world_size)
181 )181 )
182 self.assertEqual(ref_global_mesh, global_mesh)182 self.assertEqual(ref_global_mesh, global_mesh)
183 self.assertEqual(ref_global_mesh._dim_group_infos, global_mesh._dim_group_infos)183 self.assertEqual(ref_global_mesh._dim_group_infos, global_mesh._dim_group_infos)
184 self.assertEqual(184 self.assertEqual(
185 ref_global_mesh._coordinate_on_dim, global_mesh._coordinate_on_dim185 ref_global_mesh._coordinate_on_dim, global_mesh._coordinate_on_dim
186 )186 )
187 187 
188 @skipIfUnsupportMultiNPU(2)188 @skipIfUnsupportMultiNPU(2)
189 def test_raises_invalid_device_type(self):189 def test_raises_invalid_device_type(self):
190 with self.assertRaisesRegex(190 with self.assertRaisesRegex(
191 RuntimeError,191 RuntimeError,
192 "Device type with index is not supported",192 "Device type with index is not supported",
193 ):193 ):
194 # test init_device_mesh with an invalid device type that contains a NPU index194 # test init_device_mesh with an invalid device type that contains a NPU index
195 mesh_shape = (2, self.world_size // 2)195 mesh_shape = (2, self.world_size // 2)
196 mesh_2d = init_device_mesh(196 mesh_2d = init_device_mesh(
197 "npu:0", mesh_shape=mesh_shape, mesh_dim_names=("dp", "tp")197 "npu:0", mesh_shape=mesh_shape, mesh_dim_names=("dp", "tp")
198 )198 )
199 199 
200 @skipIfUnsupportMultiNPU(2)200 @skipIfUnsupportMultiNPU(2)
201 @with_comms201 @with_comms
202 def test_set_mesh_dim_group_options(self):202 def test_set_mesh_dim_group_options(self):
203 device_type = "npu" if torch.npu.is_available() else "cpu"203 device_type = "npu" if torch.npu.is_available() else "cpu"
204 _mesh_resources._set_mesh_dim_group_options(1, "fake", None)204 _mesh_resources._set_mesh_dim_group_options(1, "fake", None)
205 205 
206 mesh_tensor = torch.arange(2).reshape(2, 1)206 mesh_tensor = torch.arange(2).reshape(2, 1)
207 mesh = DeviceMesh(device_type, mesh_tensor)207 mesh = DeviceMesh(device_type, mesh_tensor)
208 # Fake pg only have BackendType as BackendType::CUSTOM.208 # Fake pg only have BackendType as BackendType::CUSTOM.
209 self.assertEqual(mesh.get_group(1)._get_backend_name(), "custom")209 self.assertEqual(mesh.get_group(1)._get_backend_name(), "custom")
210 210 
211 211 
212#DeviceMeshTest with resetting world_size to 4.212#DeviceMeshTest with resetting world_size to 4.
213class DeviceMeshTestF(DTensorTestBase):213class DeviceMeshTestF(DTensorTestBase):
214 @property214 @property
215 def world_size(self):215 def world_size(self):
216 return 4216 return 4
217 217 
218 @skipIfUnsupportMultiNPU(4)218 @skipIfUnsupportMultiNPU(4)
219 @with_comms219 @with_comms
220 def test_assert_invalid_mesh_tensor(self):220 def test_assert_invalid_mesh_tensor(self):
221 mesh = torch.arange(self.world_size).to(self.rank)221 mesh = torch.arange(self.world_size).to(self.rank)
222 with self.assertRaises(ValueError):222 with self.assertRaises(ValueError):
223 device_mesh = DeviceMesh(self.device_type, mesh)223 device_mesh = DeviceMesh(self.device_type, mesh)
224 224
225 @skipIfUnsupportMultiNPU(4)225 @skipIfUnsupportMultiNPU(4)
226 @with_comms226 @with_comms
227 def test_get_local_rank(self):227 def test_get_local_rank(self):
228 mesh_shape = (2, self.world_size // 2)228 mesh_shape = (2, self.world_size // 2)
229 mesh_2d = init_device_mesh(229 mesh_2d = init_device_mesh(
230 self.device_type, mesh_shape, mesh_dim_names=("dp", "tp")230 self.device_type, mesh_shape, mesh_dim_names=("dp", "tp")
231 )231 )
232 self.assertEqual(mesh_2d.get_local_rank("dp"), mesh_2d.get_local_rank(0))232 self.assertEqual(mesh_2d.get_local_rank("dp"), mesh_2d.get_local_rank(0))
233 self.assertEqual(mesh_2d.get_local_rank("tp"), mesh_2d.get_local_rank(1))233 self.assertEqual(mesh_2d.get_local_rank("tp"), mesh_2d.get_local_rank(1))
234 234 
235 dp_mesh = mesh_2d["dp"]235 dp_mesh = mesh_2d["dp"]
236 tp_mesh = mesh_2d["tp"]236 tp_mesh = mesh_2d["tp"]
237 self.assertEqual(dp_mesh.get_local_rank(), mesh_2d.get_local_rank("dp"))237 self.assertEqual(dp_mesh.get_local_rank(), mesh_2d.get_local_rank("dp"))
238 self.assertEqual(tp_mesh.get_local_rank(), mesh_2d.get_local_rank("tp"))238 self.assertEqual(tp_mesh.get_local_rank(), mesh_2d.get_local_rank("tp"))
239 239 
240 # Verify flattened mesh local rank correctness.240 # Verify flattened mesh local rank correctness.
241 flattened_mesh = mesh_2d["dp", "tp"]._flatten()241 flattened_mesh = mesh_2d["dp", "tp"]._flatten()
242 self.assertEqual(flattened_mesh.get_local_rank(), self.rank)242 self.assertEqual(flattened_mesh.get_local_rank(), self.rank)
243 243 
244 @skipIfUnsupportMultiNPU(4)244 @skipIfUnsupportMultiNPU(4)
245 @with_comms245 @with_comms
246 def test_device_mesh_2d(self):246 def test_device_mesh_2d(self):
247 mesh_tensor = torch.arange(4).reshape(2, 2)247 mesh_tensor = torch.arange(4).reshape(2, 2)
248 # construct a npu device mesh248 # construct a npu device mesh
249 mesh = DeviceMesh(self.device_type, mesh_tensor)249 mesh = DeviceMesh(self.device_type, mesh_tensor)
250 250 
251 # check all dim groups251 # check all dim groups
252 dim_to_subgroups = mesh.get_all_groups()252 dim_to_subgroups = mesh.get_all_groups()
253 253 
254 expected_ranks_by_dim = [[[0, 2], [1, 3]], [[0, 1], [2, 3]]]254 expected_ranks_by_dim = [[[0, 2], [1, 3]], [[0, 1], [2, 3]]]
255 for dim, dim_group in enumerate(dim_to_subgroups):255 for dim, dim_group in enumerate(dim_to_subgroups):
256 self.assertTrue(dim < 2)256 self.assertTrue(dim < 2)
257 dim_ranks = expected_ranks_by_dim[dim]257 dim_ranks = expected_ranks_by_dim[dim]
258 258 
259 dim_group_size = get_world_size(dim_group)259 dim_group_size = get_world_size(dim_group)
260 self.assertIsInstance(dim_group, ProcessGroup)260 self.assertIsInstance(dim_group, ProcessGroup)
261 self.assertEqual(dim_group_size, 2)261 self.assertEqual(dim_group_size, 2)
262 global_ranks = [262 global_ranks = [
263 get_global_rank(dim_group, i) for i in range(dim_group_size)263 get_global_rank(dim_group, i) for i in range(dim_group_size)
264 ]264 ]
265 current_rank_expected_group_ranks = (265 current_rank_expected_group_ranks = (
266 dim_ranks[0] if self.rank in dim_ranks[0] else dim_ranks[1]266 dim_ranks[0] if self.rank in dim_ranks[0] else dim_ranks[1]
267 )267 )
268 self.assertEqual(global_ranks, current_rank_expected_group_ranks)268 self.assertEqual(global_ranks, current_rank_expected_group_ranks)
269 269 
270 @skipIfUnsupportMultiNPU(4)270 @skipIfUnsupportMultiNPU(4)
271 @with_comms271 @with_comms
272 def test_from_group_with_invalid_mesh(self):272 def test_from_group_with_invalid_mesh(self):
273 global_pg = _get_default_group()273 global_pg = _get_default_group()
274 global_pg_size = global_pg.size()274 global_pg_size = global_pg.size()
275 assert global_pg_size == 4, "Test assumes global world size of 4"275 assert global_pg_size == 4, "Test assumes global world size of 4"
276 invalid_mesh = [[0, 1], [2, 3]] # 2D mesh when we need 1D276 invalid_mesh = [[0, 1], [2, 3]] # 2D mesh when we need 1D
277 regex = r"Invalid mesh \[\[0, 1\], \[2, 3\]\] for ProcessGroup with ranks \[0, 1, 2, 3\]"277 regex = r"Invalid mesh \[\[0, 1\], \[2, 3\]\] for ProcessGroup with ranks \[0, 1, 2, 3\]"
278 with self.assertRaisesRegex(ValueError, regex):278 with self.assertRaisesRegex(ValueError, regex):
279 DeviceMesh.from_group(279 DeviceMesh.from_group(
280 global_pg, "npu", invalid_mesh, mesh_dim_names=("dim0", "dim1")280 global_pg, "npu", invalid_mesh, mesh_dim_names=("dim0", "dim1")
281 )281 )
282 282 
283 device_mesh = init_device_mesh(self.device_type, (2, 2))283 device_mesh = init_device_mesh(self.device_type, (2, 2))
284 groups = device_mesh.get_all_groups()284 groups = device_mesh.get_all_groups()
285 invalid_mesh = (0, 1, 2, 3) # 1D mesh when we need 2D285 invalid_mesh = (0, 1, 2, 3) # 1D mesh when we need 2D
286 regex = r"Expects mesh with ndim equal to number of ProcessGroups but got mesh \[0, 1, 2, 3\] and 2 ProcessGroups"286 regex = r"Expects mesh with ndim equal to number of ProcessGroups but got mesh \[0, 1, 2, 3\] and 2 ProcessGroups"
287 with self.assertRaisesRegex(ValueError, regex):287 with self.assertRaisesRegex(ValueError, regex):
288 DeviceMesh.from_group(288 DeviceMesh.from_group(
289 groups, self.device_type, invalid_mesh, mesh_dim_names=("dim0", "dim1")289 groups, self.device_type, invalid_mesh, mesh_dim_names=("dim0", "dim1")
290 )290 )
291 291 
292 292 
293class DeviceMeshTestNDim(DTensorTestBase):293class DeviceMeshTestNDim(DTensorTestBase):
294 @property294 @property
295 def world_size(self):295 def world_size(self):
296 return 2296 return 2
297 297 
298 @skipIfUnsupportMultiNPU(2)298 @skipIfUnsupportMultiNPU(2)
299 @with_comms299 @with_comms
300 def test_device_mesh_parent_child_hash(self):300 def test_device_mesh_parent_child_hash(self):
301 mesh_2d = init_device_mesh(301 mesh_2d = init_device_mesh(
302 self.device_type, (2, self.world_size // 2), mesh_dim_names=("DP", "TP")302 self.device_type, (2, self.world_size // 2), mesh_dim_names=("DP", "TP")
303 )303 )
304 304 
305 mesh_group_1 = torch.arange(0, self.world_size // 2)305 mesh_group_1 = torch.arange(0, self.world_size // 2)
306 mesh_group_2 = torch.arange(self.world_size // 2, self.world_size)306 mesh_group_2 = torch.arange(self.world_size // 2, self.world_size)
307 ep_mesh_1 = DeviceMesh(self.device_type, mesh_group_1)307 ep_mesh_1 = DeviceMesh(self.device_type, mesh_group_1)
308 ep_mesh_2 = DeviceMesh(self.device_type, mesh_group_2)308 ep_mesh_2 = DeviceMesh(self.device_type, mesh_group_2)
309 ep_mesh = ep_mesh_1 if self.rank < self.world_size // 2 else ep_mesh_2309 ep_mesh = ep_mesh_1 if self.rank < self.world_size // 2 else ep_mesh_2
310 # ep_mesh is considered different from mesh_2d["TP"]310 # ep_mesh is considered different from mesh_2d["TP"]
311 self.assertEqual(mesh_2d["TP"]._flatten_mesh_list, ep_mesh._flatten_mesh_list)311 self.assertEqual(mesh_2d["TP"]._flatten_mesh_list, ep_mesh._flatten_mesh_list)
312 self.assertEqual(mesh_2d["TP"].mesh.shape, ep_mesh.mesh.shape)312 self.assertEqual(mesh_2d["TP"].mesh.shape, ep_mesh.mesh.shape)
313 self.assertEqual(mesh_2d["TP"].device_type, ep_mesh.device_type)313 self.assertEqual(mesh_2d["TP"].device_type, ep_mesh.device_type)
314 self.assertNotEqual(mesh_2d["TP"].mesh_dim_names, ep_mesh.mesh_dim_names)314 self.assertNotEqual(mesh_2d["TP"].mesh_dim_names, ep_mesh.mesh_dim_names)
315 self.assertEqual(mesh_2d["TP"]._thread_id, ep_mesh._thread_id)315 self.assertEqual(mesh_2d["TP"]._thread_id, ep_mesh._thread_id)
316 self.assertNotEqual(hash(mesh_2d["TP"]), hash(ep_mesh))316 self.assertNotEqual(hash(mesh_2d["TP"]), hash(ep_mesh))
317 self.assertNotEqual(mesh_2d["TP"], ep_mesh)317 self.assertNotEqual(mesh_2d["TP"], ep_mesh)
318 318 
319 another_mesh_1 = DeviceMesh(self.device_type, mesh_group_1)319 another_mesh_1 = DeviceMesh(self.device_type, mesh_group_1)
320 another_mesh_2 = DeviceMesh(self.device_type, mesh_group_2)320 another_mesh_2 = DeviceMesh(self.device_type, mesh_group_2)
321 another_mesh = (321 another_mesh = (
322 another_mesh_1 if self.rank < self.world_size // 2 else another_mesh_2322 another_mesh_1 if self.rank < self.world_size // 2 else another_mesh_2
323 )323 )
324 # another_mesh is considered the same as ep_mesh324 # another_mesh is considered the same as ep_mesh
325 self.assertEqual(ep_mesh._flatten_mesh_list, another_mesh._flatten_mesh_list)325 self.assertEqual(ep_mesh._flatten_mesh_list, another_mesh._flatten_mesh_list)
326 self.assertEqual(ep_mesh.mesh.shape, another_mesh.mesh.shape)326 self.assertEqual(ep_mesh.mesh.shape, another_mesh.mesh.shape)
327 self.assertEqual(ep_mesh.device_type, another_mesh.device_type)327 self.assertEqual(ep_mesh.device_type, another_mesh.device_type)
328 self.assertEqual(ep_mesh.mesh_dim_names, another_mesh.mesh_dim_names)328 self.assertEqual(ep_mesh.mesh_dim_names, another_mesh.mesh_dim_names)
329 self.assertEqual(ep_mesh._thread_id, another_mesh._thread_id)329 self.assertEqual(ep_mesh._thread_id, another_mesh._thread_id)
330 self.assertEqual(hash(ep_mesh), hash(another_mesh))330 self.assertEqual(hash(ep_mesh), hash(another_mesh))
331 self.assertEqual(ep_mesh, another_mesh)331 self.assertEqual(ep_mesh, another_mesh)
332 332 
333 333 
334#DeviceMeshTestNDim with resetting world_size to 8.334#DeviceMeshTestNDim with resetting world_size to 8.
335class DeviceMeshTestNDimE(DTensorTestBase):335class DeviceMeshTestNDimE(DTensorTestBase):
336 @property336 @property
337 def world_size(self):337 def world_size(self):
338 return 8338 return 8
339 339 
340 @skipIfUnsupportMultiNPU(8)340 @skipIfUnsupportMultiNPU(8)
341 @with_comms341 @with_comms
342 def test_device_mesh_nd(self):342 def test_device_mesh_nd(self):
343 # construct a npu device mesh343 # construct a npu device mesh
344 mesh_tensor = torch.arange(8).reshape(2, 2, 2)344 mesh_tensor = torch.arange(8).reshape(2, 2, 2)
345 mesh = DeviceMesh(self.device_type, mesh_tensor)345 mesh = DeviceMesh(self.device_type, mesh_tensor)
346 346 
347 # check all dim groups347 # check all dim groups
348 dim_to_subgroups = mesh.get_all_groups()348 dim_to_subgroups = mesh.get_all_groups()
349 349 
350 for dim, dim_group in enumerate(dim_to_subgroups):350 for dim, dim_group in enumerate(dim_to_subgroups):
351 self.assertTrue(dim < mesh_tensor.ndim)351 self.assertTrue(dim < mesh_tensor.ndim)
352 dim_ranks = mesh_tensor.swapdims(-1, dim).reshape(-1, 2)352 dim_ranks = mesh_tensor.swapdims(-1, dim).reshape(-1, 2)
353 353 
354 dim_group_size = get_world_size(dim_group)354 dim_group_size = get_world_size(dim_group)
355 self.assertIsInstance(dim_group, ProcessGroup)355 self.assertIsInstance(dim_group, ProcessGroup)
356 self.assertEqual(dim_group_size, 2)356 self.assertEqual(dim_group_size, 2)
357 global_ranks = [357 global_ranks = [
358 get_global_rank(dim_group, i) for i in range(dim_group_size)358 get_global_rank(dim_group, i) for i in range(dim_group_size)
359 ]359 ]
360 for ranks in dim_ranks:360 for ranks in dim_ranks:
361 if self.rank in ranks:361 if self.rank in ranks:
362 self.assertEqual(global_ranks, ranks.tolist())362 self.assertEqual(global_ranks, ranks.tolist())
363 363 
364 @skipIfUnsupportMultiNPU(8)364 @skipIfUnsupportMultiNPU(8)
365 @with_comms365 @with_comms
366 def test_device_mesh_hash(self):366 def test_device_mesh_hash(self):
367 mesh_tensor_2d = torch.arange(8).reshape(4, 2)367 mesh_tensor_2d = torch.arange(8).reshape(4, 2)
368 mesh = DeviceMesh(self.device_type, mesh_tensor_2d)368 mesh = DeviceMesh(self.device_type, mesh_tensor_2d)
369 mesh2 = DeviceMesh(self.device_type, mesh_tensor_2d)369 mesh2 = DeviceMesh(self.device_type, mesh_tensor_2d)
370 self.assertEqual(hash(mesh), hash(mesh2))370 self.assertEqual(hash(mesh), hash(mesh2))
371 mesh_tensor_3d = torch.arange(8).reshape(2, 2, 2)371 mesh_tensor_3d = torch.arange(8).reshape(2, 2, 2)
372 mesh3 = DeviceMesh(self.device_type, mesh_tensor_3d)372 mesh3 = DeviceMesh(self.device_type, mesh_tensor_3d)
373 self.assertNotEqual(hash(mesh), hash(mesh3))373 self.assertNotEqual(hash(mesh), hash(mesh3))
374 self.assertNotEqual(hash(mesh2), hash(mesh3))374 self.assertNotEqual(hash(mesh2), hash(mesh3))
375 375 
376 @skipIfUnsupportMultiNPU(8)376 @skipIfUnsupportMultiNPU(8)
377 @with_comms377 @with_comms
378 def test_get_local_rank_3d(self):378 def test_get_local_rank_3d(self):
379 """379 """
380 If we have a 3D mesh and we want to apply dp, pp, tp to it,380 If we have a 3D mesh and we want to apply dp, pp, tp to it,
381 mesh_dim_names = ["dp", "pp", "tp"], and the mesh tensor would be:381 mesh_dim_names = ["dp", "pp", "tp"], and the mesh tensor would be:
382 mesh_3d_tensor = [382 mesh_3d_tensor = [
383 [383 [
384 [0, 1],384 [0, 1],
385 [2, 3],385 [2, 3],
386 ],386 ],
387 [387 [
388 [4, 5],388 [4, 5],
389 [6, 7],389 [6, 7],
390 ]390 ]
391 391 
392 ]392 ]
393 """393 """
394 mesh_shape = (2, 2, 2)394 mesh_shape = (2, 2, 2)
395 mesh_3d = init_device_mesh(395 mesh_3d = init_device_mesh(
396 self.device_type, mesh_shape, mesh_dim_names=("dp", "pp", "tp")396 self.device_type, mesh_shape, mesh_dim_names=("dp", "pp", "tp")
397 )397 )
398 398 
399 # tp_rank_0: [0, 2, 4, 6], tp_rank_1: [1, 3, 5, 7]399 # tp_rank_0: [0, 2, 4, 6], tp_rank_1: [1, 3, 5, 7]
400 tp_rank = mesh_3d.get_local_rank("tp")400 tp_rank = mesh_3d.get_local_rank("tp")
401 expected_tp_rank = self.rank % 2401 expected_tp_rank = self.rank % 2
402 self.assertEqual(tp_rank, expected_tp_rank)402 self.assertEqual(tp_rank, expected_tp_rank)
403 403 
404 # pp_rank_0: [0, 1, 4, 5], pp_rank_1: [2, 3, 6, 7]404 # pp_rank_0: [0, 1, 4, 5], pp_rank_1: [2, 3, 6, 7]
405 pp_rank = mesh_3d.get_local_rank("pp")405 pp_rank = mesh_3d.get_local_rank("pp")
406 expected_pp_rank = 0 if self.rank % 4 <= 1 else 1406 expected_pp_rank = 0 if self.rank % 4 <= 1 else 1
407 self.assertEqual(pp_rank, expected_pp_rank)407 self.assertEqual(pp_rank, expected_pp_rank)
408 408 
409 # dp_rank_0: [0, 1, 2, 3], dp_rank_1: [4, 5, 6, 7]409 # dp_rank_0: [0, 1, 2, 3], dp_rank_1: [4, 5, 6, 7]
410 dp_rank = mesh_3d.get_local_rank("dp")410 dp_rank = mesh_3d.get_local_rank("dp")
411 expected_dp_rank = self.rank // 4411 expected_dp_rank = self.rank // 4
412 self.assertEqual(dp_rank, expected_dp_rank)412 self.assertEqual(dp_rank, expected_dp_rank)
413 413 
414 @skipIfUnsupportMultiNPU(8)414 @skipIfUnsupportMultiNPU(8)
415 @with_comms415 @with_comms
416 def test_from_group_with_mesh_shape(self):416 def test_from_group_with_mesh_shape(self):
417 """Tests ``from_group`` when passing ``mesh_shape`` as 2D."""417 """Tests ``from_group`` when passing ``mesh_shape`` as 2D."""
418 # Consider two different logical views of the same mesh:418 # Consider two different logical views of the same mesh:
419 # - (4, 2) ("dp", "tp") mesh419 # - (4, 2) ("dp", "tp") mesh
420 # - (2, 2, 2) ("dp_replicate", "dp_shard", "tp") mesh420 # - (2, 2, 2) ("dp_replicate", "dp_shard", "tp") mesh
421 mesh_shape = (2, 2, 2)421 mesh_shape = (2, 2, 2)
422 mesh_dim_names = ("dp_replicate", "dp_shard", "tp")422 mesh_dim_names = ("dp_replicate", "dp_shard", "tp")
423 ref_mesh = init_device_mesh(423 ref_mesh = init_device_mesh(
424 self.device_type, mesh_shape, mesh_dim_names=mesh_dim_names424 self.device_type, mesh_shape, mesh_dim_names=mesh_dim_names
425 )425 )
426 426 
427 dp_shard_group = ref_mesh["dp_shard"].get_group()427 dp_shard_group = ref_mesh["dp_shard"].get_group()
428 dp_replicate_group = ref_mesh["dp_replicate"].get_group()428 dp_replicate_group = ref_mesh["dp_replicate"].get_group()
429 429 
430 dp_mesh = DeviceMesh.from_group(430 dp_mesh = DeviceMesh.from_group(
431 [dp_replicate_group, dp_shard_group],431 [dp_replicate_group, dp_shard_group],
432 self.device_type,432 self.device_type,
433 mesh=ref_mesh.mesh[:, :, ref_mesh.get_local_rank(2)],433 mesh=ref_mesh.mesh[:, :, ref_mesh.get_local_rank(2)],
434 mesh_dim_names=mesh_dim_names[:2],434 mesh_dim_names=mesh_dim_names[:2],
435 )435 )
436 436 
437 ref_mesh_dp_dim_group_infos = ref_mesh._dim_group_infos[:2]437 ref_mesh_dp_dim_group_infos = ref_mesh._dim_group_infos[:2]
438 for (_, ref_ranks, _), (_, ranks, _) in zip(438 for (_, ref_ranks, _), (_, ranks, _) in zip(
439 ref_mesh_dp_dim_group_infos, dp_mesh._dim_group_infos439 ref_mesh_dp_dim_group_infos, dp_mesh._dim_group_infos
440 ):440 ):
441 self.assertEqual(ref_ranks, ranks)441 self.assertEqual(ref_ranks, ranks)
442 # Cannot check directly for mesh equality since parent meshes are not442 # Cannot check directly for mesh equality since parent meshes are not
443 # the same since the ref's parent mesh is 3D443 # the same since the ref's parent mesh is 3D
444 self.assertEqual(dp_mesh["dp_replicate"].mesh, ref_mesh["dp_replicate"].mesh)444 self.assertEqual(dp_mesh["dp_replicate"].mesh, ref_mesh["dp_replicate"].mesh)
445 for (_, ref_ranks, _), (_, ranks, _) in zip(445 for (_, ref_ranks, _), (_, ranks, _) in zip(
446 dp_mesh["dp_replicate"]._dim_group_infos,446 dp_mesh["dp_replicate"]._dim_group_infos,
447 ref_mesh["dp_replicate"]._dim_group_infos,447 ref_mesh["dp_replicate"]._dim_group_infos,
448 ):448 ):
449 self.assertEqual(ref_ranks, ranks)449 self.assertEqual(ref_ranks, ranks)
450 self.assertEqual(dp_mesh["dp_shard"].mesh, ref_mesh["dp_shard"].mesh)450 self.assertEqual(dp_mesh["dp_shard"].mesh, ref_mesh["dp_shard"].mesh)
451 for (_, ref_ranks, _), (_, ranks, _) in zip(451 for (_, ref_ranks, _), (_, ranks, _) in zip(
452 dp_mesh["dp_shard"]._dim_group_infos, ref_mesh["dp_shard"]._dim_group_infos452 dp_mesh["dp_shard"]._dim_group_infos, ref_mesh["dp_shard"]._dim_group_infos
453 ):453 ):
454 self.assertEqual(ref_ranks, ranks)454 self.assertEqual(ref_ranks, ranks)
455 455 
456 456 
457class InitDeviceMeshTest(DTensorTestBase):457class InitDeviceMeshTest(DTensorTestBase):
458 @property458 @property
459 def world_size(self):459 def world_size(self):
460 return 2460 return 2
461 461 
462 @skipIfUnsupportMultiNPU(2)462 @skipIfUnsupportMultiNPU(2)
463 @with_comms463 @with_comms
464 def test_init_device_mesh(self):464 def test_init_device_mesh(self):
465 mesh_shape = (2, 1)465 mesh_shape = (2, 1)
466 mesh_dim_names = ("DP", "TP")466 mesh_dim_names = ("DP", "TP")
467 ref_mesh = DeviceMesh(467 ref_mesh = DeviceMesh(
468 self.device_type,468 self.device_type,
469 torch.arange(2).view(mesh_shape),469 torch.arange(2).view(mesh_shape),
470 mesh_dim_names=mesh_dim_names,470 mesh_dim_names=mesh_dim_names,
471 )471 )
472 472 
473 # test init_device_mesh with mesh_dim_names473 # test init_device_mesh with mesh_dim_names
474 mesh_2d = init_device_mesh(474 mesh_2d = init_device_mesh(
475 self.device_type, mesh_shape, mesh_dim_names=mesh_dim_names475 self.device_type, mesh_shape, mesh_dim_names=mesh_dim_names
476 )476 )
477 self.assertEqual(mesh_2d, ref_mesh)477 self.assertEqual(mesh_2d, ref_mesh)
478 self.assertEqual(mesh_2d.mesh_dim_names, mesh_dim_names)478 self.assertEqual(mesh_2d.mesh_dim_names, mesh_dim_names)
479 479 
480 @skipIfUnsupportMultiNPU(2)480 @skipIfUnsupportMultiNPU(2)
481 @with_comms481 @with_comms
482 def test_raises_duplicate_mesh_dim_names(self):482 def test_raises_duplicate_mesh_dim_names(self):
483 with self.assertRaisesRegex(483 with self.assertRaisesRegex(
484 RuntimeError,484 RuntimeError,
485 "Each mesh_dim_name must be unique.",485 "Each mesh_dim_name must be unique.",
486 ):486 ):
487 mesh = init_device_mesh(487 mesh = init_device_mesh(
488 self.device_type,488 self.device_type,
489 (1, 2),489 (1, 2),
490 mesh_dim_names=["dp", "dp"],490 mesh_dim_names=["dp", "dp"],
491 )491 )
492 492 
493 @skipIfUnsupportMultiNPU(2)493 @skipIfUnsupportMultiNPU(2)
494 @with_comms494 @with_comms
495 def test_raises_mesh_shape_mesh_dim_names_mismatch(self):495 def test_raises_mesh_shape_mesh_dim_names_mismatch(self):
496 with self.assertRaisesRegex(496 with self.assertRaisesRegex(
497 RuntimeError,497 RuntimeError,
498 "mesh_shape and mesh_dim_names should have same length!",498 "mesh_shape and mesh_dim_names should have same length!",
499 ):499 ):
500 mesh = init_device_mesh(500 mesh = init_device_mesh(
501 self.device_type,501 self.device_type,
502 (2,),502 (2,),
503 mesh_dim_names=["dp", "tp"],503 mesh_dim_names=["dp", "tp"],
504 )504 )
505 505 
506 506 
507class TestDeviceMeshGetItem(DTensorTestBase):507class TestDeviceMeshGetItem(DTensorTestBase):
508 @property508 @property
509 def world_size(self):509 def world_size(self):
510 return 2510 return 2
511 511 
512 @skipIfUnsupportMultiNPU(2)512 @skipIfUnsupportMultiNPU(2)
513 @with_comms513 @with_comms
514 def test_raises_no_mesh_dim_found(self):514 def test_raises_no_mesh_dim_found(self):
515 with self.assertRaisesRegex(515 with self.assertRaisesRegex(
516 RuntimeError, "Cannot slice a DeviceMesh without mesh_dim_names!"516 RuntimeError, "Cannot slice a DeviceMesh without mesh_dim_names!"
517 ):517 ):
518 mesh = init_device_mesh(self.device_type, (1, 2))518 mesh = init_device_mesh(self.device_type, (1, 2))
519 child_mesh = mesh["DP"]519 child_mesh = mesh["DP"]
520 520 
521 @skipIfUnsupportMultiNPU(2)521 @skipIfUnsupportMultiNPU(2)
522 @with_comms522 @with_comms
523 def test_raises_invalid_mesh_dim_name(self):523 def test_raises_invalid_mesh_dim_name(self):
524 child_mesh_dim_name = ("PP",)524 child_mesh_dim_name = ("PP",)
525 with self.assertRaisesRegex(KeyError, "Invalid mesh_dim_name"):525 with self.assertRaisesRegex(KeyError, "Invalid mesh_dim_name"):
526 mesh_dim_names = ("DP", "TP")526 mesh_dim_names = ("DP", "TP")
527 mesh = init_device_mesh(527 mesh = init_device_mesh(
528 self.device_type, (1, 2), mesh_dim_names=mesh_dim_names528 self.device_type, (1, 2), mesh_dim_names=mesh_dim_names
529 )529 )
530 child_mesh = mesh[child_mesh_dim_name]530 child_mesh = mesh[child_mesh_dim_name]
531 531 
532 @skipIfUnsupportMultiNPU(2)532 @skipIfUnsupportMultiNPU(2)
533 @with_comms533 @with_comms
534 def test_get_item_1d(self):534 def test_get_item_1d(self):
535 mesh = init_device_mesh(self.device_type, (2,), mesh_dim_names=("dp",))535 mesh = init_device_mesh(self.device_type, (2,), mesh_dim_names=("dp",))
536 # Make sure slicing out 1D mesh from a 1D mesh works.536 # Make sure slicing out 1D mesh from a 1D mesh works.
537 dp_mesh = mesh["dp"]537 dp_mesh = mesh["dp"]
538 self.assertEqual(dp_mesh, mesh)538 self.assertEqual(dp_mesh, mesh)
539 539 
540 with self.assertRaisesRegex(KeyError, "Invalid mesh_dim_name"):540 with self.assertRaisesRegex(KeyError, "Invalid mesh_dim_name"):
541 dp_mesh = mesh["dim0"]541 dp_mesh = mesh["dim0"]
542 542 
543 @skipIfUnsupportMultiNPU(2)543 @skipIfUnsupportMultiNPU(2)
544 @with_comms544 @with_comms
545 def test_cache_and_reuse_submesh_slice_result(self):545 def test_cache_and_reuse_submesh_slice_result(self):
546 mesh = init_device_mesh(self.device_type, (1, 2), mesh_dim_names=("dp", "tp"))546 mesh = init_device_mesh(self.device_type, (1, 2), mesh_dim_names=("dp", "tp"))
547 547 
548 dp_mesh = mesh["dp"]548 dp_mesh = mesh["dp"]
549 ref_pg_count = _world.group_count549 ref_pg_count = _world.group_count
550 550 
551 # When we access the "dp" slice again it should not create any new pg.551 # When we access the "dp" slice again it should not create any new pg.
552 # As we are just using the cached result so the pg count should be the same.552 # As we are just using the cached result so the pg count should be the same.
553 dp_mesh_2 = mesh["dp"]553 dp_mesh_2 = mesh["dp"]
554 self.assertEqual(ref_pg_count, _world.group_count)554 self.assertEqual(ref_pg_count, _world.group_count)
555 555 
556 # When we access the "tp" slice, it should not create a new pg, as the "tp" slice would556 # When we access the "tp" slice, it should not create a new pg, as the "tp" slice would
557 # just reuse the parent mesh pg.557 # just reuse the parent mesh pg.
558 tp_mesh = mesh["tp"]558 tp_mesh = mesh["tp"]
559 self.assertEqual(_world.group_count, ref_pg_count)559 self.assertEqual(_world.group_count, ref_pg_count)
560 560 
561 @skipIfUnsupportMultiNPU(2)561 @skipIfUnsupportMultiNPU(2)
562 @with_comms562 @with_comms
563 def test_flatten_mesh_3d(self):563 def test_flatten_mesh_3d(self):
564 mesh_shape = (1, 1, 2)564 mesh_shape = (1, 1, 2)
565 mesh_dim_names = ("dp", "cp", "tp")565 mesh_dim_names = ("dp", "cp", "tp")
566 mesh_3d = init_device_mesh(566 mesh_3d = init_device_mesh(
567 self.device_type, mesh_shape, mesh_dim_names=mesh_dim_names567 self.device_type, mesh_shape, mesh_dim_names=mesh_dim_names
568 )568 )
569 569 
570 # Test flatten contiguous dims570 # Test flatten contiguous dims
571 dp_cp_mesh = mesh_3d["dp", "cp"]571 dp_cp_mesh = mesh_3d["dp", "cp"]
572 flattened_dp_cp_mesh = dp_cp_mesh._flatten()572 flattened_dp_cp_mesh = dp_cp_mesh._flatten()
573 self.assertEqual(dp_cp_mesh.mesh.flatten(), flattened_dp_cp_mesh.mesh)573 self.assertEqual(dp_cp_mesh.mesh.flatten(), flattened_dp_cp_mesh.mesh)
574 self.assertEqual(flattened_dp_cp_mesh.mesh_dim_names[0], "dp_cp")574 self.assertEqual(flattened_dp_cp_mesh.mesh_dim_names[0], "dp_cp")
575 root_mesh = _mesh_resources.get_root_mesh(dp_cp_mesh)575 root_mesh = _mesh_resources.get_root_mesh(dp_cp_mesh)
576 self.assertEqual(root_mesh, mesh_3d)576 self.assertEqual(root_mesh, mesh_3d)
577 flatten_mesh_root_dims = _mesh_resources.flatten_name_to_root_dims[root_mesh][577 flatten_mesh_root_dims = _mesh_resources.flatten_name_to_root_dims[root_mesh][
578 "dp_cp"578 "dp_cp"
579 ]579 ]
580 self.assertEqual(flatten_mesh_root_dims, (0, 1))580 self.assertEqual(flatten_mesh_root_dims, (0, 1))
581 581 
582 ref_pg_count = _world.group_count582 ref_pg_count = _world.group_count
583 # Calling flatten again should not create a new pg.583 # Calling flatten again should not create a new pg.
584 flattened_dp_cp_mesh_2 = dp_cp_mesh._flatten()584 flattened_dp_cp_mesh_2 = dp_cp_mesh._flatten()
585 self.assertEqual(flattened_dp_cp_mesh, flattened_dp_cp_mesh_2)585 self.assertEqual(flattened_dp_cp_mesh, flattened_dp_cp_mesh_2)
586 self.assertEqual(ref_pg_count, _world.group_count)586 self.assertEqual(ref_pg_count, _world.group_count)
587 587 
588 # Test flatten non-contiguous dims588 # Test flatten non-contiguous dims
589 dp_tp_mesh = mesh_3d["dp", "tp"]589 dp_tp_mesh = mesh_3d["dp", "tp"]
590 flattened_dp_tp_mesh = dp_tp_mesh._flatten()590 flattened_dp_tp_mesh = dp_tp_mesh._flatten()
591 self.assertEqual(dp_tp_mesh.mesh.flatten(), flattened_dp_tp_mesh.mesh)591 self.assertEqual(dp_tp_mesh.mesh.flatten(), flattened_dp_tp_mesh.mesh)
592 self.assertEqual(flattened_dp_tp_mesh.mesh_dim_names[0], "dp_tp")592 self.assertEqual(flattened_dp_tp_mesh.mesh_dim_names[0], "dp_tp")
593 root_mesh = _mesh_resources.get_root_mesh(dp_tp_mesh)593 root_mesh = _mesh_resources.get_root_mesh(dp_tp_mesh)
594 self.assertEqual(root_mesh, mesh_3d)594 self.assertEqual(root_mesh, mesh_3d)
595 flatten_mesh_root_dims = _mesh_resources.flatten_name_to_root_dims[root_mesh][595 flatten_mesh_root_dims = _mesh_resources.flatten_name_to_root_dims[root_mesh][
596 "dp_tp"596 "dp_tp"
597 ]597 ]
598 self.assertEqual(flatten_mesh_root_dims, (0, 2))598 self.assertEqual(flatten_mesh_root_dims, (0, 2))
599 599 
600 # Test flatten with a flattened mesh_dim_name600 # Test flatten with a flattened mesh_dim_name
601 cp_tp_mesh = mesh_3d["cp", "tp"]601 cp_tp_mesh = mesh_3d["cp", "tp"]
602 cp_tp_mesh._flatten("dummy")602 cp_tp_mesh._flatten("dummy")
603 self.assertEqual(mesh_3d["dummy"].mesh_dim_names[0], "dummy")603 self.assertEqual(mesh_3d["dummy"].mesh_dim_names[0], "dummy")
604 604 
605 @skipIfUnsupportMultiNPU(2)605 @skipIfUnsupportMultiNPU(2)
606 @with_comms606 @with_comms
607 def test_flatten_mesh_4d(self):607 def test_flatten_mesh_4d(self):
608 with self.subTest(eager_init=True):608 with self.subTest(eager_init=True):
609 mesh_shape = (2, 1, 1, 1)609 mesh_shape = (2, 1, 1, 1)
610 mesh_dim_names = ("dp_replicate", "dp_shard", "cp", "tp")610 mesh_dim_names = ("dp_replicate", "dp_shard", "cp", "tp")
611 mesh_4d = init_device_mesh(611 mesh_4d = init_device_mesh(
612 self.device_type, mesh_shape, mesh_dim_names=mesh_dim_names612 self.device_type, mesh_shape, mesh_dim_names=mesh_dim_names
613 )613 )
614 614 
615 # flatten HSDP and CP into one mesh615 # flatten HSDP and CP into one mesh
616 dp_cp_mesh = mesh_4d[mesh_dim_names[:3]]._flatten("dp_cp")616 dp_cp_mesh = mesh_4d[mesh_dim_names[:3]]._flatten("dp_cp")
617 # check flattened mesh integrity617 # check flattened mesh integrity
618 self.assertEqual(mesh_4d["dp_cp"].mesh.flatten(), dp_cp_mesh.mesh)618 self.assertEqual(mesh_4d["dp_cp"].mesh.flatten(), dp_cp_mesh.mesh)
619 # check flattened mesh dim names is correct619 # check flattened mesh dim names is correct
620 self.assertEqual(dp_cp_mesh.mesh_dim_names, ("dp_cp",))620 self.assertEqual(dp_cp_mesh.mesh_dim_names, ("dp_cp",))
621 # check flattened mesh dependency621 # check flattened mesh dependency
622 self.assertEqual(_mesh_resources.get_root_mesh(dp_cp_mesh), mesh_4d)622 self.assertEqual(_mesh_resources.get_root_mesh(dp_cp_mesh), mesh_4d)
623 623 
624 with self.subTest(eager_init=False):624 with self.subTest(eager_init=False):
625 mesh_shape = (2, 1, 1, 1)625 mesh_shape = (2, 1, 1, 1)
626 mesh_dim_names = ("dp_replicate", "dp_shard", "cp", "tp")626 mesh_dim_names = ("dp_replicate", "dp_shard", "cp", "tp")
627 mesh_4d = init_device_mesh(627 mesh_4d = init_device_mesh(
628 self.device_type, mesh_shape, mesh_dim_names=mesh_dim_names628 self.device_type, mesh_shape, mesh_dim_names=mesh_dim_names
629 )629 )
630 630 
631 # flatten HSDP and CP into one mesh631 # flatten HSDP and CP into one mesh
632 dp_cp_mesh = mesh_4d[mesh_dim_names[:3]]._flatten("dp_cp")632 dp_cp_mesh = mesh_4d[mesh_dim_names[:3]]._flatten("dp_cp")
633 # check flattened mesh integrity633 # check flattened mesh integrity
634 self.assertEqual(mesh_4d["dp_cp"].mesh.flatten(), dp_cp_mesh.mesh)634 self.assertEqual(mesh_4d["dp_cp"].mesh.flatten(), dp_cp_mesh.mesh)
635 # check flattened mesh dim names is correct635 # check flattened mesh dim names is correct
636 self.assertEqual(dp_cp_mesh.mesh_dim_names, ("dp_cp",))636 self.assertEqual(dp_cp_mesh.mesh_dim_names, ("dp_cp",))
637 # check flattened mesh dependency637 # check flattened mesh dependency
638 self.assertEqual(_mesh_resources.get_root_mesh(dp_cp_mesh), mesh_4d)638 self.assertEqual(_mesh_resources.get_root_mesh(dp_cp_mesh), mesh_4d)
639 639 
640 640 
641#TestDeviceMeshGetItem with resetting world_size to 8.641#TestDeviceMeshGetItem with resetting world_size to 8.
642class TestDeviceMeshGetItemE(DTensorTestBase):642class TestDeviceMeshGetItemE(DTensorTestBase):
643 @property643 @property
644 def world_size(self):644 def world_size(self):
645 return 8645 return 8
646 646 
647 @skipIfUnsupportMultiNPU(8)647 @skipIfUnsupportMultiNPU(8)
648 @with_comms648 @with_comms
649 def test_get_item_2d(self):649 def test_get_item_2d(self):
650 mesh_shape = (2, 4)650 mesh_shape = (2, 4)
651 mesh_dim_names = ("DP", "TP")651 mesh_dim_names = ("DP", "TP")
652 mesh_2d = init_device_mesh(652 mesh_2d = init_device_mesh(
653 self.device_type, mesh_shape, mesh_dim_names=mesh_dim_names653 self.device_type, mesh_shape, mesh_dim_names=mesh_dim_names
654 )654 )
655 655 
656 pg_ranks_by_dim_name = {}656 pg_ranks_by_dim_name = {}
657 for mesh_dim_name in mesh_dim_names:657 for mesh_dim_name in mesh_dim_names:
658 mesh_dim = mesh_dim_names.index(mesh_dim_name)658 mesh_dim = mesh_dim_names.index(mesh_dim_name)
659 pg_ranks_by_dim_name[mesh_dim_name] = mesh_2d.mesh.swapdims(659 pg_ranks_by_dim_name[mesh_dim_name] = mesh_2d.mesh.swapdims(
660 -1, mesh_dim660 -1, mesh_dim
661 ).reshape(-1, mesh_2d.mesh.size(mesh_dim))661 ).reshape(-1, mesh_2d.mesh.size(mesh_dim))
662 662 
663 tp_mesh = mesh_2d["TP"]663 tp_mesh = mesh_2d["TP"]
664 tp_group_idx = self.rank // 4664 tp_group_idx = self.rank // 4
665 self.assertEqual(tp_mesh.mesh, pg_ranks_by_dim_name["TP"][tp_group_idx])665 self.assertEqual(tp_mesh.mesh, pg_ranks_by_dim_name["TP"][tp_group_idx])
666 666 
667 dp_mesh = mesh_2d["DP"]667 dp_mesh = mesh_2d["DP"]
668 dp_group_idx = self.rank % 4668 dp_group_idx = self.rank % 4
669 self.assertEqual(mesh_2d["DP"].mesh, pg_ranks_by_dim_name["DP"][dp_group_idx])669 self.assertEqual(mesh_2d["DP"].mesh, pg_ranks_by_dim_name["DP"][dp_group_idx])
670 670 
671 @skipIfUnsupportMultiNPU(8)671 @skipIfUnsupportMultiNPU(8)
672 @with_comms672 @with_comms
673 def test_get_item_3d(self):673 def test_get_item_3d(self):
674 mesh_shape = (2, 2, 2)674 mesh_shape = (2, 2, 2)
675 mesh_dim_names = ("Replicate", "Shard", "TP")675 mesh_dim_names = ("Replicate", "Shard", "TP")
676 mesh_3d = init_device_mesh(676 mesh_3d = init_device_mesh(
677 self.device_type, mesh_shape, mesh_dim_names=mesh_dim_names677 self.device_type, mesh_shape, mesh_dim_names=mesh_dim_names
678 )678 )
679 679 
680 tp_group = [[0, 1], [2, 3], [4, 5], [6, 7]]680 tp_group = [[0, 1], [2, 3], [4, 5], [6, 7]]
681 tp_group_idx = int(self.rank / 2)681 tp_group_idx = int(self.rank / 2)
682 self.assertEqual(mesh_3d["TP"].mesh.tolist(), tp_group[tp_group_idx])682 self.assertEqual(mesh_3d["TP"].mesh.tolist(), tp_group[tp_group_idx])
683 683 
684 shard_group = [[0, 2], [1, 3], [4, 6], [5, 7]]684 shard_group = [[0, 2], [1, 3], [4, 6], [5, 7]]
685 shard_group_idx = self.rank % 2 + self.rank // 4 * 2685 shard_group_idx = self.rank % 2 + self.rank // 4 * 2
686 self.assertEqual(mesh_3d["Shard"].mesh.tolist(), shard_group[shard_group_idx])686 self.assertEqual(mesh_3d["Shard"].mesh.tolist(), shard_group[shard_group_idx])
687 687 
688 replicate_group = [[0, 4], [1, 5], [2, 6], [3, 7]]688 replicate_group = [[0, 4], [1, 5], [2, 6], [3, 7]]
689 replicate_group_idx = self.rank % 4689 replicate_group_idx = self.rank % 4
690 self.assertEqual(690 self.assertEqual(
691 mesh_3d["Replicate"].mesh.tolist(), replicate_group[replicate_group_idx]691 mesh_3d["Replicate"].mesh.tolist(), replicate_group[replicate_group_idx]
692 )692 )
693 693 
694 # We support both UX for nD slicing.694 # We support both UX for nD slicing.
695 # E.g. mesh_3d[["Replicate", "Shard"]] or mesh_3d["Replicate", "Shard"].695 # E.g. mesh_3d[["Replicate", "Shard"]] or mesh_3d["Replicate", "Shard"].
696 hsdp_mesh_1 = mesh_3d[["Replicate", "Shard"]]696 hsdp_mesh_1 = mesh_3d[["Replicate", "Shard"]]
697 hsdp_mesh_2 = mesh_3d["Replicate", "Shard"]697 hsdp_mesh_2 = mesh_3d["Replicate", "Shard"]
698 hsdp_group = [[[0, 2], [4, 6]], [[1, 3], [5, 7]]]698 hsdp_group = [[[0, 2], [4, 6]], [[1, 3], [5, 7]]]
699 hsdp_group_idx = self.rank % 2699 hsdp_group_idx = self.rank % 2
700 self.assertEqual(hsdp_mesh_1.mesh.tolist(), hsdp_group[hsdp_group_idx])700 self.assertEqual(hsdp_mesh_1.mesh.tolist(), hsdp_group[hsdp_group_idx])
701 self.assertEqual(hsdp_mesh_2.mesh.tolist(), hsdp_group[hsdp_group_idx])701 self.assertEqual(hsdp_mesh_2.mesh.tolist(), hsdp_group[hsdp_group_idx])
702 self.assertEqual(hsdp_mesh_1, hsdp_mesh_2)702 self.assertEqual(hsdp_mesh_1, hsdp_mesh_2)
703 703 
704 @skipIfUnsupportMultiNPU(8)704 @skipIfUnsupportMultiNPU(8)
705 @with_comms705 @with_comms
706 def test_get_item_3d_noncontiguous_slicing(self):706 def test_get_item_3d_noncontiguous_slicing(self):
707 mesh_shape = (2, 2, 2)707 mesh_shape = (2, 2, 2)
708 mesh_dim_names = ("dp", "pp", "cp")708 mesh_dim_names = ("dp", "pp", "cp")
709 mesh_3d = init_device_mesh(709 mesh_3d = init_device_mesh(
710 self.device_type, mesh_shape, mesh_dim_names=mesh_dim_names710 self.device_type, mesh_shape, mesh_dim_names=mesh_dim_names
711 )711 )
712 712 
713 # Slice order simply decides which mesh_dim sits on which mesh_dim.713 # Slice order simply decides which mesh_dim sits on which mesh_dim.
714 # For dp_cp_mesh, cp mesh is the innermost dimension.714 # For dp_cp_mesh, cp mesh is the innermost dimension.
715 dp_cp_mesh = mesh_3d["dp", "cp"]715 dp_cp_mesh = mesh_3d["dp", "cp"]
716 expected_mesh_tensor = (716 expected_mesh_tensor = (
717 torch.tensor([[0, 1], [4, 5]], dtype=torch.int)717 torch.tensor([[0, 1], [4, 5]], dtype=torch.int)
718 if self.rank in (0, 1, 4, 5)718 if self.rank in (0, 1, 4, 5)
719 else torch.tensor([[2, 3], [6, 7]], dtype=torch.int)719 else torch.tensor([[2, 3], [6, 7]], dtype=torch.int)
720 )720 )
721 dp_local_rank = dp_cp_mesh.get_local_rank("dp")721 dp_local_rank = dp_cp_mesh.get_local_rank("dp")
722 self.assertEqual(dp_cp_mesh.mesh, expected_mesh_tensor)722 self.assertEqual(dp_cp_mesh.mesh, expected_mesh_tensor)
723 cp_mesh = mesh_3d["cp"]723 cp_mesh = mesh_3d["cp"]
724 # Check on the current dp_local_rank, whether the cp mesh tensor is the same.724 # Check on the current dp_local_rank, whether the cp mesh tensor is the same.
725 self.assertEqual(dp_cp_mesh.mesh[dp_local_rank], cp_mesh.mesh)725 self.assertEqual(dp_cp_mesh.mesh[dp_local_rank], cp_mesh.mesh)
726 726 
727 with self.assertRaisesRegex(727 with self.assertRaisesRegex(
728 KeyError,728 KeyError,
729 "Invalid mesh_dim_names",729 "Invalid mesh_dim_names",
730 ):730 ):
731 cp_dp_mesh = mesh_3d["cp", "dp"]731 cp_dp_mesh = mesh_3d["cp", "dp"]
732 732 
733 @skipIfUnsupportMultiNPU(8)733 @skipIfUnsupportMultiNPU(8)
734 @with_comms734 @with_comms
735 def test_reconstruct_mesh_with_flatten_dim(self):735 def test_reconstruct_mesh_with_flatten_dim(self):
736 mesh_3d = init_device_mesh(736 mesh_3d = init_device_mesh(
737 self.device_type, (2, 2, 2), mesh_dim_names=("replicate", "shard", "cp")737 self.device_type, (2, 2, 2), mesh_dim_names=("replicate", "shard", "cp")
738 )738 )
739 shard_cp_mesh = mesh_3d["shard", "cp"]._flatten()739 shard_cp_mesh = mesh_3d["shard", "cp"]._flatten()
740 hsdp_mesh = mesh_3d["replicate", "shard_cp"]740 hsdp_mesh = mesh_3d["replicate", "shard_cp"]
741 expected_mesh_tensor = torch.tensor(741 expected_mesh_tensor = torch.tensor(
742 [[0, 1, 2, 3], [4, 5, 6, 7]], dtype=torch.int742 [[0, 1, 2, 3], [4, 5, 6, 7]], dtype=torch.int
743 )743 )
744 self.assertEqual(hsdp_mesh.mesh, expected_mesh_tensor)744 self.assertEqual(hsdp_mesh.mesh, expected_mesh_tensor)
745 self.assertEqual(shard_cp_mesh.get_group(), mesh_3d["shard_cp"].get_group())745 self.assertEqual(shard_cp_mesh.get_group(), mesh_3d["shard_cp"].get_group())
746 self.assertEqual(746 self.assertEqual(
747 shard_cp_mesh.get_group(), mesh_3d.get_group(mesh_dim="shard_cp")747 shard_cp_mesh.get_group(), mesh_3d.get_group(mesh_dim="shard_cp")
748 )748 )
749 749 
750 mesh_3d = init_device_mesh(750 mesh_3d = init_device_mesh(
751 self.device_type, (2, 2, 2), mesh_dim_names=("dp", "cp", "tp")751 self.device_type, (2, 2, 2), mesh_dim_names=("dp", "cp", "tp")
752 )752 )
753 dp_cp_mesh = mesh_3d["dp", "cp"]._flatten()753 dp_cp_mesh = mesh_3d["dp", "cp"]._flatten()
754 spmd_mesh = mesh_3d["dp_cp", "tp"]754 spmd_mesh = mesh_3d["dp_cp", "tp"]
755 expected_mesh_tensor = torch.tensor(755 expected_mesh_tensor = torch.tensor(
756 [[0, 1], [2, 3], [4, 5], [6, 7]], dtype=torch.int756 [[0, 1], [2, 3], [4, 5], [6, 7]], dtype=torch.int
757 )757 )
758 self.assertEqual(spmd_mesh.mesh, expected_mesh_tensor)758 self.assertEqual(spmd_mesh.mesh, expected_mesh_tensor)
759 self.assertEqual(dp_cp_mesh.get_group(), mesh_3d["dp_cp"].get_group())759 self.assertEqual(dp_cp_mesh.get_group(), mesh_3d["dp_cp"].get_group())
760 self.assertEqual(dp_cp_mesh.get_group(), mesh_3d.get_group(mesh_dim="dp_cp"))760 self.assertEqual(dp_cp_mesh.get_group(), mesh_3d.get_group(mesh_dim="dp_cp"))
761 761 
762 762 
763class TestMeshEnv(DTensorTestBase):763class TestMeshEnv(DTensorTestBase):
764 @property764 @property
765 def world_size(self):765 def world_size(self):
766 return 2766 return 2
767 767 
768 @skipIfUnsupportMultiNPU(2)768 @skipIfUnsupportMultiNPU(2)
769 @with_comms769 @with_comms
770 def test_get_root_mesh(self):770 def test_get_root_mesh(self):
771 mesh_3d = init_device_mesh(771 mesh_3d = init_device_mesh(
772 self.device_type, (2, 1, 1), mesh_dim_names=("dp", "cp", "tp")772 self.device_type, (2, 1, 1), mesh_dim_names=("dp", "cp", "tp")
773 )773 )
774 774 
775 dp_cp_mesh = mesh_3d["dp", "cp"]775 dp_cp_mesh = mesh_3d["dp", "cp"]
776 dp_tp_mesh = mesh_3d["dp", "tp"]776 dp_tp_mesh = mesh_3d["dp", "tp"]
777 cp_tp_mesh = mesh_3d["cp", "tp"]777 cp_tp_mesh = mesh_3d["cp", "tp"]
778 dp_mesh = mesh_3d["dp"]778 dp_mesh = mesh_3d["dp"]
779 cp_mesh = mesh_3d["cp"]779 cp_mesh = mesh_3d["cp"]
780 tp_mesh = mesh_3d["tp"]780 tp_mesh = mesh_3d["tp"]
781 self.assertEqual(_mesh_resources.get_root_mesh(dp_cp_mesh), mesh_3d)781 self.assertEqual(_mesh_resources.get_root_mesh(dp_cp_mesh), mesh_3d)
782 self.assertEqual(_mesh_resources.get_root_mesh(dp_tp_mesh), mesh_3d)782 self.assertEqual(_mesh_resources.get_root_mesh(dp_tp_mesh), mesh_3d)
783 self.assertEqual(_mesh_resources.get_root_mesh(cp_tp_mesh), mesh_3d)783 self.assertEqual(_mesh_resources.get_root_mesh(cp_tp_mesh), mesh_3d)
784 self.assertEqual(_mesh_resources.get_root_mesh(dp_mesh), mesh_3d)784 self.assertEqual(_mesh_resources.get_root_mesh(dp_mesh), mesh_3d)
785 self.assertEqual(_mesh_resources.get_root_mesh(cp_mesh), mesh_3d)785 self.assertEqual(_mesh_resources.get_root_mesh(cp_mesh), mesh_3d)
786 self.assertEqual(_mesh_resources.get_root_mesh(tp_mesh), mesh_3d)786 self.assertEqual(_mesh_resources.get_root_mesh(tp_mesh), mesh_3d)
787 787 
788 @skipIfUnsupportMultiNPU(2)788 @skipIfUnsupportMultiNPU(2)
789 @with_comms789 @with_comms
790 def test_get_root_mesh_dim_exist(self):790 def test_get_root_mesh_dim_exist(self):
791 mesh_shape = (2, self.world_size // 2)791 mesh_shape = (2, self.world_size // 2)
792 mesh_dim_names = ("DP", "TP")792 mesh_dim_names = ("DP", "TP")
793 mesh_2d = init_device_mesh(793 mesh_2d = init_device_mesh(
794 self.device_type, mesh_shape, mesh_dim_names=mesh_dim_names794 self.device_type, mesh_shape, mesh_dim_names=mesh_dim_names
795 )795 )
796 796 
797 self.assertEqual(_mesh_resources.get_root_mesh_dim(mesh_2d["DP"]), 0)797 self.assertEqual(_mesh_resources.get_root_mesh_dim(mesh_2d["DP"]), 0)
798 self.assertEqual(_mesh_resources.get_root_mesh_dim(mesh_2d["TP"]), 1)798 self.assertEqual(_mesh_resources.get_root_mesh_dim(mesh_2d["TP"]), 1)
799 799 
800 @skipIfUnsupportMultiNPU(2)800 @skipIfUnsupportMultiNPU(2)
801 @with_comms801 @with_comms
802 def test_get_root_mesh_dim_not_exist(self):802 def test_get_root_mesh_dim_not_exist(self):
803 mesh_shape = (self.world_size,)803 mesh_shape = (self.world_size,)
804 mesh = init_device_mesh(self.device_type, mesh_shape)804 mesh = init_device_mesh(self.device_type, mesh_shape)
805 805 
806 self.assertEqual(_mesh_resources.get_root_mesh_dim(mesh), None)806 self.assertEqual(_mesh_resources.get_root_mesh_dim(mesh), None)
807 807 
808 @skipIfUnsupportMultiNPU(2)808 @skipIfUnsupportMultiNPU(2)
809 @with_comms809 @with_comms
810 def test_get_mesh_dim_by_name(self):810 def test_get_mesh_dim_by_name(self):
811 mesh_shape = (2, self.world_size // 2)811 mesh_shape = (2, self.world_size // 2)
812 mesh_dim_names = ("DP", "TP")812 mesh_dim_names = ("DP", "TP")
813 mesh_2d = init_device_mesh(813 mesh_2d = init_device_mesh(
814 self.device_type, mesh_shape, mesh_dim_names=mesh_dim_names814 self.device_type, mesh_shape, mesh_dim_names=mesh_dim_names
815 )815 )
816 816 
817 self.assertEqual(_mesh_resources.get_mesh_dim_by_name(mesh_2d, "DP"), 0)817 self.assertEqual(_mesh_resources.get_mesh_dim_by_name(mesh_2d, "DP"), 0)
818 self.assertEqual(_mesh_resources.get_mesh_dim_by_name(mesh_2d, "TP"), 1)818 self.assertEqual(_mesh_resources.get_mesh_dim_by_name(mesh_2d, "TP"), 1)
819 819 
820 @skipIfUnsupportMultiNPU(2)820 @skipIfUnsupportMultiNPU(2)
821 @with_comms821 @with_comms
822 def test_get_all_submeshes(self):822 def test_get_all_submeshes(self):
823 mesh_2d = init_device_mesh(823 mesh_2d = init_device_mesh(
824 self.device_type, (1, 2), mesh_dim_names=("replicate", "shard")824 self.device_type, (1, 2), mesh_dim_names=("replicate", "shard")
825 )825 )
826 all_submeshes = _mesh_resources._get_all_submeshes(mesh_2d, "replicate")826 all_submeshes = _mesh_resources._get_all_submeshes(mesh_2d, "replicate")
827 self.assertEqual(len(all_submeshes), 2)827 self.assertEqual(len(all_submeshes), 2)
828 self.assertEqual(828 self.assertEqual(
829 all(submesh.mesh.numel() == 1 for submesh in all_submeshes), True829 all(submesh.mesh.numel() == 1 for submesh in all_submeshes), True
830 )830 )
831 831 
832 832 
833class DeviceMeshCollectiveTest(DTensorTestBase):833class DeviceMeshCollectiveTest(DTensorTestBase):
834 @property834 @property
835 def world_size(self):835 def world_size(self):
836 return 2836 return 2
837 837 
838 @skipIfUnsupportMultiNPU(2)838 @skipIfUnsupportMultiNPU(2)
839 @with_comms839 @with_comms
840 def test_broadcast_1d(self):840 def test_broadcast_1d(self):
841 mesh = DeviceMesh(self.device_type, torch.arange(self.world_size))841 mesh = DeviceMesh(self.device_type, torch.arange(self.world_size))
842 local_tensor = torch.ones(3, 3, device=self.device_type) * self.rank842 local_tensor = torch.ones(3, 3, device=self.device_type) * self.rank
843 mesh_broadcast(local_tensor, mesh, mesh_dim=0)843 mesh_broadcast(local_tensor, mesh, mesh_dim=0)
844 self.assertEqual(local_tensor, torch.zeros(3, 3))844 self.assertEqual(local_tensor, torch.zeros(3, 3))
845 845 
846 @skipIfUnsupportMultiNPU(2)846 @skipIfUnsupportMultiNPU(2)
847 @with_comms847 @with_comms
848 def test_scatter_1d(self):848 def test_scatter_1d(self):
849 mesh = DeviceMesh(self.device_type, torch.arange(self.world_size))849 mesh = DeviceMesh(self.device_type, torch.arange(self.world_size))
850 scatter_tensor_shape = [3, 3, 3]850 scatter_tensor_shape = [3, 3, 3]
851 len_scatter_tensor_shape = len(scatter_tensor_shape)851 len_scatter_tensor_shape = len(scatter_tensor_shape)
852 for scatter_dim in range(len_scatter_tensor_shape):852 for scatter_dim in range(len_scatter_tensor_shape):
853 shard_placement = Shard(scatter_dim)853 shard_placement = Shard(scatter_dim)
854 scatter_tensor_shape[scatter_dim] *= self.world_size854 scatter_tensor_shape[scatter_dim] *= self.world_size
855 # make the random seed same across rank855 # make the random seed same across rank
856 torch.manual_seed(0)856 torch.manual_seed(0)
857 global_tensor = torch.randn(scatter_tensor_shape, device=self.device_type)857 global_tensor = torch.randn(scatter_tensor_shape, device=self.device_type)
858 splitted_list, _ = shard_placement._split_tensor(858 splitted_list, _ = shard_placement._split_tensor(
859 global_tensor, mesh.size(), with_padding=True, contiguous=True859 global_tensor, mesh.size(), with_padding=True, contiguous=True
860 )860 )
861 recv_tensor = torch.empty_like(splitted_list[mesh.get_rank()])861 recv_tensor = torch.empty_like(splitted_list[mesh.get_rank()])
862 # scatter on dim > 0 would generate non-contiguous tensor, verify that works862 # scatter on dim > 0 would generate non-contiguous tensor, verify that works
863 mesh_scatter(recv_tensor, splitted_list, mesh, mesh_dim=0)863 mesh_scatter(recv_tensor, splitted_list, mesh, mesh_dim=0)
864 self.assertEqual(recv_tensor, splitted_list[mesh.get_rank()])864 self.assertEqual(recv_tensor, splitted_list[mesh.get_rank()])
865 865 
866 @skipIfUnsupportMultiNPU(2)866 @skipIfUnsupportMultiNPU(2)
867 @with_comms867 @with_comms
868 def test_scatter_uneven(self):868 def test_scatter_uneven(self):
869 device_mesh = DeviceMesh(self.device_type, list(range(self.world_size)))869 device_mesh = DeviceMesh(self.device_type, list(range(self.world_size)))
870 my_rank = device_mesh.get_rank()870 my_rank = device_mesh.get_rank()
871 tensor_to_split = torch.randn(871 tensor_to_split = torch.randn(
872 device_mesh.size() + 3, device_mesh.size() + 1, device=self.device_type872 device_mesh.size() + 3, device_mesh.size() + 1, device=self.device_type
873 )873 )
874 874 
875 for shard_dim in range(tensor_to_split.ndim):875 for shard_dim in range(tensor_to_split.ndim):
876 shard_placement = Shard(shard_dim)876 shard_placement = Shard(shard_dim)
877 877 
878 tensor_to_scatter = tensor_to_split.clone()878 tensor_to_scatter = tensor_to_split.clone()
879 tensor_splitted_list = list(879 tensor_splitted_list = list(
880 torch.chunk(tensor_to_split, self.world_size, dim=shard_dim)880 torch.chunk(tensor_to_split, self.world_size, dim=shard_dim)
881 )881 )
882 for _ in range(self.world_size - len(tensor_splitted_list)):882 for _ in range(self.world_size - len(tensor_splitted_list)):
883 tensor_splitted_list.append(torch.tensor([], device=self.device_type))883 tensor_splitted_list.append(torch.tensor([], device=self.device_type))
884 884 
885 padded_tensor_list, pad_sizes = shard_placement._split_tensor(885 padded_tensor_list, pad_sizes = shard_placement._split_tensor(
886 tensor_to_scatter,886 tensor_to_scatter,
887 device_mesh.size(),887 device_mesh.size(),
888 with_padding=True,888 with_padding=True,
889 contiguous=True,889 contiguous=True,
890 )890 )
891 891 
892 scattered_tensor = torch.empty_like(padded_tensor_list[my_rank])892 scattered_tensor = torch.empty_like(padded_tensor_list[my_rank])
893 mesh_scatter(scattered_tensor, padded_tensor_list, device_mesh, mesh_dim=0)893 mesh_scatter(scattered_tensor, padded_tensor_list, device_mesh, mesh_dim=0)
894 894 
895 if pad_sizes[my_rank] != 0:895 if pad_sizes[my_rank] != 0:
896 scattered_tensor = unpad_tensor(896 scattered_tensor = unpad_tensor(
897 scattered_tensor, shard_dim, pad_sizes[my_rank]897 scattered_tensor, shard_dim, pad_sizes[my_rank]
898 )898 )
899 899 
900 if scattered_tensor.numel() == 0:900 if scattered_tensor.numel() == 0:
901 # We need to check numel() instead of size if a tensor is ([]) after unpadding,901 # We need to check numel() instead of size if a tensor is ([]) after unpadding,
902 # since the size could be ([0, 8]) after unpadding.902 # since the size could be ([0, 8]) after unpadding.
903 self.assertEqual(903 self.assertEqual(
904 scattered_tensor.numel(), tensor_splitted_list[my_rank].numel()904 scattered_tensor.numel(), tensor_splitted_list[my_rank].numel()
905 )905 )
906 else:906 else:
907 self.assertEqual(907 self.assertEqual(
908 scattered_tensor.size(), tensor_splitted_list[my_rank].size()908 scattered_tensor.size(), tensor_splitted_list[my_rank].size()
909 )909 )
910 self.assertEqual(scattered_tensor, tensor_splitted_list[my_rank])910 self.assertEqual(scattered_tensor, tensor_splitted_list[my_rank])
911 911 
912 @skipIfUnsupportMultiNPU(2)912 @skipIfUnsupportMultiNPU(2)
913 @with_comms913 @with_comms
914 def test_all_gather_uneven(self):914 def test_all_gather_uneven(self):
915 device_mesh = DeviceMesh(self.device_type, list(range(self.world_size)))915 device_mesh = DeviceMesh(self.device_type, list(range(self.world_size)))
916 my_rank = device_mesh.get_rank()916 my_rank = device_mesh.get_rank()
917 tensor_to_split = torch.ones(917 tensor_to_split = torch.ones(
918 device_mesh.size() + 3,918 device_mesh.size() + 3,
919 device_mesh.size() + 1,919 device_mesh.size() + 1,
920 device=self.device_type,920 device=self.device_type,
921 )921 )
922 922 
923 for shard_dim in range(tensor_to_split.ndim):923 for shard_dim in range(tensor_to_split.ndim):
924 shard_placement = Shard(shard_dim)924 shard_placement = Shard(shard_dim)
925 tensor_padded_list, pad_sizes = shard_placement._split_tensor(925 tensor_padded_list, pad_sizes = shard_placement._split_tensor(
926 tensor_to_split,926 tensor_to_split,
927 device_mesh.size(),927 device_mesh.size(),
928 with_padding=True,928 with_padding=True,
929 contiguous=True,929 contiguous=True,
930 )930 )
931 local_tensor = tensor_padded_list[my_rank]931 local_tensor = tensor_padded_list[my_rank]
932 big_tensor = funcol.all_gather_tensor(932 big_tensor = funcol.all_gather_tensor(
933 local_tensor, gather_dim=shard_dim, group=(device_mesh, 0)933 local_tensor, gather_dim=shard_dim, group=(device_mesh, 0)
934 )934 )
935 big_tensor_chunks = list(935 big_tensor_chunks = list(
936 torch.chunk(big_tensor, device_mesh.size(), dim=shard_dim)936 torch.chunk(big_tensor, device_mesh.size(), dim=shard_dim)
937 )937 )
938 unpadded_list = [938 unpadded_list = [
939 (939 (
940 unpad_tensor(big_tensor, shard_dim, pad_sizes[i])940 unpad_tensor(big_tensor, shard_dim, pad_sizes[i])
941 if pad_sizes[i] > 0941 if pad_sizes[i] > 0
942 else big_tensor942 else big_tensor
943 )943 )
944 for i, big_tensor in enumerate(big_tensor_chunks)944 for i, big_tensor in enumerate(big_tensor_chunks)
945 ]945 ]
946 all_gathered_tensor = torch.cat(unpadded_list, dim=shard_dim)946 all_gathered_tensor = torch.cat(unpadded_list, dim=shard_dim)
947 947 
948 self.assertEqual(all_gathered_tensor.size(), tensor_to_split.size())948 self.assertEqual(all_gathered_tensor.size(), tensor_to_split.size())
949 self.assertEqual(all_gathered_tensor, tensor_to_split)949 self.assertEqual(all_gathered_tensor, tensor_to_split)
950 950 
951 @skipIfUnsupportMultiNPU(2)951 @skipIfUnsupportMultiNPU(2)
952 @with_comms952 @with_comms
953 def test_reduce_scatter_contiguous(self):953 def test_reduce_scatter_contiguous(self):
954 device_mesh = DeviceMesh(self.device_type, list(range(self.world_size)))954 device_mesh = DeviceMesh(self.device_type, list(range(self.world_size)))
955 my_rank = device_mesh.get_rank()955 my_rank = device_mesh.get_rank()
956 956 
957 # Init the tensor957 # Init the tensor
958 step = self.world_size * 2958 step = self.world_size * 2
959 total_elem = step**2959 total_elem = step**2
960 tensor = torch.arange(0, total_elem).view(step, -1).to(device=self.device_type)960 tensor = torch.arange(0, total_elem).view(step, -1).to(device=self.device_type)
961 tensor = tensor * (my_rank + 1)961 tensor = tensor * (my_rank + 1)
962 962 
963 # Get non-contiguous tensor by slicing963 # Get non-contiguous tensor by slicing
964 tensor_to_reduce = tensor[::2, :2]964 tensor_to_reduce = tensor[::2, :2]
965 tensor_contiguous = tensor_to_reduce.clone().contiguous()965 tensor_contiguous = tensor_to_reduce.clone().contiguous()
966 966 
967 # Partial to Shard to trigger reduce_scatter967 # Partial to Shard to trigger reduce_scatter
968 tensor_to_reduce = DTensor.from_local(968 tensor_to_reduce = DTensor.from_local(
969 tensor_to_reduce, device_mesh, [_Partial()]969 tensor_to_reduce, device_mesh, [_Partial()]
970 )970 )
971 tensor_contiguous = DTensor.from_local(971 tensor_contiguous = DTensor.from_local(
972 tensor_contiguous, device_mesh, [_Partial()]972 tensor_contiguous, device_mesh, [_Partial()]
973 )973 )
974 new_tensor = tensor_to_reduce.redistribute(device_mesh, [Shard(0)])974 new_tensor = tensor_to_reduce.redistribute(device_mesh, [Shard(0)])
975 new_tensor_contiguous = tensor_contiguous.redistribute(device_mesh, [Shard(0)])975 new_tensor_contiguous = tensor_contiguous.redistribute(device_mesh, [Shard(0)])
976 976 
977 # The output for contiguous and non-contiguous tensors of the same value977 # The output for contiguous and non-contiguous tensors of the same value
978 # should return the same reducescatter value.978 # should return the same reducescatter value.
979 new_tensor_local = new_tensor._local_tensor979 new_tensor_local = new_tensor._local_tensor
980 new_tensor_contiguous_local = new_tensor_contiguous._local_tensor980 new_tensor_contiguous_local = new_tensor_contiguous._local_tensor
981 self.assertEqual(new_tensor_local, new_tensor_contiguous_local)981 self.assertEqual(new_tensor_local, new_tensor_contiguous_local)
982 self.assertEqual(list(new_tensor_local.size()), [1, 2])982 self.assertEqual(list(new_tensor_local.size()), [1, 2])
983 983 
984 # Check the reduce numerical value984 # Check the reduce numerical value
985 sum_base = (1 + self.world_size) * self.world_size / 2985 sum_base = (1 + self.world_size) * self.world_size / 2
986 first_elem = my_rank * sum_base * step * 2986 first_elem = my_rank * sum_base * step * 2
987 expected_tensor = torch.tensor(987 expected_tensor = torch.tensor(
988 [[first_elem, first_elem + sum_base]],988 [[first_elem, first_elem + sum_base]],
989 dtype=new_tensor_local.dtype,989 dtype=new_tensor_local.dtype,
990 device=self.device_type,990 device=self.device_type,
991 )991 )
992 self.assertEqual(new_tensor_local, expected_tensor)992 self.assertEqual(new_tensor_local, expected_tensor)
993 993 
994 @skipIfUnsupportMultiNPU(2)994 @skipIfUnsupportMultiNPU(2)
995 @with_comms995 @with_comms
996 def test_reduce_scatter_uneven(self):996 def test_reduce_scatter_uneven(self):
997 device_mesh = DeviceMesh(self.device_type, list(range(self.world_size)))997 device_mesh = DeviceMesh(self.device_type, list(range(self.world_size)))
998 my_rank = device_mesh.get_rank()998 my_rank = device_mesh.get_rank()
999 tensor_to_split = (999 tensor_to_split = (
1000 torch.ones(1000 torch.ones(
1001 device_mesh.size() + 3,1001 device_mesh.size() + 3,
1002 device_mesh.size() + 1,1002 device_mesh.size() + 1,
1003 device=self.device_type,1003 device=self.device_type,
1004 )1004 )
1005 * self.rank1005 * self.rank
1006 )1006 )
1007 1007 
1008 for shard_dim in range(tensor_to_split.ndim):1008 for shard_dim in range(tensor_to_split.ndim):
1009 shard_placement = Shard(shard_dim)1009 shard_placement = Shard(shard_dim)
1010 tensor_to_scatter = tensor_to_split.clone()1010 tensor_to_scatter = tensor_to_split.clone()
1011 1011 
1012 tensor_splitted_list = list(1012 tensor_splitted_list = list(
1013 torch.chunk(tensor_to_split, self.world_size, dim=shard_dim)1013 torch.chunk(tensor_to_split, self.world_size, dim=shard_dim)
1014 )1014 )
1015 for _ in range(self.world_size - len(tensor_splitted_list)):1015 for _ in range(self.world_size - len(tensor_splitted_list)):
1016 tensor_splitted_list.append(torch.tensor([], device=self.device_type))1016 tensor_splitted_list.append(torch.tensor([], device=self.device_type))
1017 1017 
1018 padded_tensor_list, pad_sizes = shard_placement._split_tensor(1018 padded_tensor_list, pad_sizes = shard_placement._split_tensor(
1019 tensor_to_scatter,1019 tensor_to_scatter,
1020 device_mesh.size(),1020 device_mesh.size(),
1021 with_padding=True,1021 with_padding=True,
1022 contiguous=True,1022 contiguous=True,
1023 )1023 )
1024 1024 
1025 tensor_to_reduce = torch.cat(padded_tensor_list, shard_dim)1025 tensor_to_reduce = torch.cat(padded_tensor_list, shard_dim)
1026 1026 
1027 res_num = ((0 + self.world_size - 1) * self.world_size) / 21027 res_num = ((0 + self.world_size - 1) * self.world_size) / 2
1028 1028 
1029 scattered_tensor = funcol.reduce_scatter_tensor(1029 scattered_tensor = funcol.reduce_scatter_tensor(
1030 tensor_to_reduce,1030 tensor_to_reduce,
1031 reduceOp="sum",1031 reduceOp="sum",
1032 scatter_dim=shard_dim,1032 scatter_dim=shard_dim,
1033 group=(device_mesh, 0),1033 group=(device_mesh, 0),
1034 )1034 )
1035 1035 
1036 # unpad scattered_tensor1036 # unpad scattered_tensor
1037 if pad_sizes[my_rank] > 0:1037 if pad_sizes[my_rank] > 0:
1038 scattered_tensor = unpad_tensor(1038 scattered_tensor = unpad_tensor(
1039 scattered_tensor, shard_dim, pad_sizes[my_rank]1039 scattered_tensor, shard_dim, pad_sizes[my_rank]
1040 )1040 )
1041 1041 
1042 if scattered_tensor.numel() == 0:1042 if scattered_tensor.numel() == 0:
1043 # We need to check numel() instead of size if a tensor is ([]) after unpadding,1043 # We need to check numel() instead of size if a tensor is ([]) after unpadding,
1044 # since the size could be ([0, 8]) after unpadding.1044 # since the size could be ([0, 8]) after unpadding.
1045 self.assertEqual(1045 self.assertEqual(
1046 scattered_tensor.numel(), tensor_splitted_list[my_rank].numel()1046 scattered_tensor.numel(), tensor_splitted_list[my_rank].numel()
1047 )1047 )
1048 else:1048 else:
1049 self.assertEqual(1049 self.assertEqual(
1050 scattered_tensor.size(), tensor_splitted_list[my_rank].size()1050 scattered_tensor.size(), tensor_splitted_list[my_rank].size()
1051 )1051 )
1052 self.assertEqual(1052 self.assertEqual(
1053 scattered_tensor,1053 scattered_tensor,
1054 torch.ones_like(tensor_splitted_list[my_rank]) * res_num,1054 torch.ones_like(tensor_splitted_list[my_rank]) * res_num,
1055 )1055 )
1056 1056 
1057 @skipIfUnsupportMultiNPU(2)1057 @skipIfUnsupportMultiNPU(2)
1058 @with_comms1058 @with_comms
1059 def test_broadcast_nd(self):1059 def test_broadcast_nd(self):
1060 mesh_tensor = torch.arange(2).reshape(2, 1, 1)1060 mesh_tensor = torch.arange(2).reshape(2, 1, 1)
1061 mesh = DeviceMesh(self.device_type, mesh_tensor)1061 mesh = DeviceMesh(self.device_type, mesh_tensor)
1062 local_tensor = torch.ones(3, 3, device=self.device_type) * self.rank1062 local_tensor = torch.ones(3, 3, device=self.device_type) * self.rank
1063 1063 
1064 # check all dim groups1064 # check all dim groups
1065 dim_to_subgroups = mesh.get_all_groups()1065 dim_to_subgroups = mesh.get_all_groups()
1066 for dim, dim_group in enumerate(dim_to_subgroups):1066 for dim, dim_group in enumerate(dim_to_subgroups):
1067 dim_group_size = get_world_size(dim_group)1067 dim_group_size = get_world_size(dim_group)
1068 global_ranks = [1068 global_ranks = [
1069 get_global_rank(dim_group, i) for i in range(dim_group_size)1069 get_global_rank(dim_group, i) for i in range(dim_group_size)
1070 ]1070 ]
1071 cloned_local_tensor = local_tensor.clone()1071 cloned_local_tensor = local_tensor.clone()
1072 mesh_broadcast(cloned_local_tensor, mesh, mesh_dim=dim)1072 mesh_broadcast(cloned_local_tensor, mesh, mesh_dim=dim)
1073 res_num = global_ranks[0]1073 res_num = global_ranks[0]
1074 self.assertEqual(cloned_local_tensor, torch.ones(3, 3) * res_num)1074 self.assertEqual(cloned_local_tensor, torch.ones(3, 3) * res_num)
1075 1075 
1076 @skipIfUnsupportMultiNPU(2)1076 @skipIfUnsupportMultiNPU(2)
1077 @with_comms1077 @with_comms
1078 def test_scatter_nd(self):1078 def test_scatter_nd(self):
1079 mesh_tensor = torch.arange(2).reshape(2, 1, 1)1079 mesh_tensor = torch.arange(2).reshape(2, 1, 1)
1080 mesh = DeviceMesh(self.device_type, mesh_tensor)1080 mesh = DeviceMesh(self.device_type, mesh_tensor)
1081 1081 
1082 # check all dim groups1082 # check all dim groups
1083 dim_to_subgroups = mesh.get_all_groups()1083 dim_to_subgroups = mesh.get_all_groups()
1084 for dim, dim_group in enumerate(dim_to_subgroups):1084 for dim, dim_group in enumerate(dim_to_subgroups):
1085 dim_group_size = get_world_size(dim_group)1085 dim_group_size = get_world_size(dim_group)
1086 global_ranks = [1086 global_ranks = [
1087 get_global_rank(dim_group, i) for i in range(dim_group_size)1087 get_global_rank(dim_group, i) for i in range(dim_group_size)
1088 ]1088 ]
1089 scattered_tensors = [1089 scattered_tensors = [
1090 torch.ones(3, 3, device=self.device_type) * global_rank1090 torch.ones(3, 3, device=self.device_type) * global_rank
1091 for global_rank in global_ranks1091 for global_rank in global_ranks
1092 ]1092 ]
1093 received_tensor = torch.empty_like(1093 received_tensor = torch.empty_like(
1094 scattered_tensors[mesh.get_coordinate()[dim]]1094 scattered_tensors[mesh.get_coordinate()[dim]]
1095 )1095 )
1096 mesh_scatter(received_tensor, scattered_tensors, mesh, mesh_dim=dim)1096 mesh_scatter(received_tensor, scattered_tensors, mesh, mesh_dim=dim)
1097 self.assertEqual(received_tensor, torch.ones(3, 3) * self.rank)1097 self.assertEqual(received_tensor, torch.ones(3, 3) * self.rank)
1098 1098 
1099 1099 
1100if __name__ == "__main__":1100if __name__ == "__main__":
1101 run_tests()1101 run_tests()
Mtest/distributed/watchdog/watchdog_quick_exit.py+27-27
@@ -1,27 +1,27 @@
1import os1import os
2import time2import time
3import datetime3import datetime
4import torch.distributed as dist4import torch.distributed as dist
5import torch5import torch
6import torch_npu6import torch_npu
7 7 
8 8 
9def main():9def main():
10 torch.npu.set_compile_mode(jit_compile=True)10 torch.npu.set_compile_mode(jit_compile=True)
11 rank = int(os.environ['RANK'])11 rank = int(os.environ['RANK'])
12 local_rank = int(os.environ['LOCAL_RANK'])12 local_rank = int(os.environ['LOCAL_RANK'])
13 device = torch.device('npu:{}'.format(local_rank))13 device = torch.device('npu:{}'.format(local_rank))
14 torch.npu.set_device(device)14 torch.npu.set_device(device)
15 dist.init_process_group(backend='hccl', rank=rank, world_size=2, timeout=datetime.timedelta(seconds=120))15 dist.init_process_group(backend='hccl', rank=rank, world_size=2, timeout=datetime.timedelta(seconds=120))
16 tensor = torch.tensor(1).npu()16 tensor = torch.tensor(1).npu()
17 dist.all_reduce(tensor)17 dist.all_reduce(tensor)
18 if rank == 0:18 if rank == 0:
19 x1 = torch.randn(3).float().npu()19 x1 = torch.randn(3).float().npu()
20 x2 = torch.randn(1).long().npu()20 x2 = torch.randn(1).long().npu()
21 x3 = torch.randn(1).float().npu()21 x3 = torch.randn(1).float().npu()
22 y = torch.addcmul(x1, x2, x3)22 y = torch.addcmul(x1, x2, x3)
23 dist.all_reduce(tensor)23 dist.all_reduce(tensor)
24 24 
25 25 
26if __name__ == "__main__":26if __name__ == "__main__":
27 main()27 main()
Mtest/dynamo/test_stream.py+32-32
@@ -1,32 +1,32 @@
1# Owner(s): ["module: dynamo"]1# Owner(s): ["module: dynamo"]
2import functools2import functools
3import unittest3import unittest
4import torch4import torch
5import torch._dynamo.test_case5import torch._dynamo.test_case
6import torch_npu6import torch_npu
7 7 
8requires_npu = functools.partial(unittest.skipIf, not torch.npu.is_available(), "requires npu")8requires_npu = functools.partial(unittest.skipIf, not torch.npu.is_available(), "requires npu")
9 9 
10 10 
11class StreamintoDynamoTests(torch._dynamo.test_case.TestCase):11class StreamintoDynamoTests(torch._dynamo.test_case.TestCase):
12 12 
13 @requires_npu()13 @requires_npu()
14 def test_stream(self):14 def test_stream(self):
15 def model_1(x):15 def model_1(x):
16 a = x * x16 a = x * x
17 s = torch.npu.Stream()17 s = torch.npu.Stream()
18 s.wait_stream(torch.npu.current_stream())18 s.wait_stream(torch.npu.current_stream())
19 with torch.npu.stream(s):19 with torch.npu.stream(s):
20 b = x + a20 b = x + a
21 return b21 return b
22 inp = torch.randn(2, 8).npu()22 inp = torch.randn(2, 8).npu()
23 m = torch.compile(model_1, backend="aot_eager", fullgraph=True)23 m = torch.compile(model_1, backend="aot_eager", fullgraph=True)
24 output = m(inp)24 output = m(inp)
25 output1 = model_1(inp)25 output1 = model_1(inp)
26 torch.allclose(output, output1)26 torch.allclose(output, output1)
27 27 
28 28 
29if __name__ == "__main__":29if __name__ == "__main__":
30 from torch._dynamo.test_case import run_tests30 from torch._dynamo.test_case import run_tests
31 31 
32 run_tests()32 run_tests()
Mtest/get_failed_ut_from_log.py+0-1
@@ -44,4 +44,3 @@ if __name__ == "__main__":
44 args = parser.parse_args()44 args = parser.parse_args()
45 failed_ut = get_error_or_fail_ut(args.file)45 failed_ut = get_error_or_fail_ut(args.file)
46 write_to_json(ut_list=failed_ut)46 write_to_json(ut_list=failed_ut)
47 
Mtest/nn/test_uninitialized_parameter_cls_to_become.py+35-35
@@ -1,36 +1,36 @@
1import torch1import torch
2from torch.testing._internal.common_utils import TestCase, run_tests2from torch.testing._internal.common_utils import TestCase, run_tests
3import torch_npu3import torch_npu
4 4 
5# 关闭NPU JIT编译,减少CI耗时5# 关闭NPU JIT编译,减少CI耗时
6torch_npu.npu.set_compile_mode(jit_compile=False)6torch_npu.npu.set_compile_mode(jit_compile=False)
7 7 
8 8 
9# 修复:将自定义属性设为类属性(确保实例化后必存在)9# 修复:将自定义属性设为类属性(确保实例化后必存在)
10class CustomParameter(torch.nn.Parameter):10class CustomParameter(torch.nn.Parameter):
11 custom_attr = "custom_param" # 类属性,所有实例共享,无需__init__赋值11 custom_attr = "custom_param" # 类属性,所有实例共享,无需__init__赋值
12 12
13 def __init__(self, data=None, requires_grad=True):13 def __init__(self, data=None, requires_grad=True):
14 super().__init__(data, requires_grad)14 super().__init__(data, requires_grad)
15 15 
16 16 
17class TestUninitializedParameterClsToBecome(TestCase):17class TestUninitializedParameterClsToBecome(TestCase):
18 18
19 def test_core_functionality_npu(self):19 def test_core_functionality_npu(self):
20 """极简验证NPU环境下cls_to_become+materialize核心功能"""20 """极简验证NPU环境下cls_to_become+materialize核心功能"""
21 # 1. 创建NPU未初始化参数21 # 1. 创建NPU未初始化参数
22 uninit_param = torch.nn.parameter.UninitializedParameter(device="npu")22 uninit_param = torch.nn.parameter.UninitializedParameter(device="npu")
23 # 2. 绑定自定义类23 # 2. 绑定自定义类
24 uninit_param.cls_to_become = CustomParameter24 uninit_param.cls_to_become = CustomParameter
25 # 3. 实例化参数25 # 3. 实例化参数
26 uninit_param.materialize(shape=(3, 3))26 uninit_param.materialize(shape=(3, 3))
27 27 
28 # 核心断言(全部通过,无报错)28 # 核心断言(全部通过,无报错)
29 self.assertEqual(uninit_param.shape, torch.Size((3, 3)))29 self.assertEqual(uninit_param.shape, torch.Size((3, 3)))
30 self.assertEqual(uninit_param.device.type, "npu")30 self.assertEqual(uninit_param.device.type, "npu")
31 self.assertIsInstance(uninit_param, CustomParameter)31 self.assertIsInstance(uninit_param, CustomParameter)
32 self.assertEqual(uninit_param.custom_attr, "custom_param") # 现在能正常访问32 self.assertEqual(uninit_param.custom_attr, "custom_param") # 现在能正常访问
33 33 
34 34 
35if __name__ == "__main__":35if __name__ == "__main__":
36 run_tests()36 run_tests()
Mtest/npu/test_amp.py+526-526
@@ -1,526 +1,526 @@
1import unittest1import unittest
2from itertools import chain2from itertools import chain
3 3 
4import torch4import torch
5 5 
6import torch_npu6import torch_npu
7from torch_npu.npu.amp import GradScaler, autocast7from torch_npu.npu.amp import GradScaler, autocast
8from torch_npu.testing.common_utils import SupportedDevices8from torch_npu.testing.common_utils import SupportedDevices
9from torch_npu.testing.testcase import TestCase, run_tests9from torch_npu.testing.testcase import TestCase, run_tests
10 10 
11 11 
12def make_device_overflow_1():12def make_device_overflow_1():
13 float_tensor = torch.tensor([40000.0], dtype=torch.float16).npu()13 float_tensor = torch.tensor([40000.0], dtype=torch.float16).npu()
14 float_tensor = float_tensor + float_tensor14 float_tensor = float_tensor + float_tensor
15 15 
16 16 
17def make_device_overflow_2(model):17def make_device_overflow_2(model):
18 for param in model.parameters():18 for param in model.parameters():
19 if param.grad is not None:19 if param.grad is not None:
20 param.grad = torch.full_like(param.grad, float("inf"))20 param.grad = torch.full_like(param.grad, float("inf"))
21 break21 break
22 22 
23 23 
24class TestAmp(TestCase):24class TestAmp(TestCase):
25 25 
26 def test_grad_scaling_scale(self):26 def test_grad_scaling_scale(self):
27 scaler = GradScaler(init_scale=2.)27 scaler = GradScaler(init_scale=2.)
28 t0 = torch.full((1,), 4.0, dtype=torch.float32, device="npu")28 t0 = torch.full((1,), 4.0, dtype=torch.float32, device="npu")
29 t1 = torch.full((1,), 4.0, dtype=torch.float32, device="npu")29 t1 = torch.full((1,), 4.0, dtype=torch.float32, device="npu")
30 # Create some nested iterables of tensors on different devices.30 # Create some nested iterables of tensors on different devices.
31 outputs = (t1.clone(), (t0.clone(), t1.clone()), [t0.clone(), (t1.clone(), t0.clone())])31 outputs = (t1.clone(), (t0.clone(), t1.clone()), [t0.clone(), (t1.clone(), t0.clone())])
32 outputs = scaler.scale(outputs)32 outputs = scaler.scale(outputs)
33 self.assertTrue(outputs[0] == 8.0 and outputs[1][0] == 8.0 and outputs[1][1] == 8.0 and33 self.assertTrue(outputs[0] == 8.0 and outputs[1][0] == 8.0 and outputs[1][1] == 8.0 and
34 outputs[2][0] == 8.0 and outputs[2][1][0] == 8.0 and outputs[2][1][1] == 8.0)34 outputs[2][0] == 8.0 and outputs[2][1][0] == 8.0 and outputs[2][1][1] == 8.0)
35 self.assertTrue(scaler._scale.device == t1.device)35 self.assertTrue(scaler._scale.device == t1.device)
36 36 
37 def test_grad_scaling_state_dict(self):37 def test_grad_scaling_state_dict(self):
38 for lazy_init_scale in True, False:38 for lazy_init_scale in True, False:
39 s0 = GradScaler(init_scale=3., growth_factor=4., backoff_factor=.5, growth_interval=2)39 s0 = GradScaler(init_scale=3., growth_factor=4., backoff_factor=.5, growth_interval=2)
40 s1 = GradScaler(init_scale=6., growth_factor=7., backoff_factor=.8, growth_interval=1)40 s1 = GradScaler(init_scale=6., growth_factor=7., backoff_factor=.8, growth_interval=1)
41 41 
42 # sets a random value for load_state_dict to overwrite42 # sets a random value for load_state_dict to overwrite
43 s1._init_growth_tracker = 743 s1._init_growth_tracker = 7
44 44 
45 if lazy_init_scale:45 if lazy_init_scale:
46 # Dummy scale() call to ensure the scale tensor is lazily initialized.46 # Dummy scale() call to ensure the scale tensor is lazily initialized.
47 s1.scale(torch.full((1,), 4.0, dtype=torch.float32, device="npu"))47 s1.scale(torch.full((1,), 4.0, dtype=torch.float32, device="npu"))
48 self.assertTrue(isinstance(s1._scale, torch.npu.FloatTensor))48 self.assertTrue(isinstance(s1._scale, torch.npu.FloatTensor))
49 49 
50 s1.load_state_dict(s0.state_dict())50 s1.load_state_dict(s0.state_dict())
51 51 
52 self.assertTrue(s1.get_scale() == 3.)52 self.assertTrue(s1.get_scale() == 3.)
53 self.assertTrue(s1.get_growth_factor() == 4.)53 self.assertTrue(s1.get_growth_factor() == 4.)
54 self.assertTrue(s1.get_backoff_factor() == .5)54 self.assertTrue(s1.get_backoff_factor() == .5)
55 self.assertTrue(s1.get_growth_interval() == 2)55 self.assertTrue(s1.get_growth_interval() == 2)
56 self.assertTrue(s1._init_growth_tracker == 0)56 self.assertTrue(s1._init_growth_tracker == 0)
57 57 
58 def _create_scaling_models_optimizers(self, device="npu"):58 def _create_scaling_models_optimizers(self, device="npu"):
59 # Create a module+optimizer that will use scaling, and a control module+optimizer59 # Create a module+optimizer that will use scaling, and a control module+optimizer
60 # that will not use scaling, against which the scaling-enabled module+optimizer can be compared.60 # that will not use scaling, against which the scaling-enabled module+optimizer can be compared.
61 mod_control = torch.nn.Sequential(torch.nn.Linear(8, 8), torch.nn.Linear(8, 8)).to(device=device)61 mod_control = torch.nn.Sequential(torch.nn.Linear(8, 8), torch.nn.Linear(8, 8)).to(device=device)
62 mod_scaling = torch.nn.Sequential(torch.nn.Linear(8, 8), torch.nn.Linear(8, 8)).to(device=device)62 mod_scaling = torch.nn.Sequential(torch.nn.Linear(8, 8), torch.nn.Linear(8, 8)).to(device=device)
63 for c, s in zip(mod_control.parameters(), mod_scaling.parameters()):63 for c, s in zip(mod_control.parameters(), mod_scaling.parameters()):
64 s.data.copy_(c.data)64 s.data.copy_(c.data)
65 65 
66 opt_control = torch.optim.SGD(mod_control.parameters(), lr=1.0)66 opt_control = torch.optim.SGD(mod_control.parameters(), lr=1.0)
67 opt_scaling = torch.optim.SGD(mod_scaling.parameters(), lr=1.0)67 opt_scaling = torch.optim.SGD(mod_scaling.parameters(), lr=1.0)
68 68 
69 ret = (mod_control, mod_scaling, opt_control, opt_scaling)69 ret = (mod_control, mod_scaling, opt_control, opt_scaling)
70 return ret70 return ret
71 71 
72 def _create_scaling_case(self, device="npu", dtype=torch.float):72 def _create_scaling_case(self, device="npu", dtype=torch.float):
73 data = [(torch.randn((8, 8), dtype=dtype, device=device), torch.randn((8, 8), dtype=dtype, device=device)),73 data = [(torch.randn((8, 8), dtype=dtype, device=device), torch.randn((8, 8), dtype=dtype, device=device)),
74 (torch.randn((8, 8), dtype=dtype, device=device), torch.randn((8, 8), dtype=dtype, device=device)),74 (torch.randn((8, 8), dtype=dtype, device=device), torch.randn((8, 8), dtype=dtype, device=device)),
75 (torch.randn((8, 8), dtype=dtype, device=device), torch.randn((8, 8), dtype=dtype, device=device)),75 (torch.randn((8, 8), dtype=dtype, device=device), torch.randn((8, 8), dtype=dtype, device=device)),
76 (torch.randn((8, 8), dtype=dtype, device=device), torch.randn((8, 8), dtype=dtype, device=device))]76 (torch.randn((8, 8), dtype=dtype, device=device), torch.randn((8, 8), dtype=dtype, device=device))]
77 77 
78 loss_fn = torch.nn.MSELoss().npu()78 loss_fn = torch.nn.MSELoss().npu()
79 79 
80 skip_iter = 280 skip_iter = 2
81 81 
82 return self._create_scaling_models_optimizers(device=device) + (data, loss_fn, skip_iter)82 return self._create_scaling_models_optimizers(device=device) + (data, loss_fn, skip_iter)
83 83 
84 # _run_scaling_case generalizes some single-optimizer test logic to avoid too much copy-pasting below.84 # _run_scaling_case generalizes some single-optimizer test logic to avoid too much copy-pasting below.
85 def _run_scaling_case(self, run, unskipped, skipped, atol=1e-7):85 def _run_scaling_case(self, run, unskipped, skipped, atol=1e-7):
86 # Ensure scaling can be disabled without changing user control flow.86 # Ensure scaling can be disabled without changing user control flow.
87 for enabled in True, False:87 for enabled in True, False:
88 mod_control, mod_scaling, opt_control, opt_scaling, data, loss_fn, skip_iter = self._create_scaling_case()88 mod_control, mod_scaling, opt_control, opt_scaling, data, loss_fn, skip_iter = self._create_scaling_case()
89 89 
90 # For functionality, test with a modest initial scale, and an unrealistically-large growth factor90 # For functionality, test with a modest initial scale, and an unrealistically-large growth factor
91 # so any potential errors with the growth factor handling will be magnified.91 # so any potential errors with the growth factor handling will be magnified.
92 scaler = GradScaler(init_scale=128., growth_factor=2.0, enabled=enabled, growth_interval=1)92 scaler = GradScaler(init_scale=128., growth_factor=2.0, enabled=enabled, growth_interval=1)
93 93 
94 _ = run(data, mod_control, opt_control, scaler, loss_fn, skip_iter, False)94 _ = run(data, mod_control, opt_control, scaler, loss_fn, skip_iter, False)
95 ret = run(data, mod_scaling, opt_scaling, scaler, loss_fn, skip_iter, True)95 ret = run(data, mod_scaling, opt_scaling, scaler, loss_fn, skip_iter, True)
96 96 
97 # Allows run() to optionally return a different scaler instance.97 # Allows run() to optionally return a different scaler instance.
98 scaler = ret if ret else scaler98 scaler = ret if ret else scaler
99 99 
100 # If scaling was enabled, the scale factor should have been multiplied by the growth factor100 # If scaling was enabled, the scale factor should have been multiplied by the growth factor
101 # len(data) - skipped times and the backoff factor "skipped" times.101 # len(data) - skipped times and the backoff factor "skipped" times.
102 if enabled:102 if enabled:
103 net_growth = scaler.get_growth_factor()**unskipped if unskipped > 0 else 1.0103 net_growth = scaler.get_growth_factor()**unskipped if unskipped > 0 else 1.0
104 net_backoff = scaler.get_backoff_factor()**skipped if skipped > 0 else 1.0104 net_backoff = scaler.get_backoff_factor()**skipped if skipped > 0 else 1.0
105 self.assertTrue(scaler.get_scale() == (128. * net_growth * net_backoff))105 self.assertTrue(scaler.get_scale() == (128. * net_growth * net_backoff))
106 else:106 else:
107 self.assertTrue(scaler.get_scale() == 1.0)107 self.assertTrue(scaler.get_scale() == 1.0)
108 108 
109 for c, s in zip(mod_control.parameters(), mod_scaling.parameters()):109 for c, s in zip(mod_control.parameters(), mod_scaling.parameters()):
110 c = c.cpu().to(torch.float).detach().numpy()110 c = c.cpu().to(torch.float).detach().numpy()
111 s = s.cpu().to(torch.float).detach().numpy()111 s = s.cpu().to(torch.float).detach().numpy()
112 self.assertRtolEqual(c, s, atol)112 self.assertRtolEqual(c, s, atol)
113 113 
114 # Compares no scaling + no autocasting against scaling + autocasting.114 # Compares no scaling + no autocasting against scaling + autocasting.
115 @SupportedDevices(['Ascend910A', 'Ascend910P'])115 @SupportedDevices(['Ascend910A', 'Ascend910P'])
116 def test_grad_scaling_autocast_1(self):116 def test_grad_scaling_autocast_1(self):
117 def run(data, model, optimizer, scaler, loss_fn, skip_iter, try_scaling_api):117 def run(data, model, optimizer, scaler, loss_fn, skip_iter, try_scaling_api):
118 for i, (input_data, target) in enumerate(data):118 for i, (input_data, target) in enumerate(data):
119 optimizer.zero_grad()119 optimizer.zero_grad()
120 with torch.autocast('npu', enabled=try_scaling_api):120 with torch.autocast('npu', enabled=try_scaling_api):
121 output = model(input_data)121 output = model(input_data)
122 loss = loss_fn(output, target)122 loss = loss_fn(output, target)
123 if try_scaling_api:123 if try_scaling_api:
124 scaler.scale(loss).backward()124 scaler.scale(loss).backward()
125 if i == skip_iter and scaler.is_enabled():125 if i == skip_iter and scaler.is_enabled():
126 make_device_overflow_1()126 make_device_overflow_1()
127 scaler.step(optimizer)127 scaler.step(optimizer)
128 scaler.update()128 scaler.update()
129 else:129 else:
130 loss.backward()130 loss.backward()
131 if (not scaler.is_enabled()) or (i != skip_iter):131 if (not scaler.is_enabled()) or (i != skip_iter):
132 optimizer.step()132 optimizer.step()
133 return scaler133 return scaler
134 134 
135 # sets atol=1e-3 because we're comparing pure fp32 arithmetic vs a mixture of fp16 and fp32135 # sets atol=1e-3 because we're comparing pure fp32 arithmetic vs a mixture of fp16 and fp32
136 self._run_scaling_case(run, unskipped=3, skipped=1, atol=1e-3)136 self._run_scaling_case(run, unskipped=3, skipped=1, atol=1e-3)
137 137 
138 @SupportedDevices(['Ascend910B'])138 @SupportedDevices(['Ascend910B'])
139 def test_grad_scaling_autocast_2(self):139 def test_grad_scaling_autocast_2(self):
140 def run(data, model, optimizer, scaler, loss_fn, skip_iter, try_scaling_api):140 def run(data, model, optimizer, scaler, loss_fn, skip_iter, try_scaling_api):
141 for i, (input_data, target) in enumerate(data):141 for i, (input_data, target) in enumerate(data):
142 optimizer.zero_grad()142 optimizer.zero_grad()
143 with torch.autocast('npu', enabled=try_scaling_api):143 with torch.autocast('npu', enabled=try_scaling_api):
144 output = model(input_data)144 output = model(input_data)
145 loss = loss_fn(output, target)145 loss = loss_fn(output, target)
146 if try_scaling_api:146 if try_scaling_api:
147 scaler.scale(loss).backward()147 scaler.scale(loss).backward()
148 if i == skip_iter and scaler.is_enabled():148 if i == skip_iter and scaler.is_enabled():
149 make_device_overflow_2(model)149 make_device_overflow_2(model)
150 scaler.step(optimizer)150 scaler.step(optimizer)
151 scaler.update()151 scaler.update()
152 else:152 else:
153 loss.backward()153 loss.backward()
154 if (not scaler.is_enabled()) or (i != skip_iter):154 if (not scaler.is_enabled()) or (i != skip_iter):
155 optimizer.step()155 optimizer.step()
156 return scaler156 return scaler
157 157 
158 # sets atol=1e-3 because we're comparing pure fp32 arithmetic vs a mixture of fp16 and fp32158 # sets atol=1e-3 because we're comparing pure fp32 arithmetic vs a mixture of fp16 and fp32
159 self._run_scaling_case(run, unskipped=3, skipped=1, atol=1e-3)159 self._run_scaling_case(run, unskipped=3, skipped=1, atol=1e-3)
160 160 
161 @SupportedDevices(['Ascend910A', 'Ascend910P'])161 @SupportedDevices(['Ascend910A', 'Ascend910P'])
162 def test_grad_scaling_clipping_1(self):162 def test_grad_scaling_clipping_1(self):
163 def run(data, model, optimizer, scaler, loss_fn, skip_iter, try_scaling_api):163 def run(data, model, optimizer, scaler, loss_fn, skip_iter, try_scaling_api):
164 max_norm = 0.2 # A reasonable value that actually has an effect, based on printouts of grads164 max_norm = 0.2 # A reasonable value that actually has an effect, based on printouts of grads
165 for i, (input_data, target) in enumerate(data):165 for i, (input_data, target) in enumerate(data):
166 optimizer.zero_grad()166 optimizer.zero_grad()
167 output = model(input_data)167 output = model(input_data)
168 loss = loss_fn(output, target)168 loss = loss_fn(output, target)
169 if try_scaling_api:169 if try_scaling_api:
170 scaler.scale(loss).backward()170 scaler.scale(loss).backward()
171 torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm * scaler.get_scale())171 torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm * scaler.get_scale())
172 if i == skip_iter and scaler.is_enabled():172 if i == skip_iter and scaler.is_enabled():
173 make_device_overflow_1()173 make_device_overflow_1()
174 scaler.step(optimizer)174 scaler.step(optimizer)
175 scaler.update()175 scaler.update()
176 else:176 else:
177 loss.backward()177 loss.backward()
178 torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm)178 torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm)
179 if (not scaler.is_enabled()) or (i != skip_iter):179 if (not scaler.is_enabled()) or (i != skip_iter):
180 optimizer.step()180 optimizer.step()
181 181 
182 self._run_scaling_case(run, unskipped=3, skipped=1, atol=1e-6)182 self._run_scaling_case(run, unskipped=3, skipped=1, atol=1e-6)
183 183 
184 @SupportedDevices(['Ascend910B'])184 @SupportedDevices(['Ascend910B'])
185 def test_grad_scaling_clipping_2(self):185 def test_grad_scaling_clipping_2(self):
186 def run(data, model, optimizer, scaler, loss_fn, skip_iter, try_scaling_api):186 def run(data, model, optimizer, scaler, loss_fn, skip_iter, try_scaling_api):
187 max_norm = 0.2 # A reasonable value that actually has an effect, based on printouts of grads187 max_norm = 0.2 # A reasonable value that actually has an effect, based on printouts of grads
188 for i, (input_data, target) in enumerate(data):188 for i, (input_data, target) in enumerate(data):
189 optimizer.zero_grad()189 optimizer.zero_grad()
190 output = model(input_data)190 output = model(input_data)
191 loss = loss_fn(output, target)191 loss = loss_fn(output, target)
192 if try_scaling_api:192 if try_scaling_api:
193 scaler.scale(loss).backward()193 scaler.scale(loss).backward()
194 torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm * scaler.get_scale())194 torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm * scaler.get_scale())
195 if i == skip_iter and scaler.is_enabled():195 if i == skip_iter and scaler.is_enabled():
196 make_device_overflow_2(model)196 make_device_overflow_2(model)
197 scaler.step(optimizer)197 scaler.step(optimizer)
198 scaler.update()198 scaler.update()
199 else:199 else:
200 loss.backward()200 loss.backward()
201 torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm)201 torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm)
202 if (not scaler.is_enabled()) or (i != skip_iter):202 if (not scaler.is_enabled()) or (i != skip_iter):
203 optimizer.step()203 optimizer.step()
204 204 
205 self._run_scaling_case(run, unskipped=3, skipped=1, atol=1e-6)205 self._run_scaling_case(run, unskipped=3, skipped=1, atol=1e-6)
206 206 
207 @SupportedDevices(['Ascend910A', 'Ascend910P'])207 @SupportedDevices(['Ascend910A', 'Ascend910P'])
208 def test_grad_scaling_clipping_separate_unscale_1(self):208 def test_grad_scaling_clipping_separate_unscale_1(self):
209 def run(data, model, optimizer, scaler, loss_fn, skip_iter, try_scaling_api):209 def run(data, model, optimizer, scaler, loss_fn, skip_iter, try_scaling_api):
210 max_norm = 0.2 # A reasonable value that actually has an effect, based on printouts of grads210 max_norm = 0.2 # A reasonable value that actually has an effect, based on printouts of grads
211 for i, (input_data, target) in enumerate(data):211 for i, (input_data, target) in enumerate(data):
212 optimizer.zero_grad()212 optimizer.zero_grad()
213 output = model(input_data)213 output = model(input_data)
214 loss = loss_fn(output, target)214 loss = loss_fn(output, target)
215 if try_scaling_api:215 if try_scaling_api:
216 scaler.scale(loss).backward()216 scaler.scale(loss).backward()
217 if i == skip_iter and scaler.is_enabled():217 if i == skip_iter and scaler.is_enabled():
218 make_device_overflow_1()218 make_device_overflow_1()
219 scaler.unscale_(optimizer)219 scaler.unscale_(optimizer)
220 torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm)220 torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm)
221 scaler.step(optimizer)221 scaler.step(optimizer)
222 scaler.update()222 scaler.update()
223 else:223 else:
224 loss.backward()224 loss.backward()
225 torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm)225 torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm)
226 if (not scaler.is_enabled()) or (i != skip_iter):226 if (not scaler.is_enabled()) or (i != skip_iter):
227 optimizer.step()227 optimizer.step()
228 228 
229 self._run_scaling_case(run, unskipped=3, skipped=1)229 self._run_scaling_case(run, unskipped=3, skipped=1)
230 230 
231 @SupportedDevices(['Ascend910B'])231 @SupportedDevices(['Ascend910B'])
232 def test_grad_scaling_clipping_separate_unscale_2(self):232 def test_grad_scaling_clipping_separate_unscale_2(self):
233 def run(data, model, optimizer, scaler, loss_fn, skip_iter, try_scaling_api):233 def run(data, model, optimizer, scaler, loss_fn, skip_iter, try_scaling_api):
234 max_norm = 0.2 # A reasonable value that actually has an effect, based on printouts of grads234 max_norm = 0.2 # A reasonable value that actually has an effect, based on printouts of grads
235 for i, (input_data, target) in enumerate(data):235 for i, (input_data, target) in enumerate(data):
236 optimizer.zero_grad()236 optimizer.zero_grad()
237 output = model(input_data)237 output = model(input_data)
238 loss = loss_fn(output, target)238 loss = loss_fn(output, target)
239 if try_scaling_api:239 if try_scaling_api:
240 scaler.scale(loss).backward()240 scaler.scale(loss).backward()
241 if i == skip_iter and scaler.is_enabled():241 if i == skip_iter and scaler.is_enabled():
242 make_device_overflow_2(model)242 make_device_overflow_2(model)
243 scaler.unscale_(optimizer)243 scaler.unscale_(optimizer)
244 torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm)244 torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm)
245 scaler.step(optimizer)245 scaler.step(optimizer)
246 scaler.update()246 scaler.update()
247 else:247 else:
248 loss.backward()248 loss.backward()
249 torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm)249 torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm)
250 if (not scaler.is_enabled()) or (i != skip_iter):250 if (not scaler.is_enabled()) or (i != skip_iter):
251 optimizer.step()251 optimizer.step()
252 252 
253 self._run_scaling_case(run, unskipped=3, skipped=1)253 self._run_scaling_case(run, unskipped=3, skipped=1)
254 254 
255 @SupportedDevices(['Ascend910A', 'Ascend910P'])255 @SupportedDevices(['Ascend910A', 'Ascend910P'])
256 def test_grad_scaling_penalty_1(self):256 def test_grad_scaling_penalty_1(self):
257 def run(data, model, optimizer, scaler, loss_fn, skip_iter, try_scaling_api):257 def run(data, model, optimizer, scaler, loss_fn, skip_iter, try_scaling_api):
258 for i, (input_data, target) in enumerate(data):258 for i, (input_data, target) in enumerate(data):
259 optimizer.zero_grad()259 optimizer.zero_grad()
260 output = model(input_data)260 output = model(input_data)
261 loss = loss_fn(output, target)261 loss = loss_fn(output, target)
262 262 
263 if try_scaling_api:263 if try_scaling_api:
264 grad_params = torch.autograd.grad(scaler.scale(loss),264 grad_params = torch.autograd.grad(scaler.scale(loss),
265 model.parameters(), create_graph=True)265 model.parameters(), create_graph=True)
266 inv_scale = 1. / scaler.get_scale()266 inv_scale = 1. / scaler.get_scale()
267 grad_params = [p * inv_scale for p in grad_params]267 grad_params = [p * inv_scale for p in grad_params]
268 else:268 else:
269 grad_params = torch.autograd.grad(loss, model.parameters(), create_graph=True)269 grad_params = torch.autograd.grad(loss, model.parameters(), create_graph=True)
270 270 
271 grad_norm = 0271 grad_norm = 0
272 for grad in grad_params:272 for grad in grad_params:
273 grad_norm += grad.pow(2).sum()273 grad_norm += grad.pow(2).sum()
274 grad_norm = grad_norm.sqrt()274 grad_norm = grad_norm.sqrt()
275 loss = loss + grad_norm275 loss = loss + grad_norm
276 276 
277 if try_scaling_api:277 if try_scaling_api:
278 scaler.scale(loss).backward()278 scaler.scale(loss).backward()
279 if i == skip_iter and scaler.is_enabled():279 if i == skip_iter and scaler.is_enabled():
280 make_device_overflow_1()280 make_device_overflow_1()
281 scaler.step(optimizer)281 scaler.step(optimizer)
282 scaler.update()282 scaler.update()
283 else:283 else:
284 loss.backward()284 loss.backward()
285 if (not scaler.is_enabled()) or (i != skip_iter):285 if (not scaler.is_enabled()) or (i != skip_iter):
286 optimizer.step()286 optimizer.step()
287 287 
288 self._run_scaling_case(run, unskipped=3, skipped=1)288 self._run_scaling_case(run, unskipped=3, skipped=1)
289 289 
290 @SupportedDevices(['Ascend910B'])290 @SupportedDevices(['Ascend910B'])
291 def test_grad_scaling_penalty_2(self):291 def test_grad_scaling_penalty_2(self):
292 def run(data, model, optimizer, scaler, loss_fn, skip_iter, try_scaling_api):292 def run(data, model, optimizer, scaler, loss_fn, skip_iter, try_scaling_api):
293 for i, (input_data, target) in enumerate(data):293 for i, (input_data, target) in enumerate(data):
294 optimizer.zero_grad()294 optimizer.zero_grad()
295 output = model(input_data)295 output = model(input_data)
296 loss = loss_fn(output, target)296 loss = loss_fn(output, target)
297 297 
298 if try_scaling_api:298 if try_scaling_api:
299 grad_params = torch.autograd.grad(scaler.scale(loss),299 grad_params = torch.autograd.grad(scaler.scale(loss),
300 model.parameters(), create_graph=True)300 model.parameters(), create_graph=True)
301 inv_scale = 1. / scaler.get_scale()301 inv_scale = 1. / scaler.get_scale()
302 grad_params = [p * inv_scale for p in grad_params]302 grad_params = [p * inv_scale for p in grad_params]
303 else:303 else:
304 grad_params = torch.autograd.grad(loss, model.parameters(), create_graph=True)304 grad_params = torch.autograd.grad(loss, model.parameters(), create_graph=True)
305 305 
306 grad_norm = 0306 grad_norm = 0
307 for grad in grad_params:307 for grad in grad_params:
308 grad_norm += grad.pow(2).sum()308 grad_norm += grad.pow(2).sum()
309 grad_norm = grad_norm.sqrt()309 grad_norm = grad_norm.sqrt()
310 loss = loss + grad_norm310 loss = loss + grad_norm
311 311 
312 if try_scaling_api:312 if try_scaling_api:
313 scaler.scale(loss).backward()313 scaler.scale(loss).backward()
314 if i == skip_iter and scaler.is_enabled():314 if i == skip_iter and scaler.is_enabled():
315 make_device_overflow_2(model)315 make_device_overflow_2(model)
316 scaler.step(optimizer)316 scaler.step(optimizer)
317 scaler.update()317 scaler.update()
318 else:318 else:
319 loss.backward()319 loss.backward()
320 if (not scaler.is_enabled()) or (i != skip_iter):320 if (not scaler.is_enabled()) or (i != skip_iter):
321 optimizer.step()321 optimizer.step()
322 322 
323 self._run_scaling_case(run, unskipped=3, skipped=1)323 self._run_scaling_case(run, unskipped=3, skipped=1)
324 324 
325 def test_grad_scaling_accumulation(self):325 def test_grad_scaling_accumulation(self):
326 def run(data, model, optimizer, scaler, loss_fn, skip_iter, try_scaling_api):326 def run(data, model, optimizer, scaler, loss_fn, skip_iter, try_scaling_api):
327 iters_to_accumulate = 2327 iters_to_accumulate = 2
328 for i, (input_data, target) in enumerate(data):328 for i, (input_data, target) in enumerate(data):
329 output = model(input_data)329 output = model(input_data)
330 loss = loss_fn(output, target)330 loss = loss_fn(output, target)
331 loss = loss / iters_to_accumulate331 loss = loss / iters_to_accumulate
332 if try_scaling_api:332 if try_scaling_api:
333 scaler.scale(loss).backward()333 scaler.scale(loss).backward()
334 else:334 else:
335 loss.backward()335 loss.backward()
336 if (i + 1) % iters_to_accumulate == 0:336 if (i + 1) % iters_to_accumulate == 0:
337 if try_scaling_api:337 if try_scaling_api:
338 scaler.step(optimizer)338 scaler.step(optimizer)
339 scaler.update()339 scaler.update()
340 optimizer.zero_grad()340 optimizer.zero_grad()
341 else:341 else:
342 optimizer.step()342 optimizer.step()
343 optimizer.zero_grad()343 optimizer.zero_grad()
344 344 
345 self._run_scaling_case(run, unskipped=2, skipped=0)345 self._run_scaling_case(run, unskipped=2, skipped=0)
346 346 
347 @SupportedDevices(['Ascend910A', 'Ascend910P'])347 @SupportedDevices(['Ascend910A', 'Ascend910P'])
348 def test_grad_scaling_multiple_1(self):348 def test_grad_scaling_multiple_1(self):
349 # Tests gradient scaling with 2 models and 2 optimizers that both receive gradients from 2 losses.349 # Tests gradient scaling with 2 models and 2 optimizers that both receive gradients from 2 losses.
350 # Some of the logic here cannot reuse the generic helper functions created for the 1-optimizer cases.350 # Some of the logic here cannot reuse the generic helper functions created for the 1-optimizer cases.
351 for enabled in True, False:351 for enabled in True, False:
352 mod_control0, mod_scaling0, opt_control0, opt_scaling0, data, loss_fn, skip_iter = \352 mod_control0, mod_scaling0, opt_control0, opt_scaling0, data, loss_fn, skip_iter = \
353 self._create_scaling_case()353 self._create_scaling_case()
354 mod_control1, mod_scaling1, opt_control1, opt_scaling1 = \354 mod_control1, mod_scaling1, opt_control1, opt_scaling1 = \
355 self._create_scaling_models_optimizers()355 self._create_scaling_models_optimizers()
356 356 
357 scaler = GradScaler(init_scale=128., growth_factor=2.0, enabled=enabled, growth_interval=1)357 scaler = GradScaler(init_scale=128., growth_factor=2.0, enabled=enabled, growth_interval=1)
358 358 
359 def run(model0, model1, optimizer0, optimizer1, try_scaling_api):359 def run(model0, model1, optimizer0, optimizer1, try_scaling_api):
360 for i, (input_data, target) in enumerate(data):360 for i, (input_data, target) in enumerate(data):
361 optimizer0.zero_grad()361 optimizer0.zero_grad()
362 optimizer1.zero_grad()362 optimizer1.zero_grad()
363 output0 = model0(input_data)363 output0 = model0(input_data)
364 output1 = model1(input_data)364 output1 = model1(input_data)
365 loss0 = loss_fn(0.3 * output0 + 0.7 * output1, target)365 loss0 = loss_fn(0.3 * output0 + 0.7 * output1, target)
366 loss1 = loss_fn(0.6 * output0 - 0.4 * output1, target)366 loss1 = loss_fn(0.6 * output0 - 0.4 * output1, target)
367 367 
368 if try_scaling_api:368 if try_scaling_api:
369 scaler.scale(loss0).backward(retain_graph=True)369 scaler.scale(loss0).backward(retain_graph=True)
370 scaler.scale(loss1).backward()370 scaler.scale(loss1).backward()
371 if i == skip_iter and scaler.is_enabled():371 if i == skip_iter and scaler.is_enabled():
372 make_device_overflow_1()372 make_device_overflow_1()
373 373 
374 # As an additional stress test, separately unscale for one of the optimizers.374 # As an additional stress test, separately unscale for one of the optimizers.
375 scaler.unscale_(optimizer0)375 scaler.unscale_(optimizer0)
376 376 
377 scaler.step(optimizer0)377 scaler.step(optimizer0)
378 scaler.step(optimizer1)378 scaler.step(optimizer1)
379 scaler.update()379 scaler.update()
380 else:380 else:
381 loss0.backward(retain_graph=True)381 loss0.backward(retain_graph=True)
382 loss1.backward()382 loss1.backward()
383 if (not scaler.is_enabled()) or (i != skip_iter):383 if (not scaler.is_enabled()) or (i != skip_iter):
384 optimizer0.step()384 optimizer0.step()
385 optimizer1.step()385 optimizer1.step()
386 386 
387 run(mod_control0, mod_control1, opt_control0, opt_control1, False)387 run(mod_control0, mod_control1, opt_control0, opt_control1, False)
388 run(mod_scaling0, mod_scaling1, opt_scaling0, opt_scaling1, True)388 run(mod_scaling0, mod_scaling1, opt_scaling0, opt_scaling1, True)
389 389 
390 # The loss scale should have been multiplied by the growth factor 3 times and the backoff factor once.390 # The loss scale should have been multiplied by the growth factor 3 times and the backoff factor once.
391 self.assertTrue(scaler.get_scale() == (128. * scaler.get_growth_factor()**3 *391 self.assertTrue(scaler.get_scale() == (128. * scaler.get_growth_factor()**3 *
392 scaler.get_backoff_factor()**1) if enabled else 1.0)392 scaler.get_backoff_factor()**1) if enabled else 1.0)
393 393 
394 for c, s in zip(chain(mod_control0.parameters(), mod_control1.parameters()),394 for c, s in zip(chain(mod_control0.parameters(), mod_control1.parameters()),
395 chain(mod_scaling0.parameters(), mod_scaling1.parameters())):395 chain(mod_scaling0.parameters(), mod_scaling1.parameters())):
396 c = c.cpu().to(torch.float).detach().numpy()396 c = c.cpu().to(torch.float).detach().numpy()
397 s = s.cpu().to(torch.float).detach().numpy()397 s = s.cpu().to(torch.float).detach().numpy()
398 self.assertRtolEqual(c, s, 1e-7)398 self.assertRtolEqual(c, s, 1e-7)
399 399 
400 @SupportedDevices(['Ascend910B'])400 @SupportedDevices(['Ascend910B'])
401 def test_grad_scaling_multiple_2(self):401 def test_grad_scaling_multiple_2(self):
402 # Tests gradient scaling with 2 models and 2 optimizers that both receive gradients from 2 losses.402 # Tests gradient scaling with 2 models and 2 optimizers that both receive gradients from 2 losses.
403 # Some of the logic here cannot reuse the generic helper functions created for the 1-optimizer cases.403 # Some of the logic here cannot reuse the generic helper functions created for the 1-optimizer cases.
404 for enabled in True, False:404 for enabled in True, False:
405 mod_control0, mod_scaling0, opt_control0, opt_scaling0, data, loss_fn, skip_iter = \405 mod_control0, mod_scaling0, opt_control0, opt_scaling0, data, loss_fn, skip_iter = \
406 self._create_scaling_case()406 self._create_scaling_case()
407 mod_control1, mod_scaling1, opt_control1, opt_scaling1 = \407 mod_control1, mod_scaling1, opt_control1, opt_scaling1 = \
408 self._create_scaling_models_optimizers()408 self._create_scaling_models_optimizers()
409 409 
410 scaler = GradScaler(init_scale=128., growth_factor=2.0, enabled=enabled, growth_interval=1)410 scaler = GradScaler(init_scale=128., growth_factor=2.0, enabled=enabled, growth_interval=1)
411 411 
412 def run(model0, model1, optimizer0, optimizer1, try_scaling_api):412 def run(model0, model1, optimizer0, optimizer1, try_scaling_api):
413 for i, (input_data, target) in enumerate(data):413 for i, (input_data, target) in enumerate(data):
414 optimizer0.zero_grad()414 optimizer0.zero_grad()
415 optimizer1.zero_grad()415 optimizer1.zero_grad()
416 output0 = model0(input_data)416 output0 = model0(input_data)
417 output1 = model1(input_data)417 output1 = model1(input_data)
418 loss0 = loss_fn(0.3 * output0 + 0.7 * output1, target)418 loss0 = loss_fn(0.3 * output0 + 0.7 * output1, target)
419 loss1 = loss_fn(0.6 * output0 - 0.4 * output1, target)419 loss1 = loss_fn(0.6 * output0 - 0.4 * output1, target)
420 420 
421 if try_scaling_api:421 if try_scaling_api:
422 scaler.scale(loss0).backward(retain_graph=True)422 scaler.scale(loss0).backward(retain_graph=True)
423 scaler.scale(loss1).backward()423 scaler.scale(loss1).backward()
424 if i == skip_iter and scaler.is_enabled():424 if i == skip_iter and scaler.is_enabled():
425 make_device_overflow_2(model0)425 make_device_overflow_2(model0)
426 426 
427 # As an additional stress test, separately unscale for one of the optimizers.427 # As an additional stress test, separately unscale for one of the optimizers.
428 scaler.unscale_(optimizer0)428 scaler.unscale_(optimizer0)
429 429 
430 scaler.step(optimizer0)430 scaler.step(optimizer0)
431 scaler.step(optimizer1)431 scaler.step(optimizer1)
432 scaler.update()432 scaler.update()
433 else:433 else:
434 loss0.backward(retain_graph=True)434 loss0.backward(retain_graph=True)
435 loss1.backward()435 loss1.backward()
436 if (not scaler.is_enabled()) or (i != skip_iter):436 if (not scaler.is_enabled()) or (i != skip_iter):
437 optimizer0.step()437 optimizer0.step()
438 optimizer1.step()438 optimizer1.step()
439 439 
440 run(mod_control0, mod_control1, opt_control0, opt_control1, False)440 run(mod_control0, mod_control1, opt_control0, opt_control1, False)
441 run(mod_scaling0, mod_scaling1, opt_scaling0, opt_scaling1, True)441 run(mod_scaling0, mod_scaling1, opt_scaling0, opt_scaling1, True)
442 442 
443 # The loss scale should have been multiplied by the growth factor 3 times and the backoff factor once.443 # The loss scale should have been multiplied by the growth factor 3 times and the backoff factor once.
444 self.assertTrue(scaler.get_scale() == (128. * scaler.get_growth_factor() ** 3 *444 self.assertTrue(scaler.get_scale() == (128. * scaler.get_growth_factor() ** 3 *
445 scaler.get_backoff_factor() ** 1) if enabled else 1.0)445 scaler.get_backoff_factor() ** 1) if enabled else 1.0)
446 446 
447 for c, s in zip(chain(mod_control0.parameters(), mod_control1.parameters()),447 for c, s in zip(chain(mod_control0.parameters(), mod_control1.parameters()),
448 chain(mod_scaling0.parameters(), mod_scaling1.parameters())):448 chain(mod_scaling0.parameters(), mod_scaling1.parameters())):
449 c = c.cpu().to(torch.float).detach().numpy()449 c = c.cpu().to(torch.float).detach().numpy()
450 s = s.cpu().to(torch.float).detach().numpy()450 s = s.cpu().to(torch.float).detach().numpy()
451 self.assertRtolEqual(c, s, 1e-7)451 self.assertRtolEqual(c, s, 1e-7)
452 452 
453 def test_autocast_custom_enabled(self):453 def test_autocast_custom_enabled(self):
454 class MyMM(torch.autograd.Function):454 class MyMM(torch.autograd.Function):
455 @staticmethod455 @staticmethod
456 @torch.npu.amp.custom_fwd456 @torch.npu.amp.custom_fwd
457 def forward(ctx, a, b):457 def forward(ctx, a, b):
458 self.assertTrue(ctx._dtype is torch.get_autocast_dtype("npu"))458 self.assertTrue(ctx._dtype is torch.get_autocast_dtype("npu"))
459 self.assertTrue(a.dtype is torch.float32)459 self.assertTrue(a.dtype is torch.float32)
460 self.assertTrue(b.dtype is torch.float32)460 self.assertTrue(b.dtype is torch.float32)
461 self.assertTrue(torch.npu.is_autocast_enabled())461 self.assertTrue(torch.npu.is_autocast_enabled())
462 ctx.save_for_backward(a, b)462 ctx.save_for_backward(a, b)
463 return a.mm(b)463 return a.mm(b)
464 464 
465 @staticmethod465 @staticmethod
466 @torch.npu.amp.custom_bwd466 @torch.npu.amp.custom_bwd
467 def backward(ctx, grad):467 def backward(ctx, grad):
468 self.assertTrue(ctx._dtype is torch.get_autocast_dtype("npu"))468 self.assertTrue(ctx._dtype is torch.get_autocast_dtype("npu"))
469 self.assertTrue(torch.npu.is_autocast_enabled())469 self.assertTrue(torch.npu.is_autocast_enabled())
470 a, b = ctx.saved_tensors470 a, b = ctx.saved_tensors
471 return grad.mm(b.t()), a.t().mm(grad)471 return grad.mm(b.t()), a.t().mm(grad)
472 472 
473 mymm = MyMM.apply473 mymm = MyMM.apply
474 474 
475 x = torch.randn((8, 8), device="npu", dtype=torch.float32, requires_grad=True)475 x = torch.randn((8, 8), device="npu", dtype=torch.float32, requires_grad=True)
476 y = torch.randn((8, 8), device="npu", dtype=torch.float32, requires_grad=True)476 y = torch.randn((8, 8), device="npu", dtype=torch.float32, requires_grad=True)
477 477 
478 with torch.npu.amp.autocast():478 with torch.npu.amp.autocast():
479 output = mymm(x, y)479 output = mymm(x, y)
480 self.assertTrue(output.dtype is torch.float16)480 self.assertTrue(output.dtype is torch.float16)
481 loss = output.sum()481 loss = output.sum()
482 loss.backward()482 loss.backward()
483 483 
484 def test_autocast_custom_cast_inputs(self):484 def test_autocast_custom_cast_inputs(self):
485 class MyMM(torch.autograd.Function):485 class MyMM(torch.autograd.Function):
486 @staticmethod486 @staticmethod
487 @torch.npu.amp.custom_fwd(cast_inputs=torch.float32)487 @torch.npu.amp.custom_fwd(cast_inputs=torch.float32)
488 def forward(ctx, a, container, expect_type):488 def forward(ctx, a, container, expect_type):
489 self.assertTrue(ctx._dtype is torch.get_autocast_dtype("npu"))489 self.assertTrue(ctx._dtype is torch.get_autocast_dtype("npu"))
490 b = container[1][0]490 b = container[1][0]
491 self.assertTrue(a.dtype is expect_type)491 self.assertTrue(a.dtype is expect_type)
492 self.assertTrue(b.dtype is expect_type)492 self.assertTrue(b.dtype is expect_type)
493 self.assertFalse(torch.npu.is_autocast_enabled())493 self.assertFalse(torch.npu.is_autocast_enabled())
494 ctx.save_for_backward(a, b)494 ctx.save_for_backward(a, b)
495 return a.mm(b)495 return a.mm(b)
496 496 
497 @staticmethod497 @staticmethod
498 @torch.npu.amp.custom_bwd498 @torch.npu.amp.custom_bwd
499 def backward(ctx, grad):499 def backward(ctx, grad):
500 self.assertTrue(ctx._dtype is torch.get_autocast_dtype("npu"))500 self.assertTrue(ctx._dtype is torch.get_autocast_dtype("npu"))
501 a, b = ctx.saved_tensors501 a, b = ctx.saved_tensors
502 return grad.mm(b.t()), None, None502 return grad.mm(b.t()), None, None
503 503 
504 mymm = MyMM.apply504 mymm = MyMM.apply
505 505 
506 x = torch.randn((8, 8), device="npu", dtype=torch.float16, requires_grad=True)506 x = torch.randn((8, 8), device="npu", dtype=torch.float16, requires_grad=True)
507 # Puts one input tensor in a nested container. y's contained Tensor won't receive a gradient,507 # Puts one input tensor in a nested container. y's contained Tensor won't receive a gradient,
508 # because torch.autograd.Function can't hand gradients back to non-Tensor forward arguments.508 # because torch.autograd.Function can't hand gradients back to non-Tensor forward arguments.
509 # Sets requires_grad=False explicitly so we don't lie about expecting a gradient.509 # Sets requires_grad=False explicitly so we don't lie about expecting a gradient.
510 y = (0, {0: torch.randn((8, 8), device="npu", dtype=torch.float16, requires_grad=False)})510 y = (0, {0: torch.randn((8, 8), device="npu", dtype=torch.float16, requires_grad=False)})
511 511 
512 with torch.autocast('npu', ):512 with torch.autocast('npu', ):
513 output = mymm(x, y, torch.float32)513 output = mymm(x, y, torch.float32)
514 self.assertTrue(output.dtype is torch.float32)514 self.assertTrue(output.dtype is torch.float32)
515 loss = output.sum()515 loss = output.sum()
516 loss.backward()516 loss.backward()
517 517 
518 # Tests if custom_fwd becomes a no-op when mymm runs outside an autocast-enabled region.518 # Tests if custom_fwd becomes a no-op when mymm runs outside an autocast-enabled region.
519 output = mymm(x, y, torch.float16)519 output = mymm(x, y, torch.float16)
520 self.assertTrue(output.dtype is torch.float16)520 self.assertTrue(output.dtype is torch.float16)
521 loss = output.sum()521 loss = output.sum()
522 loss.backward()522 loss.backward()
523 523 
524 524 
525if __name__ == "__main__":525if __name__ == "__main__":
526 run_tests()526 run_tests()
Mtest/npu/test_copy.py+137-137
@@ -1,138 +1,138 @@
1import unittest1import unittest
2import torch2import torch
3import numpy as np3import numpy as np
4 4 
5import torch_npu5import torch_npu
6from torch_npu.testing.testcase import TestCase, run_tests6from torch_npu.testing.testcase import TestCase, run_tests
7from torch_npu.testing.common_utils import create_common_tensor7from torch_npu.testing.common_utils import create_common_tensor
8 8 
9 9 
10class TestCopyKernelMemoryFormat(TestCase):10class TestCopyKernelMemoryFormat(TestCase):
11 def test_h2d_copy_contiguous_tensor(self):11 def test_h2d_copy_contiguous_tensor(self):
12 dtype_list = [np.float16, np.float32, np.int32, np.int64]12 dtype_list = [np.float16, np.float32, np.int32, np.int64]
13 shape_list = [[10, 20], [32, 64, 128], [2, 3, 4, 5]]13 shape_list = [[10, 20], [32, 64, 128], [2, 3, 4, 5]]
14 shape_format = [14 shape_format = [
15 [dtype, 2, shape] for dtype in dtype_list for shape in shape_list15 [dtype, 2, shape] for dtype in dtype_list for shape in shape_list
16 ]16 ]
17 17
18 for item in shape_format:18 for item in shape_format:
19 cpu_input, npu_input = create_common_tensor(item, -100, 100)19 cpu_input, npu_input = create_common_tensor(item, -100, 100)
20 npu_input_copy = cpu_input.npu()20 npu_input_copy = cpu_input.npu()
21 self.assertRtolEqual(npu_input_copy.cpu().numpy(), cpu_input.numpy())21 self.assertRtolEqual(npu_input_copy.cpu().numpy(), cpu_input.numpy())
22 22 
23 def test_h2d_copy_non_contiguous_tensor(self):23 def test_h2d_copy_non_contiguous_tensor(self):
24 dtype_list = [np.float16, np.float32]24 dtype_list = [np.float16, np.float32]
25 shape_list = [[32, 64], [16, 32, 64]]25 shape_list = [[32, 64], [16, 32, 64]]
26 shape_format = [26 shape_format = [
27 [dtype, 2, shape] for dtype in dtype_list for shape in shape_list27 [dtype, 2, shape] for dtype in dtype_list for shape in shape_list
28 ]28 ]
29 29
30 for item in shape_format:30 for item in shape_format:
31 cpu_input, npu_input = create_common_tensor(item, -100, 100)31 cpu_input, npu_input = create_common_tensor(item, -100, 100)
32 cpu_transposed = cpu_input.transpose(-1, -2)32 cpu_transposed = cpu_input.transpose(-1, -2)
33 npu_transposed = cpu_transposed.npu()33 npu_transposed = cpu_transposed.npu()
34 npu_contiguous = npu_transposed.contiguous()34 npu_contiguous = npu_transposed.contiguous()
35 self.assertRtolEqual(npu_contiguous.cpu().numpy(), cpu_transposed.contiguous().numpy())35 self.assertRtolEqual(npu_contiguous.cpu().numpy(), cpu_transposed.contiguous().numpy())
36 36 
37 def test_d2h_copy_contiguous_tensor(self):37 def test_d2h_copy_contiguous_tensor(self):
38 dtype_list = [np.float16, np.float32, np.int32, np.int64]38 dtype_list = [np.float16, np.float32, np.int32, np.int64]
39 shape_list = [[10, 20], [32, 64, 128], [2, 3, 4, 5]]39 shape_list = [[10, 20], [32, 64, 128], [2, 3, 4, 5]]
40 shape_format = [40 shape_format = [
41 [dtype, 2, shape] for dtype in dtype_list for shape in shape_list41 [dtype, 2, shape] for dtype in dtype_list for shape in shape_list
42 ]42 ]
43 43
44 for item in shape_format:44 for item in shape_format:
45 cpu_input, npu_input = create_common_tensor(item, -100, 100)45 cpu_input, npu_input = create_common_tensor(item, -100, 100)
46 cpu_output = npu_input.cpu()46 cpu_output = npu_input.cpu()
47 self.assertRtolEqual(cpu_output.numpy(), cpu_input.numpy())47 self.assertRtolEqual(cpu_output.numpy(), cpu_input.numpy())
48 48 
49 def test_d2h_copy_non_contiguous_tensor(self):49 def test_d2h_copy_non_contiguous_tensor(self):
50 dtype_list = [np.float16, np.float32]50 dtype_list = [np.float16, np.float32]
51 shape_list = [[32, 64], [16, 32, 64]]51 shape_list = [[32, 64], [16, 32, 64]]
52 shape_format = [52 shape_format = [
53 [dtype, 2, shape] for dtype in dtype_list for shape in shape_list53 [dtype, 2, shape] for dtype in dtype_list for shape in shape_list
54 ]54 ]
55 55
56 for item in shape_format:56 for item in shape_format:
57 cpu_input, npu_input = create_common_tensor(item, -100, 100)57 cpu_input, npu_input = create_common_tensor(item, -100, 100)
58 npu_transposed = npu_input.transpose(-1, -2)58 npu_transposed = npu_input.transpose(-1, -2)
59 cpu_output = npu_transposed.cpu()59 cpu_output = npu_transposed.cpu()
60 self.assertRtolEqual(cpu_output.numpy(), cpu_input.transpose(-1, -2).contiguous().numpy())60 self.assertRtolEqual(cpu_output.numpy(), cpu_input.transpose(-1, -2).contiguous().numpy())
61 61 
62 def test_h2d_copy_different_dtype(self):62 def test_h2d_copy_different_dtype(self):
63 src_dtype_list = [np.float32, np.float16]63 src_dtype_list = [np.float32, np.float16]
64 dst_dtype_list = [torch.float16, torch.float32]64 dst_dtype_list = [torch.float16, torch.float32]
65 shape = [32, 64]65 shape = [32, 64]
66 66
67 for src_dtype, dst_dtype in zip(src_dtype_list, dst_dtype_list):67 for src_dtype, dst_dtype in zip(src_dtype_list, dst_dtype_list):
68 cpu_input = torch.randn(shape, dtype=torch.float32) * 10068 cpu_input = torch.randn(shape, dtype=torch.float32) * 100
69 cpu_input = cpu_input.to(torch.from_numpy(np.array([])).dtype if src_dtype == np.float32 else torch.float16)69 cpu_input = cpu_input.to(torch.from_numpy(np.array([])).dtype if src_dtype == np.float32 else torch.float16)
70 70
71 npu_input = cpu_input.npu()71 npu_input = cpu_input.npu()
72 npu_output = npu_input.to(dst_dtype)72 npu_output = npu_input.to(dst_dtype)
73 73
74 cpu_output = cpu_input.to(dst_dtype)74 cpu_output = cpu_input.to(dst_dtype)
75 self.assertRtolEqual(npu_output.cpu().numpy(), cpu_output.numpy())75 self.assertRtolEqual(npu_output.cpu().numpy(), cpu_output.numpy())
76 76 
77 def test_d2h_copy_different_dtype(self):77 def test_d2h_copy_different_dtype(self):
78 dtype_pairs = [78 dtype_pairs = [
79 (np.float16, torch.float32),79 (np.float16, torch.float32),
80 (np.float32, torch.float16),80 (np.float32, torch.float16),
81 ]81 ]
82 shape = [32, 64]82 shape = [32, 64]
83 83
84 for src_dtype, dst_dtype in dtype_pairs:84 for src_dtype, dst_dtype in dtype_pairs:
85 cpu_input, npu_input = create_common_tensor([src_dtype, 0, shape], -100, 100)85 cpu_input, npu_input = create_common_tensor([src_dtype, 0, shape], -100, 100)
86 cpu_output = npu_input.cpu().to(dst_dtype)86 cpu_output = npu_input.cpu().to(dst_dtype)
87 87
88 expected = cpu_input.to(dst_dtype)88 expected = cpu_input.to(dst_dtype)
89 self.assertRtolEqual(cpu_output.numpy(), expected.numpy())89 self.assertRtolEqual(cpu_output.numpy(), expected.numpy())
90 90 
91 def test_h2d_copy_slice_tensor(self):91 def test_h2d_copy_slice_tensor(self):
92 shape = [64, 128]92 shape = [64, 128]
93 cpu_input = torch.randn(shape)93 cpu_input = torch.randn(shape)
94 94
95 cpu_slice = cpu_input[10:30, 20:60]95 cpu_slice = cpu_input[10:30, 20:60]
96 npu_slice = cpu_slice.npu()96 npu_slice = cpu_slice.npu()
97 97
98 npu_contiguous = npu_slice.contiguous()98 npu_contiguous = npu_slice.contiguous()
99 self.assertRtolEqual(npu_contiguous.cpu().numpy(), cpu_slice.contiguous().numpy())99 self.assertRtolEqual(npu_contiguous.cpu().numpy(), cpu_slice.contiguous().numpy())
100 100 
101 def test_d2h_copy_slice_tensor(self):101 def test_d2h_copy_slice_tensor(self):
102 shape = [64, 128]102 shape = [64, 128]
103 cpu_input = torch.randn(shape)103 cpu_input = torch.randn(shape)
104 npu_input = cpu_input.npu()104 npu_input = cpu_input.npu()
105 105
106 npu_slice = npu_input[10:30, 20:60]106 npu_slice = npu_input[10:30, 20:60]
107 cpu_slice = npu_slice.cpu()107 cpu_slice = npu_slice.cpu()
108 self.assertRtolEqual(cpu_slice.numpy(), cpu_input[10:30, 20:60].contiguous().numpy())108 self.assertRtolEqual(cpu_slice.numpy(), cpu_input[10:30, 20:60].contiguous().numpy())
109 109 
110 def test_d2h_copy_broadcast_tensor(self):110 def test_d2h_copy_broadcast_tensor(self):
111 shape = [1, 64, 1]111 shape = [1, 64, 1]
112 cpu_input = torch.randn(shape)112 cpu_input = torch.randn(shape)
113 npu_input = cpu_input.npu()113 npu_input = cpu_input.npu()
114 114
115 npu_broadcast = npu_input.expand(4, 64, 128)115 npu_broadcast = npu_input.expand(4, 64, 128)
116 cpu_output = npu_broadcast.cpu()116 cpu_output = npu_broadcast.cpu()
117 self.assertRtolEqual(cpu_output.numpy(), cpu_input.expand(4, 64, 128).contiguous().numpy())117 self.assertRtolEqual(cpu_output.numpy(), cpu_input.expand(4, 64, 128).contiguous().numpy())
118 118 
119 def test_h2d_copy_permute_tensor(self):119 def test_h2d_copy_permute_tensor(self):
120 shape = [32, 64, 128]120 shape = [32, 64, 128]
121 cpu_input = torch.randn(shape)121 cpu_input = torch.randn(shape)
122 cpu_permuted = cpu_input.permute(2, 0, 1)122 cpu_permuted = cpu_input.permute(2, 0, 1)
123 npu_permuted = cpu_permuted.npu()123 npu_permuted = cpu_permuted.npu()
124 npu_contiguous = npu_permuted.contiguous()124 npu_contiguous = npu_permuted.contiguous()
125 self.assertRtolEqual(npu_contiguous.cpu().numpy(), cpu_permuted.contiguous().numpy())125 self.assertRtolEqual(npu_contiguous.cpu().numpy(), cpu_permuted.contiguous().numpy())
126 126 
127 def test_d2h_copy_permute_tensor(self):127 def test_d2h_copy_permute_tensor(self):
128 shape = [32, 64, 128]128 shape = [32, 64, 128]
129 cpu_input = torch.randn(shape)129 cpu_input = torch.randn(shape)
130 npu_input = cpu_input.npu()130 npu_input = cpu_input.npu()
131 131
132 npu_permuted = npu_input.permute(2, 0, 1) 132 npu_permuted = npu_input.permute(2, 0, 1)
133 cpu_output = npu_permuted.cpu()133 cpu_output = npu_permuted.cpu()
134 self.assertRtolEqual(cpu_output.numpy(), cpu_input.permute(2, 0, 1).contiguous().numpy())134 self.assertRtolEqual(cpu_output.numpy(), cpu_input.permute(2, 0, 1).contiguous().numpy())
135 135 
136 136 
137if __name__ == "__main__":137if __name__ == "__main__":
138 run_tests()138 run_tests()
Mtest/npu/test_expandable_segments.py+105-105
@@ -1,105 +1,105 @@
1import os1import os
2import gc2import gc
3import unittest3import unittest
4 4 
5import torch5import torch
6import torch_npu6import torch_npu
7from torch_npu.testing.testcase import TestCase, run_tests7from torch_npu.testing.testcase import TestCase, run_tests
8from torch.testing._internal.common_utils import TestCase, run_tests, TEST_PRIVATEUSE18from torch.testing._internal.common_utils import TestCase, run_tests, TEST_PRIVATEUSE1
9 9 
10os.environ["PYTORCH_NPU_ALLOC_CONF"] = "expandable_segments:True"10os.environ["PYTORCH_NPU_ALLOC_CONF"] = "expandable_segments:True"
11 11 
12device_name = torch_npu.npu.get_device_name(0)12device_name = torch_npu.npu.get_device_name(0)
13 13 
14 14 
15class Test_expandable_segments(TestCase):15class Test_expandable_segments(TestCase):
16 @unittest.skipIf(device_name == "Ascend910B4", "Skip when device name is Ascend910B4")16 @unittest.skipIf(device_name == "Ascend910B4", "Skip when device name is Ascend910B4")
17 def test_empty_virt_addr_cache(self):17 def test_empty_virt_addr_cache(self):
18 gc.collect()18 gc.collect()
19 torch_npu.npu.empty_cache()19 torch_npu.npu.empty_cache()
20 prev = 020 prev = 0
21 21 
22 x = torch.empty((7500, 1024, 1024), device="npu")22 x = torch.empty((7500, 1024, 1024), device="npu")
23 del x23 del x
24 last_r = torch_npu.npu.memory_reserved()24 last_r = torch_npu.npu.memory_reserved()
25 25 
26 torch_npu.npu.empty_virt_addr_cache()26 torch_npu.npu.empty_virt_addr_cache()
27 new_r = torch_npu.npu.memory_reserved()27 new_r = torch_npu.npu.memory_reserved()
28 self.assertEqual(new_r, prev)28 self.assertEqual(new_r, prev)
29 self.assertEqual(torch_npu.npu.max_memory_reserved(), last_r)29 self.assertEqual(torch_npu.npu.max_memory_reserved(), last_r)
30 30 
31 # test re-alloc after empty virtual address31 # test re-alloc after empty virtual address
32 try:32 try:
33 y = torch.empty((7500, 1024, 1024), device="npu")33 y = torch.empty((7500, 1024, 1024), device="npu")
34 self.assertGreater(torch_npu.npu.memory_allocated(), prev)34 self.assertGreater(torch_npu.npu.memory_allocated(), prev)
35 finally:35 finally:
36 if y is not None:36 if y is not None:
37 del y37 del y
38 self.assertEqual(torch_npu.npu.memory_allocated(), prev)38 self.assertEqual(torch_npu.npu.memory_allocated(), prev)
39 torch_npu.npu.empty_virt_addr_cache()39 torch_npu.npu.empty_virt_addr_cache()
40 # empty unmapped physical handles with empty_cache()40 # empty unmapped physical handles with empty_cache()
41 torch_npu.npu.empty_cache()41 torch_npu.npu.empty_cache()
42 self.assertEqual(torch_npu.npu.memory_reserved(), prev)42 self.assertEqual(torch_npu.npu.memory_reserved(), prev)
43 43 
44 @unittest.skipIf(TEST_PRIVATEUSE1, "NPU not available for graph capture")44 @unittest.skipIf(TEST_PRIVATEUSE1, "NPU not available for graph capture")
45 def test_set_segment_state_to_checkpoint_when_expandable_segments(self):45 def test_set_segment_state_to_checkpoint_when_expandable_segments(self):
46 def tensor_metadata(x):46 def tensor_metadata(x):
47 return {47 return {
48 "nbytes": x.untyped_storage().nbytes(),48 "nbytes": x.untyped_storage().nbytes(),
49 "data_ptr": x.untyped_storage().data_ptr(),49 "data_ptr": x.untyped_storage().data_ptr(),
50 "size": x.shape,50 "size": x.shape,
51 "stride": x.stride(),51 "stride": x.stride(),
52 "dtype": x.dtype,52 "dtype": x.dtype,
53 "device": x.device,53 "device": x.device,
54 "storage_offset": x.storage_offset(), }54 "storage_offset": x.storage_offset(), }
55 55 
56 def reconstruct_from_tensor_metadata(metadata):56 def reconstruct_from_tensor_metadata(metadata):
57 s = torch._C._construct_storage_from_data_pointer(57 s = torch._C._construct_storage_from_data_pointer(
58 metadata["data_ptr"], metadata["device"], metadata["nbytes"])58 metadata["data_ptr"], metadata["device"], metadata["nbytes"])
59 t = torch.empty([0], device=metadata["device"], dtype=metadata["dtype"])59 t = torch.empty([0], device=metadata["device"], dtype=metadata["dtype"])
60 t.set_(source=s, storage_offset=metadata["storage_offset"],60 t.set_(source=s, storage_offset=metadata["storage_offset"],
61 size=metadata["size"], stride=metadata["stride"], )61 size=metadata["size"], stride=metadata["stride"], )
62 return t62 return t
63 63 
64 def cudagraphify(fn, inputs, pool, stream):64 def cudagraphify(fn, inputs, pool, stream):
65 torch.npu.synchronize()65 torch.npu.synchronize()
66 gc.collect()66 gc.collect()
67 torch.npu.empty_cache()67 torch.npu.empty_cache()
68 68 
69 graph = torch.npu.NPUGraph()69 graph = torch.npu.NPUGraph()
70 with torch.npu.graph(graph, stream=stream, pool=pool):70 with torch.npu.graph(graph, stream=stream, pool=pool):
71 static_outputs = fn(*inputs)71 static_outputs = fn(*inputs)
72 return graph, static_outputs72 return graph, static_outputs
73 73 
74 def foo(x, idx):74 def foo(x, idx):
75 r1 = x.expand([1, 2097152 // 8]).sqrt()75 r1 = x.expand([1, 2097152 // 8]).sqrt()
76 r2 = x.expand([idx, 2097152]).clone()76 r2 = x.expand([idx, 2097152]).clone()
77 return r1, r277 return r1, r2
78 78 
79 # init79 # init
80 pool_id = torch.npu.graph_pool_handle()80 pool_id = torch.npu.graph_pool_handle()
81 com_stream = torch.npu.Stream()81 com_stream = torch.npu.Stream()
82 com_device = torch_npu.npu.current_device()82 com_device = torch_npu.npu.current_device()
83 inp = torch.tensor([7]).npu()83 inp = torch.tensor([7]).npu()
84 84 
85 # start capture graph185 # start capture graph1
86 graph1, outputs1 = cudagraphify(foo, [inp, 1], pool=pool_id, stream=com_stream)86 graph1, outputs1 = cudagraphify(foo, [inp, 1], pool=pool_id, stream=com_stream)
87 graph1_state = torch_npu._C._npu_getCheckpointState(com_device, pool_id)87 graph1_state = torch_npu._C._npu_getCheckpointState(com_device, pool_id)
88 output1_metadata = [tensor_metadata(t) for t in outputs1]88 output1_metadata = [tensor_metadata(t) for t in outputs1]
89 outputs1 = None89 outputs1 = None
90 90 
91 # start capture graph291 # start capture graph2
92 graph2, outputs2 = cudagraphify(foo, [inp, 2], pool=pool_id, stream=com_stream)92 graph2, outputs2 = cudagraphify(foo, [inp, 2], pool=pool_id, stream=com_stream)
93 graph2_state = torch_npu._C._npu_getCheckpointState(com_device, pool_id)93 graph2_state = torch_npu._C._npu_getCheckpointState(com_device, pool_id)
94 graph2.replay()94 graph2.replay()
95 outputs2 = None95 outputs2 = None
96 96 
97 # replay graph197 # replay graph1
98 graph1.replay()98 graph1.replay()
99 reconstructed_tensors1 = [reconstruct_from_tensor_metadata(metadata) for metadata in output1_metadata]99 reconstructed_tensors1 = [reconstruct_from_tensor_metadata(metadata) for metadata in output1_metadata]
100 output1_new_storage = [output.untyped_storage()._cdata for output in reconstructed_tensors1]100 output1_new_storage = [output.untyped_storage()._cdata for output in reconstructed_tensors1]
101 torch_npu._C._npu_setCheckpointPoolState(com_device, graph1_state, [], output1_new_storage)101 torch_npu._C._npu_setCheckpointPoolState(com_device, graph1_state, [], output1_new_storage)
102 102 
103 103 
104if __name__ == '__main__':104if __name__ == '__main__':
105 run_tests()105 run_tests()
Mtest/npu/test_kernel_check.py+0-1
@@ -118,4 +118,3 @@ class TestKernelCheck(TestCase):
118 118 
119if __name__ == "__main__":119if __name__ == "__main__":
120 run_tests()120 run_tests()
121 
Mtest/npu/test_pin_memory_host_register.py+19-19
@@ -1,19 +1,19 @@
1import unittest1import unittest
2 2 
3import os3import os
4import torch4import torch
5from torch.testing._internal.common_utils import TestCase, run_tests5from torch.testing._internal.common_utils import TestCase, run_tests
6from torch_npu.npu.utils import get_cann_version6from torch_npu.npu.utils import get_cann_version
7 7 
8 8 
9class TestPinMemoryHostRegister(TestCase):9class TestPinMemoryHostRegister(TestCase):
10 10 
11 @unittest.skipUnless(get_cann_version("RUNTIME") >= "8.5.0" and get_cann_version(module="DRIVER") >= "25.5.0", "This feature is not supported in older versions.")11 @unittest.skipUnless(get_cann_version("RUNTIME") >= "8.5.0" and get_cann_version(module="DRIVER") >= "25.5.0", "This feature is not supported in older versions.")
12 def test_pin_memory_host_register(self):12 def test_pin_memory_host_register(self):
13 os.environ["PYTORCH_NPU_ALLOC_CONF"] = "pinned_mem_register:True"13 os.environ["PYTORCH_NPU_ALLOC_CONF"] = "pinned_mem_register:True"
14 cpu_tensor = torch.ones([2, 3])14 cpu_tensor = torch.ones([2, 3])
15 pin_tensor = cpu_tensor.pin_memory()15 pin_tensor = cpu_tensor.pin_memory()
16 self.assertTrue(pin_tensor.is_pinned())16 self.assertTrue(pin_tensor.is_pinned())
17 17 
18if __name__ == '__main__':18if __name__ == '__main__':
19 run_tests()19 run_tests()
Mtest/npu/test_save_async.py+119-119
@@ -1,119 +1,119 @@
1import os1import os
2import time2import time
3import copy3import copy
4 4 
5import torch5import torch
6import torch.nn as nn6import torch.nn as nn
7import torch.optim as optim7import torch.optim as optim
8 8 
9import torch_npu9import torch_npu
10from torch_npu.testing.testcase import TestCase, run_tests10from torch_npu.testing.testcase import TestCase, run_tests
11from torch_npu.utils._path_manager import PathManager11from torch_npu.utils._path_manager import PathManager
12 12 
13 13 
14class TestAsyncSave(TestCase):14class TestAsyncSave(TestCase):
15 test_save_path = os.path.join(15 test_save_path = os.path.join(
16 os.path.realpath(os.path.dirname(__file__)), "test_save_async")16 os.path.realpath(os.path.dirname(__file__)), "test_save_async")
17 17 
18 @classmethod18 @classmethod
19 def setUpClass(cls):19 def setUpClass(cls):
20 PathManager.make_dir_safety(TestAsyncSave.test_save_path)20 PathManager.make_dir_safety(TestAsyncSave.test_save_path)
21 21 
22 @classmethod22 @classmethod
23 def tearDownClass(cls):23 def tearDownClass(cls):
24 PathManager.remove_path_safety(TestAsyncSave.test_save_path)24 PathManager.remove_path_safety(TestAsyncSave.test_save_path)
25 25
26 def wait_for_save_completion(self, file_path, timeout_sec=60, poll_interval_sec=0.5):26 def wait_for_save_completion(self, file_path, timeout_sec=60, poll_interval_sec=0.5):
27 start_time = time.time()27 start_time = time.time()
28 28 
29 while time.time() - start_time < timeout_sec:29 while time.time() - start_time < timeout_sec:
30 if os.path.exists(file_path):30 if os.path.exists(file_path):
31 current_size = os.path.getsize(file_path)31 current_size = os.path.getsize(file_path)
32 time.sleep(poll_interval_sec)32 time.sleep(poll_interval_sec)
33 new_size = os.path.getsize(file_path)33 new_size = os.path.getsize(file_path)
34 34 
35 if current_size == new_size:35 if current_size == new_size:
36 return True36 return True
37 else:37 else:
38 time.sleep(poll_interval_sec)38 time.sleep(poll_interval_sec)
39 39 
40 return False40 return False
41 41 
42 def test_save_async_tensor(self):42 def test_save_async_tensor(self):
43 save_tensor = torch.rand(1024, dtype=torch.float32).npu()43 save_tensor = torch.rand(1024, dtype=torch.float32).npu()
44 async_save_path = os.path.join(TestAsyncSave.test_save_path, "async_save_tensor.pt")44 async_save_path = os.path.join(TestAsyncSave.test_save_path, "async_save_tensor.pt")
45 torch_npu.utils.save_async(save_tensor, async_save_path)45 torch_npu.utils.save_async(save_tensor, async_save_path)
46 46
47 if self.wait_for_save_completion(async_save_path):47 if self.wait_for_save_completion(async_save_path):
48 tensor_async = torch.load(async_save_path, weights_only=False)48 tensor_async = torch.load(async_save_path, weights_only=False)
49 self.assertEqual(tensor_async, save_tensor)49 self.assertEqual(tensor_async, save_tensor)
50 else:50 else:
51 self.assertTrue(False, f"{async_save_path} is not exist!")51 self.assertTrue(False, f"{async_save_path} is not exist!")
52 52
53 def test_save_async(self):53 def test_save_async(self):
54 loss1 = [1.6099495, 1.6099086, 1.6098710]54 loss1 = [1.6099495, 1.6099086, 1.6098710]
55 loss2 = []55 loss2 = []
56 model_list = []56 model_list = []
57 checkpoint_list = []57 checkpoint_list = []
58 model_origin = nn.Sequential(58 model_origin = nn.Sequential(
59 nn.Linear(100, 50),59 nn.Linear(100, 50),
60 nn.ReLU(),60 nn.ReLU(),
61 nn.Linear(50, 20),61 nn.Linear(50, 20),
62 nn.ReLU(),62 nn.ReLU(),
63 nn.Linear(20, 5),63 nn.Linear(20, 5),
64 nn.ReLU()64 nn.ReLU()
65 )65 )
66 66 
67 input_data = torch.ones(6400, 100).npu()67 input_data = torch.ones(6400, 100).npu()
68 labels = torch.arange(5).repeat(1280).npu()68 labels = torch.arange(5).repeat(1280).npu()
69 69 
70 criterion = nn.CrossEntropyLoss()70 criterion = nn.CrossEntropyLoss()
71 model = model_origin.npu()71 model = model_origin.npu()
72 optimerizer = optim.SGD(model.parameters(), lr=0.1)72 optimerizer = optim.SGD(model.parameters(), lr=0.1)
73 for step in range(3):73 for step in range(3):
74 outputs = model(input_data)74 outputs = model(input_data)
75 loss = criterion(outputs, labels)75 loss = criterion(outputs, labels)
76 76 
77 optimerizer.zero_grad()77 optimerizer.zero_grad()
78 loss.backward()78 loss.backward()
79 79 
80 optimerizer.step()80 optimerizer.step()
81 81
82 loss2.append(loss)82 loss2.append(loss)
83 checkpoint = {83 checkpoint = {
84 "model": model.state_dict(),84 "model": model.state_dict(),
85 "optimizer": optimerizer.state_dict()85 "optimizer": optimerizer.state_dict()
86 }86 }
87 checkpoint_list.append(copy.deepcopy(checkpoint))87 checkpoint_list.append(copy.deepcopy(checkpoint))
88 model_list.append(copy.deepcopy(model))88 model_list.append(copy.deepcopy(model))
89 checkpoint_async_path = os.path.join(TestAsyncSave.test_save_path, f"checkpoint_async_{step}.path")89 checkpoint_async_path = os.path.join(TestAsyncSave.test_save_path, f"checkpoint_async_{step}.path")
90 model_async_path = os.path.join(TestAsyncSave.test_save_path, f"model_async_{step}.path")90 model_async_path = os.path.join(TestAsyncSave.test_save_path, f"model_async_{step}.path")
91 torch_npu.utils.save_async(checkpoint, checkpoint_async_path, model=model)91 torch_npu.utils.save_async(checkpoint, checkpoint_async_path, model=model)
92 torch_npu.utils.save_async(model, model_async_path, model=model)92 torch_npu.utils.save_async(model, model_async_path, model=model)
93 93 
94 for i in range(3):94 for i in range(3):
95 self.assertEqual(loss1[i], loss2[i].item())95 self.assertEqual(loss1[i], loss2[i].item())
96 checkpoint_async_path = os.path.join(TestAsyncSave.test_save_path, f"checkpoint_async_{i}.path")96 checkpoint_async_path = os.path.join(TestAsyncSave.test_save_path, f"checkpoint_async_{i}.path")
97 if self.wait_for_save_completion(checkpoint_async_path):97 if self.wait_for_save_completion(checkpoint_async_path):
98 checkpoint_async = torch.load(checkpoint_async_path, weights_only=False)98 checkpoint_async = torch.load(checkpoint_async_path, weights_only=False)
99 self.assertEqual(checkpoint_list[i], checkpoint_async, prec=2e-3)99 self.assertEqual(checkpoint_list[i], checkpoint_async, prec=2e-3)
100 else:100 else:
101 self.assertTrue(False, f"{checkpoint_async_path} is not exist!")101 self.assertTrue(False, f"{checkpoint_async_path} is not exist!")
102 model_async_path = os.path.join(TestAsyncSave.test_save_path, f"model_async_{i}.path")102 model_async_path = os.path.join(TestAsyncSave.test_save_path, f"model_async_{i}.path")
103 if self.wait_for_save_completion(model_async_path):103 if self.wait_for_save_completion(model_async_path):
104 model_async = torch.load(model_async_path, weights_only=False)104 model_async = torch.load(model_async_path, weights_only=False)
105 else:105 else:
106 self.assertTrue(False, f"{model_async_path} is not exist!")106 self.assertTrue(False, f"{model_async_path} is not exist!")
107 state_dict_sync = model_list[i].state_dict()107 state_dict_sync = model_list[i].state_dict()
108 state_dict_async = model_async.state_dict()108 state_dict_async = model_async.state_dict()
109 109 
110 key_sync = sorted(state_dict_sync.keys())110 key_sync = sorted(state_dict_sync.keys())
111 key_async = sorted(state_dict_async.keys())111 key_async = sorted(state_dict_async.keys())
112 112 
113 self.assertEqual(key_sync, key_async)113 self.assertEqual(key_sync, key_async)
114 for key in key_async:114 for key in key_async:
115 self.assertEqual(state_dict_async[key], state_dict_sync[key], prec=2e-3)115 self.assertEqual(state_dict_async[key], state_dict_sync[key], prec=2e-3)
116 116 
117if __name__ == '__main__':117if __name__ == '__main__':
118 torch.npu.set_device(0)118 torch.npu.set_device(0)
119 run_tests()119 run_tests()
Mtest/profiler/analysis/test_profiler_config.py+0-1
@@ -81,4 +81,3 @@ class TestProfilerConfig(TestCase):
81 81 
82if __name__ == "__main__":82if __name__ == "__main__":
83 run_tests()83 run_tests()
84 
Mtest/profiler/test_non_intrusive_profile.py+0-1
@@ -39,4 +39,3 @@ class TestNoneInstrusiveProfile(TestCase):
39 39 
40if __name__ == "__main__":40if __name__ == "__main__":
41 run_tests()41 run_tests()
42 
Mtest/test_fake_tensor.py+2016-2016
Mtest/unsupported_test_cases/.pytorch-disabled-tests.json+3-1
@@ -32154,5 +32154,7 @@
32154 "test_to_complex_npu (__main__.TestNNDeviceTypePRIVATEUSE1)": ["", [""]],32154 "test_to_complex_npu (__main__.TestNNDeviceTypePRIVATEUSE1)": ["", [""]],
32155 "test_npu_roi_align_1 (__main__.TestPsRoiPooling)": ["", [""]],32155 "test_npu_roi_align_1 (__main__.TestPsRoiPooling)": ["", [""]],
32156 "test_silu (__main__.TestActivations)": ["", [""]],32156 "test_silu (__main__.TestActivations)": ["", [""]],
32157 "test_codegen_upcast_to_fp32_emits_cast_bfloat16_upcast_flag_True (__main__.TestCodegenUpcastToFP32)": ["", [""]]32157 "test_codegen_upcast_to_fp32_emits_cast_bfloat16_upcast_flag_True (__main__.TestCodegenUpcastToFP32)": ["", [""]],
32158 "test_data_parallel_rnn (__main__.TestDataParallel)": ["", ["Disabled during A1 to A2 chip transition"]],
32159 "test_alltoall_single_2p_size_dist (__main__.HcclAlltoAllSingleTest)": ["", ["Disabled during A1 to A2 chip transition"]]
32158}32160}
Mtorch_npu/_inductor/ascend_npu_ir/ascend_npu_ir/npu/codegen/meta_kernel.py+522-522
@@ -1,523 +1,523 @@
1from itertools import count1from itertools import count
2from typing import List, Union, Optional, Tuple, Any, Dict2from typing import List, Union, Optional, Tuple, Any, Dict
3import os3import os
4import sympy4import sympy
5import textwrap5import textwrap
6 6 
7import torch7import torch
8import torch.fx8import torch.fx
9 9 
10from torch._functorch.aot_autograd import set_model_name, get_aot_compilation_context10from torch._functorch.aot_autograd import set_model_name, get_aot_compilation_context
11from torch._inductor.codegen.simd import (11from torch._inductor.codegen.simd import (
12 log,12 log,
13 SIMDKernel,13 SIMDKernel,
14 SIMDKernelFeatures,14 SIMDKernelFeatures,
15 MultiKernel,15 MultiKernel,
16 code_hash16 code_hash
17)17)
18from torch._inductor.codegen.triton import (18from torch._inductor.codegen.triton import (
19 SIMDScheduling,19 SIMDScheduling,
20 FixedTritonConfig,20 FixedTritonConfig,
21)21)
22from torch._inductor import config, ir, scheduler, metrics22from torch._inductor import config, ir, scheduler, metrics
23from torch._inductor.codecache import get_path23from torch._inductor.codecache import get_path
24from torch._dynamo.utils import counters24from torch._dynamo.utils import counters
25from torch._inductor.codegen.common import (25from torch._inductor.codegen.common import (
26 IndentedBuffer,26 IndentedBuffer,
27 Kernel,27 Kernel,
28)28)
29from torch._inductor.virtualized import V29from torch._inductor.virtualized import V
30from torch._inductor.codegen.triton import (30from torch._inductor.codegen.triton import (
31 TritonKernel31 TritonKernel
32)32)
33from torch._inductor.utils import (33from torch._inductor.utils import (
34 get_fused_kernel_name,34 get_fused_kernel_name,
35 get_kernel_metadata,35 get_kernel_metadata,
36)36)
37from torch._inductor.scheduler import Scheduler37from torch._inductor.scheduler import Scheduler
38from torch_mlir.compiler_utils import OutputType38from torch_mlir.compiler_utils import OutputType
39 39 
40from torch.fx.experimental.proxy_tensor import make_fx40from torch.fx.experimental.proxy_tensor import make_fx
41from torch._dynamo.device_interface import get_interface_for_device41from torch._dynamo.device_interface import get_interface_for_device
42from ..torch_mlir_patch import stateless_fx_import42from ..torch_mlir_patch import stateless_fx_import
43from ...npu.inductor_patch.lowering import map_strings_to_operators43from ...npu.inductor_patch.lowering import map_strings_to_operators
44from ...npu.utils import (44from ...npu.utils import (
45 parse_fx_example_inputs,45 parse_fx_example_inputs,
46 npu_cast_to_prim_cast,46 npu_cast_to_prim_cast,
47 get_fx_graph_code,47 get_fx_graph_code,
48 scalarize_tensor_ops_on_scalars,48 scalarize_tensor_ops_on_scalars,
49 to_folder,49 to_folder,
50 modify_gm_for_acc_comp,50 modify_gm_for_acc_comp,
51 get_num_call_functions,51 get_num_call_functions,
52 is_fx_dynamic,52 is_fx_dynamic,
53 view_to_reshape53 view_to_reshape
54)54)
55from ... import config as anir_config55from ... import config as anir_config
56from ...npu.inductor_patch.lowering import merge_fx_graphs56from ...npu.inductor_patch.lowering import merge_fx_graphs
57 57 
58 58 
59id_iter = count()59id_iter = count()
60 60 
61 61 
62class NpuTritonKernel(TritonKernel):62class NpuTritonKernel(TritonKernel):
63 def __init__(self, 63 def __init__(self,
64 tiling: Dict[str, sympy.Expr],64 tiling: Dict[str, sympy.Expr],
65 min_elem_per_thread=0,65 min_elem_per_thread=0,
66 optimize_mask=True,66 optimize_mask=True,
67 fixed_config: Optional[FixedTritonConfig] = None,67 fixed_config: Optional[FixedTritonConfig] = None,
68 **kwargs,68 **kwargs,
69 ):69 ):
70 super().__init__(70 super().__init__(
71 tiling,71 tiling,
72 min_elem_per_thread=min_elem_per_thread,72 min_elem_per_thread=min_elem_per_thread,
73 optimize_mask=optimize_mask,73 optimize_mask=optimize_mask,
74 fixed_config = fixed_config,74 fixed_config = fixed_config,
75 **kwargs,75 **kwargs,
76 )76 )
77 77 
78 @staticmethod78 @staticmethod
79 def inductor_meta_common():79 def inductor_meta_common():
80 return {}80 return {}
81 81
82 def call_kernel(self, call_args, name: str):82 def call_kernel(self, call_args, name: str):
83 wrapper = V.graph.wrapper_code83 wrapper = V.graph.wrapper_code
84 for call_arg in call_args:84 for call_arg in call_args:
85 if call_arg.startswith('_uwu_'):85 if call_arg.startswith('_uwu_'):
86 expression = map_strings_to_operators(call_arg)86 expression = map_strings_to_operators(call_arg)
87 wrapper.writeline(f'{call_arg} = {expression}')87 wrapper.writeline(f'{call_arg} = {expression}')
88 if len(call_args) > 0:88 if len(call_args) > 0:
89 wrapper.generate_kernel_call(89 wrapper.generate_kernel_call(
90 name,90 name,
91 call_args,91 call_args,
92 )92 )
93 93 
94 94 
95def _nc_key(nc):95def _nc_key(nc):
96 if isinstance(nc, dict):96 if isinstance(nc, dict):
97 return (tuple(nc.get("inputs", [])), tuple(nc.get("outputs", [])))97 return (tuple(nc.get("inputs", [])), tuple(nc.get("outputs", [])))
98 return tuple(nc)98 return tuple(nc)
99 99 
100 100 
101def find_common_positions(list1, list2):101def find_common_positions(list1, list2):
102 common_elements = set(list1) & set(list2)102 common_elements = set(list1) & set(list2)
103 merged_list = list1 + list2103 merged_list = list1 + list2
104 positions = [index for index, element in enumerate(merged_list) if element in common_elements]104 positions = [index for index, element in enumerate(merged_list) if element in common_elements]
105 105 
106 return merged_list, positions106 return merged_list, positions
107 107 
108 108 
109def refresh_input_meta_with_buffer_layout(node):109def refresh_input_meta_with_buffer_layout(node):
110 val = node.meta.get('val')110 val = node.meta.get('val')
111 try:111 try:
112 layout = getattr(V.graph.try_get_buffer(node.target), "layout", None)112 layout = getattr(V.graph.try_get_buffer(node.target), "layout", None)
113 except Exception:113 except Exception:
114 layout = None114 layout = None
115 if not torch.is_tensor(val) or layout is None:115 if not torch.is_tensor(val) or layout is None:
116 return val116 return val
117 117 
118 size, stride = tuple(layout.size), tuple(layout.stride)118 size, stride = tuple(layout.size), tuple(layout.stride)
119 if any(not isinstance(x, int) for x in (*size, *stride)):119 if any(not isinstance(x, int) for x in (*size, *stride)):
120 return val120 return val
121 121 
122 if val.size() != size or val.stride() != stride:122 if val.size() != size or val.stride() != stride:
123 with V.graph.fake_mode:123 with V.graph.fake_mode:
124 val = torch.empty_strided(124 val = torch.empty_strided(
125 size,125 size,
126 stride,126 stride,
127 dtype=val.dtype,127 dtype=val.dtype,
128 device=val.device,128 device=val.device,
129 requires_grad=val.requires_grad,129 requires_grad=val.requires_grad,
130 )130 )
131 node.meta['val'] = val131 node.meta['val'] = val
132 return val132 return val
133 133 
134 134 
135def create_fx_from_snodes_by_traced_graph(snodes: List[scheduler.SchedulerNode], triton_kernel: TritonKernel):135def create_fx_from_snodes_by_traced_graph(snodes: List[scheduler.SchedulerNode], triton_kernel: TritonKernel):
136 call_inputs = []136 call_inputs = []
137 for snode in snodes:137 for snode in snodes:
138 snode.node.data.traced_graph.last_node.name = snode.node.get_name()138 snode.node.data.traced_graph.last_node.name = snode.node.get_name()
139 if len(snodes) == 1:139 if len(snodes) == 1:
140 traced_graph = snodes[0].node.data.traced_graph140 traced_graph = snodes[0].node.data.traced_graph
141 else:141 else:
142 traced_graph = merge_fx_graphs([snode.node.data.traced_graph for snode in snodes])142 traced_graph = merge_fx_graphs([snode.node.data.traced_graph for snode in snodes])
143 inputs = []143 inputs = []
144 for node in traced_graph.graph.nodes:144 for node in traced_graph.graph.nodes:
145 if node.op == 'placeholder':145 if node.op == 'placeholder':
146 call_inputs.append(node.target)146 call_inputs.append(node.target)
147 inputs.append(refresh_input_meta_with_buffer_layout(node))147 inputs.append(refresh_input_meta_with_buffer_layout(node))
148 non_contiguous_indices = {}148 non_contiguous_indices = {}
149 non_contiguous_indices["inputs"] = [i for i, inp in enumerate(inputs) if torch.is_tensor(inp) and not inp.is_contiguous()]149 non_contiguous_indices["inputs"] = [i for i, inp in enumerate(inputs) if torch.is_tensor(inp) and not inp.is_contiguous()]
150 num_inputs = len(call_inputs)150 num_inputs = len(call_inputs)
151 call_outputs = []151 call_outputs = []
152 for snode in snodes:152 for snode in snodes:
153 if snode.has_aliasing_or_mutation():153 if snode.has_aliasing_or_mutation():
154 for buf in snode.get_outputs():154 for buf in snode.get_outputs():
155 if len(buf.get_mutations()):155 if len(buf.get_mutations()):
156 call_outputs.extend(buf.get_mutations())156 call_outputs.extend(buf.get_mutations())
157 elif len(buf.get_aliases()):157 elif len(buf.get_aliases()):
158 call_outputs.append(buf.get_name())158 call_outputs.append(buf.get_name())
159 elif snode.node.get_name() not in (V.graph.removed_buffers | V.graph.inplaced_to_remove):159 elif snode.node.get_name() not in (V.graph.removed_buffers | V.graph.inplaced_to_remove):
160 call_outputs.append(snode.node.get_name())160 call_outputs.append(snode.node.get_name())
161 num_outputs = len(call_outputs)161 num_outputs = len(call_outputs)
162 call_args, mutated_indices = find_common_positions(call_inputs, call_outputs)162 call_args, mutated_indices = find_common_positions(call_inputs, call_outputs)
163 outputs = traced_graph.last_node if isinstance(traced_graph.last_node, List) \163 outputs = traced_graph.last_node if isinstance(traced_graph.last_node, List) \
164 else [traced_graph.last_node]164 else [traced_graph.last_node]
165 outputs = [output for output in outputs if output.name not in (V.graph.removed_buffers | V.graph.inplaced_to_remove)]165 outputs = [output for output in outputs if output.name not in (V.graph.removed_buffers | V.graph.inplaced_to_remove)]
166 traced_graph.graph.output(tuple(outputs))166 traced_graph.graph.output(tuple(outputs))
167 traced_graph.graph.lint()167 traced_graph.graph.lint()
168 orig_module = torch.nn.Module()168 orig_module = torch.nn.Module()
169 gm = torch.fx.GraphModule(orig_module, traced_graph.graph)169 gm = torch.fx.GraphModule(orig_module, traced_graph.graph)
170 gm.recompile()170 gm.recompile()
171 171 
172 def runnable_gm(*args):172 def runnable_gm(*args):
173 return torch.fx.Interpreter(gm).run(*args)173 return torch.fx.Interpreter(gm).run(*args)
174 with V.graph.fake_mode: 174 with V.graph.fake_mode:
175 gm = make_fx(runnable_gm)(*inputs)175 gm = make_fx(runnable_gm)(*inputs)
176 view_to_reshape(gm)176 view_to_reshape(gm)
177 non_contiguous_indices["outputs"] = [i + num_inputs 177 non_contiguous_indices["outputs"] = [i + num_inputs
178 for i, call_output in enumerate(call_outputs)178 for i, call_output in enumerate(call_outputs)
179 if not V.graph.try_get_buffer(call_output).layout.is_contiguous()]179 if not V.graph.try_get_buffer(call_output).layout.is_contiguous()]
180 return (gm, call_args, {"num_outputs": num_outputs, 180 return (gm, call_args, {"num_outputs": num_outputs,
181 "non_contiguous_indices": non_contiguous_indices, 181 "non_contiguous_indices": non_contiguous_indices,
182 "mutated_indices": mutated_indices, })182 "mutated_indices": mutated_indices, })
183 183 
184 184 
185class NpuMetaKernel(Kernel):185class NpuMetaKernel(Kernel):
186 def __init__(self, gm: torch.fx.GraphModule, snodes: list[scheduler.SchedulerNode], call_args: list[str], non_contiguous_indices: list[int], num_outputs: list[int] = None, mutated_indices: list[int] = None):186 def __init__(self, gm: torch.fx.GraphModule, snodes: list[scheduler.SchedulerNode], call_args: list[str], non_contiguous_indices: list[int], num_outputs: list[int] = None, mutated_indices: list[int] = None):
187 super().__init__()187 super().__init__()
188 if gm is None:188 if gm is None:
189 self._gm = None189 self._gm = None
190 self._gm_with_prim_cast = None190 self._gm_with_prim_cast = None
191 self._is_dynamic = False191 self._is_dynamic = False
192 else:192 else:
193 self._gm = gm193 self._gm = gm
194 self._gm_with_prim_cast = self.build_gm_with_prim_cast(gm)194 self._gm_with_prim_cast = self.build_gm_with_prim_cast(gm)
195 self._is_dynamic = is_fx_dynamic(self._gm)195 self._is_dynamic = is_fx_dynamic(self._gm)
196 196
197 if anir_config.online_acc_comp:197 if anir_config.online_acc_comp:
198 modify_gm_for_acc_comp(self._gm)198 modify_gm_for_acc_comp(self._gm)
199 199
200 self._snodes = snodes200 self._snodes = snodes
201 self._call_args = call_args201 self._call_args = call_args
202 self.non_contiguous_indices = non_contiguous_indices202 self.non_contiguous_indices = non_contiguous_indices
203 self.num_outputs = num_outputs203 self.num_outputs = num_outputs
204 self.mutated_indices = mutated_indices204 self.mutated_indices = mutated_indices
205 205 
206 def get_mlir_output_type(self):206 def get_mlir_output_type(self):
207 return OutputType.RAW207 return OutputType.RAW
208 208 
209 def imports_for_benchmark_kernel(self):209 def imports_for_benchmark_kernel(self):
210 return textwrap.dedent(210 return textwrap.dedent(
211 """211 """
212 from torch._dynamo.testing import rand_strided212 from torch._dynamo.testing import rand_strided
213 {}213 {}
214 import torch214 import torch
215 """.format(215 """.format(
216 V.graph.device_ops.import_get_raw_stream_as("get_raw_stream")216 V.graph.device_ops.import_get_raw_stream_as("get_raw_stream")
217 )217 )
218 )218 )
219 219
220 def build_gm_with_prim_cast(self, gm):220 def build_gm_with_prim_cast(self, gm):
221 return npu_cast_to_prim_cast(gm)221 return npu_cast_to_prim_cast(gm)
222 222 
223 def codegen_kernel(self, name=None):223 def codegen_kernel(self, name=None):
224 code = IndentedBuffer()224 code = IndentedBuffer()
225 225 
226 scalarize_tensor_ops_on_scalars(self._gm_with_prim_cast)226 scalarize_tensor_ops_on_scalars(self._gm_with_prim_cast)
227 227 
228 set_model_name(f'MODEL_NAME')228 set_model_name(f'MODEL_NAME')
229 *_, model_name, nth_graph = get_aot_compilation_context()229 *_, model_name, nth_graph = get_aot_compilation_context()
230 230 
231 import torch_mlir231 import torch_mlir
232 232 
233 mlir_module = stateless_fx_import(233 mlir_module = stateless_fx_import(
234 self._gm_with_prim_cast,234 self._gm_with_prim_cast,
235 model_name=model_name,235 model_name=model_name,
236 output_type=self.get_mlir_output_type(),236 output_type=self.get_mlir_output_type(),
237 import_symbolic_shape_expressions=False237 import_symbolic_shape_expressions=False
238 )238 )
239 from torch_mlir.compiler_utils import run_pipeline_with_repro_report239 from torch_mlir.compiler_utils import run_pipeline_with_repro_report
240 240 
241 run_pipeline_with_repro_report(241 run_pipeline_with_repro_report(
242 mlir_module,242 mlir_module,
243 f"builtin.module(torch-lower-to-backend-contract)",243 f"builtin.module(torch-lower-to-backend-contract)",
244 "Lowering TorchFX IR -> Torch Backend IR",244 "Lowering TorchFX IR -> Torch Backend IR",
245 )245 )
246 code.splice(f'{str(mlir_module)}')246 code.splice(f'{str(mlir_module)}')
247 247 
248 return code.getvalue()248 return code.getvalue()
249 249 
250 def get_call_args(self):250 def get_call_args(self):
251 return self._call_args251 return self._call_args
252 252 
253 def call_kernel(self, name: str, node=None):253 def call_kernel(self, name: str, node=None):
254 wrapper = V.graph.wrapper_code254 wrapper = V.graph.wrapper_code
255 call_args = self.get_call_args()255 call_args = self.get_call_args()
256 256
257 for call_arg in call_args:257 for call_arg in call_args:
258 if call_arg.startswith('_uwu'):258 if call_arg.startswith('_uwu'):
259 expression = map_strings_to_operators(call_arg)259 expression = map_strings_to_operators(call_arg)
260 wrapper.writeline(f'{call_arg} = {expression}')260 wrapper.writeline(f'{call_arg} = {expression}')
261 261
262 if len(call_args) > 0:262 if len(call_args) > 0:
263 wrapper.generate_kernel_call(name, call_args)263 wrapper.generate_kernel_call(name, call_args)
264 264 
265 def codegen_debug_performance(self, fd):265 def codegen_debug_performance(self, fd):
266 from ...npu.utils import generate_compiler_repro_string, generate_fake_inputs266 from ...npu.utils import generate_compiler_repro_string, generate_fake_inputs
267 name_to_example_inputs = parse_fx_example_inputs(self._gm)267 name_to_example_inputs = parse_fx_example_inputs(self._gm)
268 call_args_str = ", ".join(list(name_to_example_inputs.keys()))268 call_args_str = ", ".join(list(name_to_example_inputs.keys()))
269 fd.write(generate_compiler_repro_string(self._gm))269 fd.write(generate_compiler_repro_string(self._gm))
270 fd.write("\n")270 fd.write("\n")
271 fd.write("if __name__ == '__main__':\n")271 fd.write("if __name__ == '__main__':\n")
272 fd.write(" from torch._inductor.utils import print_performance\n")272 fd.write(" from torch._inductor.utils import print_performance\n")
273 fd.write(f" with torch.no_grad():\n")273 fd.write(f" with torch.no_grad():\n")
274 fd.write(generate_fake_inputs(name_to_example_inputs))274 fd.write(generate_fake_inputs(name_to_example_inputs))
275 fd.write('\n')275 fd.write('\n')
276 fd.write(f" fn = lambda: mod({call_args_str})\n")276 fd.write(f" fn = lambda: mod({call_args_str})\n")
277 fd.write(f" print_performance(fn, times=10, repeat=10)\n")277 fd.write(f" print_performance(fn, times=10, repeat=10)\n")
278 278 
279 279 
280class NpuMetaScheduling(SIMDScheduling):280class NpuMetaScheduling(SIMDScheduling):
281 kernel_type = NpuTritonKernel281 kernel_type = NpuTritonKernel
282 meta_kernel_type = NpuMetaKernel282 meta_kernel_type = NpuMetaKernel
283 283 
284 def __init__(self, sched: Scheduler):284 def __init__(self, sched: Scheduler):
285 super().__init__(sched)285 super().__init__(sched)
286 self.orig_fnode_name_to_fnode = {}286 self.orig_fnode_name_to_fnode = {}
287 287 
288 def _postprocess_src_code(self, src_code, mlir_kernel, kernel_name):288 def _postprocess_src_code(self, src_code, mlir_kernel, kernel_name):
289 return src_code, {}289 return src_code, {}
290 290 
291 def define_kernel(self, src_code, mlir_kernel, traced_graph, mode=None):291 def define_kernel(self, src_code, mlir_kernel, traced_graph, mode=None):
292 if mode is None:292 if mode is None:
293 mode = anir_config._get_compile_mode()293 mode = anir_config._get_compile_mode()
294 294
295 wrapper = V.graph.wrapper_code295 wrapper = V.graph.wrapper_code
296 296 
297 kernel_key = (src_code, tuple(mlir_kernel.non_contiguous_indices))297 kernel_key = (src_code, tuple(mlir_kernel.non_contiguous_indices))
298 298 
299 if kernel_key in wrapper.src_to_kernel:299 if kernel_key in wrapper.src_to_kernel:
300 cached_val = wrapper.src_to_kernel[kernel_key]300 cached_val = wrapper.src_to_kernel[kernel_key]
301 if isinstance(cached_val, str):301 if isinstance(cached_val, str):
302 return cached_val302 return cached_val
303 else:303 else:
304 log.warning(f"Found invalid cache entry for kernel {mlir_kernel}. Recompiling.")304 log.warning(f"Found invalid cache entry for kernel {mlir_kernel}. Recompiling.")
305 del wrapper.src_to_kernel[kernel_key]305 del wrapper.src_to_kernel[kernel_key]
306 306 
307 fused_name = (307 fused_name = (
308 get_fused_kernel_name(mlir_kernel._snodes, config.triton.descriptive_names)308 get_fused_kernel_name(mlir_kernel._snodes, config.triton.descriptive_names)
309 if config.triton.descriptive_names309 if config.triton.descriptive_names
310 else ""310 else ""
311 )311 )
312 312 
313 if mode in ["complete_fallback", "auto_fallback"]:313 if mode in ["complete_fallback", "auto_fallback"]:
314 fx_graph_suffix = f"{next(id_iter)}"314 fx_graph_suffix = f"{next(id_iter)}"
315 prefix = self._get_kernel_prefix()315 prefix = self._get_kernel_prefix()
316 kernel_name = "_".join([prefix, fused_name, fx_graph_suffix])316 kernel_name = "_".join([prefix, fused_name, fx_graph_suffix])
317 else:317 else:
318 kernel_suffix = wrapper.next_kernel_suffix()318 kernel_suffix = wrapper.next_kernel_suffix()
319 prefix = self._get_kernel_prefix()319 prefix = self._get_kernel_prefix()
320 kernel_name = "_".join([prefix, fused_name, kernel_suffix])320 kernel_name = "_".join([prefix, fused_name, kernel_suffix])
321 compile_src_code, extra_kernel_meta = self._postprocess_src_code(src_code, mlir_kernel, kernel_name)321 compile_src_code, extra_kernel_meta = self._postprocess_src_code(src_code, mlir_kernel, kernel_name)
322 322 
323 current_device = V.graph.get_current_device_or_throw()323 current_device = V.graph.get_current_device_or_throw()
324 traced_graph_hash = code_hash(traced_graph.print_readable(print_output=False) + kernel_name)324 traced_graph_hash = code_hash(traced_graph.print_readable(print_output=False) + kernel_name)
325 num_call_functions = get_num_call_functions(mlir_kernel._gm)325 num_call_functions = get_num_call_functions(mlir_kernel._gm)
326 326 
327 if num_call_functions <= 1 or kernel_name in anir_config.force_fallback_kernel_names:327 if num_call_functions <= 1 or kernel_name in anir_config.force_fallback_kernel_names:
328 mode = "complete_fallback"328 mode = "complete_fallback"
329 329 
330 kernel_meta = self._prepare_kernel_meta(330 kernel_meta = self._prepare_kernel_meta(
331 mlir_kernel, current_device, kernel_name, traced_graph_hash, num_call_functions, compile_src_code331 mlir_kernel, current_device, kernel_name, traced_graph_hash, num_call_functions, compile_src_code
332 )332 )
333 kernel_meta.update(extra_kernel_meta)333 kernel_meta.update(extra_kernel_meta)
334 334 
335 wrapper.src_to_kernel[kernel_key] = kernel_name335 wrapper.src_to_kernel[kernel_key] = kernel_name
336 336
337 subs_name = kernel_name if config.triton.unique_kernel_names else f"{self._get_kernel_prefix()}_"337 subs_name = kernel_name if config.triton.unique_kernel_names else f"{self._get_kernel_prefix()}_"
338 338
339 compile_wrapper = IndentedBuffer()339 compile_wrapper = IndentedBuffer()
340 metadata_comment = ""340 metadata_comment = ""
341 341 
342 if mode == "auto_fallback":342 if mode == "auto_fallback":
343 src_code = src_code.replace("MODEL_NAME", kernel_name)343 src_code = src_code.replace("MODEL_NAME", kernel_name)
344 self._handle_auto_fallback_mode(344 self._handle_auto_fallback_mode(
345 compile_wrapper, src_code, kernel_name, subs_name, kernel_meta, wrapper, metadata_comment, mlir_kernel345 compile_wrapper, src_code, kernel_name, subs_name, kernel_meta, wrapper, metadata_comment, mlir_kernel
346 )346 )
347 elif mode == "complete_fallback":347 elif mode == "complete_fallback":
348 self._handle_complete_fallback_mode(348 self._handle_complete_fallback_mode(
349 compile_wrapper, kernel_name, kernel_meta, wrapper, metadata_comment, mlir_kernel349 compile_wrapper, kernel_name, kernel_meta, wrapper, metadata_comment, mlir_kernel
350 )350 )
351 else:351 else:
352 src_code = src_code.replace("MODEL_NAME", kernel_name)352 src_code = src_code.replace("MODEL_NAME", kernel_name)
353 self._handle_default_mode(353 self._handle_default_mode(
354 compile_wrapper, src_code, kernel_name, subs_name, kernel_meta, wrapper, metadata_comment, mlir_kernel354 compile_wrapper, src_code, kernel_name, subs_name, kernel_meta, wrapper, metadata_comment, mlir_kernel
355 )355 )
356 356 
357 if mode in ["complete_fallback", "auto_fallback"]:357 if mode in ["complete_fallback", "auto_fallback"]:
358 self._dump_fx_graph_for_fallback(358 self._dump_fx_graph_for_fallback(
359 mlir_kernel, current_device, traced_graph_hash, kernel_name, compile_wrapper.getvalue()359 mlir_kernel, current_device, traced_graph_hash, kernel_name, compile_wrapper.getvalue()
360 )360 )
361 361 
362 return kernel_name362 return kernel_name
363 363 
364 def _get_kernel_prefix(self) -> str:364 def _get_kernel_prefix(self) -> str:
365 return "mlir"365 return "mlir"
366 366 
367 def _prepare_kernel_meta(self, mlir_kernel, device, name, hash_val, num_calls, src_code) -> Dict[str, Any]:367 def _prepare_kernel_meta(self, mlir_kernel, device, name, hash_val, num_calls, src_code) -> Dict[str, Any]:
368 device_interface = get_interface_for_device(device.type)368 device_interface = get_interface_for_device(device.type)
369 device = torch.device(device.type, device.index)369 device = torch.device(device.type, device.index)
370 device_name = device_interface.get_compute_capability(device)370 device_name = device_interface.get_compute_capability(device)
371 return {371 return {
372 'device_str': device.type,372 'device_str': device.type,
373 'device_index': device.index,373 'device_index': device.index,
374 'device_name': device_name,374 'device_name': device_name,
375 'num_outputs': mlir_kernel.num_outputs,375 'num_outputs': mlir_kernel.num_outputs,
376 'non_contiguous_indices': mlir_kernel.non_contiguous_indices,376 'non_contiguous_indices': mlir_kernel.non_contiguous_indices,
377 'dynamic': mlir_kernel._is_dynamic,377 'dynamic': mlir_kernel._is_dynamic,
378 'mutated_indices': mlir_kernel.mutated_indices,378 'mutated_indices': mlir_kernel.mutated_indices,
379 'traced_graph_cache': anir_config.traced_graph_cache or "traced_graph_cache",379 'traced_graph_cache': anir_config.traced_graph_cache or "traced_graph_cache",
380 'traced_graph_hash': hash_val,380 'traced_graph_hash': hash_val,
381 'num_call_functions': num_calls,381 'num_call_functions': num_calls,
382 'is_reduction': 'linalg.reduce' in src_code,382 'is_reduction': 'linalg.reduce' in src_code,
383 'are_deterministic_algorithms_enabled': torch.are_deterministic_algorithms_enabled(),383 'are_deterministic_algorithms_enabled': torch.are_deterministic_algorithms_enabled(),
384 }384 }
385 385 
386 def _handle_auto_fallback_mode(self, compile_wrapper, src_code, name, subs_name, meta, wrapper, metadata_comment, mlir_kernel=None):386 def _handle_auto_fallback_mode(self, compile_wrapper, src_code, name, subs_name, meta, wrapper, metadata_comment, mlir_kernel=None):
387 _basename, _, kernel_path = get_path(code_hash(src_code.strip()), "py")387 _basename, _, kernel_path = get_path(code_hash(src_code.strip()), "py")
388 388
389 compile_wrapper.writeline(f"async_compile.{self._get_compile_api()}({subs_name!r}, '''")389 compile_wrapper.writeline(f"async_compile.{self._get_compile_api()}({subs_name!r}, '''")
390 compile_wrapper.splice(src_code, strip=True)390 compile_wrapper.splice(src_code, strip=True)
391 compile_wrapper.writeline(f"''', kernel_meta={meta})")391 compile_wrapper.writeline(f"''', kernel_meta={meta})")
392 392 
393 metadata_comment = f"# kernel path: {kernel_path}"393 metadata_comment = f"# kernel path: {kernel_path}"
394 394 
395 origins, detailed_origins = get_kernel_metadata(mlir_kernel._snodes, wrapper)395 origins, detailed_origins = get_kernel_metadata(mlir_kernel._snodes, wrapper)
396 metadata_comment += "\n" + origins + "\n" + detailed_origins396 metadata_comment += "\n" + origins + "\n" + detailed_origins
397 397
398 wrapper.define_kernel(name, compile_wrapper.getvalue(), metadata_comment)398 wrapper.define_kernel(name, compile_wrapper.getvalue(), metadata_comment)
399 399 
400 if metrics.is_metric_table_enabled("kernel_metadata"):400 if metrics.is_metric_table_enabled("kernel_metadata"):
401 metrics.log_kernel_metadata(name, kernel_path, src_code)401 metrics.log_kernel_metadata(name, kernel_path, src_code)
402 402 
403 def _handle_complete_fallback_mode(self, compile_wrapper, name, meta, wrapper, metadata_comment, mlir_kernel):403 def _handle_complete_fallback_mode(self, compile_wrapper, name, meta, wrapper, metadata_comment, mlir_kernel):
404 compile_wrapper.writeline(f"async_compile.import_fx({name!r}, kernel_meta={meta})")404 compile_wrapper.writeline(f"async_compile.import_fx({name!r}, kernel_meta={meta})")
405 metadata_comment = f'"""\n{mlir_kernel._gm.print_readable(print_output=False)}\n"""'405 metadata_comment = f'"""\n{mlir_kernel._gm.print_readable(print_output=False)}\n"""'
406 wrapper.define_kernel(name, compile_wrapper.getvalue(), metadata_comment)406 wrapper.define_kernel(name, compile_wrapper.getvalue(), metadata_comment)
407 407 
408 def _handle_default_mode(self, compile_wrapper, src_code, name, subs_name, meta, wrapper, metadata_comment):408 def _handle_default_mode(self, compile_wrapper, src_code, name, subs_name, meta, wrapper, metadata_comment):
409 self._handle_auto_fallback_mode(compile_wrapper, src_code, name, subs_name, meta, wrapper, metadata_comment)409 self._handle_auto_fallback_mode(compile_wrapper, src_code, name, subs_name, meta, wrapper, metadata_comment)
410 410 
411 def _get_compile_api(self) -> str:411 def _get_compile_api(self) -> str:
412 return "auto_fallback"412 return "auto_fallback"
413 413 
414 def _dump_fx_graph_for_fallback(self, mlir_kernel, device, graph_hash, kernel_name, compile_code):414 def _dump_fx_graph_for_fallback(self, mlir_kernel, device, graph_hash, kernel_name, compile_code):
415 415
416 cache_root = os.getenv("TORCHINDUCTOR_CACHE_DIR")416 cache_root = os.getenv("TORCHINDUCTOR_CACHE_DIR")
417 dump_path = os.path.join(417 dump_path = os.path.join(
418 cache_root, 418 cache_root,
419 anir_config.traced_graph_cache or "traced_graph_cache", 419 anir_config.traced_graph_cache or "traced_graph_cache",
420 str(device.index), 420 str(device.index),
421 graph_hash421 graph_hash
422 )422 )
423 423
424 if not os.path.exists(dump_path):424 if not os.path.exists(dump_path):
425 os.makedirs(dump_path, exist_ok=True)425 os.makedirs(dump_path, exist_ok=True)
426 to_folder(mlir_kernel._gm, dump_path, graph_hash=graph_hash, module_name=graph_hash)426 to_folder(mlir_kernel._gm, dump_path, graph_hash=graph_hash, module_name=graph_hash)
427 427 
428 if anir_config.fx_subgraph_dump_path is not None:428 if anir_config.fx_subgraph_dump_path is not None:
429 subgraph_dump_path = os.path.join(anir_config.fx_subgraph_dump_path, str(device.index), kernel_name)429 subgraph_dump_path = os.path.join(anir_config.fx_subgraph_dump_path, str(device.index), kernel_name)
430 os.makedirs(subgraph_dump_path, exist_ok=True)430 os.makedirs(subgraph_dump_path, exist_ok=True)
431 431
432 num_args = len(mlir_kernel._gm.code.split('forward(', )[1].split(')')[0].split(', ')) - 1432 num_args = len(mlir_kernel._gm.code.split('forward(', )[1].split(')')[0].split(', ')) - 1
433 fx_graph_code = get_fx_graph_code(mlir_kernel._gm.code, num_args, runnable=False, kernel_code=compile_code, kernel_name=kernel_name)433 fx_graph_code = get_fx_graph_code(mlir_kernel._gm.code, num_args, runnable=False, kernel_code=compile_code, kernel_name=kernel_name)
434 runnable_fx_graph_code = get_fx_graph_code(mlir_kernel._gm.code, num_args, runnable=True, kernel_code=compile_code, kernel_name=kernel_name)434 runnable_fx_graph_code = get_fx_graph_code(mlir_kernel._gm.code, num_args, runnable=True, kernel_code=compile_code, kernel_name=kernel_name)
435 435
436 with open(os.path.join(subgraph_dump_path, f'{kernel_name}.py'), 'w') as f:436 with open(os.path.join(subgraph_dump_path, f'{kernel_name}.py'), 'w') as f:
437 f.write(fx_graph_code)437 f.write(fx_graph_code)
438 with open(os.path.join(subgraph_dump_path, f'runnable_{kernel_name}.py'), 'w') as f:438 with open(os.path.join(subgraph_dump_path, f'runnable_{kernel_name}.py'), 'w') as f:
439 f.write(runnable_fx_graph_code)439 f.write(runnable_fx_graph_code)
440 440 
441 441 
442 def codegen_node_schedule(self, kernel_features: SIMDKernelFeatures, nodes):442 def codegen_node_schedule(self, kernel_features: SIMDKernelFeatures, nodes):
443 node_schedule = kernel_features.node_schedule443 node_schedule = kernel_features.node_schedule
444 444 
445 tiling = self.select_tiling(445 tiling = self.select_tiling(
446 node_schedule, kernel_features.numel, kernel_features.reduction_numel446 node_schedule, kernel_features.numel, kernel_features.reduction_numel
447 )447 )
448 448 
449 kernels = self.create_kernel_choices(449 kernels = self.create_kernel_choices(
450 kernel_features, [tiling], {"features": kernel_features}450 kernel_features, [tiling], {"features": kernel_features}
451 )451 )
452 for kernel in kernels:452 for kernel in kernels:
453 super().codegen_node_schedule_with_kernel(node_schedule, kernel)453 super().codegen_node_schedule_with_kernel(node_schedule, kernel)
454 MultiKernel.merge_workspaces_inplace(kernels)454 MultiKernel.merge_workspaces_inplace(kernels)
455 for kernel in kernels:455 for kernel in kernels:
456 V.graph.removed_buffers |= kernel.removed_buffers456 V.graph.removed_buffers |= kernel.removed_buffers
457 V.graph.inplaced_to_remove |= kernel.inplaced_to_remove457 V.graph.inplaced_to_remove |= kernel.inplaced_to_remove
458 if not anir_config.traced_graph_cache:458 if not anir_config.traced_graph_cache:
459 anir_config.traced_graph_cache = "traced_graph_cache"459 anir_config.traced_graph_cache = "traced_graph_cache"
460 os.makedirs(460 os.makedirs(
461 os.path.join(os.getenv("TORCHINDUCTOR_CACHE_DIR"), anir_config.traced_graph_cache),461 os.path.join(os.getenv("TORCHINDUCTOR_CACHE_DIR"), anir_config.traced_graph_cache),
462 exist_ok=True,462 exist_ok=True,
463 )463 )
464 traced_graph, call_args, compile_kwargs = create_fx_from_snodes_by_traced_graph(464 traced_graph, call_args, compile_kwargs = create_fx_from_snodes_by_traced_graph(
465 nodes, kernel465 nodes, kernel
466 )466 )
467 mlir_kernel = self.meta_kernel_type(traced_graph, nodes, call_args, **compile_kwargs)467 mlir_kernel = self.meta_kernel_type(traced_graph, nodes, call_args, **compile_kwargs)
468 with V.set_kernel_handler(mlir_kernel):468 with V.set_kernel_handler(mlir_kernel):
469 src_code = mlir_kernel.codegen_kernel()469 src_code = mlir_kernel.codegen_kernel()
470 kernel_name = self.define_kernel(src_code, mlir_kernel, traced_graph)470 kernel_name = self.define_kernel(src_code, mlir_kernel, traced_graph)
471 log.debug("Generating kernel code with kernel_name: %s", kernel_name)471 log.debug("Generating kernel code with kernel_name: %s", kernel_name)
472 kernel.kernel_name = kernel_name472 kernel.kernel_name = kernel_name
473 kernel.code_hash = code_hash(src_code)473 kernel.code_hash = code_hash(src_code)
474 del kernel474 del kernel
475 475 
476 final_kernel: Union[SIMDKernel, MultiKernel]476 final_kernel: Union[SIMDKernel, MultiKernel]
477 if len(kernels) > 1:477 if len(kernels) > 1:
478 raise RuntimeError("MultiKernel not Implemented for this backend!")478 raise RuntimeError("MultiKernel not Implemented for this backend!")
479 else:479 else:
480 (final_kernel,) = kernels480 (final_kernel,) = kernels
481 481 
482 with V.set_kernel_handler(final_kernel):482 with V.set_kernel_handler(final_kernel):
483 for node in kernel_features.scheduler_nodes():483 for node in kernel_features.scheduler_nodes():
484 node.mark_run()484 node.mark_run()
485 485 
486 self.codegen_comment(node_schedule)486 self.codegen_comment(node_schedule)
487 final_kernel.call_kernel(call_args, final_kernel.kernel_name)487 final_kernel.call_kernel(call_args, final_kernel.kernel_name)
488 488 
489 if config.nan_asserts:489 if config.nan_asserts:
490 final_kernel.codegen_nan_check()490 final_kernel.codegen_nan_check()
491 if config.warn_mix_layout:491 if config.warn_mix_layout:
492 final_kernel.warn_mix_layout(kernels[0].kernel_name)492 final_kernel.warn_mix_layout(kernels[0].kernel_name)
493 493 
494 if (494 if (
495 V.graph.wrapper_code.supports_intermediate_hooks495 V.graph.wrapper_code.supports_intermediate_hooks
496 and config.generate_intermediate_hooks496 and config.generate_intermediate_hooks
497 ):497 ):
498 live_outs = kernels[0].args.live_output_buffers()498 live_outs = kernels[0].args.live_output_buffers()
499 for node in kernel_features.scheduler_nodes():499 for node in kernel_features.scheduler_nodes():
500 name = node.get_name()500 name = node.get_name()
501 if name not in live_outs:501 if name not in live_outs:
502 continue502 continue
503 if node.node is None:503 if node.node is None:
504 raise RuntimeError("assert node.node is not None")504 raise RuntimeError("assert node.node is not None")
505 505 
506 origin_node = node.node.get_origin_node()506 origin_node = node.node.get_origin_node()
507 if origin_node is not None:507 if origin_node is not None:
508 counters["inductor"]["intermediate_hooks"] += 1508 counters["inductor"]["intermediate_hooks"] += 1
509 V.graph.wrapper_code.writeline(509 V.graph.wrapper_code.writeline(
510 f"run_intermediate_hooks({origin_node.name!r}, {name})"510 f"run_intermediate_hooks({origin_node.name!r}, {name})"
511 )511 )
512 512 
513 self.scheduler.free_buffers()513 self.scheduler.free_buffers()
514 514 
515 def codegen_node(self, node: Union[scheduler.SchedulerNode, object]):515 def codegen_node(self, node: Union[scheduler.SchedulerNode, object]):
516 nodes: List[scheduler.SchedulerNode] = node.get_nodes()516 nodes: List[scheduler.SchedulerNode] = node.get_nodes()
517 517
518 _, (numel, rnumel) = max(nodes, key=lambda x: int(x.is_reduction())).group518 _, (numel, rnumel) = max(nodes, key=lambda x: int(x.is_reduction())).group
519 519 
520 node_schedule = self.generate_node_schedule(nodes, numel, rnumel)520 node_schedule = self.generate_node_schedule(nodes, numel, rnumel)
521 kernel_features = SIMDKernelFeatures(node_schedule, numel, rnumel)521 kernel_features = SIMDKernelFeatures(node_schedule, numel, rnumel)
522 522
523 return self.codegen_node_schedule(kernel_features, nodes)523 return self.codegen_node_schedule(kernel_features, nodes)
Mtorch_npu/_inductor/ascend_npu_ir/ascend_npu_ir/npu/meta_compiler.py+329-329
@@ -1,330 +1,330 @@
1import os1import os
2import sys2import sys
3import importlib3import importlib
4import shutil4import shutil
5from itertools import count5from itertools import count
6from typing import Any, Callable, Dict, List, Optional, Tuple, Iterator6from typing import Any, Callable, Dict, List, Optional, Tuple, Iterator
7 7 
8import torch8import torch
9from torch._inductor.compile_fx import clone_preserve_strides9from torch._inductor.compile_fx import clone_preserve_strides
10 10 
11from .. import config as anir_config11from .. import config as anir_config
12from .utils import replace_placeholders12from .utils import replace_placeholders
13 13 
14 14 
15_dump_id_iter: Iterator[int] = count()15_dump_id_iter: Iterator[int] = count()
16 16 
17class MetaCompiler:17class MetaCompiler:
18 def __init__(18 def __init__(
19 self,19 self,
20 kernel_name: str = "",20 kernel_name: str = "",
21 multiprocess_compile: bool = False,21 multiprocess_compile: bool = False,
22 no_more_compile: bool = False,22 no_more_compile: bool = False,
23 kernel_meta: Optional[Dict[str, Any]] = None,23 kernel_meta: Optional[Dict[str, Any]] = None,
24 autotune: bool = True,24 autotune: bool = True,
25 ):25 ):
26 kernel_meta = kernel_meta or {}26 kernel_meta = kernel_meta or {}
27 27 
28 self.kernel_name = kernel_name28 self.kernel_name = kernel_name
29 self.kernel_meta = kernel_meta29 self.kernel_meta = kernel_meta
30 30 
31 self.dynamic = kernel_meta.get("dynamic")31 self.dynamic = kernel_meta.get("dynamic")
32 self.mutated_indices = kernel_meta.get("mutated_indices") or []32 self.mutated_indices = kernel_meta.get("mutated_indices") or []
33 self.kernel_hash = kernel_meta.get("kernel_hash")33 self.kernel_hash = kernel_meta.get("kernel_hash")
34 self.signature = kernel_meta.get("signature")34 self.signature = kernel_meta.get("signature")
35 self.ranks = kernel_meta.get("ranks")35 self.ranks = kernel_meta.get("ranks")
36 self.num_outputs = kernel_meta.get("num_outputs")36 self.num_outputs = kernel_meta.get("num_outputs")
37 self.num_call_functions = kernel_meta.get("num_call_functions")37 self.num_call_functions = kernel_meta.get("num_call_functions")
38 self.device_index = kernel_meta.get("device_index", 0)38 self.device_index = kernel_meta.get("device_index", 0)
39 self.traced_graph_hash = kernel_meta.get("traced_graph_hash")39 self.traced_graph_hash = kernel_meta.get("traced_graph_hash")
40 40 
41 self.multiprocess_compile = multiprocess_compile41 self.multiprocess_compile = multiprocess_compile
42 self.no_more_compile = no_more_compile42 self.no_more_compile = no_more_compile
43 self.autotune = autotune43 self.autotune = autotune
44 44 
45 self._fallback_call: Optional[Callable[..., Any]] = None45 self._fallback_call: Optional[Callable[..., Any]] = None
46 self._nc_input_indices: Optional[List[int]] = None46 self._nc_input_indices: Optional[List[int]] = None
47 self._nc_output_indices: Optional[List[int]] = None47 self._nc_output_indices: Optional[List[int]] = None
48 48 
49 self.autotuned: bool = False49 self.autotuned: bool = False
50 self.launchers: list[Callable[..., Any]] = []50 self.launchers: list[Callable[..., Any]] = []
51 self.kernel_paths: list[Any] = []51 self.kernel_paths: list[Any] = []
52 self.is_fallback_kernels: list[bool] = []52 self.is_fallback_kernels: list[bool] = []
53 53 
54 def register_launcher(54 def register_launcher(
55 self,55 self,
56 launcher: Callable[..., Any],56 launcher: Callable[..., Any],
57 kernel_path: Any = None,57 kernel_path: Any = None,
58 is_fallback_kernel: bool = False,58 is_fallback_kernel: bool = False,
59 ) -> None:59 ) -> None:
60 """Register a compiled or fallback launcher for runtime execution."""60 """Register a compiled or fallback launcher for runtime execution."""
61 self.launchers.append(launcher)61 self.launchers.append(launcher)
62 self.kernel_paths.append(kernel_path)62 self.kernel_paths.append(kernel_path)
63 self.is_fallback_kernels.append(is_fallback_kernel)63 self.is_fallback_kernels.append(is_fallback_kernel)
64 64 
65 def get_primary_launcher_index(self) -> int:65 def get_primary_launcher_index(self) -> int:
66 if not self.launchers:66 if not self.launchers:
67 raise RuntimeError("No valid launcher")67 raise RuntimeError("No valid launcher")
68 for idx, is_fallback_kernel in enumerate(self.is_fallback_kernels):68 for idx, is_fallback_kernel in enumerate(self.is_fallback_kernels):
69 if not is_fallback_kernel:69 if not is_fallback_kernel:
70 return idx70 return idx
71 return 071 return 0
72 72 
73 def get_primary_launcher(self) -> Callable[..., Any]:73 def get_primary_launcher(self) -> Callable[..., Any]:
74 return self.launchers[self.get_primary_launcher_index()]74 return self.launchers[self.get_primary_launcher_index()]
75 75 
76 def data_dump(self, *args, dump_path=None):76 def data_dump(self, *args, dump_path=None):
77 if not dump_path:77 if not dump_path:
78 dump_path = os.path.join(anir_config.fx_subgraph_dump_path, str(self.device_index), self.kernel_name)78 dump_path = os.path.join(anir_config.fx_subgraph_dump_path, str(self.device_index), self.kernel_name)
79 data_dump_path = os.path.join(dump_path, 'data.pth')79 data_dump_path = os.path.join(dump_path, 'data.pth')
80 args_cpu = [arg.cpu() if isinstance(arg, torch.Tensor) else arg for arg in args]80 args_cpu = [arg.cpu() if isinstance(arg, torch.Tensor) else arg for arg in args]
81 torch.save(args_cpu, data_dump_path)81 torch.save(args_cpu, data_dump_path)
82 82 
83 def data_dump_fake(self, *args, dump_path=None):83 def data_dump_fake(self, *args, dump_path=None):
84 if not dump_path:84 if not dump_path:
85 dump_path = os.path.join(anir_config.fx_subgraph_dump_path, str(self.device_index), self.kernel_name)85 dump_path = os.path.join(anir_config.fx_subgraph_dump_path, str(self.device_index), self.kernel_name)
86 runable_py_path = os.path.join(dump_path, f'runnable_{self.kernel_name}.py')86 runable_py_path = os.path.join(dump_path, f'runnable_{self.kernel_name}.py')
87 fake_inputs = [f'rand_strided({arg.shape}, {arg.stride()}, device="{arg.device.type}", dtype={arg.dtype})' \87 fake_inputs = [f'rand_strided({arg.shape}, {arg.stride()}, device="{arg.device.type}", dtype={arg.dtype})' \
88 if isinstance(arg, torch.Tensor) else str(arg) for arg in args[:-self.num_outputs]]88 if isinstance(arg, torch.Tensor) else str(arg) for arg in args[:-self.num_outputs]]
89 fake_outputs = [f'empty_strided({arg.shape}, {arg.stride()}, device="{arg.device.type}", dtype={arg.dtype})' \89 fake_outputs = [f'empty_strided({arg.shape}, {arg.stride()}, device="{arg.device.type}", dtype={arg.dtype})' \
90 if isinstance(arg, torch.Tensor) else str(arg) for arg in args[-self.num_outputs:]]90 if isinstance(arg, torch.Tensor) else str(arg) for arg in args[-self.num_outputs:]]
91 replacements = {"FAKE_ARGS_PLACEHOLDER": f"args = [{', '.join(fake_inputs + fake_outputs)}]"}91 replacements = {"FAKE_ARGS_PLACEHOLDER": f"args = [{', '.join(fake_inputs + fake_outputs)}]"}
92 replace_placeholders(runable_py_path, replacements)92 replace_placeholders(runable_py_path, replacements)
93 93 
94 def fx_subgraph_dump(self, suffix):94 def fx_subgraph_dump(self, suffix):
95 subgraph_dump_path = os.path.join(anir_config.fx_subgraph_dump_path, str(self.device_index), self.kernel_name)95 subgraph_dump_path = os.path.join(anir_config.fx_subgraph_dump_path, str(self.device_index), self.kernel_name)
96 failed_fx_subgraph_dump_path = anir_config.fx_subgraph_dump_path + f'_{suffix}'96 failed_fx_subgraph_dump_path = anir_config.fx_subgraph_dump_path + f'_{suffix}'
97 failed_subgraph_dump_path = os.path.join(failed_fx_subgraph_dump_path, str(self.device_index), f'{next(_dump_id_iter)}_' + self.kernel_name)97 failed_subgraph_dump_path = os.path.join(failed_fx_subgraph_dump_path, str(self.device_index), f'{next(_dump_id_iter)}_' + self.kernel_name)
98 if os.path.exists(failed_subgraph_dump_path):98 if os.path.exists(failed_subgraph_dump_path):
99 shutil.rmtree(failed_subgraph_dump_path)99 shutil.rmtree(failed_subgraph_dump_path)
100 shutil.copytree(subgraph_dump_path, failed_subgraph_dump_path)100 shutil.copytree(subgraph_dump_path, failed_subgraph_dump_path)
101 return failed_subgraph_dump_path101 return failed_subgraph_dump_path
102 102
103 def acc_compare_and_dump(self, *args, **kwargs):103 def acc_compare_and_dump(self, *args, **kwargs):
104 from torch.testing._comparison import _make_mismatch_msg104 from torch.testing._comparison import _make_mismatch_msg
105 self.register_fx_fallback(self.kernel_meta)105 self.register_fx_fallback(self.kernel_meta)
106 launcher_fx = self.launchers[1]106 launcher_fx = self.launchers[1]
107 launcher = self.launchers[0]107 launcher = self.launchers[0]
108 108 
109 fx_outputs = [clone_preserve_strides(arg).to(torch.float32) if arg.dtype == torch.bfloat16 \109 fx_outputs = [clone_preserve_strides(arg).to(torch.float32) if arg.dtype == torch.bfloat16 \
110 else clone_preserve_strides(arg) for arg in args[-self.num_outputs:]]110 else clone_preserve_strides(arg) for arg in args[-self.num_outputs:]]
111 fx_inputs = [clone_preserve_strides(arg) if isinstance(arg, torch.Tensor) else arg for arg in args[:-self.num_outputs]]111 fx_inputs = [clone_preserve_strides(arg) if isinstance(arg, torch.Tensor) else arg for arg in args[:-self.num_outputs]]
112 fx_inputs = [inp.float() if isinstance(inp, torch.Tensor) and inp.dtype == torch.bfloat16 else inp for inp in fx_inputs]112 fx_inputs = [inp.float() if isinstance(inp, torch.Tensor) and inp.dtype == torch.bfloat16 else inp for inp in fx_inputs]
113 113
114 fx_args = fx_inputs + fx_outputs114 fx_args = fx_inputs + fx_outputs
115 launcher_fx(*fx_args, **kwargs)115 launcher_fx(*fx_args, **kwargs)
116 116 
117 if self.dynamic:117 if self.dynamic:
118 args_new = self.prepare_runtime_args(118 args_new = self.prepare_runtime_args(
119 list(args),119 list(args),
120 )120 )
121 else:121 else:
122 args_new = args122 args_new = args
123 123
124 output = launcher(*args_new, **kwargs)124 output = launcher(*args_new, **kwargs)
125 125 
126 has_acc_error = False126 has_acc_error = False
127 num_inputs = len(args) - self.num_outputs127 num_inputs = len(args) - self.num_outputs
128 for idx, (actual, expected) in enumerate(zip(args[num_inputs:], fx_outputs)):128 for idx, (actual, expected) in enumerate(zip(args[num_inputs:], fx_outputs)):
129 if actual.dtype != expected.dtype:129 if actual.dtype != expected.dtype:
130 expected = expected.to(actual.dtype)130 expected = expected.to(actual.dtype)
131 acc_comp_tol = anir_config.acc_comp_tol.get(actual.dtype, anir_config.acc_comp_tol['default'])131 acc_comp_tol = anir_config.acc_comp_tol.get(actual.dtype, anir_config.acc_comp_tol['default'])
132 rtol = acc_comp_tol['rtol']132 rtol = acc_comp_tol['rtol']
133 atol = acc_comp_tol['atol']133 atol = acc_comp_tol['atol']
134 matches = torch.isclose(134 matches = torch.isclose(
135 actual, expected, rtol=rtol, atol=atol, equal_nan=True135 actual, expected, rtol=rtol, atol=atol, equal_nan=True
136 )136 )
137 if not matches.all():137 if not matches.all():
138 abs_diff = abs(actual - expected)138 abs_diff = abs(actual - expected)
139 rel_diff = abs_diff / abs(expected)139 rel_diff = abs_diff / abs(expected)
140 rel_diff.masked_fill_(matches, 0)140 rel_diff.masked_fill_(matches, 0)
141 number_of_elements = matches.numel()141 number_of_elements = matches.numel()
142 total_mismatches = number_of_elements - int(torch.sum(matches))142 total_mismatches = number_of_elements - int(torch.sum(matches))
143 extra = (143 extra = (
144 f"Mismatched elements: {total_mismatches} / {number_of_elements} "144 f"Mismatched elements: {total_mismatches} / {number_of_elements} "
145 f"({total_mismatches / number_of_elements:.1%})"145 f"({total_mismatches / number_of_elements:.1%})"
146 )146 )
147 msg = _make_mismatch_msg(147 msg = _make_mismatch_msg(
148 default_identifier="Tensor-likes",148 default_identifier="Tensor-likes",
149 identifier=None,149 identifier=None,
150 extra=extra,150 extra=extra,
151 abs_diff=abs_diff.max().item(),151 abs_diff=abs_diff.max().item(),
152 abs_diff_idx=None,152 abs_diff_idx=None,
153 atol=atol,153 atol=atol,
154 rel_diff=rel_diff.max().item(),154 rel_diff=rel_diff.max().item(),
155 rel_diff_idx=None,155 rel_diff_idx=None,
156 rtol=rtol,156 rtol=rtol,
157 )157 )
158 print(f"Kernel Name: {self.kernel_name}\n{msg}", flush=True)158 print(f"Kernel Name: {self.kernel_name}\n{msg}", flush=True)
159 has_acc_error = True159 has_acc_error = True
160 160 
161 del abs_diff161 del abs_diff
162 del rel_diff162 del rel_diff
163 del matches163 del matches
164 del expected164 del expected
165 165
166 if anir_config.fx_subgraph_dump_path:166 if anir_config.fx_subgraph_dump_path:
167 data = args167 data = args
168 if has_acc_error:168 if has_acc_error:
169 data_dump_path = self.fx_subgraph_dump('acc_failed')169 data_dump_path = self.fx_subgraph_dump('acc_failed')
170 self.data_dump_fake(*data, dump_path=data_dump_path)170 self.data_dump_fake(*data, dump_path=data_dump_path)
171 del fx_inputs171 del fx_inputs
172 torch.npu.synchronize()172 torch.npu.synchronize()
173 self.launchers = [self.launchers[0]]173 self.launchers = [self.launchers[0]]
174 self.is_fallback_kernels = [self.is_fallback_kernels[0]]174 self.is_fallback_kernels = [self.is_fallback_kernels[0]]
175 175
176 return output176 return output
177 177 
178 def compile(self, *args, **kwargs):178 def compile(self, *args, **kwargs):
179 raise NotImplementedError179 raise NotImplementedError
180 180 
181 def ensure_runtime_ready(self, *args, **kwargs) -> None:181 def ensure_runtime_ready(self, *args, **kwargs) -> None:
182 if not self.autotuned:182 if not self.autotuned:
183 if self.autotune:183 if self.autotune:
184 self.register_fx_fallback(self.kernel_meta)184 self.register_fx_fallback(self.kernel_meta)
185 self.autotune_to_one_config(*args, **kwargs)185 self.autotune_to_one_config(*args, **kwargs)
186 self.autotuned = True186 self.autotuned = True
187 187 
188 def prepare_runtime_args(188 def prepare_runtime_args(
189 self,189 self,
190 args_list: List[Any],190 args_list: List[Any],
191 ) -> List[Any]:191 ) -> List[Any]:
192 args_new = ()192 args_new = ()
193 for arg in args_list:193 for arg in args_list:
194 if not torch.is_tensor(arg):194 if not torch.is_tensor(arg):
195 args_new = args_new + (arg,)195 args_new = args_new + (arg,)
196 continue196 continue
197 args_new = args_new + (arg, arg, 0) + arg.size() + arg.stride()197 args_new = args_new + (arg, arg, 0) + arg.size() + arg.stride()
198 args_list = list(args_new)198 args_list = list(args_new)
199 return args_list199 return args_list
200 200 
201 def autotune_to_one_config(self, *args, **kwargs):201 def autotune_to_one_config(self, *args, **kwargs):
202 return None202 return None
203 203 
204 def _normalize_contiguous_args(204 def _normalize_contiguous_args(
205 self, args: List[Any]205 self, args: List[Any]
206 ) -> Tuple[List[Any], Optional[List[torch.Tensor]]]:206 ) -> Tuple[List[Any], Optional[List[torch.Tensor]]]:
207 meta = self.kernel_meta or {}207 meta = self.kernel_meta or {}
208 num_outputs = int(meta.get("num_outputs") or 0)208 num_outputs = int(meta.get("num_outputs") or 0)
209 num_call_functions = int(meta.get("num_call_functions") or 0)209 num_call_functions = int(meta.get("num_call_functions") or 0)
210 210 
211 if num_outputs < 0 or len(args) < num_outputs:211 if num_outputs < 0 or len(args) < num_outputs:
212 return args, None212 return args, None
213 213 
214 num_inputs = len(args) - num_outputs214 num_inputs = len(args) - num_outputs
215 215 
216 if self._nc_input_indices is None:216 if self._nc_input_indices is None:
217 self._nc_input_indices = []217 self._nc_input_indices = []
218 if num_call_functions > 0:218 if num_call_functions > 0:
219 input_slice = args[:num_inputs] if num_outputs > 0 else args219 input_slice = args[:num_inputs] if num_outputs > 0 else args
220 for idx, arg in enumerate(input_slice):220 for idx, arg in enumerate(input_slice):
221 if not isinstance(arg, torch.Tensor) or arg.is_contiguous():221 if not isinstance(arg, torch.Tensor) or arg.is_contiguous():
222 continue222 continue
223 args[idx] = arg.contiguous()223 args[idx] = arg.contiguous()
224 self._nc_input_indices.append(idx)224 self._nc_input_indices.append(idx)
225 else:225 else:
226 for idx in self._nc_input_indices:226 for idx in self._nc_input_indices:
227 if idx < len(args) and isinstance(args[idx], torch.Tensor):227 if idx < len(args) and isinstance(args[idx], torch.Tensor):
228 args[idx] = args[idx].contiguous()228 args[idx] = args[idx].contiguous()
229 229 
230 if num_outputs == 0:230 if num_outputs == 0:
231 return args, None231 return args, None
232 232 
233 original_outputs: Optional[List[torch.Tensor]] = None233 original_outputs: Optional[List[torch.Tensor]] = None
234 if self._nc_output_indices is None:234 if self._nc_output_indices is None:
235 self._nc_output_indices = []235 self._nc_output_indices = []
236 original_outputs = []236 original_outputs = []
237 for j, out in enumerate(args[num_inputs:]):237 for j, out in enumerate(args[num_inputs:]):
238 if not isinstance(out, torch.Tensor) or out.is_contiguous():238 if not isinstance(out, torch.Tensor) or out.is_contiguous():
239 continue239 continue
240 tmp = torch.empty(out.shape, dtype=out.dtype, device=out.device)240 tmp = torch.empty(out.shape, dtype=out.dtype, device=out.device)
241 out_idx = num_inputs + j241 out_idx = num_inputs + j
242 original_outputs.append(out)242 original_outputs.append(out)
243 args[out_idx] = tmp243 args[out_idx] = tmp
244 self._nc_output_indices.append(out_idx)244 self._nc_output_indices.append(out_idx)
245 else:245 else:
246 original_outputs = []246 original_outputs = []
247 for out_idx in self._nc_output_indices:247 for out_idx in self._nc_output_indices:
248 tmp = torch.empty(248 tmp = torch.empty(
249 args[out_idx].shape, dtype=args[out_idx].dtype, device=args[out_idx].device249 args[out_idx].shape, dtype=args[out_idx].dtype, device=args[out_idx].device
250 )250 )
251 original_outputs.append(args[out_idx])251 original_outputs.append(args[out_idx])
252 args[out_idx] = tmp252 args[out_idx] = tmp
253 253 
254 return args, original_outputs254 return args, original_outputs
255 255 
256 def _copy_back_non_contiguous_outputs(256 def _copy_back_non_contiguous_outputs(
257 self,257 self,
258 args_list: List[Any],258 args_list: List[Any],
259 original_outputs: Optional[List[torch.Tensor]],259 original_outputs: Optional[List[torch.Tensor]],
260 ) -> None:260 ) -> None:
261 if original_outputs and self._nc_output_indices:261 if original_outputs and self._nc_output_indices:
262 for orig, idx in zip(original_outputs, self._nc_output_indices):262 for orig, idx in zip(original_outputs, self._nc_output_indices):
263 orig.copy_(args_list[idx])263 orig.copy_(args_list[idx])
264 264 
265 265 
266 def _fx_graph_call_factory(self, module: torch.nn.Module, num_outputs: int) -> Callable[..., Any]:266 def _fx_graph_call_factory(self, module: torch.nn.Module, num_outputs: int) -> Callable[..., Any]:
267 def module_call(*args, **kwargs):267 def module_call(*args, **kwargs):
268 actual_args = args[:-num_outputs] if num_outputs > 0 else args268 actual_args = args[:-num_outputs] if num_outputs > 0 else args
269 actual_outputs = module.forward(*actual_args)269 actual_outputs = module.forward(*actual_args)
270 for out1, out2 in zip(actual_outputs, args[-num_outputs:]):270 for out1, out2 in zip(actual_outputs, args[-num_outputs:]):
271 if isinstance(out1, torch.Tensor) and not out1.is_contiguous():271 if isinstance(out1, torch.Tensor) and not out1.is_contiguous():
272 out1 = out1.contiguous()272 out1 = out1.contiguous()
273 out2.data = out1.data273 out2.data = out1.data
274 return module_call274 return module_call
275 275 
276 def _load_traced_graph_model(self) -> torch.nn.Module:276 def _load_traced_graph_model(self) -> torch.nn.Module:
277 meta = self.kernel_meta or {}277 meta = self.kernel_meta or {}
278 traced_graph_hash = meta.get("traced_graph_hash")278 traced_graph_hash = meta.get("traced_graph_hash")
279 if not traced_graph_hash:279 if not traced_graph_hash:
280 raise RuntimeError("traced_graph_hash missing, cannot build FX fallback")280 raise RuntimeError("traced_graph_hash missing, cannot build FX fallback")
281 281 
282 traced_graph_cache = meta.get("traced_graph_cache")282 traced_graph_cache = meta.get("traced_graph_cache")
283 if traced_graph_cache is None:283 if traced_graph_cache is None:
284 raise RuntimeError("traced_graph_cache missing, cannot locate traced graph dump")284 raise RuntimeError("traced_graph_cache missing, cannot locate traced graph dump")
285 285 
286 base_cache = os.getenv("TORCHINDUCTOR_CACHE_DIR", "")286 base_cache = os.getenv("TORCHINDUCTOR_CACHE_DIR", "")
287 dump_root = os.path.join(base_cache, traced_graph_cache)287 dump_root = os.path.join(base_cache, traced_graph_cache)
288 dump_path = os.path.join(dump_root, str(self.device_index), traced_graph_hash)288 dump_path = os.path.join(dump_root, str(self.device_index), traced_graph_hash)
289 289 
290 sys.path.append(dump_path)290 sys.path.append(dump_path)
291 try:291 try:
292 module = importlib.import_module(traced_graph_hash)292 module = importlib.import_module(traced_graph_hash)
293 finally:293 finally:
294 sys.path.remove(dump_path)294 sys.path.remove(dump_path)
295 295 
296 Model = getattr(module, traced_graph_hash, None)296 Model = getattr(module, traced_graph_hash, None)
297 if Model is None:297 if Model is None:
298 raise RuntimeError("Cannot find valid graph module class in traced graph dump")298 raise RuntimeError("Cannot find valid graph module class in traced graph dump")
299 299 
300 return Model()300 return Model()
301 301 
302 def register_fx_fallback(self, kernel_meta) -> None:302 def register_fx_fallback(self, kernel_meta) -> None:
303 model = self._load_traced_graph_model()303 model = self._load_traced_graph_model()
304 num_outputs = kernel_meta.get("num_outputs", 0)304 num_outputs = kernel_meta.get("num_outputs", 0)
305 module_call = self._fx_graph_call_factory(model, num_outputs)305 module_call = self._fx_graph_call_factory(model, num_outputs)
306 self.register_launcher(306 self.register_launcher(
307 module_call,307 module_call,
308 kernel_path=self.kernel_name + "_fx_fallback",308 kernel_path=self.kernel_name + "_fx_fallback",
309 is_fallback_kernel=True,309 is_fallback_kernel=True,
310 )310 )
311 311 
312 def run(self, *args, **kwargs):312 def run(self, *args, **kwargs):
313 args_list = list(args)313 args_list = list(args)
314 args_list, original_outputs = self._normalize_contiguous_args(args_list)314 args_list, original_outputs = self._normalize_contiguous_args(args_list)
315 self.ensure_runtime_ready(*args_list, **kwargs)315 self.ensure_runtime_ready(*args_list, **kwargs)
316 316 
317 launcher_idx = self.get_primary_launcher_index()317 launcher_idx = self.get_primary_launcher_index()
318 launcher = self.launchers[launcher_idx]318 launcher = self.launchers[launcher_idx]
319 is_fallback_kernel = self.is_fallback_kernels[launcher_idx]319 is_fallback_kernel = self.is_fallback_kernels[launcher_idx]
320 if anir_config.online_acc_comp and not is_fallback_kernel:320 if anir_config.online_acc_comp and not is_fallback_kernel:
321 output = self.acc_compare_and_dump(*args_list, **kwargs)321 output = self.acc_compare_and_dump(*args_list, **kwargs)
322 self._copy_back_non_contiguous_outputs(args_list, original_outputs)322 self._copy_back_non_contiguous_outputs(args_list, original_outputs)
323 return output323 return output
324 if self.dynamic and not is_fallback_kernel:324 if self.dynamic and not is_fallback_kernel:
325 args_list = self.prepare_runtime_args(325 args_list = self.prepare_runtime_args(
326 args_list,326 args_list,
327 )327 )
328 ret = launcher(*tuple(args_list), **kwargs)328 ret = launcher(*tuple(args_list), **kwargs)
329 self._copy_back_non_contiguous_outputs(args_list, original_outputs)329 self._copy_back_non_contiguous_outputs(args_list, original_outputs)
330 return ret330 return ret
Mtorch_npu/_inductor/docs/feature/non_contiguous_accesses/arch.drawio.svg+597-597
@@ -1,598 +1,598 @@
1<svg host="65bd71144e" xmlns="http://www.w3.org/2000/svg" style="background: transparent; background-color: transparent;" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="1111px" height="601px" viewBox="-0.5 -0.5 1111 601" content="&lt;mxfile&gt;&lt;diagram id=&quot;uiDLYcUB2_ILZagOPzox&quot; name=&quot;Page-1&quot;&gt;7Vxbc5s4FP41THd3Jh7ul0d8SZuZps0k6Wz75MEg29oC8mI5sffXrwTCIBAOtnGcZMxDgo4uCH0fR+ccSZa0QbT+nHiL+S0KQCipcrCWtKGkqoqlkL9UsMkEhmZlglkCA1amEDzA/wATyky6ggFYcgUxQiGGC17oozgGPuZkXpKgZ77YFIX8UxfeDNQED74X1qV/wwDPM6ltyIX8C4Czef5kRWY5kZcXZoLl3AvQc0mkjSRtkCCEs7toPQAhHbt8XLJ61w25244lIMZtKqhZhScvXLF3Y/3Cm/xlE7SKA0DLy5LWf55DDB4Wnk9znwm6RDbHUUhSCrn1QjiLyb1Png8SIngCCYZk5FyWMUEYo4hkTFGMr70IhpQDX0D4BGg5lsEgV1SWHqAQJWl3tOyij1phtMzK0Y4lgCS8Sdpr2pMpDMNStev0IvIlTtBvUMox04vkhN4EhHekTQyR8B2+VgpgRN++PuQMBVoNrEsiBsFngCKAkw0pkufKOUE2PNGfC3YpSi6cl6hl5hU9RunZtvECdXLDgBeTQKthDgLCd5ZECZ6jGYq9cFRI+zwrijJfER2UFIF/AMYbhiQFi2cKGa1k85PW7xl58hdrLk0M11xqw1IH8SYAU28VYp41ioA1jWAu0Srx2egYTOV4yQzkpexMRgduJ+IJCD0Mn3hFcgx4+gW8o8FzzgWeIVC/ZvqqdAA4WM1/VyjPuMoGwSUFFH2xTl89zyd3s/T/yJJcU+qTG1NyDMnVpJEtuSOpfy2NSHIoOTYt01fSMhbNcqw8S877Qd4g6wpr9bSzQwSDIGVoa6LsNwsEHrCnft4MewtFOCv4NphMO1Lvms2rd1UW6HdVoN71DrS7dVEQeymIfJotawjVPJeGsC/oHY+e0TV6aVU3SbxNqcACwRgvSy3fUUFJDZgOrwZ0Xe8ZvHlerWJrxu4q5CbrR8Gm7Qu1IphzIdjxBJPfLcEM/dQEywdMYOQsF158lJETIi8gz19ilABSbvjwtWS3ZK1/CLtlavvAb2W3TGyCqNyR3WJqPJ80MyfHq1guilZjDg57DHNyx2CvIEteDh8KXxUG9sWRdo2+ZAzrKoQf/xjFoAJeLjpOcfGwd4CsUbFINU2ErCMAVusC2Ga/J4BPxTebiSZCFTHx/N+z9Cu+8rPxopoCxhBDLxQqCxwtym7NZPscbcho9QeMFziR1P7mz+3Dk2p3SNVSJyHRInRQ16SW/Vepyy88sz1rQzDFb5ezeiNnO1FAeiUuZgkcJ13AUqMLltr7T1wUxqtsAqF0jBGbTAT+eXeOvkMd975OHX17JLmGwNFv8uY/4mR5Jie/Olmq9is6+XkI681z1ZKc/oWr5+aqYp6Rq2qHDoHcnsQPN7ekQTkNh5pS36E3riLZ9sdk1plcBr3CLEMVugzWqbilCLhVjW/EgUsXgQtLJ/CW8xRYhQeRR/y0wQewhvgnexK9T8MhPcsxWLqIiNDEppS4AwkkA0VZVoRMsuCKQ9RpObxC2tOk3SGWNFVtspEZL0Y8SqAbO+y0/QIj9TBGdQHVkJWeyreSBXFYxR0hEdKY1bMsZ3tZXMu64/Sc8qXzj8niQrXHHBA4yalb4vIARQsYElhG11J/QHTXI1F6phdR5ZP9/Xb34+rmPs+vB/fer3fc7Gl07h3LFVPO0PW6CrNP5Byr9ajHTRysfEze+oLmIWgaFWPH0gRTkmhG6gROvQanS8YVr+KPFLp6RTjNiqrXFZGFcbKvszl0xRuPnTlfMA5gAnw8ZoHPbZqFPxuM1zfo/OUzVTxZLniPrpWjt1MsiBu+pXcnzscjcz5cm7od1AsZpm7vDndkv2HhhuDiu+yvWSzjvL6L+YJqOY1fnG4CciX3OuPoxRfubvlMb8Un+VR8OiB+vZtPDEiaw1YlhNOVYEFk3+np+H5s2lL5/Rpd7dYL5S6ovFV6+UKMIwgYiojcic1VD25f1oG7MaaV6qKFUcf1VKvAWj0O7GfxjXGEAl4fLGGExygON9yHXrX8aCnSYFZOxjCE8UxKj4FM4aylpfReF2JfkTSmWvHA9Fe1k7R6jHc3bzCIFqGHQRvuFGUvtOmYNrbeijYiddMJbepxtV20CV5iS3BRMafjil4N8oi5Itr60QlX6kG7IgYrtzpa8XHMEfMVYa9sYBVYI4poGakTc8SqYe7S2gRd8sf4QIC+5j5DpQKoVV9JOVXkXav7vxcYD7T4TKMKo0Adi7RxJ0DW/b8LkAfaYMo5gdTrKrYGY/n0CRvE8sGRfJdEL98X8auU07BH4sDDJlnXKjscXj4fwrQOd8BUFqPS1XGQIzYZ6HVn6ubb8Mfg8fv9mNzc3I8Gj+Pb0e33+1/j2+9D0sbwEzV+x6lnFcH1p8uHeNBaQ8XAFW/A1072Jdb15+4PrxX3dbPO/dOcvavvANIrkSylugW8Yf/PId9M80KNYBmSrR3620WGwq3U5PRqXndsHR9Xdx2QKk55p7uCHNfDIO6BaAKCgLqvI02yZclWUnEWv+dEMw/P6Z6jWrHxEoT091VeXJpsWMgUjNZbG8AstiwewWwMFivMD83S9zBVc52Myol0q9ylbu1CH6rVkx6Cn0DRO1opI8niF3ay77/4mSJt9D8=&lt;/diagram&gt;&lt;/mxfile&gt;">1<svg host="65bd71144e" xmlns="http://www.w3.org/2000/svg" style="background: transparent; background-color: transparent;" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="1111px" height="601px" viewBox="-0.5 -0.5 1111 601" content="&lt;mxfile&gt;&lt;diagram id=&quot;uiDLYcUB2_ILZagOPzox&quot; name=&quot;Page-1&quot;&gt;7Vxbc5s4FP41THd3Jh7ul0d8SZuZps0k6Wz75MEg29oC8mI5sffXrwTCIBAOtnGcZMxDgo4uCH0fR+ccSZa0QbT+nHiL+S0KQCipcrCWtKGkqoqlkL9UsMkEhmZlglkCA1amEDzA/wATyky6ggFYcgUxQiGGC17oozgGPuZkXpKgZ77YFIX8UxfeDNQED74X1qV/wwDPM6ltyIX8C4Czef5kRWY5kZcXZoLl3AvQc0mkjSRtkCCEs7toPQAhHbt8XLJ61w25244lIMZtKqhZhScvXLF3Y/3Cm/xlE7SKA0DLy5LWf55DDB4Wnk9znwm6RDbHUUhSCrn1QjiLyb1Png8SIngCCYZk5FyWMUEYo4hkTFGMr70IhpQDX0D4BGg5lsEgV1SWHqAQJWl3tOyij1phtMzK0Y4lgCS8Sdpr2pMpDMNStev0IvIlTtBvUMox04vkhN4EhHekTQyR8B2+VgpgRN++PuQMBVoNrEsiBsFngCKAkw0pkufKOUE2PNGfC3YpSi6cl6hl5hU9RunZtvECdXLDgBeTQKthDgLCd5ZECZ6jGYq9cFRI+zwrijJfER2UFIF/AMYbhiQFi2cKGa1k85PW7xl58hdrLk0M11xqw1IH8SYAU28VYp41ioA1jWAu0Srx2egYTOV4yQzkpexMRgduJ+IJCD0Mn3hFcgx4+gW8o8FzzgWeIVC/ZvqqdAA4WM1/VyjPuMoGwSUFFH2xTl89zyd3s/T/yJJcU+qTG1NyDMnVpJEtuSOpfy2NSHIoOTYt01fSMhbNcqw8S877Qd4g6wpr9bSzQwSDIGVoa6LsNwsEHrCnft4MewtFOCv4NphMO1Lvms2rd1UW6HdVoN71DrS7dVEQeymIfJotawjVPJeGsC/oHY+e0TV6aVU3SbxNqcACwRgvSy3fUUFJDZgOrwZ0Xe8ZvHlerWJrxu4q5CbrR8Gm7Qu1IphzIdjxBJPfLcEM/dQEywdMYOQsF158lJETIi8gz19ilABSbvjwtWS3ZK1/CLtlavvAb2W3TGyCqNyR3WJqPJ80MyfHq1guilZjDg57DHNyx2CvIEteDh8KXxUG9sWRdo2+ZAzrKoQf/xjFoAJeLjpOcfGwd4CsUbFINU2ErCMAVusC2Ga/J4BPxTebiSZCFTHx/N+z9Cu+8rPxopoCxhBDLxQqCxwtym7NZPscbcho9QeMFziR1P7mz+3Dk2p3SNVSJyHRInRQ16SW/Vepyy88sz1rQzDFb5ezeiNnO1FAeiUuZgkcJ13AUqMLltr7T1wUxqtsAqF0jBGbTAT+eXeOvkMd975OHX17JLmGwNFv8uY/4mR5Jie/Olmq9is6+XkI681z1ZKc/oWr5+aqYp6Rq2qHDoHcnsQPN7ekQTkNh5pS36E3riLZ9sdk1plcBr3CLEMVugzWqbilCLhVjW/EgUsXgQtLJ/CW8xRYhQeRR/y0wQewhvgnexK9T8MhPcsxWLqIiNDEppS4AwkkA0VZVoRMsuCKQ9RpObxC2tOk3SGWNFVtspEZL0Y8SqAbO+y0/QIj9TBGdQHVkJWeyreSBXFYxR0hEdKY1bMsZ3tZXMu64/Sc8qXzj8niQrXHHBA4yalb4vIARQsYElhG11J/QHTXI1F6phdR5ZP9/Xb34+rmPs+vB/fer3fc7Gl07h3LFVPO0PW6CrNP5Byr9ajHTRysfEze+oLmIWgaFWPH0gRTkmhG6gROvQanS8YVr+KPFLp6RTjNiqrXFZGFcbKvszl0xRuPnTlfMA5gAnw8ZoHPbZqFPxuM1zfo/OUzVTxZLniPrpWjt1MsiBu+pXcnzscjcz5cm7od1AsZpm7vDndkv2HhhuDiu+yvWSzjvL6L+YJqOY1fnG4CciX3OuPoxRfubvlMb8Un+VR8OiB+vZtPDEiaw1YlhNOVYEFk3+np+H5s2lL5/Rpd7dYL5S6ovFV6+UKMIwgYiojcic1VD25f1oG7MaaV6qKFUcf1VKvAWj0O7GfxjXGEAl4fLGGExygON9yHXrX8aCnSYFZOxjCE8UxKj4FM4aylpfReF2JfkTSmWvHA9Fe1k7R6jHc3bzCIFqGHQRvuFGUvtOmYNrbeijYiddMJbepxtV20CV5iS3BRMafjil4N8oi5Itr60QlX6kG7IgYrtzpa8XHMEfMVYa9sYBVYI4poGakTc8SqYe7S2gRd8sf4QIC+5j5DpQKoVV9JOVXkXav7vxcYD7T4TKMKo0Adi7RxJ0DW/b8LkAfaYMo5gdTrKrYGY/n0CRvE8sGRfJdEL98X8auU07BH4sDDJlnXKjscXj4fwrQOd8BUFqPS1XGQIzYZ6HVn6ubb8Mfg8fv9mNzc3I8Gj+Pb0e33+1/j2+9D0sbwEzV+x6lnFcH1p8uHeNBaQ8XAFW/A1072Jdb15+4PrxX3dbPO/dOcvavvANIrkSylugW8Yf/PId9M80KNYBmSrR3620WGwq3U5PRqXndsHR9Xdx2QKk55p7uCHNfDIO6BaAKCgLqvI02yZclWUnEWv+dEMw/P6Z6jWrHxEoT091VeXJpsWMgUjNZbG8AstiwewWwMFivMD83S9zBVc52Myol0q9ylbu1CH6rVkx6Cn0DRO1opI8niF3ay77/4mSJt9D8=&lt;/diagram&gt;&lt;/mxfile&gt;">
2 <defs/>2 <defs/>
3 <g>3 <g>
4 <g>4 <g>
5 <rect x="0" y="0" width="1110" height="600" fill="#ffffff" stroke="#666666" pointer-events="all" style="fill: light-dark(rgb(255, 255, 255), rgb(18, 18, 18)); stroke: light-dark(rgb(102, 102, 102), rgb(149, 149, 149));"/>5 <rect x="0" y="0" width="1110" height="600" fill="#ffffff" stroke="#666666" pointer-events="all" style="fill: light-dark(rgb(255, 255, 255), rgb(18, 18, 18)); stroke: light-dark(rgb(102, 102, 102), rgb(149, 149, 149));"/>
6 </g>6 </g>
7 <g>7 <g>
8 <path d="M 500 210 L 690 210 L 690 263.63" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke" style="stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/>8 <path d="M 500 210 L 690 210 L 690 263.63" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke" style="stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/>
9 <path d="M 690 268.88 L 686.5 261.88 L 690 263.63 L 693.5 261.88 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all" style="fill: light-dark(rgb(0, 0, 0), rgb(255, 255, 255)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/>9 <path d="M 690 268.88 L 686.5 261.88 L 690 263.63 L 693.5 261.88 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all" style="fill: light-dark(rgb(0, 0, 0), rgb(255, 255, 255)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/>
10 </g>10 </g>
11 <g>11 <g>
12 <path d="M 380 210 L 220 210 L 220 263.63" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke" style="stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/>12 <path d="M 380 210 L 220 210 L 220 263.63" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke" style="stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/>
13 <path d="M 220 268.88 L 216.5 261.88 L 220 263.63 L 223.5 261.88 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all" style="fill: light-dark(rgb(0, 0, 0), rgb(255, 255, 255)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/>13 <path d="M 220 268.88 L 216.5 261.88 L 220 263.63 L 223.5 261.88 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all" style="fill: light-dark(rgb(0, 0, 0), rgb(255, 255, 255)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/>
14 </g>14 </g>
15 <g>15 <g>
16 <rect x="380" y="190" width="120" height="40" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all" style="fill: light-dark(rgb(218, 232, 252), rgb(29, 41, 59)); stroke: light-dark(rgb(108, 142, 191), rgb(92, 121, 163));"/>16 <rect x="380" y="190" width="120" height="40" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all" style="fill: light-dark(rgb(218, 232, 252), rgb(29, 41, 59)); stroke: light-dark(rgb(108, 142, 191), rgb(92, 121, 163));"/>
17 </g>17 </g>
18 <g>18 <g>
19 <g transform="translate(-0.5 -0.5)">19 <g transform="translate(-0.5 -0.5)">
20 <switch>20 <switch>
21 <foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility">21 <foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility">
22 <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 210px; margin-left: 381px;">22 <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 210px; margin-left: 381px;">
23 <div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; ">23 <div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; ">
24 <div style="display: inline-block; font-size: 12px; font-family: &quot;Helvetica&quot;; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: normal; word-wrap: normal; ">24 <div style="display: inline-block; font-size: 12px; font-family: &quot;Helvetica&quot;; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: normal; word-wrap: normal; ">
25 <font style="font-size: 14px;">25 <font style="font-size: 14px;">
26 离散访存类算子26 离散访存类算子
27 </font>27 </font>
28 </div>28 </div>
29 </div>29 </div>
30 </div>30 </div>
31 </foreignObject>31 </foreignObject>
32 <text x="440" y="214" fill="light-dark(#000000, #ffffff)" font-family="&quot;Helvetica&quot;" font-size="12px" text-anchor="middle" font-weight="bold">32 <text x="440" y="214" fill="light-dark(#000000, #ffffff)" font-family="&quot;Helvetica&quot;" font-size="12px" text-anchor="middle" font-weight="bold">
33 离散访存类算子33 离散访存类算子
34 </text>34 </text>
35 </switch>35 </switch>
36 </g>36 </g>
37 </g>37 </g>
38 <g>38 <g>
39 <path d="M 690 394.5 L 690 508.13" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke" style="stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/>39 <path d="M 690 394.5 L 690 508.13" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke" style="stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/>
40 <path d="M 690 513.38 L 686.5 506.38 L 690 508.13 L 693.5 506.38 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all" style="fill: light-dark(rgb(0, 0, 0), rgb(255, 255, 255)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/>40 <path d="M 690 513.38 L 686.5 506.38 L 690 508.13 L 693.5 506.38 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all" style="fill: light-dark(rgb(0, 0, 0), rgb(255, 255, 255)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/>
41 </g>41 </g>
42 <g>42 <g>
43 <path d="M 690 394.5 L 690 434.5 L 835 434.5 L 835 508.13" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke" style="stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/>43 <path d="M 690 394.5 L 690 434.5 L 835 434.5 L 835 508.13" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke" style="stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/>
44 <path d="M 835 513.38 L 831.5 506.38 L 835 508.13 L 838.5 506.38 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all" style="fill: light-dark(rgb(0, 0, 0), rgb(255, 255, 255)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/>44 <path d="M 835 513.38 L 831.5 506.38 L 835 508.13 L 838.5 506.38 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all" style="fill: light-dark(rgb(0, 0, 0), rgb(255, 255, 255)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/>
45 </g>45 </g>
46 <g>46 <g>
47 <path d="M 690 394.5 L 690 434.5 L 545 434.5 L 545 508.13" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke" style="stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/>47 <path d="M 690 394.5 L 690 434.5 L 545 434.5 L 545 508.13" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke" style="stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/>
48 <path d="M 545 513.38 L 541.5 506.38 L 545 508.13 L 548.5 506.38 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all" style="fill: light-dark(rgb(0, 0, 0), rgb(255, 255, 255)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/>48 <path d="M 545 513.38 L 541.5 506.38 L 545 508.13 L 548.5 506.38 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all" style="fill: light-dark(rgb(0, 0, 0), rgb(255, 255, 255)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/>
49 </g>49 </g>
50 <g>50 <g>
51 <rect x="630" y="354.5" width="120" height="40" fill="#f8cecc" stroke="#b85450" pointer-events="all" style="fill: light-dark(rgb(248, 206, 204), rgb(81, 45, 43)); stroke: light-dark(rgb(184, 84, 80), rgb(215, 129, 126));"/>51 <rect x="630" y="354.5" width="120" height="40" fill="#f8cecc" stroke="#b85450" pointer-events="all" style="fill: light-dark(rgb(248, 206, 204), rgb(81, 45, 43)); stroke: light-dark(rgb(184, 84, 80), rgb(215, 129, 126));"/>
52 </g>52 </g>
53 <g>53 <g>
54 <g transform="translate(-0.5 -0.5)">54 <g transform="translate(-0.5 -0.5)">
55 <switch>55 <switch>
56 <foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility">56 <foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility">
57 <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 375px; margin-left: 631px;">57 <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 375px; margin-left: 631px;">
58 <div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; ">58 <div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; ">
59 <div style="display: inline-block; font-size: 12px; font-family: &quot;Helvetica&quot;; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: normal; word-wrap: normal; ">59 <div style="display: inline-block; font-size: 12px; font-family: &quot;Helvetica&quot;; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: normal; word-wrap: normal; ">
60 <span style="font-size: 14px;">60 <span style="font-size: 14px;">
61 load/store DSL61 load/store DSL
62 </span>62 </span>
63 </div>63 </div>
64 </div>64 </div>
65 </div>65 </div>
66 </foreignObject>66 </foreignObject>
67 <text x="690" y="378" fill="light-dark(#000000, #ffffff)" font-family="&quot;Helvetica&quot;" font-size="12px" text-anchor="middle" font-weight="bold">67 <text x="690" y="378" fill="light-dark(#000000, #ffffff)" font-family="&quot;Helvetica&quot;" font-size="12px" text-anchor="middle" font-weight="bold">
68 load/store DSL68 load/store DSL
69 </text>69 </text>
70 </switch>70 </switch>
71 </g>71 </g>
72 </g>72 </g>
73 <g>73 <g>
74 <rect x="580" y="324.5" width="90" height="30" fill="none" stroke="none" pointer-events="all"/>74 <rect x="580" y="324.5" width="90" height="30" fill="none" stroke="none" pointer-events="all"/>
75 </g>75 </g>
76 <g>76 <g>
77 <g transform="translate(-0.5 -0.5)">77 <g transform="translate(-0.5 -0.5)">
78 <switch>78 <switch>
79 <foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility">79 <foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility">
80 <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 340px; margin-left: 625px;">80 <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 340px; margin-left: 625px;">
81 <div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; ">81 <div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; ">
82 <div style="display: inline-block; font-size: 12px; font-family: &quot;Helvetica&quot;; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: nowrap; ">82 <div style="display: inline-block; font-size: 12px; font-family: &quot;Helvetica&quot;; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: nowrap; ">
83 tl.load/tl.store83 tl.load/tl.store
84 </div>84 </div>
85 </div>85 </div>
86 </div>86 </div>
87 </foreignObject>87 </foreignObject>
88 <text x="625" y="343" fill="light-dark(#000000, #ffffff)" font-family="&quot;Helvetica&quot;" font-size="12px" text-anchor="middle" font-weight="bold">88 <text x="625" y="343" fill="light-dark(#000000, #ffffff)" font-family="&quot;Helvetica&quot;" font-size="12px" text-anchor="middle" font-weight="bold">
89 tl.load/tl.store89 tl.load/tl.store
90 </text>90 </text>
91 </switch>91 </switch>
92 </g>92 </g>
93 </g>93 </g>
94 <g>94 <g>
95 <rect x="640" y="160" width="140" height="50" fill="none" stroke="none" pointer-events="all"/>95 <rect x="640" y="160" width="140" height="50" fill="none" stroke="none" pointer-events="all"/>
96 </g>96 </g>
97 <g>97 <g>
98 <g transform="translate(-0.5 -0.5)">98 <g transform="translate(-0.5 -0.5)">
99 <switch>99 <switch>
100 <foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility">100 <foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility">
101 <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 1px; height: 1px; padding-top: 185px; margin-left: 642px;">101 <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 1px; height: 1px; padding-top: 185px; margin-left: 642px;">
102 <div style="box-sizing: border-box; font-size: 0; text-align: left; color: #000000; ">102 <div style="box-sizing: border-box; font-size: 0; text-align: left; color: #000000; ">
103 <div style="display: inline-block; font-size: 14px; font-family: &quot;Helvetica&quot;; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: nowrap; ">103 <div style="display: inline-block; font-size: 14px; font-family: &quot;Helvetica&quot;; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: nowrap; ">
104 <div>104 <div>
105 <b style="background-color: initial;">105 <b style="background-color: initial;">
106 tmp0106 tmp0
107 </b>107 </b>
108 =tl.load(inptr+y)108 =tl.load(inptr+y)
109 <br/>109 <br/>
110 </div>110 </div>
111 index=x+8*111 index=x+8*
112 <b>112 <b>
113 tmp0113 tmp0
114 </b>114 </b>
115 </div>115 </div>
116 </div>116 </div>
117 </div>117 </div>
118 </foreignObject>118 </foreignObject>
119 <text x="642" y="189" fill="light-dark(#000000, #ffffff)" font-family="&quot;Helvetica&quot;" font-size="14px">119 <text x="642" y="189" fill="light-dark(#000000, #ffffff)" font-family="&quot;Helvetica&quot;" font-size="14px">
120 tmp0=tl.load(inptr+y...120 tmp0=tl.load(inptr+y...
121 </text>121 </text>
122 </switch>122 </switch>
123 </g>123 </g>
124 </g>124 </g>
125 <g>125 <g>
126 <rect x="630" y="270" width="120" height="40" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all" style="fill: light-dark(rgb(218, 232, 252), rgb(29, 41, 59)); stroke: light-dark(rgb(108, 142, 191), rgb(92, 121, 163));"/>126 <rect x="630" y="270" width="120" height="40" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all" style="fill: light-dark(rgb(218, 232, 252), rgb(29, 41, 59)); stroke: light-dark(rgb(108, 142, 191), rgb(92, 121, 163));"/>
127 </g>127 </g>
128 <g>128 <g>
129 <g transform="translate(-0.5 -0.5)">129 <g transform="translate(-0.5 -0.5)">
130 <switch>130 <switch>
131 <foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility">131 <foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility">
132 <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 290px; margin-left: 631px;">132 <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 290px; margin-left: 631px;">
133 <div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; ">133 <div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; ">
134 <div style="display: inline-block; font-size: 12px; font-family: &quot;Helvetica&quot;; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: normal; word-wrap: normal; ">134 <div style="display: inline-block; font-size: 12px; font-family: &quot;Helvetica&quot;; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: normal; word-wrap: normal; ">
135 <span style="text-wrap: nowrap;">135 <span style="text-wrap: nowrap;">
136 <font style="font-size: 14px;">136 <font style="font-size: 14px;">
137 间接访存137 间接访存
138 </font>138 </font>
139 </span>139 </span>
140 </div>140 </div>
141 </div>141 </div>
142 </div>142 </div>
143 </foreignObject>143 </foreignObject>
144 <text x="690" y="294" fill="light-dark(#000000, #ffffff)" font-family="&quot;Helvetica&quot;" font-size="12px" text-anchor="middle" font-weight="bold">144 <text x="690" y="294" fill="light-dark(#000000, #ffffff)" font-family="&quot;Helvetica&quot;" font-size="12px" text-anchor="middle" font-weight="bold">
145 间接访存145 间接访存
146 </text>146 </text>
147 </switch>147 </switch>
148 </g>148 </g>
149 </g>149 </g>
150 <g>150 <g>
151 <rect x="160" y="270" width="120" height="40" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all" style="fill: light-dark(rgb(218, 232, 252), rgb(29, 41, 59)); stroke: light-dark(rgb(108, 142, 191), rgb(92, 121, 163));"/>151 <rect x="160" y="270" width="120" height="40" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all" style="fill: light-dark(rgb(218, 232, 252), rgb(29, 41, 59)); stroke: light-dark(rgb(108, 142, 191), rgb(92, 121, 163));"/>
152 </g>152 </g>
153 <g>153 <g>
154 <g transform="translate(-0.5 -0.5)">154 <g transform="translate(-0.5 -0.5)">
155 <switch>155 <switch>
156 <foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility">156 <foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility">
157 <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 290px; margin-left: 161px;">157 <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 290px; margin-left: 161px;">
158 <div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; ">158 <div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; ">
159 <div style="display: inline-block; font-size: 12px; font-family: &quot;Helvetica&quot;; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: normal; word-wrap: normal; ">159 <div style="display: inline-block; font-size: 12px; font-family: &quot;Helvetica&quot;; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: normal; word-wrap: normal; ">
160 <span style="text-wrap: nowrap;">160 <span style="text-wrap: nowrap;">
161 <font style="font-size: 14px;">161 <font style="font-size: 14px;">
162 直接访存162 直接访存
163 </font>163 </font>
164 </span>164 </span>
165 </div>165 </div>
166 </div>166 </div>
167 </div>167 </div>
168 </foreignObject>168 </foreignObject>
169 <text x="220" y="294" fill="light-dark(#000000, #ffffff)" font-family="&quot;Helvetica&quot;" font-size="12px" text-anchor="middle" font-weight="bold">169 <text x="220" y="294" fill="light-dark(#000000, #ffffff)" font-family="&quot;Helvetica&quot;" font-size="12px" text-anchor="middle" font-weight="bold">
170 直接访存170 直接访存
171 </text>171 </text>
172 </switch>172 </switch>
173 </g>173 </g>
174 </g>174 </g>
175 <g>175 <g>
176 <rect x="460" y="514.5" width="170" height="40" fill="#f8cecc" stroke="#b85450" pointer-events="all" style="fill: light-dark(rgb(248, 206, 204), rgb(81, 45, 43)); stroke: light-dark(rgb(184, 84, 80), rgb(215, 129, 126));"/>176 <rect x="460" y="514.5" width="170" height="40" fill="#f8cecc" stroke="#b85450" pointer-events="all" style="fill: light-dark(rgb(248, 206, 204), rgb(81, 45, 43)); stroke: light-dark(rgb(184, 84, 80), rgb(215, 129, 126));"/>
177 </g>177 </g>
178 <g>178 <g>
179 <g transform="translate(-0.5 -0.5)">179 <g transform="translate(-0.5 -0.5)">
180 <switch>180 <switch>
181 <foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility">181 <foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility">
182 <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 168px; height: 1px; padding-top: 535px; margin-left: 461px;">182 <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 168px; height: 1px; padding-top: 535px; margin-left: 461px;">
183 <div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; ">183 <div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; ">
184 <div style="display: inline-block; font-size: 12px; font-family: &quot;Helvetica&quot;; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: normal; word-wrap: normal; ">184 <div style="display: inline-block; font-size: 12px; font-family: &quot;Helvetica&quot;; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: normal; word-wrap: normal; ">
185 <span style="font-size: 14px; text-wrap: nowrap;">185 <span style="font-size: 14px; text-wrap: nowrap;">
186 SIMD 方案186 SIMD 方案
187 </span>187 </span>
188 </div>188 </div>
189 </div>189 </div>
190 </div>190 </div>
191 </foreignObject>191 </foreignObject>
192 <text x="545" y="538" fill="light-dark(#000000, #ffffff)" font-family="&quot;Helvetica&quot;" font-size="12px" text-anchor="middle" font-weight="bold">192 <text x="545" y="538" fill="light-dark(#000000, #ffffff)" font-family="&quot;Helvetica&quot;" font-size="12px" text-anchor="middle" font-weight="bold">
193 SIMD 方案193 SIMD 方案
194 </text>194 </text>
195 </switch>195 </switch>
196 </g>196 </g>
197 </g>197 </g>
198 <g>198 <g>
199 <path d="M 0 491.2 L 1107.78 490" fill="none" stroke="#000000" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke" style="stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/>199 <path d="M 0 491.2 L 1107.78 490" fill="none" stroke="#000000" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke" style="stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/>
200 </g>200 </g>
201 <g>201 <g>
202 <rect x="30" y="534" width="180" height="30" fill="none" stroke="none" pointer-events="all"/>202 <rect x="30" y="534" width="180" height="30" fill="none" stroke="none" pointer-events="all"/>
203 </g>203 </g>
204 <g>204 <g>
205 <g transform="translate(-0.5 -0.5)">205 <g transform="translate(-0.5 -0.5)">
206 <switch>206 <switch>
207 <foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility">207 <foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility">
208 <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 549px; margin-left: 120px;">208 <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 549px; margin-left: 120px;">
209 <div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; ">209 <div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; ">
210 <div style="display: inline-block; font-size: 14px; font-family: &quot;Helvetica&quot;; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: nowrap; ">210 <div style="display: inline-block; font-size: 14px; font-family: &quot;Helvetica&quot;; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: nowrap; ">
211 Compiler(TA&amp;NPU-IR)211 Compiler(TA&amp;NPU-IR)
212 </div>212 </div>
213 </div>213 </div>
214 </div>214 </div>
215 </foreignObject>215 </foreignObject>
216 <text x="120" y="553" fill="light-dark(#000000, #ffffff)" font-family="&quot;Helvetica&quot;" font-size="14px" text-anchor="middle" font-weight="bold">216 <text x="120" y="553" fill="light-dark(#000000, #ffffff)" font-family="&quot;Helvetica&quot;" font-size="14px" text-anchor="middle" font-weight="bold">
217 Compiler(TA&amp;NPU-IR)217 Compiler(TA&amp;NPU-IR)
218 </text>218 </text>
219 </switch>219 </switch>
220 </g>220 </g>
221 </g>221 </g>
222 <g>222 <g>
223 <rect x="50" y="263.5" width="70" height="30" fill="none" stroke="none" pointer-events="all"/>223 <rect x="50" y="263.5" width="70" height="30" fill="none" stroke="none" pointer-events="all"/>
224 </g>224 </g>
225 <g>225 <g>
226 <g transform="translate(-0.5 -0.5)">226 <g transform="translate(-0.5 -0.5)">
227 <switch>227 <switch>
228 <foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility">228 <foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility">
229 <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 279px; margin-left: 85px;">229 <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 279px; margin-left: 85px;">
230 <div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; ">230 <div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; ">
231 <div style="display: inline-block; font-size: 14px; font-family: &quot;Helvetica&quot;; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: nowrap; ">231 <div style="display: inline-block; font-size: 14px; font-family: &quot;Helvetica&quot;; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: nowrap; ">
232 Inductor232 Inductor
233 </div>233 </div>
234 </div>234 </div>
235 </div>235 </div>
236 </foreignObject>236 </foreignObject>
237 <text x="85" y="283" fill="light-dark(#000000, #ffffff)" font-family="&quot;Helvetica&quot;" font-size="14px" text-anchor="middle" font-weight="bold">237 <text x="85" y="283" fill="light-dark(#000000, #ffffff)" font-family="&quot;Helvetica&quot;" font-size="14px" text-anchor="middle" font-weight="bold">
238 Inductor238 Inductor
239 </text>239 </text>
240 </switch>240 </switch>
241 </g>241 </g>
242 </g>242 </g>
243 <g>243 <g>
244 <rect x="600" y="404.5" width="80" height="30" fill="none" stroke="none" pointer-events="all"/>244 <rect x="600" y="404.5" width="80" height="30" fill="none" stroke="none" pointer-events="all"/>
245 </g>245 </g>
246 <g>246 <g>
247 <g transform="translate(-0.5 -0.5)">247 <g transform="translate(-0.5 -0.5)">
248 <switch>248 <switch>
249 <foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility">249 <foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility">
250 <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 420px; margin-left: 640px;">250 <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 420px; margin-left: 640px;">
251 <div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; ">251 <div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; ">
252 <div style="display: inline-block; font-size: 14px; font-family: &quot;Helvetica&quot;; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: nowrap; ">252 <div style="display: inline-block; font-size: 14px; font-family: &quot;Helvetica&quot;; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: nowrap; ">
253 Autotune253 Autotune
254 </div>254 </div>
255 </div>255 </div>
256 </div>256 </div>
257 </foreignObject>257 </foreignObject>
258 <text x="640" y="424" fill="light-dark(#000000, #ffffff)" font-family="&quot;Helvetica&quot;" font-size="14px" text-anchor="middle" font-weight="bold">258 <text x="640" y="424" fill="light-dark(#000000, #ffffff)" font-family="&quot;Helvetica&quot;" font-size="14px" text-anchor="middle" font-weight="bold">
259 Autotune259 Autotune
260 </text>260 </text>
261 </switch>261 </switch>
262 </g>262 </g>
263 </g>263 </g>
264 <g>264 <g>
265 <rect x="750" y="514.5" width="170" height="40" fill="#f8cecc" stroke="#b85450" pointer-events="all" style="fill: light-dark(rgb(248, 206, 204), rgb(81, 45, 43)); stroke: light-dark(rgb(184, 84, 80), rgb(215, 129, 126));"/>265 <rect x="750" y="514.5" width="170" height="40" fill="#f8cecc" stroke="#b85450" pointer-events="all" style="fill: light-dark(rgb(248, 206, 204), rgb(81, 45, 43)); stroke: light-dark(rgb(184, 84, 80), rgb(215, 129, 126));"/>
266 </g>266 </g>
267 <g>267 <g>
268 <g transform="translate(-0.5 -0.5)">268 <g transform="translate(-0.5 -0.5)">
269 <switch>269 <switch>
270 <foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility">270 <foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility">
271 <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 168px; height: 1px; padding-top: 535px; margin-left: 751px;">271 <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 168px; height: 1px; padding-top: 535px; margin-left: 751px;">
272 <div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; ">272 <div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; ">
273 <div style="display: inline-block; font-size: 12px; font-family: &quot;Helvetica&quot;; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: normal; word-wrap: normal; ">273 <div style="display: inline-block; font-size: 12px; font-family: &quot;Helvetica&quot;; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: normal; word-wrap: normal; ">
274 <span>274 <span>
275 <span style="text-wrap: nowrap;">275 <span style="text-wrap: nowrap;">
276 indirect_load/indirect_store276 indirect_load/indirect_store
277 </span>277 </span>
278 <span style="text-wrap: nowrap;">278 <span style="text-wrap: nowrap;">
279 <font style="font-size: 14px;">279 <font style="font-size: 14px;">
280 </font>280 </font>
281 </span>281 </span>
282 </span>282 </span>
283 <div>283 <div>
284 <span style="text-wrap: nowrap;">284 <span style="text-wrap: nowrap;">
285 <font style="font-size: 14px;">285 <font style="font-size: 14px;">
286 SIMT 模板方案286 SIMT 模板方案
287 </font>287 </font>
288 </span>288 </span>
289 </div>289 </div>
290 </div>290 </div>
291 </div>291 </div>
292 </div>292 </div>
293 </foreignObject>293 </foreignObject>
294 <text x="835" y="538" fill="light-dark(#000000, #ffffff)" font-family="&quot;Helvetica&quot;" font-size="12px" text-anchor="middle" font-weight="bold">294 <text x="835" y="538" fill="light-dark(#000000, #ffffff)" font-family="&quot;Helvetica&quot;" font-size="12px" text-anchor="middle" font-weight="bold">
295 indirect_load/indirect_store...295 indirect_load/indirect_store...
296 </text>296 </text>
297 </switch>297 </switch>
298 </g>298 </g>
299 </g>299 </g>
300 <g>300 <g>
301 <rect x="640" y="514.5" width="100" height="40" fill="#f8cecc" stroke="#b85450" pointer-events="all" style="fill: light-dark(rgb(248, 206, 204), rgb(81, 45, 43)); stroke: light-dark(rgb(184, 84, 80), rgb(215, 129, 126));"/>301 <rect x="640" y="514.5" width="100" height="40" fill="#f8cecc" stroke="#b85450" pointer-events="all" style="fill: light-dark(rgb(248, 206, 204), rgb(81, 45, 43)); stroke: light-dark(rgb(184, 84, 80), rgb(215, 129, 126));"/>
302 </g>302 </g>
303 <g>303 <g>
304 <g transform="translate(-0.5 -0.5)">304 <g transform="translate(-0.5 -0.5)">
305 <switch>305 <switch>
306 <foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility">306 <foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility">
307 <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 98px; height: 1px; padding-top: 535px; margin-left: 641px;">307 <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 98px; height: 1px; padding-top: 535px; margin-left: 641px;">
308 <div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; ">308 <div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; ">
309 <div style="display: inline-block; font-size: 12px; font-family: &quot;Helvetica&quot;; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: normal; word-wrap: normal; ">309 <div style="display: inline-block; font-size: 12px; font-family: &quot;Helvetica&quot;; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: normal; word-wrap: normal; ">
310 <span style="font-size: 14px; text-wrap: nowrap;">310 <span style="font-size: 14px; text-wrap: nowrap;">
311 纯SIMT311 纯SIMT
312 </span>312 </span>
313 </div>313 </div>
314 </div>314 </div>
315 </div>315 </div>
316 </foreignObject>316 </foreignObject>
317 <text x="690" y="538" fill="light-dark(#000000, #ffffff)" font-family="&quot;Helvetica&quot;" font-size="12px" text-anchor="middle" font-weight="bold">317 <text x="690" y="538" fill="light-dark(#000000, #ffffff)" font-family="&quot;Helvetica&quot;" font-size="12px" text-anchor="middle" font-weight="bold">
318 纯SIMT318 纯SIMT
319 </text>319 </text>
320 </switch>320 </switch>
321 </g>321 </g>
322 </g>322 </g>
323 <g>323 <g>
324 <rect x="170" y="180" width="100" height="30" fill="none" stroke="none" pointer-events="all"/>324 <rect x="170" y="180" width="100" height="30" fill="none" stroke="none" pointer-events="all"/>
325 </g>325 </g>
326 <g>326 <g>
327 <g transform="translate(-0.5 -0.5)">327 <g transform="translate(-0.5 -0.5)">
328 <switch>328 <switch>
329 <foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility">329 <foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility">
330 <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 195px; margin-left: 220px;">330 <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 195px; margin-left: 220px;">
331 <div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; ">331 <div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; ">
332 <div style="display: inline-block; font-size: 12px; font-family: &quot;Helvetica&quot;; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: nowrap; ">332 <div style="display: inline-block; font-size: 12px; font-family: &quot;Helvetica&quot;; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: nowrap; ">
333 <span style="font-size: 14px; text-align: left;">333 <span style="font-size: 14px; text-align: left;">
334 index=x+8*334 index=x+8*
335 </span>335 </span>
336 <span style="font-size: 14px; text-align: left;">336 <span style="font-size: 14px; text-align: left;">
337 y337 y
338 </span>338 </span>
339 </div>339 </div>
340 </div>340 </div>
341 </div>341 </div>
342 </foreignObject>342 </foreignObject>
343 <text x="220" y="199" fill="light-dark(#000000, #ffffff)" font-family="&quot;Helvetica&quot;" font-size="12px" text-anchor="middle">343 <text x="220" y="199" fill="light-dark(#000000, #ffffff)" font-family="&quot;Helvetica&quot;" font-size="12px" text-anchor="middle">
344 index=x+8*y344 index=x+8*y
345 </text>345 </text>
346 </switch>346 </switch>
347 </g>347 </g>
348 </g>348 </g>
349 <g>349 <g>
350 <rect x="130" y="240" width="90" height="30" fill="none" stroke="none" pointer-events="all"/>350 <rect x="130" y="240" width="90" height="30" fill="none" stroke="none" pointer-events="all"/>
351 </g>351 </g>
352 <g>352 <g>
353 <g transform="translate(-0.5 -0.5)">353 <g transform="translate(-0.5 -0.5)">
354 <switch>354 <switch>
355 <foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility">355 <foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility">
356 <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 255px; margin-left: 175px;">356 <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 255px; margin-left: 175px;">
357 <div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; ">357 <div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; ">
358 <div style="display: inline-block; font-size: 12px; font-family: &quot;Helvetica&quot;; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: nowrap; ">358 <div style="display: inline-block; font-size: 12px; font-family: &quot;Helvetica&quot;; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: nowrap; ">
359 tl.load/tl.store359 tl.load/tl.store
360 </div>360 </div>
361 </div>361 </div>
362 </div>362 </div>
363 </foreignObject>363 </foreignObject>
364 <text x="175" y="259" fill="light-dark(#000000, #ffffff)" font-family="&quot;Helvetica&quot;" font-size="12px" text-anchor="middle" font-weight="bold">364 <text x="175" y="259" fill="light-dark(#000000, #ffffff)" font-family="&quot;Helvetica&quot;" font-size="12px" text-anchor="middle" font-weight="bold">
365 tl.load/tl.store365 tl.load/tl.store
366 </text>366 </text>
367 </switch>367 </switch>
368 </g>368 </g>
369 </g>369 </g>
370 <g>370 <g>
371 <rect x="620" y="434.5" width="170" height="40" fill="none" stroke="none" pointer-events="all"/>371 <rect x="620" y="434.5" width="170" height="40" fill="none" stroke="none" pointer-events="all"/>
372 </g>372 </g>
373 <g>373 <g>
374 <g transform="translate(-0.5 -0.5)">374 <g transform="translate(-0.5 -0.5)">
375 <switch>375 <switch>
376 <foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility">376 <foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility">
377 <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 1px; height: 1px; padding-top: 455px; margin-left: 622px;">377 <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 1px; height: 1px; padding-top: 455px; margin-left: 622px;">
378 <div style="box-sizing: border-box; font-size: 0; text-align: left; color: #000000; ">378 <div style="box-sizing: border-box; font-size: 0; text-align: left; color: #000000; ">
379 <div style="display: inline-block; font-size: 12px; font-family: &quot;Helvetica&quot;; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: nowrap; ">379 <div style="display: inline-block; font-size: 12px; font-family: &quot;Helvetica&quot;; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: nowrap; ">
380 compile_mode="simt_only"380 compile_mode="simt_only"
381 <div>381 <div>
382 simt only tiling config382 simt only tiling config
383 </div>383 </div>
384 </div>384 </div>
385 </div>385 </div>
386 </div>386 </div>
387 </foreignObject>387 </foreignObject>
388 <text x="622" y="458" fill="light-dark(#000000, #ffffff)" font-family="&quot;Helvetica&quot;" font-size="12px" font-weight="bold">388 <text x="622" y="458" fill="light-dark(#000000, #ffffff)" font-family="&quot;Helvetica&quot;" font-size="12px" font-weight="bold">
389 compile_mode="simt_only"...389 compile_mode="simt_only"...
390 </text>390 </text>
391 </switch>391 </switch>
392 </g>392 </g>
393 </g>393 </g>
394 <g>394 <g>
395 <rect x="840" y="434.5" width="190" height="40" fill="none" stroke="none" pointer-events="all"/>395 <rect x="840" y="434.5" width="190" height="40" fill="none" stroke="none" pointer-events="all"/>
396 </g>396 </g>
397 <g>397 <g>
398 <g transform="translate(-0.5 -0.5)">398 <g transform="translate(-0.5 -0.5)">
399 <switch>399 <switch>
400 <foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility">400 <foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility">
401 <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 1px; height: 1px; padding-top: 455px; margin-left: 842px;">401 <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 1px; height: 1px; padding-top: 455px; margin-left: 842px;">
402 <div style="box-sizing: border-box; font-size: 0; text-align: left; color: #000000; ">402 <div style="box-sizing: border-box; font-size: 0; text-align: left; color: #000000; ">
403 <div style="display: inline-block; font-size: 12px; font-family: &quot;Helvetica&quot;; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: nowrap; ">403 <div style="display: inline-block; font-size: 12px; font-family: &quot;Helvetica&quot;; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: nowrap; ">
404 compile_mode="simt_template"404 compile_mode="simt_template"
405 <div>405 <div>
406 simt template config406 simt template config
407 </div>407 </div>
408 </div>408 </div>
409 </div>409 </div>
410 </div>410 </div>
411 </foreignObject>411 </foreignObject>
412 <text x="842" y="458" fill="light-dark(#000000, #ffffff)" font-family="&quot;Helvetica&quot;" font-size="12px" font-weight="bold">412 <text x="842" y="458" fill="light-dark(#000000, #ffffff)" font-family="&quot;Helvetica&quot;" font-size="12px" font-weight="bold">
413 compile_mode="simt_template"...413 compile_mode="simt_template"...
414 </text>414 </text>
415 </switch>415 </switch>
416 </g>416 </g>
417 </g>417 </g>
418 <g>418 <g>
419 <rect x="400" y="434.5" width="140" height="40" fill="none" stroke="none" pointer-events="all"/>419 <rect x="400" y="434.5" width="140" height="40" fill="none" stroke="none" pointer-events="all"/>
420 </g>420 </g>
421 <g>421 <g>
422 <g transform="translate(-0.5 -0.5)">422 <g transform="translate(-0.5 -0.5)">
423 <switch>423 <switch>
424 <foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility">424 <foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility">
425 <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 1px; height: 1px; padding-top: 455px; margin-left: 402px;">425 <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 1px; height: 1px; padding-top: 455px; margin-left: 402px;">
426 <div style="box-sizing: border-box; font-size: 0; text-align: left; color: #000000; ">426 <div style="box-sizing: border-box; font-size: 0; text-align: left; color: #000000; ">
427 <div style="display: inline-block; font-size: 12px; font-family: &quot;Helvetica&quot;; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: nowrap; ">427 <div style="display: inline-block; font-size: 12px; font-family: &quot;Helvetica&quot;; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: nowrap; ">
428 compile_mode="simd"428 compile_mode="simd"
429 <div>429 <div>
430 simd tiling config430 simd tiling config
431 </div>431 </div>
432 </div>432 </div>
433 </div>433 </div>
434 </div>434 </div>
435 </foreignObject>435 </foreignObject>
436 <text x="402" y="458" fill="light-dark(#000000, #ffffff)" font-family="&quot;Helvetica&quot;" font-size="12px" font-weight="bold">436 <text x="402" y="458" fill="light-dark(#000000, #ffffff)" font-family="&quot;Helvetica&quot;" font-size="12px" font-weight="bold">
437 compile_mode="simd"...437 compile_mode="simd"...
438 </text>438 </text>
439 </switch>439 </switch>
440 </g>440 </g>
441 </g>441 </g>
442 <g>442 <g>
443 <rect x="490" y="40" width="150" height="30" fill="none" stroke="none" pointer-events="all"/>443 <rect x="490" y="40" width="150" height="30" fill="none" stroke="none" pointer-events="all"/>
444 </g>444 </g>
445 <g>445 <g>
446 <g transform="translate(-0.5 -0.5)">446 <g transform="translate(-0.5 -0.5)">
447 <switch>447 <switch>
448 <foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility">448 <foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility">
449 <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 55px; margin-left: 565px;">449 <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 55px; margin-left: 565px;">
450 <div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; ">450 <div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; ">
451 <div style="display: inline-block; font-size: 16px; font-family: &quot;Helvetica&quot;; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: nowrap; ">451 <div style="display: inline-block; font-size: 16px; font-family: &quot;Helvetica&quot;; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: nowrap; ">
452 Inductor 离散访存452 Inductor 离散访存
453 </div>453 </div>
454 </div>454 </div>
455 </div>455 </div>
456 </foreignObject>456 </foreignObject>
457 <text x="565" y="60" fill="light-dark(#000000, #ffffff)" font-family="&quot;Helvetica&quot;" font-size="16px" text-anchor="middle" font-weight="bold">457 <text x="565" y="60" fill="light-dark(#000000, #ffffff)" font-family="&quot;Helvetica&quot;" font-size="16px" text-anchor="middle" font-weight="bold">
458 Inductor 离散访存458 Inductor 离散访存
459 </text>459 </text>
460 </switch>460 </switch>
461 </g>461 </g>
462 </g>462 </g>
463 <g>463 <g>
464 <rect x="510" y="564" width="70" height="30" fill="none" stroke="none" pointer-events="all"/>464 <rect x="510" y="564" width="70" height="30" fill="none" stroke="none" pointer-events="all"/>
465 </g>465 </g>
466 <g>466 <g>
467 <g transform="translate(-0.5 -0.5)">467 <g transform="translate(-0.5 -0.5)">
468 <switch>468 <switch>
469 <foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility">469 <foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility">
470 <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 579px; margin-left: 545px;">470 <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 579px; margin-left: 545px;">
471 <div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; ">471 <div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; ">
472 <div style="display: inline-block; font-size: 12px; font-family: &quot;Helvetica&quot;; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: nowrap; ">472 <div style="display: inline-block; font-size: 12px; font-family: &quot;Helvetica&quot;; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: nowrap; ">
473 A2/A3/A5473 A2/A3/A5
474 </div>474 </div>
475 </div>475 </div>
476 </div>476 </div>
477 </foreignObject>477 </foreignObject>
478 <text x="545" y="583" fill="light-dark(#000000, #ffffff)" font-family="&quot;Helvetica&quot;" font-size="12px" text-anchor="middle" font-weight="bold">478 <text x="545" y="583" fill="light-dark(#000000, #ffffff)" font-family="&quot;Helvetica&quot;" font-size="12px" text-anchor="middle" font-weight="bold">
479 A2/A3/A5479 A2/A3/A5
480 </text>480 </text>
481 </switch>481 </switch>
482 </g>482 </g>
483 </g>483 </g>
484 <g>484 <g>
485 <rect x="665" y="564.5" width="40" height="30" fill="none" stroke="none" pointer-events="all"/>485 <rect x="665" y="564.5" width="40" height="30" fill="none" stroke="none" pointer-events="all"/>
486 </g>486 </g>
487 <g>487 <g>
488 <g transform="translate(-0.5 -0.5)">488 <g transform="translate(-0.5 -0.5)">
489 <switch>489 <switch>
490 <foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility">490 <foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility">
491 <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 580px; margin-left: 685px;">491 <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 580px; margin-left: 685px;">
492 <div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; ">492 <div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; ">
493 <div style="display: inline-block; font-size: 12px; font-family: &quot;Helvetica&quot;; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: nowrap; ">493 <div style="display: inline-block; font-size: 12px; font-family: &quot;Helvetica&quot;; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: nowrap; ">
494 A5494 A5
495 </div>495 </div>
496 </div>496 </div>
497 </div>497 </div>
498 </foreignObject>498 </foreignObject>
499 <text x="685" y="583" fill="light-dark(#000000, #ffffff)" font-family="&quot;Helvetica&quot;" font-size="12px" text-anchor="middle" font-weight="bold">499 <text x="685" y="583" fill="light-dark(#000000, #ffffff)" font-family="&quot;Helvetica&quot;" font-size="12px" text-anchor="middle" font-weight="bold">
500 A5500 A5
501 </text>501 </text>
502 </switch>502 </switch>
503 </g>503 </g>
504 </g>504 </g>
505 <g>505 <g>
506 <rect x="815" y="564.5" width="40" height="30" fill="none" stroke="none" pointer-events="all"/>506 <rect x="815" y="564.5" width="40" height="30" fill="none" stroke="none" pointer-events="all"/>
507 </g>507 </g>
508 <g>508 <g>
509 <g transform="translate(-0.5 -0.5)">509 <g transform="translate(-0.5 -0.5)">
510 <switch>510 <switch>
511 <foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility">511 <foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility">
512 <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 580px; margin-left: 835px;">512 <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 580px; margin-left: 835px;">
513 <div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; ">513 <div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; ">
514 <div style="display: inline-block; font-size: 12px; font-family: &quot;Helvetica&quot;; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: nowrap; ">514 <div style="display: inline-block; font-size: 12px; font-family: &quot;Helvetica&quot;; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: nowrap; ">
515 A5515 A5
516 </div>516 </div>
517 </div>517 </div>
518 </div>518 </div>
519 </foreignObject>519 </foreignObject>
520 <text x="835" y="583" fill="light-dark(#000000, #ffffff)" font-family="&quot;Helvetica&quot;" font-size="12px" text-anchor="middle" font-weight="bold">520 <text x="835" y="583" fill="light-dark(#000000, #ffffff)" font-family="&quot;Helvetica&quot;" font-size="12px" text-anchor="middle" font-weight="bold">
521 A5521 A5
522 </text>522 </text>
523 </switch>523 </switch>
524 </g>524 </g>
525 </g>525 </g>
526 <g>526 <g>
527 <path d="M 690 310 L 690 348.13" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke" style="stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/>527 <path d="M 690 310 L 690 348.13" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke" style="stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/>
528 <path d="M 690 353.38 L 686.5 346.38 L 690 348.13 L 693.5 346.38 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all" style="fill: light-dark(rgb(0, 0, 0), rgb(255, 255, 255)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/>528 <path d="M 690 353.38 L 686.5 346.38 L 690 348.13 L 693.5 346.38 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all" style="fill: light-dark(rgb(0, 0, 0), rgb(255, 255, 255)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/>
529 </g>529 </g>
530 <g>530 <g>
531 <rect x="700" y="324.5" width="340" height="30" fill="none" stroke="none" pointer-events="all"/>531 <rect x="700" y="324.5" width="340" height="30" fill="none" stroke="none" pointer-events="all"/>
532 </g>532 </g>
533 <g>533 <g>
534 <g transform="translate(-0.5 -0.5)">534 <g transform="translate(-0.5 -0.5)">
535 <switch>535 <switch>
536 <foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility">536 <foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility">
537 <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 340px; margin-left: 870px;">537 <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 340px; margin-left: 870px;">
538 <div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; ">538 <div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; ">
539 <div style="display: inline-block; font-size: 12px; font-family: &quot;Helvetica&quot;; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: nowrap; ">539 <div style="display: inline-block; font-size: 12px; font-family: &quot;Helvetica&quot;; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: nowrap; ">
540 INDUCTOR_INDIRECT_MEMORY_MODE='simd_simt_mix'540 INDUCTOR_INDIRECT_MEMORY_MODE='simd_simt_mix'
541 </div>541 </div>
542 </div>542 </div>
543 </div>543 </div>
544 </foreignObject>544 </foreignObject>
545 <text x="870" y="343" fill="light-dark(#000000, #ffffff)" font-family="&quot;Helvetica&quot;" font-size="12px" text-anchor="middle" font-weight="bold">545 <text x="870" y="343" fill="light-dark(#000000, #ffffff)" font-family="&quot;Helvetica&quot;" font-size="12px" text-anchor="middle" font-weight="bold">
546 INDUCTOR_INDIRECT_MEMORY_MODE='simd_simt_mix'546 INDUCTOR_INDIRECT_MEMORY_MODE='simd_simt_mix'
547 </text>547 </text>
548 </switch>548 </switch>
549 </g>549 </g>
550 </g>550 </g>
551 <g>551 <g>
552 <path d="M 440 140 L 440 183.63" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke" style="stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/>552 <path d="M 440 140 L 440 183.63" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke" style="stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/>
553 <path d="M 440 188.88 L 436.5 181.88 L 440 183.63 L 443.5 181.88 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all" style="fill: light-dark(rgb(0, 0, 0), rgb(255, 255, 255)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/>553 <path d="M 440 188.88 L 436.5 181.88 L 440 183.63 L 443.5 181.88 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all" style="fill: light-dark(rgb(0, 0, 0), rgb(255, 255, 255)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/>
554 </g>554 </g>
555 <g>555 <g>
556 <rect x="240" y="100" width="400" height="40" fill="none" stroke="none" pointer-events="all"/>556 <rect x="240" y="100" width="400" height="40" fill="none" stroke="none" pointer-events="all"/>
557 </g>557 </g>
558 <g>558 <g>
559 <g transform="translate(-0.5 -0.5)">559 <g transform="translate(-0.5 -0.5)">
560 <switch>560 <switch>
561 <foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility">561 <foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility">
562 <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 120px; margin-left: 440px;">562 <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 120px; margin-left: 440px;">
563 <div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; ">563 <div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; ">
564 <div style="display: inline-block; font-size: 12px; font-family: &quot;Helvetica&quot;; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: nowrap; ">564 <div style="display: inline-block; font-size: 12px; font-family: &quot;Helvetica&quot;; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: nowrap; ">
565 <div>565 <div>
566 <font color="#000000" style="color: light-dark(rgb(0, 0, 0), rgb(237, 237, 237));">566 <font color="#000000" style="color: light-dark(rgb(0, 0, 0), rgb(237, 237, 237));">
567 <span style="font-size: 12px;">567 <span style="font-size: 12px;">
568 load类:aten.embedding、aten.index、aten.gather、aten.index_select568 load类:aten.embedding、aten.index、aten.gather、aten.index_select
569 </span>569 </span>
570 </font>570 </font>
571 </div>571 </div>
572 <div>572 <div>
573 <font color="#000000" style="color: light-dark(rgb(0, 0, 0), rgb(237, 237, 237));">573 <font color="#000000" style="color: light-dark(rgb(0, 0, 0), rgb(237, 237, 237));">
574 <span style="font-size: 12px;">574 <span style="font-size: 12px;">
575 store类:aten.index_put、aten.scatter575 store类:aten.index_put、aten.scatter
576 </span>576 </span>
577 </font>577 </font>
578 </div>578 </div>
579 </div>579 </div>
580 </div>580 </div>
581 </div>581 </div>
582 </foreignObject>582 </foreignObject>
583 <text x="440" y="124" fill="light-dark(#000000, #ffffff)" font-family="&quot;Helvetica&quot;" font-size="12px" text-anchor="middle">583 <text x="440" y="124" fill="light-dark(#000000, #ffffff)" font-family="&quot;Helvetica&quot;" font-size="12px" text-anchor="middle">
584 load类:aten.embedding、aten.index、aten.gather、aten.index_select...584 load类:aten.embedding、aten.index、aten.gather、aten.index_select...
585 </text>585 </text>
586 </switch>586 </switch>
587 </g>587 </g>
588 </g>588 </g>
589 </g>589 </g>
590 <switch>590 <switch>
591 <g requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"/>591 <g requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"/>
592 <a transform="translate(0,-5)" xlink:href="https://www.drawio.com/doc/faq/svg-export-text-problems" target="_blank">592 <a transform="translate(0,-5)" xlink:href="https://www.drawio.com/doc/faq/svg-export-text-problems" target="_blank">
593 <text text-anchor="middle" font-size="10px" x="50%" y="100%">593 <text text-anchor="middle" font-size="10px" x="50%" y="100%">
594 Text is not SVG - cannot display594 Text is not SVG - cannot display
595 </text>595 </text>
596 </a>596 </a>
597 </switch>597 </switch>
598</svg>598</svg>
Mtorch_npu/_inductor/docs/profiling/trace.drawio.svg+7-7
此文件变更行数或变更字符数较多,你可以直接 查看源码
Mtorch_npu/_inductor/fx_passes/pattern_match/__init__.py+3-3
@@ -1,3 +1,3 @@
1from .npu_fusion_attention_graph import npu_fusion_attention_graph1from .npu_fusion_attention_graph import npu_fusion_attention_graph
2 2 
3__all__ = ["npu_fusion_attention_graph"]3__all__ = ["npu_fusion_attention_graph"]
Mtorch_npu/_inductor/fx_passes/pattern_match/npu_fusion_attention_graph.py+0-1
@@ -254,4 +254,3 @@ def register_fa_pass():
254 register_replacement(254 register_replacement(
255 **register_replacement_kwargs,255 **register_replacement_kwargs,
256 )256 )
257 
Mtorch_npu/_inductor/lowering_fallback_list.py+1104-1104
@@ -1,1105 +1,1105 @@
1"""1"""
2This file holds FALLBACK_LIST in which aten/primes ops will be fallbacked to AclNN op and2This file holds FALLBACK_LIST in which aten/primes ops will be fallbacked to AclNN op and
3will not be allowed to lowering and fusion.3will not be allowed to lowering and fusion.
4 4 
5After fixed and verified, it can be removed from FALLBACK_LIST.5After fixed and verified, it can be removed from FALLBACK_LIST.
6"""6"""
7 7 
8import torch8import torch
9 9 
10from torch.ops import (10from torch.ops import (
11 quantized_decomposed,11 quantized_decomposed,
12 rngprims,12 rngprims,
13 _inductor_test,13 _inductor_test,
14 inductor,14 inductor,
15 fsdp,15 fsdp,
16 _c10d_functional,16 _c10d_functional,
17 _dtensor,17 _dtensor,
18 _quantized,18 _quantized,
19 quantized,19 quantized,
20)20)
21 21 
22from torch._prims.rng_prims import (22from torch._prims.rng_prims import (
23 graphsafe_run_with_rng_state,23 graphsafe_run_with_rng_state,
24 run_and_save_rng_state,24 run_and_save_rng_state,
25 run_with_rng_state,25 run_with_rng_state,
26)26)
27from torch._higher_order_ops.auto_functionalize import auto_functionalized27from torch._higher_order_ops.auto_functionalize import auto_functionalized
28from torch._higher_order_ops.cond import cond28from torch._higher_order_ops.cond import cond
29from torch._higher_order_ops.while_loop import while_loop29from torch._higher_order_ops.while_loop import while_loop
30from torch._higher_order_ops._invoke_quant import invoke_quant30from torch._higher_order_ops._invoke_quant import invoke_quant
31from torch._higher_order_ops.associative_scan import associative_scan31from torch._higher_order_ops.associative_scan import associative_scan
32from torch._higher_order_ops.effects import with_effects32from torch._higher_order_ops.effects import with_effects
33 33 
34from .config import inductor_indirect_memory_mode, inductor_ascend_linear_mode34from .config import inductor_indirect_memory_mode, inductor_ascend_linear_mode
35 35 
36aten = torch.ops.aten36aten = torch.ops.aten
37prims = torch.ops.prims37prims = torch.ops.prims
38 38 
39 39 
40NPU_EXTRA_FALLBACK_LIST = [40NPU_EXTRA_FALLBACK_LIST = [
41 _c10d_functional.all_gather_into_tensor,41 _c10d_functional.all_gather_into_tensor,
42 _c10d_functional.all_gather_into_tensor.default,42 _c10d_functional.all_gather_into_tensor.default,
43 _c10d_functional.all_gather_into_tensor_coalesced,43 _c10d_functional.all_gather_into_tensor_coalesced,
44 _c10d_functional.all_gather_into_tensor_coalesced.default,44 _c10d_functional.all_gather_into_tensor_coalesced.default,
45 _c10d_functional.all_gather_into_tensor_out,45 _c10d_functional.all_gather_into_tensor_out,
46 _c10d_functional.all_gather_into_tensor_out.default,46 _c10d_functional.all_gather_into_tensor_out.default,
47 _c10d_functional.all_reduce,47 _c10d_functional.all_reduce,
48 _c10d_functional.all_reduce.default,48 _c10d_functional.all_reduce.default,
49 _c10d_functional.all_reduce_,49 _c10d_functional.all_reduce_,
50 _c10d_functional.all_reduce_.default,50 _c10d_functional.all_reduce_.default,
51 _c10d_functional.all_reduce_coalesced,51 _c10d_functional.all_reduce_coalesced,
52 _c10d_functional.all_reduce_coalesced.default,52 _c10d_functional.all_reduce_coalesced.default,
53 _c10d_functional.all_reduce_coalesced_,53 _c10d_functional.all_reduce_coalesced_,
54 _c10d_functional.all_reduce_coalesced_.default,54 _c10d_functional.all_reduce_coalesced_.default,
55 _c10d_functional.all_to_all_single,55 _c10d_functional.all_to_all_single,
56 _c10d_functional.all_to_all_single.default,56 _c10d_functional.all_to_all_single.default,
57 _c10d_functional.broadcast,57 _c10d_functional.broadcast,
58 _c10d_functional.broadcast.default,58 _c10d_functional.broadcast.default,
59 _c10d_functional.broadcast_,59 _c10d_functional.broadcast_,
60 _c10d_functional.broadcast_.default,60 _c10d_functional.broadcast_.default,
61 _c10d_functional.reduce_scatter_tensor,61 _c10d_functional.reduce_scatter_tensor,
62 _c10d_functional.reduce_scatter_tensor.default,62 _c10d_functional.reduce_scatter_tensor.default,
63 _c10d_functional.reduce_scatter_tensor_coalesced,63 _c10d_functional.reduce_scatter_tensor_coalesced,
64 _c10d_functional.reduce_scatter_tensor_coalesced.default,64 _c10d_functional.reduce_scatter_tensor_coalesced.default,
65 _c10d_functional.wait_tensor,65 _c10d_functional.wait_tensor,
66 _c10d_functional.wait_tensor.default,66 _c10d_functional.wait_tensor.default,
67 _dtensor.shard_dim_alltoall,67 _dtensor.shard_dim_alltoall,
68 _dtensor.shard_dim_alltoall.default,68 _dtensor.shard_dim_alltoall.default,
69 _inductor_test.realize,69 _inductor_test.realize,
70 _inductor_test.realize.default,70 _inductor_test.realize.default,
71 associative_scan,71 associative_scan,
72 aten.__and__,72 aten.__and__,
73 aten.__and__.bool,73 aten.__and__.bool,
74 aten.__and__.int,74 aten.__and__.int,
75 aten.__iand__,75 aten.__iand__,
76 aten.__iand__.Scalar,76 aten.__iand__.Scalar,
77 aten.__iand__.Tensor,77 aten.__iand__.Tensor,
78 aten.__ilshift__,78 aten.__ilshift__,
79 aten.__ilshift__.Scalar,79 aten.__ilshift__.Scalar,
80 aten.__ilshift__.Tensor,80 aten.__ilshift__.Tensor,
81 aten.__ior__.Scalar,81 aten.__ior__.Scalar,
82 aten.__irshift__.Scalar,82 aten.__irshift__.Scalar,
83 aten.__ixor__,83 aten.__ixor__,
84 aten.__ixor__.Scalar,84 aten.__ixor__.Scalar,
85 aten.__ixor__.Tensor,85 aten.__ixor__.Tensor,
86 aten.__lshift__,86 aten.__lshift__,
87 aten.__lshift__.Scalar,87 aten.__lshift__.Scalar,
88 aten.__lshift__.Scalar_out,88 aten.__lshift__.Scalar_out,
89 aten.__lshift__.Tensor,89 aten.__lshift__.Tensor,
90 aten.__lshift__.Tensor_out,90 aten.__lshift__.Tensor_out,
91 aten.__lshift__.int,91 aten.__lshift__.int,
92 aten.__or__,92 aten.__or__,
93 aten.__or__.bool,93 aten.__or__.bool,
94 aten.__or__.int,94 aten.__or__.int,
95 aten.__rshift__,95 aten.__rshift__,
96 aten.__rshift__.Scalar,96 aten.__rshift__.Scalar,
97 aten.__rshift__.Scalar_out,97 aten.__rshift__.Scalar_out,
98 aten.__rshift__.Tensor,98 aten.__rshift__.Tensor,
99 aten.__rshift__.Tensor_out,99 aten.__rshift__.Tensor_out,
100 aten.__rshift__.int,100 aten.__rshift__.int,
101 aten.__xor__,101 aten.__xor__,
102 aten.__xor__.bool,102 aten.__xor__.bool,
103 aten.__xor__.int,103 aten.__xor__.int,
104 aten._adaptive_avg_pool2d,104 aten._adaptive_avg_pool2d,
105 aten._adaptive_avg_pool2d.default,105 aten._adaptive_avg_pool2d.default,
106 aten._adaptive_avg_pool2d.out,106 aten._adaptive_avg_pool2d.out,
107 aten._assert_tensor_metadata,107 aten._assert_tensor_metadata,
108 aten._assert_tensor_metadata.default,108 aten._assert_tensor_metadata.default,
109 aten._convolution,109 aten._convolution,
110 aten._convolution.default,110 aten._convolution.default,
111 aten._convolution.out,111 aten._convolution.out,
112 aten._foobar,112 aten._foobar,
113 aten._foobar.default,113 aten._foobar.default,
114 aten._foobar.out,114 aten._foobar.out,
115 aten._int_mm,115 aten._int_mm,
116 aten._int_mm.default,116 aten._int_mm.default,
117 aten._int_mm.out,117 aten._int_mm.out,
118 aten._jagged_to_padded_dense_forward.default,118 aten._jagged_to_padded_dense_forward.default,
119 aten._local_scalar_dense,119 aten._local_scalar_dense,
120 aten._local_scalar_dense.default,120 aten._local_scalar_dense.default,
121 aten._neg_view,121 aten._neg_view,
122 aten._neg_view.default,122 aten._neg_view.default,
123 aten._padded_dense_to_jagged_forward,123 aten._padded_dense_to_jagged_forward,
124 aten._padded_dense_to_jagged_forward.default,124 aten._padded_dense_to_jagged_forward.default,
125 aten._scaled_mm.default,125 aten._scaled_mm.default,
126 aten._sparse_semi_structured_mm,126 aten._sparse_semi_structured_mm,
127 aten._sparse_semi_structured_mm.default,127 aten._sparse_semi_structured_mm.default,
128 aten._unsafe_index_put.hacked_twin,128 aten._unsafe_index_put.hacked_twin,
129 aten._unsafe_masked_index,129 aten._unsafe_masked_index,
130 aten._unsafe_masked_index.default,130 aten._unsafe_masked_index.default,
131 aten._unsafe_masked_index_put_accumulate,131 aten._unsafe_masked_index_put_accumulate,
132 aten._unsafe_view,132 aten._unsafe_view,
133 aten._weight_int4pack_mm_for_cpu,133 aten._weight_int4pack_mm_for_cpu,
134 aten._weight_int4pack_mm_for_cpu.default,134 aten._weight_int4pack_mm_for_cpu.default,
135 aten._weight_int8pack_mm,135 aten._weight_int8pack_mm,
136 aten._weight_int8pack_mm.default,136 aten._weight_int8pack_mm.default,
137 aten.acos,137 aten.acos,
138 aten.acos.Scalar,138 aten.acos.Scalar,
139 aten.acos.complex,139 aten.acos.complex,
140 aten.acos.default,140 aten.acos.default,
141 aten.acos.float,141 aten.acos.float,
142 aten.acos.int,142 aten.acos.int,
143 aten.acos.out,143 aten.acos.out,
144 aten.acosh,144 aten.acosh,
145 aten.acosh.Scalar,145 aten.acosh.Scalar,
146 aten.acosh.complex,146 aten.acosh.complex,
147 aten.acosh.default,147 aten.acosh.default,
148 aten.acosh.float,148 aten.acosh.float,
149 aten.acosh.int,149 aten.acosh.int,
150 aten.acosh.out,150 aten.acosh.out,
151 aten.adaptive_max_pool2d,151 aten.adaptive_max_pool2d,
152 aten.add_,152 aten.add_,
153 aten.add_.Scalar,153 aten.add_.Scalar,
154 aten.add_.Tensor,154 aten.add_.Tensor,
155 aten.add_.t,155 aten.add_.t,
156 aten.alias,156 aten.alias,
157 aten.alias.default,157 aten.alias.default,
158 aten.any,158 aten.any,
159 aten.any.all_out,159 aten.any.all_out,
160 aten.any.bool,160 aten.any.bool,
161 aten.any.default,161 aten.any.default,
162 aten.any.dim,162 aten.any.dim,
163 aten.any.dimname_out,163 aten.any.dimname_out,
164 aten.any.dims,164 aten.any.dims,
165 aten.any.dims_out,165 aten.any.dims_out,
166 aten.any.float,166 aten.any.float,
167 aten.any.int,167 aten.any.int,
168 aten.any.out,168 aten.any.out,
169 aten.any.str,169 aten.any.str,
170 aten.as_strided,170 aten.as_strided,
171 aten.as_strided.default,171 aten.as_strided.default,
172 aten.as_strided_,172 aten.as_strided_,
173 aten.as_strided_.default,173 aten.as_strided_.default,
174 aten.as_strided_copy,174 aten.as_strided_copy,
175 aten.as_strided_copy.default,175 aten.as_strided_copy.default,
176 aten.as_strided_copy.out,176 aten.as_strided_copy.out,
177 aten.as_strided_scatter,177 aten.as_strided_scatter,
178 aten.as_strided_scatter.default,178 aten.as_strided_scatter.default,
179 aten.as_strided_scatter.out,179 aten.as_strided_scatter.out,
180 aten.asin,180 aten.asin,
181 aten.asin.Scalar,181 aten.asin.Scalar,
182 aten.asin.complex,182 aten.asin.complex,
183 aten.asin.default,183 aten.asin.default,
184 aten.asin.float,184 aten.asin.float,
185 aten.asin.int,185 aten.asin.int,
186 aten.asin.out,186 aten.asin.out,
187 aten.asinh,187 aten.asinh,
188 aten.asinh.Scalar,188 aten.asinh.Scalar,
189 aten.asinh.complex,189 aten.asinh.complex,
190 aten.asinh.default,190 aten.asinh.default,
191 aten.asinh.float,191 aten.asinh.float,
192 aten.asinh.int,192 aten.asinh.int,
193 aten.asinh.out,193 aten.asinh.out,
194 aten.atan,194 aten.atan,
195 aten.atan.Scalar,195 aten.atan.Scalar,
196 aten.atan.complex,196 aten.atan.complex,
197 aten.atan.default,197 aten.atan.default,
198 aten.atan.float,198 aten.atan.float,
199 aten.atan.int,199 aten.atan.int,
200 aten.atan.out,200 aten.atan.out,
201 aten.atan2,201 aten.atan2,
202 aten.atan2.Scalar_Scalar,202 aten.atan2.Scalar_Scalar,
203 aten.atan2.default,203 aten.atan2.default,
204 aten.atan2.float,204 aten.atan2.float,
205 aten.atan2.float_int,205 aten.atan2.float_int,
206 aten.atan2.int,206 aten.atan2.int,
207 aten.atan2.int_float,207 aten.atan2.int_float,
208 aten.atan2.out,208 aten.atan2.out,
209 aten.atanh,209 aten.atanh,
210 aten.atanh.Scalar,210 aten.atanh.Scalar,
211 aten.atanh.complex,211 aten.atanh.complex,
212 aten.atanh.default,212 aten.atanh.default,
213 aten.atanh.float,213 aten.atanh.float,
214 aten.atanh.int,214 aten.atanh.int,
215 aten.atanh.out,215 aten.atanh.out,
216 aten.avg_pool2d,216 aten.avg_pool2d,
217 aten.avg_pool2d.default,217 aten.avg_pool2d.default,
218 aten.avg_pool2d.out,218 aten.avg_pool2d.out,
219 aten.avg_pool2d_backward,219 aten.avg_pool2d_backward,
220 aten.avg_pool2d_backward.default,220 aten.avg_pool2d_backward.default,
221 aten.avg_pool2d_backward.grad_input,221 aten.avg_pool2d_backward.grad_input,
222 aten.avg_pool3d,222 aten.avg_pool3d,
223 aten.avg_pool3d.default,223 aten.avg_pool3d.default,
224 aten.avg_pool3d.out,224 aten.avg_pool3d.out,
225 aten.avg_pool3d_backward,225 aten.avg_pool3d_backward,
226 aten.avg_pool3d_backward.default,226 aten.avg_pool3d_backward.default,
227 aten.avg_pool3d_backward.grad_input,227 aten.avg_pool3d_backward.grad_input,
228 aten.baddbmm,228 aten.baddbmm,
229 aten.baddbmm.default,229 aten.baddbmm.default,
230 aten.baddbmm.out,230 aten.baddbmm.out,
231 aten.bernoulli.p,231 aten.bernoulli.p,
232 aten.bernoulli_,232 aten.bernoulli_,
233 aten.bernoulli_.Tensor,233 aten.bernoulli_.Tensor,
234 aten.bernoulli_.float,234 aten.bernoulli_.float,
235 aten.bitwise_and_,235 aten.bitwise_and_,
236 aten.bitwise_left_shift,236 aten.bitwise_left_shift,
237 aten.bitwise_left_shift.Scalar_Tensor,237 aten.bitwise_left_shift.Scalar_Tensor,
238 aten.bitwise_left_shift.Scalar_Tensor_out,238 aten.bitwise_left_shift.Scalar_Tensor_out,
239 aten.bitwise_left_shift.Tensor,239 aten.bitwise_left_shift.Tensor,
240 aten.bitwise_left_shift.Tensor_Scalar,240 aten.bitwise_left_shift.Tensor_Scalar,
241 aten.bitwise_left_shift.Tensor_Scalar_out,241 aten.bitwise_left_shift.Tensor_Scalar_out,
242 aten.bitwise_left_shift.Tensor_out,242 aten.bitwise_left_shift.Tensor_out,
243 aten.bitwise_left_shift_,243 aten.bitwise_left_shift_,
244 aten.bitwise_left_shift_.Tensor,244 aten.bitwise_left_shift_.Tensor,
245 aten.bitwise_left_shift_.Tensor_Scalar,245 aten.bitwise_left_shift_.Tensor_Scalar,
246 aten.bitwise_not,246 aten.bitwise_not,
247 aten.bitwise_not.default,247 aten.bitwise_not.default,
248 aten.bitwise_not.out,248 aten.bitwise_not.out,
249 aten.bitwise_not_,249 aten.bitwise_not_,
250 aten.bitwise_not_.default,250 aten.bitwise_not_.default,
251 aten.bitwise_or,251 aten.bitwise_or,
252 aten.bitwise_or.Scalar,252 aten.bitwise_or.Scalar,
253 aten.bitwise_or.Tensor,253 aten.bitwise_or.Tensor,
254 aten.bitwise_or_,254 aten.bitwise_or_,
255 aten.bitwise_right_shift,255 aten.bitwise_right_shift,
256 aten.bitwise_right_shift.Scalar_Tensor,256 aten.bitwise_right_shift.Scalar_Tensor,
257 aten.bitwise_right_shift.Scalar_Tensor_out,257 aten.bitwise_right_shift.Scalar_Tensor_out,
258 aten.bitwise_right_shift.Tensor,258 aten.bitwise_right_shift.Tensor,
259 aten.bitwise_right_shift.Tensor_Scalar,259 aten.bitwise_right_shift.Tensor_Scalar,
260 aten.bitwise_right_shift.Tensor_Scalar_out,260 aten.bitwise_right_shift.Tensor_Scalar_out,
261 aten.bitwise_right_shift.Tensor_out,261 aten.bitwise_right_shift.Tensor_out,
262 aten.bitwise_right_shift_,262 aten.bitwise_right_shift_,
263 aten.bitwise_right_shift_.Tensor,263 aten.bitwise_right_shift_.Tensor,
264 aten.bitwise_right_shift_.Tensor_Scalar,264 aten.bitwise_right_shift_.Tensor_Scalar,
265 aten.bitwise_xor_,265 aten.bitwise_xor_,
266 aten.bitwise_xor_.Scalar,266 aten.bitwise_xor_.Scalar,
267 aten.bitwise_xor_.Tensor,267 aten.bitwise_xor_.Tensor,
268 aten.broadcast_tensors,268 aten.broadcast_tensors,
269 aten.bucketize,269 aten.bucketize,
270 aten.bucketize.Scalar,270 aten.bucketize.Scalar,
271 aten.bucketize.Scalar_out,271 aten.bucketize.Scalar_out,
272 aten.bucketize.Tensor,272 aten.bucketize.Tensor,
273 aten.bucketize.Tensor_out,273 aten.bucketize.Tensor_out,
274 aten.cat.names_out,274 aten.cat.names_out,
275 aten.cat.out,275 aten.cat.out,
276 aten.constant_pad_nd,276 aten.constant_pad_nd,
277 aten.constant_pad_nd.default,277 aten.constant_pad_nd.default,
278 aten.constant_pad_nd.out,278 aten.constant_pad_nd.out,
279 aten.convolution,279 aten.convolution,
280 aten.convolution.default,280 aten.convolution.default,
281 aten.convolution.out,281 aten.convolution.out,
282 aten.copysign,282 aten.copysign,
283 aten.copysign.Scalar,283 aten.copysign.Scalar,
284 aten.copysign.Scalar_out,284 aten.copysign.Scalar_out,
285 aten.copysign.Tensor,285 aten.copysign.Tensor,
286 aten.copysign.default,286 aten.copysign.default,
287 aten.copysign.float,287 aten.copysign.float,
288 aten.copysign.float_int,288 aten.copysign.float_int,
289 aten.copysign.int,289 aten.copysign.int,
290 aten.copysign.int_float,290 aten.copysign.int_float,
291 aten.copysign.out,291 aten.copysign.out,
292 aten.cosh,292 aten.cosh,
293 aten.cosh.Scalar,293 aten.cosh.Scalar,
294 aten.cosh.complex,294 aten.cosh.complex,
295 aten.cosh.default,295 aten.cosh.default,
296 aten.cosh.float,296 aten.cosh.float,
297 aten.cosh.int,297 aten.cosh.int,
298 aten.cosh.out,298 aten.cosh.out,
299 aten.cummax,299 aten.cummax,
300 aten.cummax.dimname_out,300 aten.cummax.dimname_out,
301 aten.cummax.out,301 aten.cummax.out,
302 aten.cummin,302 aten.cummin,
303 aten.cummin.dimname_out,303 aten.cummin.dimname_out,
304 aten.cummin.out,304 aten.cummin.out,
305 aten.cumprod,305 aten.cumprod,
306 aten.cumprod.dimname_out,306 aten.cumprod.dimname_out,
307 aten.cumprod.out,307 aten.cumprod.out,
308 aten.cumsum.dimname_out,308 aten.cumsum.dimname_out,
309 aten.cumsum.out,309 aten.cumsum.out,
310 aten.detach,310 aten.detach,
311 aten.detach_,311 aten.detach_,
312 aten.diagonal,312 aten.diagonal,
313 aten.diagonal.Dimname,313 aten.diagonal.Dimname,
314 aten.diagonal.default,314 aten.diagonal.default,
315 aten.diagonal_copy,315 aten.diagonal_copy,
316 aten.diagonal_scatter,316 aten.diagonal_scatter,
317 aten.diagonal_scatter.default,317 aten.diagonal_scatter.default,
318 aten.diagonal_scatter.out,318 aten.diagonal_scatter.out,
319 aten.div_.Tensor,319 aten.div_.Tensor,
320 aten.div_.Tensor_mode,320 aten.div_.Tensor_mode,
321 aten.empty,321 aten.empty,
322 aten.empty.memory_format,322 aten.empty.memory_format,
323 aten.empty.names,323 aten.empty.names,
324 aten.empty.names_out,324 aten.empty.names_out,
325 aten.empty.out,325 aten.empty.out,
326 aten.empty_like,326 aten.empty_like,
327 aten.empty_strided,327 aten.empty_strided,
328 aten.empty_strided.default,328 aten.empty_strided.default,
329 aten.empty_strided.out,329 aten.empty_strided.out,
330 aten.erfc,330 aten.erfc,
331 aten.erfc.Scalar,331 aten.erfc.Scalar,
332 aten.erfc.default,332 aten.erfc.default,
333 aten.erfc.float,333 aten.erfc.float,
334 aten.erfc.int,334 aten.erfc.int,
335 aten.erfc.out,335 aten.erfc.out,
336 aten.erfinv,336 aten.erfinv,
337 aten.erfinv.default,337 aten.erfinv.default,
338 aten.erfinv.out,338 aten.erfinv.out,
339 aten.exp2.out,339 aten.exp2.out,
340 aten.expand_as,340 aten.expand_as,
341 aten.expand_as.default,341 aten.expand_as.default,
342 aten.expm1,342 aten.expm1,
343 aten.expm1.Scalar,343 aten.expm1.Scalar,
344 aten.expm1.default,344 aten.expm1.default,
345 aten.expm1.float,345 aten.expm1.float,
346 aten.expm1.int,346 aten.expm1.int,
347 aten.expm1.out,347 aten.expm1.out,
348 aten.fill_,348 aten.fill_,
349 aten.fmod,349 aten.fmod,
350 aten.fmod.Scalar,350 aten.fmod.Scalar,
351 aten.fmod.Scalar_out,351 aten.fmod.Scalar_out,
352 aten.fmod.Tensor,352 aten.fmod.Tensor,
353 aten.fmod.Tensor_out,353 aten.fmod.Tensor_out,
354 aten.fmod.default,354 aten.fmod.default,
355 aten.fmod.float,355 aten.fmod.float,
356 aten.fmod.float_int,356 aten.fmod.float_int,
357 aten.fmod.int,357 aten.fmod.int,
358 aten.fmod.int_float,358 aten.fmod.int_float,
359 aten.fractional_max_pool2d,359 aten.fractional_max_pool2d,
360 aten.fractional_max_pool2d.default,360 aten.fractional_max_pool2d.default,
361 aten.fractional_max_pool2d.output,361 aten.fractional_max_pool2d.output,
362 aten.frexp,362 aten.frexp,
363 aten.frexp.Tensor,363 aten.frexp.Tensor,
364 aten.frexp.Tensor_out,364 aten.frexp.Tensor_out,
365 aten.frexp.default,365 aten.frexp.default,
366 aten.full_like,366 aten.full_like,
367 aten.glu,367 aten.glu,
368 aten.glu.default,368 aten.glu.default,
369 aten.hypot,369 aten.hypot,
370 aten.hypot.default,370 aten.hypot.default,
371 aten.hypot.out,371 aten.hypot.out,
372 aten.i0.default,372 aten.i0.default,
373 aten.i0.out,373 aten.i0.out,
374 aten.index.Tensor_out,374 aten.index.Tensor_out,
375 aten.index.list_Tensor,375 aten.index.list_Tensor,
376 aten.index.list_bool,376 aten.index.list_bool,
377 aten.index.list_float,377 aten.index.list_float,
378 aten.index.list_int,378 aten.index.list_int,
379 aten.index.list_str,379 aten.index.list_str,
380 aten.index.str,380 aten.index.str,
381 aten.index_put.hacked_twin,381 aten.index_put.hacked_twin,
382 aten.index_put_.hacked_twin,382 aten.index_put_.hacked_twin,
383 aten.isinf,383 aten.isinf,
384 aten.isinf.complex,384 aten.isinf.complex,
385 aten.isinf.default,385 aten.isinf.default,
386 aten.isinf.float,386 aten.isinf.float,
387 aten.isinf.out,387 aten.isinf.out,
388 aten.lgamma,388 aten.lgamma,
389 aten.lgamma.Scalar,389 aten.lgamma.Scalar,
390 aten.lgamma.default,390 aten.lgamma.default,
391 aten.lgamma.float,391 aten.lgamma.float,
392 aten.lgamma.int,392 aten.lgamma.int,
393 aten.lgamma.out,393 aten.lgamma.out,
394 aten.lift,394 aten.lift,
395 aten.lift_fresh,395 aten.lift_fresh,
396 aten.lift_fresh.default,396 aten.lift_fresh.default,
397 aten.lift_fresh_copy,397 aten.lift_fresh_copy,
398 aten.lift_fresh_copy.default,398 aten.lift_fresh_copy.default,
399 aten.lift_fresh_copy.out,399 aten.lift_fresh_copy.out,
400 aten.log10,400 aten.log10,
401 aten.log10.Scalar,401 aten.log10.Scalar,
402 aten.log10.complex,402 aten.log10.complex,
403 aten.log10.default,403 aten.log10.default,
404 aten.log10.float,404 aten.log10.float,
405 aten.log10.int,405 aten.log10.int,
406 aten.log10.out,406 aten.log10.out,
407 aten.logcumsumexp,407 aten.logcumsumexp,
408 aten.logcumsumexp.dimname_out,408 aten.logcumsumexp.dimname_out,
409 aten.logcumsumexp.out,409 aten.logcumsumexp.out,
410 aten.logical_and_,410 aten.logical_and_,
411 aten.logical_and_.default,411 aten.logical_and_.default,
412 aten.logical_not_,412 aten.logical_not_,
413 aten.logical_not_.default,413 aten.logical_not_.default,
414 aten.logical_or_,414 aten.logical_or_,
415 aten.logical_or_.default,415 aten.logical_or_.default,
416 aten.logical_xor,416 aten.logical_xor,
417 aten.logical_xor.default,417 aten.logical_xor.default,
418 aten.logical_xor.out,418 aten.logical_xor.out,
419 aten.logical_xor_,419 aten.logical_xor_,
420 aten.logical_xor_.default,420 aten.logical_xor_.default,
421 aten.max_pool2d_with_indices,421 aten.max_pool2d_with_indices,
422 aten.max_pool2d_with_indices_backward,422 aten.max_pool2d_with_indices_backward,
423 aten.max_pool2d_with_indices_backward.default,423 aten.max_pool2d_with_indices_backward.default,
424 aten.max_pool2d_with_indices_backward.grad_input,424 aten.max_pool2d_with_indices_backward.grad_input,
425 aten.mul_,425 aten.mul_,
426 aten.mul_.Scalar,426 aten.mul_.Scalar,
427 aten.mul_.Tensor,427 aten.mul_.Tensor,
428 aten.mul_.t,428 aten.mul_.t,
429 aten.native_dropout,429 aten.native_dropout,
430 aten.native_dropout.default,430 aten.native_dropout.default,
431 aten.native_dropout.out,431 aten.native_dropout.out,
432 aten.new_empty,432 aten.new_empty,
433 aten.new_empty_strided,433 aten.new_empty_strided,
434 aten.new_empty_strided.default,434 aten.new_empty_strided.default,
435 aten.new_empty_strided.out,435 aten.new_empty_strided.out,
436 aten.nextafter,436 aten.nextafter,
437 aten.nextafter.default,437 aten.nextafter.default,
438 aten.nextafter.out,438 aten.nextafter.out,
439 aten.prod,439 aten.prod,
440 aten.prod.Dimname_out,440 aten.prod.Dimname_out,
441 aten.prod.default,441 aten.prod.default,
442 aten.prod.dim_int,442 aten.prod.dim_int,
443 aten.prod.int_out,443 aten.prod.int_out,
444 aten.prod.out,444 aten.prod.out,
445 aten.rand,445 aten.rand,
446 aten.rand.generator_with_names,446 aten.rand.generator_with_names,
447 aten.rand.generator_with_names_out,447 aten.rand.generator_with_names_out,
448 aten.rand.names,448 aten.rand.names,
449 aten.rand.names_out,449 aten.rand.names_out,
450 aten.rand.out,450 aten.rand.out,
451 aten.randn,451 aten.randn,
452 aten.randn.generator_with_names,452 aten.randn.generator_with_names,
453 aten.randn.generator_with_names_out,453 aten.randn.generator_with_names_out,
454 aten.randn.names,454 aten.randn.names,
455 aten.randn.names_out,455 aten.randn.names_out,
456 aten.randn.out,456 aten.randn.out,
457 aten.relu_,457 aten.relu_,
458 aten.relu_.default,458 aten.relu_.default,
459 aten.remainder,459 aten.remainder,
460 aten.remainder.Scalar,460 aten.remainder.Scalar,
461 aten.remainder.Scalar_Tensor_out,461 aten.remainder.Scalar_Tensor_out,
462 aten.remainder.Scalar_out,462 aten.remainder.Scalar_out,
463 aten.remainder.Tensor,463 aten.remainder.Tensor,
464 aten.remainder.Tensor_out,464 aten.remainder.Tensor_out,
465 aten.remainder.default,465 aten.remainder.default,
466 aten.remainder.float,466 aten.remainder.float,
467 aten.remainder.float_int,467 aten.remainder.float_int,
468 aten.remainder.int,468 aten.remainder.int,
469 aten.remainder.int_float,469 aten.remainder.int_float,
470 aten.resize,470 aten.resize,
471 aten.resize.default,471 aten.resize.default,
472 aten.resize.out,472 aten.resize.out,
473 aten.round.default,473 aten.round.default,
474 aten.scatter.reduce,474 aten.scatter.reduce,
475 aten.scatter.reduce_out,475 aten.scatter.reduce_out,
476 aten.scatter.src_out,476 aten.scatter.src_out,
477 aten.scatter.value,477 aten.scatter.value,
478 aten.scatter.value_out,478 aten.scatter.value_out,
479 aten.scatter.value_reduce,479 aten.scatter.value_reduce,
480 aten.scatter.value_reduce_out,480 aten.scatter.value_reduce_out,
481 aten.scatter_.reduce,481 aten.scatter_.reduce,
482 aten.scatter_.value,482 aten.scatter_.value,
483 aten.scatter_.value_reduce,483 aten.scatter_.value_reduce,
484 aten.scatter_add,484 aten.scatter_add,
485 aten.scatter_add.default,485 aten.scatter_add.default,
486 aten.scatter_add.out,486 aten.scatter_add.out,
487 aten.scatter_add_,487 aten.scatter_add_,
488 aten.scatter_add_.default,488 aten.scatter_add_.default,
489 aten.scatter_reduce.two,489 aten.scatter_reduce.two,
490 aten.scatter_reduce.two_out,490 aten.scatter_reduce.two_out,
491 aten.scatter_reduce_.two,491 aten.scatter_reduce_.two,
492 aten.searchsorted.Tensor,492 aten.searchsorted.Tensor,
493 aten.set_.source_Tensor,493 aten.set_.source_Tensor,
494 aten.sigmoid_,494 aten.sigmoid_,
495 aten.sigmoid_.default,495 aten.sigmoid_.default,
496 aten.signbit,496 aten.signbit,
497 aten.signbit.default,497 aten.signbit.default,
498 aten.signbit.out,498 aten.signbit.out,
499 aten.sinh,499 aten.sinh,
500 aten.sinh.Scalar,500 aten.sinh.Scalar,
501 aten.sinh.complex,501 aten.sinh.complex,
502 aten.sinh.default,502 aten.sinh.default,
503 aten.sinh.float,503 aten.sinh.float,
504 aten.sinh.int,504 aten.sinh.int,
505 aten.sinh.out,505 aten.sinh.out,
506 aten.special_bessel_j0.default,506 aten.special_bessel_j0.default,
507 aten.special_bessel_j0.out,507 aten.special_bessel_j0.out,
508 aten.special_bessel_j1.default,508 aten.special_bessel_j1.default,
509 aten.special_bessel_j1.out,509 aten.special_bessel_j1.out,
510 aten.special_bessel_y0.default,510 aten.special_bessel_y0.default,
511 aten.special_bessel_y0.out,511 aten.special_bessel_y0.out,
512 aten.special_bessel_y1.default,512 aten.special_bessel_y1.default,
513 aten.special_bessel_y1.out,513 aten.special_bessel_y1.out,
514 aten.special_erf,514 aten.special_erf,
515 aten.special_erf.out,515 aten.special_erf.out,
516 aten.special_erfcx.default,516 aten.special_erfcx.default,
517 aten.special_erfcx.out,517 aten.special_erfcx.out,
518 aten.special_i1.default,518 aten.special_i1.default,
519 aten.special_i1.out,519 aten.special_i1.out,
520 aten.special_modified_bessel_i0.default,520 aten.special_modified_bessel_i0.default,
521 aten.special_modified_bessel_i0.out,521 aten.special_modified_bessel_i0.out,
522 aten.special_modified_bessel_i1.default,522 aten.special_modified_bessel_i1.default,
523 aten.special_modified_bessel_i1.out,523 aten.special_modified_bessel_i1.out,
524 aten.split.str,524 aten.split.str,
525 aten.square,525 aten.square,
526 aten.square.out,526 aten.square.out,
527 aten.squeeze_,527 aten.squeeze_,
528 aten.squeeze_.default,528 aten.squeeze_.default,
529 aten.squeeze_.dim,529 aten.squeeze_.dim,
530 aten.squeeze_.dimname,530 aten.squeeze_.dimname,
531 aten.squeeze_.dims,531 aten.squeeze_.dims,
532 aten.squeeze_copy,532 aten.squeeze_copy,
533 aten.sub_,533 aten.sub_,
534 aten.sub_.Scalar,534 aten.sub_.Scalar,
535 aten.sub_.Tensor,535 aten.sub_.Tensor,
536 aten.sym_constrain_range,536 aten.sym_constrain_range,
537 aten.sym_constrain_range.default,537 aten.sym_constrain_range.default,
538 aten.sym_numel,538 aten.sym_numel,
539 aten.sym_numel.default,539 aten.sym_numel.default,
540 aten.tan,540 aten.tan,
541 aten.tan.Scalar,541 aten.tan.Scalar,
542 aten.tan.complex,542 aten.tan.complex,
543 aten.tan.default,543 aten.tan.default,
544 aten.tan.float,544 aten.tan.float,
545 aten.tan.int,545 aten.tan.int,
546 aten.tan.out,546 aten.tan.out,
547 aten.true_divide,547 aten.true_divide,
548 aten.true_divide.out,548 aten.true_divide.out,
549 aten.trunc,549 aten.trunc,
550 aten.trunc.default,550 aten.trunc.default,
551 aten.trunc.out,551 aten.trunc.out,
552 aten.unbind,552 aten.unbind,
553 aten.unbind.Dimname,553 aten.unbind.Dimname,
554 aten.unbind.int,554 aten.unbind.int,
555 aten.unfold,555 aten.unfold,
556 aten.unfold.default,556 aten.unfold.default,
557 aten.unsqueeze_,557 aten.unsqueeze_,
558 aten.unsqueeze_.default,558 aten.unsqueeze_.default,
559 aten.upsample_nearest2d_backward.default,559 aten.upsample_nearest2d_backward.default,
560 aten.var.correction,560 aten.var.correction,
561 aten.var.correction_names_out,561 aten.var.correction_names_out,
562 aten.var.correction_out,562 aten.var.correction_out,
563 aten.var.names_out,563 aten.var.names_out,
564 aten.var.out,564 aten.var.out,
565 aten.var_mean.correction,565 aten.var_mean.correction,
566 aten.var_mean.correction_out,566 aten.var_mean.correction_out,
567 aten.view,567 aten.view,
568 aten.view.default,568 aten.view.default,
569 aten.view.dtype,569 aten.view.dtype,
570 cond,570 cond,
571 fsdp.copy_.default,571 fsdp.copy_.default,
572 inductor.resize_storage_bytes_,572 inductor.resize_storage_bytes_,
573 inductor.resize_storage_bytes_.default,573 inductor.resize_storage_bytes_.default,
574 invoke_quant,574 invoke_quant,
575 prims._low_memory_max_pool2d_offsets_to_indices,575 prims._low_memory_max_pool2d_offsets_to_indices,
576 prims._low_memory_max_pool2d_offsets_to_indices.default,576 prims._low_memory_max_pool2d_offsets_to_indices.default,
577 prims._low_memory_max_pool2d_with_offsets,577 prims._low_memory_max_pool2d_with_offsets,
578 prims._low_memory_max_pool2d_with_offsets.default,578 prims._low_memory_max_pool2d_with_offsets.default,
579 prims._sink_tokens.default,579 prims._sink_tokens.default,
580 prims._unsafe_index_put_.default,580 prims._unsafe_index_put_.default,
581 prims.abs,581 prims.abs,
582 prims.abs.default,582 prims.abs.default,
583 prims.acos,583 prims.acos,
584 prims.acos.default,584 prims.acos.default,
585 prims.acosh,585 prims.acosh,
586 prims.acosh.default,586 prims.acosh.default,
587 prims.add,587 prims.add,
588 prims.add.default,588 prims.add.default,
589 prims.asin,589 prims.asin,
590 prims.asin.default,590 prims.asin.default,
591 prims.asinh,591 prims.asinh,
592 prims.asinh.default,592 prims.asinh.default,
593 prims.atan,593 prims.atan,
594 prims.atan.default,594 prims.atan.default,
595 prims.atan2,595 prims.atan2,
596 prims.atan2.default,596 prims.atan2.default,
597 prims.atanh,597 prims.atanh,
598 prims.atanh.default,598 prims.atanh.default,
599 prims.bessel_j0,599 prims.bessel_j0,
600 prims.bessel_j0.default,600 prims.bessel_j0.default,
601 prims.bessel_j1,601 prims.bessel_j1,
602 prims.bessel_j1.default,602 prims.bessel_j1.default,
603 prims.bitwise_and,603 prims.bitwise_and,
604 prims.bitwise_and.default,604 prims.bitwise_and.default,
605 prims.bitwise_not,605 prims.bitwise_not,
606 prims.bitwise_not.default,606 prims.bitwise_not.default,
607 prims.bitwise_or,607 prims.bitwise_or,
608 prims.bitwise_or.default,608 prims.bitwise_or.default,
609 prims.bitwise_xor,609 prims.bitwise_xor,
610 prims.bitwise_xor.default,610 prims.bitwise_xor.default,
611 prims.ceil,611 prims.ceil,
612 prims.ceil.default,612 prims.ceil.default,
613 prims.cos,613 prims.cos,
614 prims.cos.default,614 prims.cos.default,
615 prims.cosh,615 prims.cosh,
616 prims.cosh.default,616 prims.cosh.default,
617 prims.digamma,617 prims.digamma,
618 prims.div,618 prims.div,
619 prims.div.default,619 prims.div.default,
620 prims.eq,620 prims.eq,
621 prims.eq.default,621 prims.eq.default,
622 prims.erf,622 prims.erf,
623 prims.erf.default,623 prims.erf.default,
624 prims.erfc,624 prims.erfc,
625 prims.erfc.default,625 prims.erfc.default,
626 prims.erfcx,626 prims.erfcx,
627 prims.erfcx.default,627 prims.erfcx.default,
628 prims.exp,628 prims.exp,
629 prims.exp.default,629 prims.exp.default,
630 prims.expm1,630 prims.expm1,
631 prims.expm1.default,631 prims.expm1.default,
632 prims.fma,632 prims.fma,
633 prims.fma.default,633 prims.fma.default,
634 prims.fmod,634 prims.fmod,
635 prims.fmod.default,635 prims.fmod.default,
636 prims.frexp,636 prims.frexp,
637 prims.frexp.default,637 prims.frexp.default,
638 prims.ge,638 prims.ge,
639 prims.ge.default,639 prims.ge.default,
640 prims.gt,640 prims.gt,
641 prims.gt.default,641 prims.gt.default,
642 prims.hypot,642 prims.hypot,
643 prims.hypot.default,643 prims.hypot.default,
644 prims.igamma,644 prims.igamma,
645 prims.igammac,645 prims.igammac,
646 prims.inductor_force_stride_order.default,646 prims.inductor_force_stride_order.default,
647 prims.inductor_lookup_seed.default,647 prims.inductor_lookup_seed.default,
648 prims.inductor_randint.default,648 prims.inductor_randint.default,
649 prims.inductor_random.default,649 prims.inductor_random.default,
650 prims.inductor_seed.default,650 prims.inductor_seed.default,
651 prims.inductor_seeds.default,651 prims.inductor_seeds.default,
652 prims.le,652 prims.le,
653 prims.le.default,653 prims.le.default,
654 prims.lgamma,654 prims.lgamma,
655 prims.lgamma.default,655 prims.lgamma.default,
656 prims.log,656 prims.log,
657 prims.log.default,657 prims.log.default,
658 prims.log10,658 prims.log10,
659 prims.log10.default,659 prims.log10.default,
660 prims.log1p,660 prims.log1p,
661 prims.log1p.default,661 prims.log1p.default,
662 prims.lt,662 prims.lt,
663 prims.lt.default,663 prims.lt.default,
664 prims.minimum,664 prims.minimum,
665 prims.minimum.default,665 prims.minimum.default,
666 prims.ndtri,666 prims.ndtri,
667 prims.ndtri.default,667 prims.ndtri.default,
668 prims.ne,668 prims.ne,
669 prims.ne.default,669 prims.ne.default,
670 prims.neg,670 prims.neg,
671 prims.neg.default,671 prims.neg.default,
672 prims.nextafter,672 prims.nextafter,
673 prims.nextafter.default,673 prims.nextafter.default,
674 prims.prepare_softmax_online.default,674 prims.prepare_softmax_online.default,
675 prims.reciprocal,675 prims.reciprocal,
676 prims.reciprocal.default,676 prims.reciprocal.default,
677 prims.remainder,677 prims.remainder,
678 prims.remainder.default,678 prims.remainder.default,
679 prims.rev.default,679 prims.rev.default,
680 prims.rsqrt.default,680 prims.rsqrt.default,
681 prims.sign,681 prims.sign,
682 prims.sign.default,682 prims.sign.default,
683 prims.signbit,683 prims.signbit,
684 prims.signbit.default,684 prims.signbit.default,
685 prims.sin,685 prims.sin,
686 prims.sin.default,686 prims.sin.default,
687 prims.sinh,687 prims.sinh,
688 prims.sinh.default,688 prims.sinh.default,
689 prims.spherical_bessel_j0,689 prims.spherical_bessel_j0,
690 prims.spherical_bessel_j0.default,690 prims.spherical_bessel_j0.default,
691 prims.sqrt,691 prims.sqrt,
692 prims.sqrt.default,692 prims.sqrt.default,
693 prims.sub,693 prims.sub,
694 prims.sub.default,694 prims.sub.default,
695 prims.sum,695 prims.sum,
696 prims.sum.default,696 prims.sum.default,
697 prims.tan,697 prims.tan,
698 prims.tan.default,698 prims.tan.default,
699 prims.var,699 prims.var,
700 prims.var.default,700 prims.var.default,
701 prims.view_of,701 prims.view_of,
702 prims.view_of.default,702 prims.view_of.default,
703 prims.xor_sum,703 prims.xor_sum,
704 prims.xor_sum.default,704 prims.xor_sum.default,
705 prims.zeta,705 prims.zeta,
706 prims.zeta.default,706 prims.zeta.default,
707 quantized_decomposed.dequantize_per_channel,707 quantized_decomposed.dequantize_per_channel,
708 quantized_decomposed.dequantize_per_channel.default,708 quantized_decomposed.dequantize_per_channel.default,
709 quantized_decomposed.dequantize_per_tensor.default,709 quantized_decomposed.dequantize_per_tensor.default,
710 quantized_decomposed.dequantize_per_tensor.tensor,710 quantized_decomposed.dequantize_per_tensor.tensor,
711 quantized_decomposed.quantize_per_channel,711 quantized_decomposed.quantize_per_channel,
712 quantized_decomposed.quantize_per_channel.default,712 quantized_decomposed.quantize_per_channel.default,
713 quantized_decomposed.quantize_per_tensor.default,713 quantized_decomposed.quantize_per_tensor.default,
714 quantized_decomposed.quantize_per_tensor.tensor,714 quantized_decomposed.quantize_per_tensor.tensor,
715 rngprims.philox_rand,715 rngprims.philox_rand,
716 rngprims.philox_rand.default,716 rngprims.philox_rand.default,
717 while_loop,717 while_loop,
718 with_effects,718 with_effects,
719]719]
720TORCH_NATIVE_FALLBACK_LIST = [720TORCH_NATIVE_FALLBACK_LIST = [
721 _quantized.wrapped_fbgemm_linear_fp16_weight.default,721 _quantized.wrapped_fbgemm_linear_fp16_weight.default,
722 _quantized.wrapped_fbgemm_pack_gemm_matrix_fp16.default,722 _quantized.wrapped_fbgemm_pack_gemm_matrix_fp16.default,
723 aten._adaptive_avg_pool2d_backward.default,723 aten._adaptive_avg_pool2d_backward.default,
724 aten._adaptive_avg_pool2d_backward.out,724 aten._adaptive_avg_pool2d_backward.out,
725 aten._adaptive_avg_pool3d.default,725 aten._adaptive_avg_pool3d.default,
726 aten._adaptive_avg_pool3d.out,726 aten._adaptive_avg_pool3d.out,
727 aten._adaptive_avg_pool3d_backward.default,727 aten._adaptive_avg_pool3d_backward.default,
728 aten._adaptive_avg_pool3d_backward.out,728 aten._adaptive_avg_pool3d_backward.out,
729 aten._addmm_activation.default,729 aten._addmm_activation.default,
730 aten._addmm_activation.out,730 aten._addmm_activation.out,
731 aten._cdist_backward.default,731 aten._cdist_backward.default,
732 aten._cdist_backward.out,732 aten._cdist_backward.out,
733 aten._cdist_forward.default,733 aten._cdist_forward.default,
734 aten._cdist_forward.out,734 aten._cdist_forward.out,
735 aten._cudnn_rnn.default,735 aten._cudnn_rnn.default,
736 aten._cudnn_rnn.out,736 aten._cudnn_rnn.out,
737 aten._cudnn_rnn_backward.default,737 aten._cudnn_rnn_backward.default,
738 aten._cudnn_rnn_backward.out,738 aten._cudnn_rnn_backward.out,
739 aten._dyn_quant_matmul_4bit.default,739 aten._dyn_quant_matmul_4bit.default,
740 aten._dyn_quant_pack_4bit_weight.default,740 aten._dyn_quant_pack_4bit_weight.default,
741 aten._efficient_attention_backward.default,741 aten._efficient_attention_backward.default,
742 aten._efficient_attention_forward.default,742 aten._efficient_attention_forward.default,
743 aten._efficientzerotensor.default,743 aten._efficientzerotensor.default,
744 aten._efficientzerotensor.out,744 aten._efficientzerotensor.out,
745 aten._embedding_bag.default,745 aten._embedding_bag.default,
746 aten._embedding_bag.out,746 aten._embedding_bag.out,
747 aten._embedding_bag_backward.default,747 aten._embedding_bag_backward.default,
748 aten._embedding_bag_forward_only.default,748 aten._embedding_bag_forward_only.default,
749 aten._embedding_bag_forward_only.out,749 aten._embedding_bag_forward_only.out,
750 aten._embedding_bag_per_sample_weights_backward.default,750 aten._embedding_bag_per_sample_weights_backward.default,
751 aten._embedding_bag_per_sample_weights_backward.out,751 aten._embedding_bag_per_sample_weights_backward.out,
752 aten._fft_r2c.default,752 aten._fft_r2c.default,
753 aten._fft_r2c.out,753 aten._fft_r2c.out,
754 aten._flash_attention_backward.default,754 aten._flash_attention_backward.default,
755 aten._flash_attention_forward.default,755 aten._flash_attention_forward.default,
756 aten._fused_moving_avg_obs_fq_helper.default,756 aten._fused_moving_avg_obs_fq_helper.default,
757 aten._fused_moving_avg_obs_fq_helper.out,757 aten._fused_moving_avg_obs_fq_helper.out,
758 aten._fused_moving_avg_obs_fq_helper_functional.default,758 aten._fused_moving_avg_obs_fq_helper_functional.default,
759 aten._histogramdd_bin_edges.default,759 aten._histogramdd_bin_edges.default,
760 aten._histogramdd_from_bin_cts.default,760 aten._histogramdd_from_bin_cts.default,
761 aten._linalg_check_errors.default,761 aten._linalg_check_errors.default,
762 aten._linalg_det.default,762 aten._linalg_det.default,
763 aten._linalg_det.result,763 aten._linalg_det.result,
764 aten._linalg_eigh.default,764 aten._linalg_eigh.default,
765 aten._linalg_eigh.eigenvalues,765 aten._linalg_eigh.eigenvalues,
766 aten._linalg_slogdet.default,766 aten._linalg_slogdet.default,
767 aten._linalg_slogdet.sign,767 aten._linalg_slogdet.sign,
768 aten._linalg_solve_ex.default,768 aten._linalg_solve_ex.default,
769 aten._linalg_solve_ex.result,769 aten._linalg_solve_ex.result,
770 aten._linalg_svd.U,770 aten._linalg_svd.U,
771 aten._linalg_svd.default,771 aten._linalg_svd.default,
772 aten._pdist_backward.default,772 aten._pdist_backward.default,
773 aten._pdist_backward.out,773 aten._pdist_backward.out,
774 aten._pdist_forward.default,774 aten._pdist_forward.default,
775 aten._pdist_forward.out,775 aten._pdist_forward.out,
776 aten._scaled_dot_product_cudnn_attention.default,776 aten._scaled_dot_product_cudnn_attention.default,
777 aten._scaled_dot_product_cudnn_attention_backward.default,777 aten._scaled_dot_product_cudnn_attention_backward.default,
778 aten._scaled_dot_product_efficient_attention.default,778 aten._scaled_dot_product_efficient_attention.default,
779 aten._scaled_dot_product_efficient_attention_backward.default,779 aten._scaled_dot_product_efficient_attention_backward.default,
780 aten._scaled_dot_product_flash_attention.default,780 aten._scaled_dot_product_flash_attention.default,
781 aten._scaled_dot_product_flash_attention_backward.default,781 aten._scaled_dot_product_flash_attention_backward.default,
782 aten._scaled_dot_product_flash_attention_for_cpu.default,782 aten._scaled_dot_product_flash_attention_for_cpu.default,
783 aten._scaled_dot_product_flash_attention_for_cpu_backward.default,783 aten._scaled_dot_product_flash_attention_for_cpu_backward.default,
784 aten._scaled_dot_product_fused_attention_overrideable.default,784 aten._scaled_dot_product_fused_attention_overrideable.default,
785 aten._scaled_dot_product_fused_attention_overrideable_backward.default,785 aten._scaled_dot_product_fused_attention_overrideable_backward.default,
786 aten._segment_reduce_backward.default,786 aten._segment_reduce_backward.default,
787 aten._sparse_coo_tensor_with_dims_and_tensors.default,787 aten._sparse_coo_tensor_with_dims_and_tensors.default,
788 aten._sparse_coo_tensor_with_dims_and_tensors.out,788 aten._sparse_coo_tensor_with_dims_and_tensors.out,
789 aten._thnn_fused_lstm_cell.default,789 aten._thnn_fused_lstm_cell.default,
790 aten._thnn_fused_lstm_cell.out,790 aten._thnn_fused_lstm_cell.out,
791 aten._to_sparse.default,791 aten._to_sparse.default,
792 aten._to_sparse.out,792 aten._to_sparse.out,
793 aten._to_sparse.sparse_dim, 793 aten._to_sparse.sparse_dim,
794 aten._to_sparse.sparse_dim_out,794 aten._to_sparse.sparse_dim_out,
795 aten._trilinear.default,795 aten._trilinear.default,
796 aten._trilinear.out,796 aten._trilinear.out,
797 aten.adaptive_max_pool2d_backward.default,797 aten.adaptive_max_pool2d_backward.default,
798 aten.adaptive_max_pool2d_backward.grad_input,798 aten.adaptive_max_pool2d_backward.grad_input,
799 aten.adaptive_max_pool3d.default,799 aten.adaptive_max_pool3d.default,
800 aten.adaptive_max_pool3d.out,800 aten.adaptive_max_pool3d.out,
801 aten.adaptive_max_pool3d_backward.default,801 aten.adaptive_max_pool3d_backward.default,
802 aten.adaptive_max_pool3d_backward.grad_input,802 aten.adaptive_max_pool3d_backward.grad_input,
803 aten.addbmm.default,803 aten.addbmm.default,
804 aten.addbmm.out,804 aten.addbmm.out,
805 aten.angle.Scalar,805 aten.angle.Scalar,
806 aten.angle.complex,806 aten.angle.complex,
807 aten.angle.default,807 aten.angle.default,
808 aten.angle.float,808 aten.angle.float,
809 aten.angle.int,809 aten.angle.int,
810 aten.angle.out,810 aten.angle.out,
811 aten.cholesky_inverse.default,811 aten.cholesky_inverse.default,
812 aten.cholesky_inverse.out,812 aten.cholesky_inverse.out,
813 aten.cholesky_solve.default,813 aten.cholesky_solve.default,
814 aten.cholesky_solve.out,814 aten.cholesky_solve.out,
815 aten.convolution_backward.default,815 aten.convolution_backward.default,
816 aten.convolution_backward.out,816 aten.convolution_backward.out,
817 aten.cummax.default,817 aten.cummax.default,
818 aten.cummin.default,818 aten.cummin.default,
819 aten.cumprod.default,819 aten.cumprod.default,
820 aten.cumsum.default,820 aten.cumsum.default,
821 aten.digamma.default,821 aten.digamma.default,
822 aten.digamma.out,822 aten.digamma.out,
823 aten.exponential.default,823 aten.exponential.default,
824 aten.fractional_max_pool2d_backward.default,824 aten.fractional_max_pool2d_backward.default,
825 aten.fractional_max_pool2d_backward.grad_input,825 aten.fractional_max_pool2d_backward.grad_input,
826 aten.fractional_max_pool3d.default,826 aten.fractional_max_pool3d.default,
827 aten.fractional_max_pool3d.output,827 aten.fractional_max_pool3d.output,
828 aten.fractional_max_pool3d_backward.default,828 aten.fractional_max_pool3d_backward.default,
829 aten.fractional_max_pool3d_backward.grad_input,829 aten.fractional_max_pool3d_backward.grad_input,
830 aten.gcd.default,830 aten.gcd.default,
831 aten.geqrf.a,831 aten.geqrf.a,
832 aten.geqrf.default,832 aten.geqrf.default,
833 aten.grid_sampler_2d_backward.default,833 aten.grid_sampler_2d_backward.default,
834 aten.grid_sampler_2d_backward.out,834 aten.grid_sampler_2d_backward.out,
835 aten.histc.default,835 aten.histc.default,
836 aten.histc.out,836 aten.histc.out,
837 aten.histogram.bin_ct,837 aten.histogram.bin_ct,
838 aten.igamma.default,838 aten.igamma.default,
839 aten.igamma.out,839 aten.igamma.out,
840 aten.igammac.default,840 aten.igammac.default,
841 aten.igammac.out,841 aten.igammac.out,
842 aten.index_reduce.default,842 aten.index_reduce.default,
843 aten.index_reduce.out,843 aten.index_reduce.out,
844 aten.kthvalue.default,844 aten.kthvalue.default,
845 aten.kthvalue.dimname,845 aten.kthvalue.dimname,
846 aten.kthvalue.dimname_out,846 aten.kthvalue.dimname_out,
847 aten.kthvalue.values,847 aten.kthvalue.values,
848 aten.linalg_cholesky_ex.L,848 aten.linalg_cholesky_ex.L,
849 aten.linalg_cholesky_ex.default,849 aten.linalg_cholesky_ex.default,
850 aten.linalg_householder_product.default,850 aten.linalg_householder_product.default,
851 aten.linalg_householder_product.out,851 aten.linalg_householder_product.out,
852 aten.linalg_inv_ex.default,852 aten.linalg_inv_ex.default,
853 aten.linalg_inv_ex.inverse,853 aten.linalg_inv_ex.inverse,
854 aten.linalg_ldl_factor_ex.default,854 aten.linalg_ldl_factor_ex.default,
855 aten.linalg_ldl_factor_ex.out,855 aten.linalg_ldl_factor_ex.out,
856 aten.linalg_ldl_solve.default,856 aten.linalg_ldl_solve.default,
857 aten.linalg_ldl_solve.out,857 aten.linalg_ldl_solve.out,
858 aten.linalg_lu.default,858 aten.linalg_lu.default,
859 aten.linalg_lu.out,859 aten.linalg_lu.out,
860 aten.linalg_lu_factor_ex.default,860 aten.linalg_lu_factor_ex.default,
861 aten.linalg_lu_factor_ex.out,861 aten.linalg_lu_factor_ex.out,
862 aten.linalg_lu_solve.default,862 aten.linalg_lu_solve.default,
863 aten.linalg_lu_solve.out,863 aten.linalg_lu_solve.out,
864 aten.linalg_matrix_exp.default,864 aten.linalg_matrix_exp.default,
865 aten.linalg_matrix_exp.out,865 aten.linalg_matrix_exp.out,
866 aten.linalg_pinv.atol_rtol_tensor,866 aten.linalg_pinv.atol_rtol_tensor,
867 aten.linalg_qr.default,867 aten.linalg_qr.default,
868 aten.linalg_qr.out,868 aten.linalg_qr.out,
869 aten.linalg_solve_triangular.default,869 aten.linalg_solve_triangular.default,
870 aten.linalg_solve_triangular.out,870 aten.linalg_solve_triangular.out,
871 aten.logcumsumexp.default,871 aten.logcumsumexp.default,
872 aten.lu_unpack.default,872 aten.lu_unpack.default,
873 aten.lu_unpack.out,873 aten.lu_unpack.out,
874 aten.masked_scatter.default,874 aten.masked_scatter.default,
875 aten.masked_scatter.out,875 aten.masked_scatter.out,
876 aten.masked_scatter_backward.default,876 aten.masked_scatter_backward.default,
877 aten.max_pool3d_with_indices.default,877 aten.max_pool3d_with_indices.default,
878 aten.max_pool3d_with_indices.out,878 aten.max_pool3d_with_indices.out,
879 aten.max_pool3d_with_indices_backward.default,879 aten.max_pool3d_with_indices_backward.default,
880 aten.max_pool3d_with_indices_backward.grad_input,880 aten.max_pool3d_with_indices_backward.grad_input,
881 aten.median.default,881 aten.median.default,
882 aten.median.dim,882 aten.median.dim,
883 aten.median.dim_values,883 aten.median.dim_values,
884 aten.median.names_dim,884 aten.median.names_dim,
885 aten.median.names_dim_values,885 aten.median.names_dim_values,
886 aten.median.out,886 aten.median.out,
887 aten.mode.default,887 aten.mode.default,
888 aten.mode.dimname,888 aten.mode.dimname,
889 aten.mode.dimname_out,889 aten.mode.dimname_out,
890 aten.mode.values,890 aten.mode.values,
891 aten.nanmedian.default,891 aten.nanmedian.default,
892 aten.nanmedian.dim,892 aten.nanmedian.dim,
893 aten.nanmedian.dim_values,893 aten.nanmedian.dim_values,
894 aten.nanmedian.names_dim,894 aten.nanmedian.names_dim,
895 aten.nanmedian.names_dim_values,895 aten.nanmedian.names_dim_values,
896 aten.nanmedian.out,896 aten.nanmedian.out,
897 aten.nonzero.default,897 aten.nonzero.default,
898 aten.ormqr.default,898 aten.ormqr.default,
899 aten.ormqr.out,899 aten.ormqr.out,
900 aten.polygamma.default,900 aten.polygamma.default,
901 aten.polygamma.out,901 aten.polygamma.out,
902 aten.rand.default,902 aten.rand.default,
903 aten.rand.generator,903 aten.rand.generator,
904 aten.randint.default,904 aten.randint.default,
905 aten.randint.generator,905 aten.randint.generator,
906 aten.randint.generator_out,906 aten.randint.generator_out,
907 aten.randint.low,907 aten.randint.low,
908 aten.randint.low_generator,908 aten.randint.low_generator,
909 aten.randint.low_generator_out,909 aten.randint.low_generator_out,
910 aten.randint.low_out,910 aten.randint.low_out,
911 aten.randint.out,911 aten.randint.out,
912 aten.randn.default,912 aten.randn.default,
913 aten.randn.generator,913 aten.randn.generator,
914 aten.randperm.default,914 aten.randperm.default,
915 aten.randperm.generator,915 aten.randperm.generator,
916 aten.randperm.generator_out,916 aten.randperm.generator_out,
917 aten.randperm.out,917 aten.randperm.out,
918 aten.replication_pad1d_backward.default,918 aten.replication_pad1d_backward.default,
919 aten.replication_pad1d_backward.grad_input,919 aten.replication_pad1d_backward.grad_input,
920 aten.replication_pad2d_backward.default,920 aten.replication_pad2d_backward.default,
921 aten.replication_pad2d_backward.grad_input,921 aten.replication_pad2d_backward.grad_input,
922 aten.resize_.default,922 aten.resize_.default,
923 aten.resize_as_.default,923 aten.resize_as_.default,
924 aten.segment_reduce.default,924 aten.segment_reduce.default,
925 aten.soft_margin_loss_backward.default,925 aten.soft_margin_loss_backward.default,
926 aten.soft_margin_loss_backward.grad_input,926 aten.soft_margin_loss_backward.grad_input,
927 aten.sort.Tensor,927 aten.sort.Tensor,
928 aten.sort.any,928 aten.sort.any,
929 aten.sort.bool,929 aten.sort.bool,
930 aten.sort.default,930 aten.sort.default,
931 aten.sort.dimname,931 aten.sort.dimname,
932 aten.sort.dimname_stable,932 aten.sort.dimname_stable,
933 aten.sort.dimname_values,933 aten.sort.dimname_values,
934 aten.sort.dimname_values_stable,934 aten.sort.dimname_values_stable,
935 aten.sort.float,935 aten.sort.float,
936 aten.sort.int,936 aten.sort.int,
937 aten.sort.stable,937 aten.sort.stable,
938 aten.sort.str,938 aten.sort.str,
939 aten.sort.values,939 aten.sort.values,
940 aten.sort.values_stable,940 aten.sort.values_stable,
941 aten.special_airy_ai.default,941 aten.special_airy_ai.default,
942 aten.special_airy_ai.out,942 aten.special_airy_ai.out,
943 aten.special_chebyshev_polynomial_t.default,943 aten.special_chebyshev_polynomial_t.default,
944 aten.special_chebyshev_polynomial_t.n_scalar,944 aten.special_chebyshev_polynomial_t.n_scalar,
945 aten.special_chebyshev_polynomial_t.n_scalar_out,945 aten.special_chebyshev_polynomial_t.n_scalar_out,
946 aten.special_chebyshev_polynomial_t.out,946 aten.special_chebyshev_polynomial_t.out,
947 aten.special_chebyshev_polynomial_t.x_scalar,947 aten.special_chebyshev_polynomial_t.x_scalar,
948 aten.special_chebyshev_polynomial_t.x_scalar_out,948 aten.special_chebyshev_polynomial_t.x_scalar_out,
949 aten.special_chebyshev_polynomial_u.default,949 aten.special_chebyshev_polynomial_u.default,
950 aten.special_chebyshev_polynomial_u.n_scalar,950 aten.special_chebyshev_polynomial_u.n_scalar,
951 aten.special_chebyshev_polynomial_u.n_scalar_out,951 aten.special_chebyshev_polynomial_u.n_scalar_out,
952 aten.special_chebyshev_polynomial_u.out,952 aten.special_chebyshev_polynomial_u.out,
953 aten.special_chebyshev_polynomial_u.x_scalar,953 aten.special_chebyshev_polynomial_u.x_scalar,
954 aten.special_chebyshev_polynomial_u.x_scalar_out,954 aten.special_chebyshev_polynomial_u.x_scalar_out,
955 aten.special_chebyshev_polynomial_v.default,955 aten.special_chebyshev_polynomial_v.default,
956 aten.special_chebyshev_polynomial_v.n_scalar,956 aten.special_chebyshev_polynomial_v.n_scalar,
957 aten.special_chebyshev_polynomial_v.n_scalar_out,957 aten.special_chebyshev_polynomial_v.n_scalar_out,
958 aten.special_chebyshev_polynomial_v.out,958 aten.special_chebyshev_polynomial_v.out,
959 aten.special_chebyshev_polynomial_v.x_scalar,959 aten.special_chebyshev_polynomial_v.x_scalar,
960 aten.special_chebyshev_polynomial_v.x_scalar_out,960 aten.special_chebyshev_polynomial_v.x_scalar_out,
961 aten.special_chebyshev_polynomial_w.default, 961 aten.special_chebyshev_polynomial_w.default,
962 aten.special_chebyshev_polynomial_w.n_scalar,962 aten.special_chebyshev_polynomial_w.n_scalar,
963 aten.special_chebyshev_polynomial_w.n_scalar_out,963 aten.special_chebyshev_polynomial_w.n_scalar_out,
964 aten.special_chebyshev_polynomial_w.out,964 aten.special_chebyshev_polynomial_w.out,
965 aten.special_chebyshev_polynomial_w.x_scalar,965 aten.special_chebyshev_polynomial_w.x_scalar,
966 aten.special_chebyshev_polynomial_w.x_scalar_out,966 aten.special_chebyshev_polynomial_w.x_scalar_out,
967 aten.special_gammainc.default,967 aten.special_gammainc.default,
968 aten.special_gammainc.out,968 aten.special_gammainc.out,
969 aten.special_gammaincc.default,969 aten.special_gammaincc.default,
970 aten.special_gammaincc.out,970 aten.special_gammaincc.out,
971 aten.special_hermite_polynomial_h.default,971 aten.special_hermite_polynomial_h.default,
972 aten.special_hermite_polynomial_h.n_scalar,972 aten.special_hermite_polynomial_h.n_scalar,
973 aten.special_hermite_polynomial_h.n_scalar_out,973 aten.special_hermite_polynomial_h.n_scalar_out,
974 aten.special_hermite_polynomial_h.out,974 aten.special_hermite_polynomial_h.out,
975 aten.special_hermite_polynomial_h.x_scalar,975 aten.special_hermite_polynomial_h.x_scalar,
976 aten.special_hermite_polynomial_h.x_scalar_out,976 aten.special_hermite_polynomial_h.x_scalar_out,
977 aten.special_hermite_polynomial_he.default,977 aten.special_hermite_polynomial_he.default,
978 aten.special_hermite_polynomial_he.n_scalar,978 aten.special_hermite_polynomial_he.n_scalar,
979 aten.special_hermite_polynomial_he.n_scalar_out,979 aten.special_hermite_polynomial_he.n_scalar_out,
980 aten.special_hermite_polynomial_he.out,980 aten.special_hermite_polynomial_he.out,
981 aten.special_hermite_polynomial_he.x_scalar,981 aten.special_hermite_polynomial_he.x_scalar,
982 aten.special_hermite_polynomial_he.x_scalar_out,982 aten.special_hermite_polynomial_he.x_scalar_out,
983 aten.special_i0e.default,983 aten.special_i0e.default,
984 aten.special_i0e.out,984 aten.special_i0e.out,
985 aten.special_i1e.default,985 aten.special_i1e.default,
986 aten.special_i1e.out,986 aten.special_i1e.out,
987 aten.special_laguerre_polynomial_l.default,987 aten.special_laguerre_polynomial_l.default,
988 aten.special_laguerre_polynomial_l.n_scalar,988 aten.special_laguerre_polynomial_l.n_scalar,
989 aten.special_laguerre_polynomial_l.n_scalar_out,989 aten.special_laguerre_polynomial_l.n_scalar_out,
990 aten.special_laguerre_polynomial_l.out,990 aten.special_laguerre_polynomial_l.out,
991 aten.special_laguerre_polynomial_l.x_scalar,991 aten.special_laguerre_polynomial_l.x_scalar,
992 aten.special_laguerre_polynomial_l.x_scalar_out,992 aten.special_laguerre_polynomial_l.x_scalar_out,
993 aten.special_legendre_polynomial_p.default,993 aten.special_legendre_polynomial_p.default,
994 aten.special_legendre_polynomial_p.n_scalar,994 aten.special_legendre_polynomial_p.n_scalar,
995 aten.special_legendre_polynomial_p.n_scalar_out,995 aten.special_legendre_polynomial_p.n_scalar_out,
996 aten.special_legendre_polynomial_p.out,996 aten.special_legendre_polynomial_p.out,
997 aten.special_legendre_polynomial_p.x_scalar,997 aten.special_legendre_polynomial_p.x_scalar,
998 aten.special_legendre_polynomial_p.x_scalar_out,998 aten.special_legendre_polynomial_p.x_scalar_out,
999 aten.special_log_ndtr.default,999 aten.special_log_ndtr.default,
1000 aten.special_log_ndtr.out,1000 aten.special_log_ndtr.out,
1001 aten.special_modified_bessel_k0.default,1001 aten.special_modified_bessel_k0.default,
1002 aten.special_modified_bessel_k0.out,1002 aten.special_modified_bessel_k0.out,
1003 aten.special_modified_bessel_k1.default,1003 aten.special_modified_bessel_k1.default,
1004 aten.special_modified_bessel_k1.out,1004 aten.special_modified_bessel_k1.out,
1005 aten.special_ndtr.default,1005 aten.special_ndtr.default,
1006 aten.special_ndtr.out,1006 aten.special_ndtr.out,
1007 aten.special_ndtri.default,1007 aten.special_ndtri.default,
1008 aten.special_ndtri.out,1008 aten.special_ndtri.out,
1009 aten.special_scaled_modified_bessel_k0.default,1009 aten.special_scaled_modified_bessel_k0.default,
1010 aten.special_scaled_modified_bessel_k0.out,1010 aten.special_scaled_modified_bessel_k0.out,
1011 aten.special_scaled_modified_bessel_k1.default,1011 aten.special_scaled_modified_bessel_k1.default,
1012 aten.special_scaled_modified_bessel_k1.out,1012 aten.special_scaled_modified_bessel_k1.out,
1013 aten.special_shifted_chebyshev_polynomial_t.default,1013 aten.special_shifted_chebyshev_polynomial_t.default,
1014 aten.special_shifted_chebyshev_polynomial_t.n_scalar,1014 aten.special_shifted_chebyshev_polynomial_t.n_scalar,
1015 aten.special_shifted_chebyshev_polynomial_t.n_scalar_out,1015 aten.special_shifted_chebyshev_polynomial_t.n_scalar_out,
1016 aten.special_shifted_chebyshev_polynomial_t.out,1016 aten.special_shifted_chebyshev_polynomial_t.out,
1017 aten.special_shifted_chebyshev_polynomial_t.x_scalar,1017 aten.special_shifted_chebyshev_polynomial_t.x_scalar,
1018 aten.special_shifted_chebyshev_polynomial_t.x_scalar_out,1018 aten.special_shifted_chebyshev_polynomial_t.x_scalar_out,
1019 aten.special_shifted_chebyshev_polynomial_u.default,1019 aten.special_shifted_chebyshev_polynomial_u.default,
1020 aten.special_shifted_chebyshev_polynomial_u.n_scalar,1020 aten.special_shifted_chebyshev_polynomial_u.n_scalar,
1021 aten.special_shifted_chebyshev_polynomial_u.n_scalar_out,1021 aten.special_shifted_chebyshev_polynomial_u.n_scalar_out,
1022 aten.special_shifted_chebyshev_polynomial_u.out,1022 aten.special_shifted_chebyshev_polynomial_u.out,
1023 aten.special_shifted_chebyshev_polynomial_u.x_scalar,1023 aten.special_shifted_chebyshev_polynomial_u.x_scalar,
1024 aten.special_shifted_chebyshev_polynomial_u.x_scalar_out,1024 aten.special_shifted_chebyshev_polynomial_u.x_scalar_out,
1025 aten.special_shifted_chebyshev_polynomial_v.default,1025 aten.special_shifted_chebyshev_polynomial_v.default,
1026 aten.special_shifted_chebyshev_polynomial_v.n_scalar,1026 aten.special_shifted_chebyshev_polynomial_v.n_scalar,
1027 aten.special_shifted_chebyshev_polynomial_v.n_scalar_out,1027 aten.special_shifted_chebyshev_polynomial_v.n_scalar_out,
1028 aten.special_shifted_chebyshev_polynomial_v.out,1028 aten.special_shifted_chebyshev_polynomial_v.out,
1029 aten.special_shifted_chebyshev_polynomial_v.x_scalar,1029 aten.special_shifted_chebyshev_polynomial_v.x_scalar,
1030 aten.special_shifted_chebyshev_polynomial_v.x_scalar_out,1030 aten.special_shifted_chebyshev_polynomial_v.x_scalar_out,
1031 aten.special_shifted_chebyshev_polynomial_w.default,1031 aten.special_shifted_chebyshev_polynomial_w.default,
1032 aten.special_shifted_chebyshev_polynomial_w.n_scalar,1032 aten.special_shifted_chebyshev_polynomial_w.n_scalar,
1033 aten.special_shifted_chebyshev_polynomial_w.n_scalar_out,1033 aten.special_shifted_chebyshev_polynomial_w.n_scalar_out,
1034 aten.special_shifted_chebyshev_polynomial_w.out,1034 aten.special_shifted_chebyshev_polynomial_w.out,
1035 aten.special_shifted_chebyshev_polynomial_w.x_scalar,1035 aten.special_shifted_chebyshev_polynomial_w.x_scalar,
1036 aten.special_shifted_chebyshev_polynomial_w.x_scalar_out,1036 aten.special_shifted_chebyshev_polynomial_w.x_scalar_out,
1037 aten.special_spherical_bessel_j0.default,1037 aten.special_spherical_bessel_j0.default,
1038 aten.special_spherical_bessel_j0.out,1038 aten.special_spherical_bessel_j0.out,
1039 aten.special_zeta.default,1039 aten.special_zeta.default,
1040 aten.special_zeta.other_scalar,1040 aten.special_zeta.other_scalar,
1041 aten.special_zeta.other_scalar_out,1041 aten.special_zeta.other_scalar_out,
1042 aten.special_zeta.out,1042 aten.special_zeta.out,
1043 aten.special_zeta.self_scalar,1043 aten.special_zeta.self_scalar,
1044 aten.special_zeta.self_scalar_out,1044 aten.special_zeta.self_scalar_out,
1045 aten.to_sparse.default,1045 aten.to_sparse.default,
1046 aten.to_sparse.sparse_dim,1046 aten.to_sparse.sparse_dim,
1047 aten.topk.default,1047 aten.topk.default,
1048 aten.topk.values,1048 aten.topk.values,
1049 aten.triangular_solve.X,1049 aten.triangular_solve.X,
1050 aten.triangular_solve.default,1050 aten.triangular_solve.default,
1051 aten.uniform.default,1051 aten.uniform.default,
1052 aten.uniform.out,1052 aten.uniform.out,
1053 aten.upsample_bicubic2d_backward.default,1053 aten.upsample_bicubic2d_backward.default,
1054 aten.upsample_bicubic2d_backward.grad_input,1054 aten.upsample_bicubic2d_backward.grad_input,
1055 aten.upsample_linear1d_backward.default,1055 aten.upsample_linear1d_backward.default,
1056 aten.upsample_linear1d_backward.grad_input,1056 aten.upsample_linear1d_backward.grad_input,
1057 aten.upsample_trilinear3d_backward.default,1057 aten.upsample_trilinear3d_backward.default,
1058 aten.upsample_trilinear3d_backward.grad_input,1058 aten.upsample_trilinear3d_backward.grad_input,
1059 aten.view_as_complex.default,1059 aten.view_as_complex.default,
1060 aten.zeros.names,1060 aten.zeros.names,
1061 auto_functionalized,1061 auto_functionalized,
1062 graphsafe_run_with_rng_state,1062 graphsafe_run_with_rng_state,
1063 prims.digamma.default,1063 prims.digamma.default,
1064 prims.igamma.default,1064 prims.igamma.default,
1065 prims.igammac.default,1065 prims.igammac.default,
1066 quantized.max_pool2d.default,1066 quantized.max_pool2d.default,
1067 run_and_save_rng_state,1067 run_and_save_rng_state,
1068 run_with_rng_state,1068 run_with_rng_state,
1069]1069]
1070 1070 
1071FALLBACK_LIST = TORCH_NATIVE_FALLBACK_LIST + NPU_EXTRA_FALLBACK_LIST1071FALLBACK_LIST = TORCH_NATIVE_FALLBACK_LIST + NPU_EXTRA_FALLBACK_LIST
1072 1072 
1073if inductor_indirect_memory_mode != 'linear':1073if inductor_indirect_memory_mode != 'linear':
1074 FALLBACK_LIST += [1074 FALLBACK_LIST += [
1075 aten.isnan,1075 aten.isnan,
1076 ]1076 ]
1077 1077 
1078INDIRECT_MEM_FALLBACK_LIST = [1078INDIRECT_MEM_FALLBACK_LIST = [
1079 aten.cat,1079 aten.cat,
1080 aten.embedding,1080 aten.embedding,
1081 aten.embedding.default,1081 aten.embedding.default,
1082 aten.embedding.out,1082 aten.embedding.out,
1083 aten.gather,1083 aten.gather,
1084 aten.gather.default,1084 aten.gather.default,
1085 aten.gather.dimname_out,1085 aten.gather.dimname_out,
1086 aten.gather.out,1086 aten.gather.out,
1087 aten.index,1087 aten.index,
1088 aten.index.Tensor,1088 aten.index.Tensor,
1089 aten._unsafe_index,1089 aten._unsafe_index,
1090 aten._unsafe_index.Tensor,1090 aten._unsafe_index.Tensor,
1091 aten.index_put,1091 aten.index_put,
1092 aten.index_put.default,1092 aten.index_put.default,
1093 aten.index_put_,1093 aten.index_put_,
1094 aten.index_put_.default,1094 aten.index_put_.default,
1095 aten._unsafe_index_put,1095 aten._unsafe_index_put,
1096 aten.scatter,1096 aten.scatter,
1097 aten.scatter.src,1097 aten.scatter.src,
1098 aten.scatter_,1098 aten.scatter_,
1099 aten.scatter_.src,1099 aten.scatter_.src,
1100 aten.scatter_reduce,1100 aten.scatter_reduce,
1101 aten.scatter_reduce_,1101 aten.scatter_reduce_,
1102]1102]
1103 1103 
1104if not inductor_indirect_memory_mode:1104if not inductor_indirect_memory_mode:
1105 FALLBACK_LIST += INDIRECT_MEM_FALLBACK_LIST1105 FALLBACK_LIST += INDIRECT_MEM_FALLBACK_LIST
Mtorch_npu/_inductor/tools/fallback_list_tool.py+16-16
@@ -1,17 +1,17 @@
1"""1"""
2this tool is to get and save FALLBACK_LIST in lowering_fallback_list.py2this tool is to get and save FALLBACK_LIST in lowering_fallback_list.py
3"""3"""
4 4 
5from torch_npu._inductor import lowering_fallback_list5from torch_npu._inductor import lowering_fallback_list
6from torch_npu._inductor.tools.aten_op_tool import write_to_file6from torch_npu._inductor.tools.aten_op_tool import write_to_file
7 7 
8 8 
9def get_npu_fallback_list():9def get_npu_fallback_list():
10 npu_fallback_list = {str(op) for op in lowering_fallback_list.FALLBACK_LIST}10 npu_fallback_list = {str(op) for op in lowering_fallback_list.FALLBACK_LIST}
11 print(f"len(lowering_fallback_list.FALLBACK_LIST): {len(lowering_fallback_list.FALLBACK_LIST)}")11 print(f"len(lowering_fallback_list.FALLBACK_LIST): {len(lowering_fallback_list.FALLBACK_LIST)}")
12 return npu_fallback_list12 return npu_fallback_list
13 13 
14 14 
15if __name__ == "__main__": 15if __name__ == "__main__":
16 npu_fallback_list = get_npu_fallback_list()16 npu_fallback_list = get_npu_fallback_list()
17 write_to_file(sorted(npu_fallback_list), f"npu_fallback_list_{len(npu_fallback_list)}.txt")17 write_to_file(sorted(npu_fallback_list), f"npu_fallback_list_{len(npu_fallback_list)}.txt")
Mtorch_npu/csrc/afd/CMakeLists.txt+5-5
@@ -1,6 +1,6 @@
1FILE(GLOB _AFD_SRCS *.cpp)1FILE(GLOB _AFD_SRCS *.cpp)
2 2 
3LIST(APPEND AFD_SRCS ${_AFD_SRCS})3LIST(APPEND AFD_SRCS ${_AFD_SRCS})
4 4 
5# Pass to parent5# Pass to parent
6set(AFD_SRCS ${AFD_SRCS} PARENT_SCOPE)6set(AFD_SRCS ${AFD_SRCS} PARENT_SCOPE)
Mtorch_npu/csrc/afd/Init.cpp+44-44
@@ -1,44 +1,44 @@
1#include "torch_npu/csrc/afd/Init.h"1#include "torch_npu/csrc/afd/Init.h"
2#include <torch/csrc/python_headers.h>2#include <torch/csrc/python_headers.h>
3#include <torch/csrc/Exceptions.h>3#include <torch/csrc/Exceptions.h>
4#include <torch/csrc/utils/object_ptr.h>4#include <torch/csrc/utils/object_ptr.h>
5#include <torch/csrc/utils/pybind.h>5#include <torch/csrc/utils/pybind.h>
6#include "torch_npu/csrc/afd/ScheduleContext.h"6#include "torch_npu/csrc/afd/ScheduleContext.h"
7 7 
8namespace torch_npu {8namespace torch_npu {
9namespace afd {9namespace afd {
10 10 
11PyObject *afd_init(PyObject * _unused, PyObject * noargs)11PyObject *afd_init(PyObject * _unused, PyObject * noargs)
12{12{
13 auto torch_npu_C_module = THPObjectPtr(PyImport_ImportModule("torch_npu._C"));13 auto torch_npu_C_module = THPObjectPtr(PyImport_ImportModule("torch_npu._C"));
14 if (!torch_npu_C_module) {14 if (!torch_npu_C_module) {
15 throw python_error();15 throw python_error();
16 }16 }
17 auto torch_npu_C_m = py::handle(torch_npu_C_module).cast<py::module>();17 auto torch_npu_C_m = py::handle(torch_npu_C_module).cast<py::module>();
18 18 
19 auto m = torch_npu_C_m.def_submodule("_afd", "Attention-FFN Disaggregation");19 auto m = torch_npu_C_m.def_submodule("_afd", "Attention-FFN Disaggregation");
20 auto module = py::handle(m).cast<py::module>();20 auto module = py::handle(m).cast<py::module>();
21 21 
22 py::class_<ScheduleContextHolder>(module, "ScheduleContextHolder")22 py::class_<ScheduleContextHolder>(module, "ScheduleContextHolder")
23 .def(py::init<int32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint64_t, uint64_t,23 .def(py::init<int32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint64_t, uint64_t,
24 uint64_t, uint64_t>())24 uint64_t, uint64_t>())
25 .def("init", &ScheduleContextHolder::Init)25 .def("init", &ScheduleContextHolder::Init)
26 .def("get_context_tensor", &ScheduleContextHolder::GetContextTensor)26 .def("get_context_tensor", &ScheduleContextHolder::GetContextTensor)
27 .def("stop_schedule", &ScheduleContextHolder::StopSchedule)27 .def("stop_schedule", &ScheduleContextHolder::StopSchedule)
28 .def("get_schedule_context_info", &ScheduleContextHolder::GetScheduleContextInfo);28 .def("get_schedule_context_info", &ScheduleContextHolder::GetScheduleContextInfo);
29 Py_RETURN_TRUE;29 Py_RETURN_TRUE;
30}30}
31 31 
32// methods on torch._C32// methods on torch._C
33PyMethodDef methods[] = {33PyMethodDef methods[] = {
34 {"_afd_init", afd_init, METH_NOARGS, nullptr},34 {"_afd_init", afd_init, METH_NOARGS, nullptr},
35 {nullptr, nullptr, 0, nullptr}35 {nullptr, nullptr, 0, nullptr}
36};36};
37 37 
38PyMethodDef *python_functions()38PyMethodDef *python_functions()
39{39{
40 return methods;40 return methods;
41}41}
42 42 
43} // namespace afd43} // namespace afd
44} // namespace torch_npu44} // namespace torch_npu
Mtorch_npu/csrc/afd/Init.h+11-11
@@ -1,12 +1,12 @@
1#pragma once1#pragma once
2 2 
3#include <torch/csrc/python_headers.h>3#include <torch/csrc/python_headers.h>
4#include "torch_npu/csrc/core/npu/NPUMacros.h"4#include "torch_npu/csrc/core/npu/NPUMacros.h"
5 5 
6namespace torch_npu {6namespace torch_npu {
7namespace afd {7namespace afd {
8 8 
9TORCH_NPU_API PyMethodDef *python_functions();9TORCH_NPU_API PyMethodDef *python_functions();
10 10 
11} // namespace afd11} // namespace afd
12} // namespace torch_npu12} // namespace torch_npu
Mtorch_npu/csrc/aten/CMakeLists.txt+21-21
@@ -1,21 +1,21 @@
1FILE(GLOB _ATEN_SRCS1FILE(GLOB _ATEN_SRCS
2 *.cpp2 *.cpp
3 common/*.cpp3 common/*.cpp
4 mirror/*.cpp4 mirror/*.cpp
5 ops/*.cpp5 ops/*.cpp
6 ops/op_api/*.cpp)6 ops/op_api/*.cpp)
7 7 
8FILE(GLOB _EXCLUDE8FILE(GLOB _EXCLUDE
9 VariableTypeEverything.cpp9 VariableTypeEverything.cpp
10 ADInplaceOrViewTypeEverything.cpp10 ADInplaceOrViewTypeEverything.cpp
11 python_functionsEverything.cpp11 python_functionsEverything.cpp
12 RegisterFunctionalizationEverything.cpp)12 RegisterFunctionalizationEverything.cpp)
13 13 
14FOREACH(ITEM ${_EXCLUDE})14FOREACH(ITEM ${_EXCLUDE})
15 LIST(REMOVE_ITEM _ATEN_SRCS ${ITEM})15 LIST(REMOVE_ITEM _ATEN_SRCS ${ITEM})
16ENDFOREACH()16ENDFOREACH()
17 17 
18LIST(APPEND ATEN_SRCS ${_ATEN_SRCS})18LIST(APPEND ATEN_SRCS ${_ATEN_SRCS})
19 19 
20# Pass to parent20# Pass to parent
21set(ATEN_SRCS ${ATEN_SRCS} PARENT_SCOPE)21set(ATEN_SRCS ${ATEN_SRCS} PARENT_SCOPE)
Mtorch_npu/csrc/aten/PinMemory.cpp+50-50
@@ -1,50 +1,50 @@
1#include <ATen/ATen.h>1#include <ATen/ATen.h>
2#include <ATen/NativeFunctions.h>2#include <ATen/NativeFunctions.h>
3#include <ATen/TensorUtils.h>3#include <ATen/TensorUtils.h>
4#include <c10/core/Storage.h>4#include <c10/core/Storage.h>
5#include "torch_npu/csrc/core/npu/NPUFunctions.h"5#include "torch_npu/csrc/core/npu/NPUFunctions.h"
6#include "torch_npu/csrc/core/npu/NPUException.h"6#include "torch_npu/csrc/core/npu/NPUException.h"
7#include "torch_npu/csrc/core/npu/CachingHostAllocator.h"7#include "torch_npu/csrc/core/npu/CachingHostAllocator.h"
8 8 
9#define TORCH_ASSERT_ONLY_METHOD_OPERATORS9#define TORCH_ASSERT_ONLY_METHOD_OPERATORS
10#include <ATen/core/Tensor.h>10#include <ATen/core/Tensor.h>
11#include <ATen/core/dispatch/DispatchKeyExtractor.h>11#include <ATen/core/dispatch/DispatchKeyExtractor.h>
12#include <torch/library.h>12#include <torch/library.h>
13 13 
14#ifndef AT_PER_OPERATOR_HEADERS14#ifndef AT_PER_OPERATOR_HEADERS
15#include <ATen/Operators.h>15#include <ATen/Operators.h>
16#else16#else
17#include <ATen/ops/is_pinned_ops.h>17#include <ATen/ops/is_pinned_ops.h>
18#include <ATen/ops/_pin_memory_ops.h>18#include <ATen/ops/_pin_memory_ops.h>
19 19 
20${ops_headers}20${ops_headers}
21#endif21#endif
22 22 
23namespace at_npu {23namespace at_npu {
24namespace native {24namespace native {
25 25 
26bool is_pinned(const at::Tensor& self, c10::optional<at::Device> device)26bool is_pinned(const at::Tensor& self, c10::optional<at::Device> device)
27{27{
28 // Only CPU tensors can be pinned28 // Only CPU tensors can be pinned
29 if (!self.is_cpu()) {29 if (!self.is_cpu()) {
30 return false;30 return false;
31 }31 }
32 c10::DispatchKeySet _dk = c10::DispatchKeySet(c10::computeDispatchKey(c10::nullopt, self.layout(), device.value_or(c10::DeviceType::PrivateUse1)));32 c10::DispatchKeySet _dk = c10::DispatchKeySet(c10::computeDispatchKey(c10::nullopt, self.layout(), device.value_or(c10::DeviceType::PrivateUse1)));
33 return at::_ops::is_pinned::redispatch(_dk, self, device);33 return at::_ops::is_pinned::redispatch(_dk, self, device);
34}34}
35 35 
36at::Tensor _pin_memory(const at::Tensor& self, c10::optional<at::Device> device)36at::Tensor _pin_memory(const at::Tensor& self, c10::optional<at::Device> device)
37{37{
38 TORCH_CHECK(self.device().is_cpu(), "cannot pin '", self.toString(), "' only dense CPU tensors can be pinned", PTA_ERROR(ErrCode::TYPE));38 TORCH_CHECK(self.device().is_cpu(), "cannot pin '", self.toString(), "' only dense CPU tensors can be pinned", PTA_ERROR(ErrCode::TYPE));
39 c10::DispatchKeySet _dk = c10::DispatchKeySet(c10::computeDispatchKey(c10::nullopt, self.layout(), device.value_or(c10::DeviceType::PrivateUse1)));39 c10::DispatchKeySet _dk = c10::DispatchKeySet(c10::computeDispatchKey(c10::nullopt, self.layout(), device.value_or(c10::DeviceType::PrivateUse1)));
40 return at::_ops::_pin_memory::redispatch(_dk, self, device);40 return at::_ops::_pin_memory::redispatch(_dk, self, device);
41}41}
42 42 
43TORCH_LIBRARY_IMPL(aten, BackendSelect, m)43TORCH_LIBRARY_IMPL(aten, BackendSelect, m)
44{44{
45 m.impl(TORCH_SELECTIVE_NAME("aten::is_pinned"), TORCH_FN(is_pinned));45 m.impl(TORCH_SELECTIVE_NAME("aten::is_pinned"), TORCH_FN(is_pinned));
46 m.impl(TORCH_SELECTIVE_NAME("aten::_pin_memory"), TORCH_FN(_pin_memory));46 m.impl(TORCH_SELECTIVE_NAME("aten::_pin_memory"), TORCH_FN(_pin_memory));
47}47}
48 48 
49}49}
50}50}
Mtorch_npu/csrc/aten/ops/op_api/CloneKernelOpApi.cpp+0-1
@@ -45,4 +45,3 @@ at::Tensor NPUNativeOpApiFunctions::clone(const at::Tensor &src, c10::optional<c
45 45 
46} // namespace native46} // namespace native
47} // namespace at_npu47} // namespace at_npu
48 
Mtorch_npu/csrc/core/CMakeLists.txt+5-5
@@ -1,6 +1,6 @@
1FILE(GLOB _CORE_SRCS *.cpp npu/*.cpp npu/*/*.cpp)1FILE(GLOB _CORE_SRCS *.cpp npu/*.cpp npu/*/*.cpp)
2 2 
3LIST(APPEND CORE_SRCS ${_CORE_SRCS})3LIST(APPEND CORE_SRCS ${_CORE_SRCS})
4 4 
5# Pass to parent5# Pass to parent
6set(CORE_SRCS ${CORE_SRCS} PARENT_SCOPE)6set(CORE_SRCS ${CORE_SRCS} PARENT_SCOPE)
Mtorch_npu/csrc/core/NPUStorageImpl.h+0-1
@@ -67,4 +67,3 @@ c10::intrusive_ptr<c10::StorageImpl> make_npu_storage_impl(
67 bool resizable);67 bool resizable);
68 68 
69} // namespace torch_npu69} // namespace torch_npu
70 
Mtorch_npu/csrc/core/npu/NPUErrorCodes.h+400-400
@@ -1,400 +1,400 @@
1#pragma once1#pragma once
2 2 
3#include <unordered_map>3#include <unordered_map>
4 4 
5namespace c10_npu::acl {5namespace c10_npu::acl {
6 6
7class AclErrorCode {7class AclErrorCode {
8public:8public:
9 std::unordered_map<int, std::string> error_code_map = {9 std::unordered_map<int, std::string> error_code_map = {
10 {100000, "Parameter verification failed.\n\10 {100000, "Parameter verification failed.\n\
11 Check whether the input parameter value of the interface is correct."},11 Check whether the input parameter value of the interface is correct."},
12 {100001, "ACL uninitialized.\n\12 {100001, "ACL uninitialized.\n\
13 (1)Check whether the acl.init interface has been invoked for initialization. Ensure that the acl.init \13 (1)Check whether the acl.init interface has been invoked for initialization. Ensure that the acl.init \
14interface has been invoked before other pyACL interfaces.\n\14interface has been invoked before other pyACL interfaces.\n\
15 (2)Check whether the initialization interface of the corresponding function has been invoked, for example, \15 (2)Check whether the initialization interface of the corresponding function has been invoked, for example, \
16the acl.mdl.init_dump interface for initializing Dump and the acl.prof.init interface for initializing Profiling."},16the acl.mdl.init_dump interface for initializing Dump and the acl.prof.init interface for initializing Profiling."},
17 {100002, "Repeated initialization or repeated loading.\n\17 {100002, "Repeated initialization or repeated loading.\n\
18 Check whether the corresponding interface is repeatedly invoked for initialization or loading."},18 Check whether the corresponding interface is repeatedly invoked for initialization or loading."},
19 {100003, "Invalid file.\n\19 {100003, "Invalid file.\n\
20 Check whether the file exists and can be accessed."},20 Check whether the file exists and can be accessed."},
21 {100004, "Failed to write the file.\n\21 {100004, "Failed to write the file.\n\
22 Check whether the file path exists and whether the file has the write permission."},22 Check whether the file path exists and whether the file has the write permission."},
23 {100005, "Invalid file size.\n\23 {100005, "Invalid file size.\n\
24 Check whether the file size meets the interface requirements."},24 Check whether the file size meets the interface requirements."},
25 {100006, "Failed to parse the file.\n\25 {100006, "Failed to parse the file.\n\
26 Check whether the file content is valid."},26 Check whether the file content is valid."},
27 {100007, "The file is missing parameters.\n\27 {100007, "The file is missing parameters.\n\
28 Check whether the file content is complete."},28 Check whether the file content is complete."},
29 {100008, "Invalid file parameter.\n\29 {100008, "Invalid file parameter.\n\
30 Check whether the parameter values in the file are correct."},30 Check whether the parameter values in the file are correct."},
31 {100009, "Invalid dump configuration.\n\31 {100009, "Invalid dump configuration.\n\
32 Check whether the dump configuration in the acl.init interface configuration file is correct. For details, \32 Check whether the dump configuration in the acl.init interface configuration file is correct. For details, \
33see 'Preparing Comparison Data > Preparing Offline Model Dump Data Files' in the <Precision Comparison Tool \33see 'Preparing Comparison Data > Preparing Offline Model Dump Data Files' in the <Precision Comparison Tool \
34User Guide>."},34User Guide>."},
35 {100010, "Invalid Profiling configuration.\n\35 {100010, "Invalid Profiling configuration.\n\
36 Check whether the profiling configuration is correct."},36 Check whether the profiling configuration is correct."},
37 {100011, "Invalid model ID.\n\37 {100011, "Invalid model ID.\n\
38 Check whether the model ID is correct and whether the model is correctly loaded."},38 Check whether the model ID is correct and whether the model is correctly loaded."},
39 {100012, "Failed to deserialize the model.\n\39 {100012, "Failed to deserialize the model.\n\
40 The model may not match the current version. Convert the model again by referring to the <ATC Tool User \40 The model may not match the current version. Convert the model again by referring to the <ATC Tool User \
41Guide>."},41Guide>."},
42 {100013, "Failed to parse the model.\n\42 {100013, "Failed to parse the model.\n\
43 The model may not match the current version. Convert the model again by referring to the <ATC Tool User \43 The model may not match the current version. Convert the model again by referring to the <ATC Tool User \
44Guide>."},44Guide>."},
45 {100014, "Failed to read the model.\n\45 {100014, "Failed to read the model.\n\
46 Check whether the model file exists and can be accessed."},46 Check whether the model file exists and can be accessed."},
47 {100015, "Invalid model size.\n\47 {100015, "Invalid model size.\n\
48 The model file is invalid, Convert the model again by referring to the <ATC Tool User Guide>."},48 The model file is invalid, Convert the model again by referring to the <ATC Tool User Guide>."},
49 {100016, "The model is missing parameters.\n\49 {100016, "The model is missing parameters.\n\
50 The model may not match the current version. Convert the model again by referring to the <ATC Tool User \50 The model may not match the current version. Convert the model again by referring to the <ATC Tool User \
51Guide>."},51Guide>."},
52 {100017, "The input for the model does not match.\n\52 {100017, "The input for the model does not match.\n\
53 Check whether the model input is correct."},53 Check whether the model input is correct."},
54 {100018, "The output of the model does not match.\n\54 {100018, "The output of the model does not match.\n\
55 Check whether the output of the model is correct."},55 Check whether the output of the model is correct."},
56 {100019, "Model is not-dynamic.\n\56 {100019, "Model is not-dynamic.\n\
57 Check whether the current model supports dynamic scenarios. If not, convert the model again by referring \57 Check whether the current model supports dynamic scenarios. If not, convert the model again by referring \
58to the <ATC Tool User Guide>."},58to the <ATC Tool User Guide>."},
59 {100020, "The type of a single operator does not match.\n\59 {100020, "The type of a single operator does not match.\n\
60 Check whether the operator type is correct."},60 Check whether the operator type is correct."},
61 {100021, "The input of a single operator does not match.\n\61 {100021, "The input of a single operator does not match.\n\
62 Check whether the operator input is correct."},62 Check whether the operator input is correct."},
63 {100022, "The output of a single operator does not match.\n\63 {100022, "The output of a single operator does not match.\n\
64 Check whether the operator output is correct."},64 Check whether the operator output is correct."},
65 {100023, "The attributes of a single operator do not match.\n\65 {100023, "The attributes of a single operator do not match.\n\
66 Check whether the operator attributes are correct."},66 Check whether the operator attributes are correct."},
67 {100024, "Single operator not found.\n\67 {100024, "Single operator not found.\n\
68 Check whether the operator type is supported."},68 Check whether the operator type is supported."},
69 {100025, "Failed to load a single operator.\n\69 {100025, "Failed to load a single operator.\n\
70 The model may not match the current version. Convert the model again by referring to the <ATC Tool User \70 The model may not match the current version. Convert the model again by referring to the <ATC Tool User \
71Guide>."},71Guide>."},
72 {100026, "Unsupported data type.\n\72 {100026, "Unsupported data type.\n\
73 Check whether the data type exists or is currently supported."},73 Check whether the data type exists or is currently supported."},
74 {100027, "The format does not match.\n\74 {100027, "The format does not match.\n\
75 Check whether the format is correct."},75 Check whether the format is correct."},
76 {100028, "When the operator interface is compiled in binary selection mode, the operator haven't registered a \76 {100028, "When the operator interface is compiled in binary selection mode, the operator haven't registered a \
77selector.\n\77selector.\n\
78 Check whether the acl.op.register_compile_func interface is invoked to register the operator selector."},78 Check whether the acl.op.register_compile_func interface is invoked to register the operator selector."},
79 {100029, "During operator compilation, the operator kernel haven't registered.\n\79 {100029, "During operator compilation, the operator kernel haven't registered.\n\
80 Check whether the acl.op.create_kernel interface is invoked to register the operator kernel."},80 Check whether the acl.op.create_kernel interface is invoked to register the operator kernel."},
81 {100030, "When the operator interface is compiled in binary selection mode, the operator is registered \81 {100030, "When the operator interface is compiled in binary selection mode, the operator is registered \
82repeatedly.\n\82repeatedly.\n\
83 Check whether the acl.op.register_compile_func interface is repeatedly invoked to register the operator \83 Check whether the acl.op.register_compile_func interface is repeatedly invoked to register the operator \
84selector."},84selector."},
85 {100031, "During operator compilation, the operator kernel is registered repeatedly.\n\85 {100031, "During operator compilation, the operator kernel is registered repeatedly.\n\
86 Check whether the acl.op.create_kernel interface is repeatedly invoked to register the operator kernel."},86 Check whether the acl.op.create_kernel interface is repeatedly invoked to register the operator kernel."},
87 {100032, "Invalid queue ID.\n\87 {100032, "Invalid queue ID.\n\
88 Check whether the queue ID is correct."},88 Check whether the queue ID is correct."},
89 {100033, "Duplicate subscription.\n\89 {100033, "Duplicate subscription.\n\
90 Check whether the acl.rt.subscribe_report interface is invoked repeatedly for the same stream."},90 Check whether the acl.rt.subscribe_report interface is invoked repeatedly for the same stream."},
91 {100034, "The stream is not subscribed.\n\91 {100034, "The stream is not subscribed.\n\
92 Check whether the acl.rt.subscribe_report interface has been invoked.\n\92 Check whether the acl.rt.subscribe_report interface has been invoked.\n\
93 [notice] This return code will be discarded in later versions. Use the 'ACL_ERROR_RT_STREAM_NO_CB_REG' \93 [notice] This return code will be discarded in later versions. Use the 'ACL_ERROR_RT_STREAM_NO_CB_REG' \
94return code."},94return code."},
95 {100035, "The thread is not subscribed.\n\95 {100035, "The thread is not subscribed.\n\
96 Check whether the acl.rt.subscribe_report interface has been invoked.\n\96 Check whether the acl.rt.subscribe_report interface has been invoked.\n\
97 [notice] This return code will be discarded in later versions. Use the 'ACL_ERROR_RT_THREAD_SUBSCRIBE' \97 [notice] This return code will be discarded in later versions. Use the 'ACL_ERROR_RT_THREAD_SUBSCRIBE' \
98return code."},98return code."},
99 {100036, "Waiting for callback time out.\n\99 {100036, "Waiting for callback time out.\n\
100 (1)Check whether the acl.rt.launch_callback interface has been invoked to deliver the callback task.\n\100 (1)Check whether the acl.rt.launch_callback interface has been invoked to deliver the callback task.\n\
101 (2)Check whether the timeout interval in the acl.rt.process_report interface is proper.\n\101 (2)Check whether the timeout interval in the acl.rt.process_report interface is proper.\n\
102 (3)Check whether the callback task has been processed. If the callback task has been processed but the \102 (3)Check whether the callback task has been processed. If the callback task has been processed but the \
103acl.rt.process_report interface is still invoked, optimize the code logic.\n\103acl.rt.process_report interface is still invoked, optimize the code logic.\n\
104 [notice] This return code will be discarded in later versions. Use the 'ACL_ERROR_RT_REPORT_TIMEOUT' \104 [notice] This return code will be discarded in later versions. Use the 'ACL_ERROR_RT_REPORT_TIMEOUT' \
105return code."},105return code."},
106 {100037, "Repeated deinitialization.\n\106 {100037, "Repeated deinitialization.\n\
107 Check whether the acl.finalize interface is repeatedly invoked for deinitialization."},107 Check whether the acl.finalize interface is repeatedly invoked for deinitialization."},
108 {100038, "The static AIPP configuration information does not exist.\n\108 {100038, "The static AIPP configuration information does not exist.\n\
109 When invoking the 'acl.mdl.get_first_aipp_info' interface, ensure that the index value is correct.\n\109 When invoking the 'acl.mdl.get_first_aipp_info' interface, ensure that the index value is correct.\n\
110 [notice] This return code will be discarded in later versions. Use the 'ACL_ERROR_GE_AIPP_NOT_EXIST' \110 [notice] This return code will be discarded in later versions. Use the 'ACL_ERROR_GE_AIPP_NOT_EXIST' \
111return code."},111return code."},
112 {100039, "The dynamic library path configured before running the application is the path of the \112 {100039, "The dynamic library path configured before running the application is the path of the \
113compilation stub, not the correct dynamic library path.\n\113compilation stub, not the correct dynamic library path.\n\
114 Check the configuration of the dynamic library path and ensure that the dynamic library in running mode \114 Check the configuration of the dynamic library path and ensure that the dynamic library in running mode \
115is used."},115is used."},
116 {100040, "Group is not set.\n\116 {100040, "Group is not set.\n\
117 Check if the aclrtSetGroup interface has been called."},117 Check if the aclrtSetGroup interface has been called."},
118 {100041, "No corresponding Group is created.\n\118 {100041, "No corresponding Group is created.\n\
119 Check whether the Group ID set during the interface invocation is within the supported range. \119 Check whether the Group ID set during the interface invocation is within the supported range. \
120The value range of the Group ID is [0, (number of groups -1)]. You can invoke the aclrtGetGroupCount interface to \120The value range of the Group ID is [0, (number of groups -1)]. You can invoke the aclrtGetGroupCount interface to \
121obtain the number of groups."},121obtain the number of groups."},
122 {100042, "A profiling data collection task exists.\n\122 {100042, "A profiling data collection task exists.\n\
123 Check whether multiple profiling configurations are delivered to the same device.\n\123 Check whether multiple profiling configurations are delivered to the same device.\n\
124 For details, see the Profiling pyACL API. (Performance data is collected and flushed to disks through \124 For details, see the Profiling pyACL API. (Performance data is collected and flushed to disks through \
125the Profiling pyACL API.) The code logic is adjusted based on the interface invoking requirements and interface \125the Profiling pyACL API.) The code logic is adjusted based on the interface invoking requirements and interface \
126invoking sequence in."},126invoking sequence in."},
127 {100043, "The acl.prof.init interface is not used for analysis initialization.\n\127 {100043, "The acl.prof.init interface is not used for analysis initialization.\n\
128 Check the interface invoking sequence for collecting and analyzing data and analyze the pyACL API by \128 Check the interface invoking sequence for collecting and analyzing data and analyze the pyACL API by \
129referring to.\n\129referring to.\n\
130 See (Performance data collected and flushed to disks by analyzing the pyACL API) Description in."},130 See (Performance data collected and flushed to disks by analyzing the pyACL API) Description in."},
131 {100044, "A task for obtaining dump data exists.\n\131 {100044, "A task for obtaining dump data exists.\n\
132 Before invoking the 'acl.mdl.init_dump', 'acl.mdl.set_dump', 'acl.mdl.finalize_dump' interfaces to configure \132 Before invoking the 'acl.mdl.init_dump', 'acl.mdl.set_dump', 'acl.mdl.finalize_dump' interfaces to configure \
133dump information: Check whether the acl.init interface has been invoked to configure the dump information.\n\133dump information: Check whether the acl.init interface has been invoked to configure the dump information.\n\
134 If yes, adjust the code logic and retain one method to configure the dump information."},134 If yes, adjust the code logic and retain one method to configure the dump information."},
135 {100045, "The acl.mdl.init_dump interface is not used to initialize the dump.\n\135 {100045, "The acl.mdl.init_dump interface is not used to initialize the dump.\n\
136 Check the invoking sequence of the interfaces for obtaining dump data. For details, see the description \136 Check the invoking sequence of the interfaces for obtaining dump data. For details, see the description \
137of the acl.mdl.init_dump interface."},137of the acl.mdl.init_dump interface."},
138 {148046, "Subscribe to the same model repeatedly.\n\138 {148046, "Subscribe to the same model repeatedly.\n\
139 Check the API invoking sequence. See (Performance data collected and flushed to disks by analyzing \139 Check the API invoking sequence. See (Performance data collected and flushed to disks by analyzing \
140the pyACL API) Description in."},140the pyACL API) Description in."},
141 {148047, "A conflict occurs in invoking the interface for collecting performance data.\n\141 {148047, "A conflict occurs in invoking the interface for collecting performance data.\n\
142 The interfaces for collecting profiling performance data in the two modes cannot be invoked crossly.\n\142 The interfaces for collecting profiling performance data in the two modes cannot be invoked crossly.\n\
143 The 'acl.prof.model_subscribe', 'acl.prof.get_op_*', 'acl.prof.model_un_subscribe' interface cannot be \143 The 'acl.prof.model_subscribe', 'acl.prof.get_op_*', 'acl.prof.model_un_subscribe' interface cannot be \
144invoked between the 'acl.prof.init' and 'acl.prof.finalize' interfaces.\n\144invoked between the 'acl.prof.init' and 'acl.prof.finalize' interfaces.\n\
145 The 'acl.prof.init', 'acl.prof.start', 'acl.prof.stop', and 'acl.prof.finalize' interfaces cannot be \145 The 'acl.prof.init', 'acl.prof.start', 'acl.prof.stop', and 'acl.prof.finalize' interfaces cannot be \
146invoked between the 'acl.prof.model_subscribe' and 'acl.prof.model_un_subscribe' interfaces."},146invoked between the 'acl.prof.model_subscribe' and 'acl.prof.model_un_subscribe' interfaces."},
147 {148048, "Invalid operator cache information aging configuration.\n\147 {148048, "Invalid operator cache information aging configuration.\n\
148 Check the aging configuration of the operator cache information. For details, see the configuration \148 Check the aging configuration of the operator cache information. For details, see the configuration \
149description and example in acl.init."},149description and example in acl.init."},
150 {148049, "The 'ASCEND_OPP_PATH' environment variable is not set, or the value of the environment variable \150 {148049, "The 'ASCEND_OPP_PATH' environment variable is not set, or the value of the environment variable \
151is incorrect.\n\151is incorrect.\n\
152 Check whether the 'ASCEND_OPP_PATH' environment variable is set and whether the value of the environment \152 Check whether the 'ASCEND_OPP_PATH' environment variable is set and whether the value of the environment \
153variable is the installation path of the opp software package."},153variable is the installation path of the opp software package."},
154 {148050, "The operator does not support dynamic Shape.\n\154 {148050, "The operator does not support dynamic Shape.\n\
155 Check whether the shape of the operator in the single-operator model file is dynamic. If yes, change the \155 Check whether the shape of the operator in the single-operator model file is dynamic. If yes, change the \
156shape to a fixed one.\n\156shape to a fixed one.\n\
157 Check whether the shape of aclTensorDesc is dynamic during operator compilation. If yes, create \157 Check whether the shape of aclTensorDesc is dynamic during operator compilation. If yes, create \
158aclTensorDesc based on the fixed shape."},158aclTensorDesc based on the fixed shape."},
159 {148051, "Related resources have not been released.\n\159 {148051, "Related resources have not been released.\n\
160 This error code is returned if the related channel is not destroyed when the channel description \160 This error code is returned if the related channel is not destroyed when the channel description \
161information is being destroyed. Check whether the channel associated with the channel description is destroyed."},161information is being destroyed. Check whether the channel associated with the channel description is destroyed."},
162 {148052, "Input image encoding format (such as arithmetic encoding and progressive encoding) that is not \162 {148052, "Input image encoding format (such as arithmetic encoding and progressive encoding) that is not \
163supported by the JPEGD function.\n\163supported by the JPEGD function.\n\
164 When JPEGD image decoding is implemented, only Huffman encoding is supported.\n\164 When JPEGD image decoding is implemented, only Huffman encoding is supported.\n\
165 The color space of the original image before compression is YUV. The ratio of pixel components is \n\165 The color space of the original image before compression is YUV. The ratio of pixel components is \n\
166 4:4:4, 4:2:2, 4:2:0, 4:0:0, or 4:4:0.\n\166 4:4:4, 4:2:2, 4:2:0, 4:0:0, or 4:4:0.\n\
167 Arithmetic coding, progressive JPEG, and JPEG2000 are not supported."},167 Arithmetic coding, progressive JPEG, and JPEG2000 are not supported."},
168 {200000, "Failed to apply for memory.\n\168 {200000, "Failed to apply for memory.\n\
169 Check the available memory in the hardware environment."},169 Check the available memory in the hardware environment."},
170 {200001, "The interface does not support this function.\n\170 {200001, "The interface does not support this function.\n\
171 Check whether the invoked interface is supported."},171 Check whether the invoked interface is supported."},
172 {200002, "Invalid device.\n\172 {200002, "Invalid device.\n\
173 Check whether the device exists.\n\173 Check whether the device exists.\n\
174 [notice] This return code will be discarded in later versions. Use the 'ACL_ERROR_RT_INVALID_DEVICEID' \174 [notice] This return code will be discarded in later versions. Use the 'ACL_ERROR_RT_INVALID_DEVICEID' \
175return code."},175return code."},
176 {200003, "The memory address is not aligned.\n\176 {200003, "The memory address is not aligned.\n\
177 Check whether the memory address meets the interface requirements."},177 Check whether the memory address meets the interface requirements."},
178 {200004, "The resources do not match.\n\178 {200004, "The resources do not match.\n\
179 Check whether the correct resources such as Stream and Context are transferred when the interface is \179 Check whether the correct resources such as Stream and Context are transferred when the interface is \
180invoked."},180invoked."},
181 {200005, "Invalid resource handle.\n\181 {200005, "Invalid resource handle.\n\
182 Check whether the transferred resources such as Stream and Context are destroyed or occupied when the \182 Check whether the transferred resources such as Stream and Context are destroyed or occupied when the \
183interface is invoked."},183interface is invoked."},
184 {200006, "This feature is not supported.\n\184 {200006, "This feature is not supported.\n\
185 Rectify the fault based on the error information in the ascend log or contact Huawei technical support. For \185 Rectify the fault based on the error information in the ascend log or contact Huawei technical support. For \
186details about logs, see the Log Reference."},186details about logs, see the Log Reference."},
187 {200007, "Unsupported profiling configurations are delivered.\n\187 {200007, "Unsupported profiling configurations are delivered.\n\
188 Check whether the profiling configuration is correct by referring to the description in \188 Check whether the profiling configuration is correct by referring to the description in \
189'acl.prof.create_config'."},189'acl.prof.create_config'."},
190 {300000, "The storage limit is exceeded.\n\190 {300000, "The storage limit is exceeded.\n\
191 Check the remaining storage space in the hardware environment."},191 Check the remaining storage space in the hardware environment."},
192 {500000, "Unknown internal error.\n\192 {500000, "Unknown internal error.\n\
193 Rectify the fault based on the error information in the ascend log."},193 Rectify the fault based on the error information in the ascend log."},
194 {500001, "The internal ACL of the system is incorrect.\n\194 {500001, "The internal ACL of the system is incorrect.\n\
195 Rectify the fault based on the error information in the ascend log."},195 Rectify the fault based on the error information in the ascend log."},
196 {500002, "A GE error occurs in the system.\n\196 {500002, "A GE error occurs in the system.\n\
197 Rectify the fault based on the error information in the ascend log."},197 Rectify the fault based on the error information in the ascend log."},
198 {500003, "The internal RUNTIME of the system is incorrect.\n\198 {500003, "The internal RUNTIME of the system is incorrect.\n\
199 Rectify the fault based on the error information in the ascend log."},199 Rectify the fault based on the error information in the ascend log."},
200 {500004, "An internal DRV (Driver) error occurs.\n\200 {500004, "An internal DRV (Driver) error occurs.\n\
201 Rectify the fault based on the error information in the ascend log."},201 Rectify the fault based on the error information in the ascend log."},
202 {500005, "Profiling error.\n\202 {500005, "Profiling error.\n\
203 Rectify the fault based on the error information in the ascend log."},203 Rectify the fault based on the error information in the ascend log."},
204 /* following return codes is for the internal RUNTIME */204 /* following return codes is for the internal RUNTIME */
205 {107000, "Parameter verification failed.\n\205 {107000, "Parameter verification failed.\n\
206 Check whether the input parameters of the interface are correct."},206 Check whether the input parameters of the interface are correct."},
207 {107001, "Invalid device ID.\n\207 {107001, "Invalid device ID.\n\
208 Check whether the device ID is valid."},208 Check whether the device ID is valid."},
209 /* Warning: key logs in the fault mode library!!! Don't make arbitrary modifications!!! */209 /* Warning: key logs in the fault mode library!!! Don't make arbitrary modifications!!! */
210 {107002, "The context is empty.\n\210 {107002, "The context is empty.\n\
211 Check whether acl.rt.set_context or acl.rt.set_device is called."},211 Check whether acl.rt.set_context or acl.rt.set_device is called."},
212 {107003, "The stream is not in the current context.\n\212 {107003, "The stream is not in the current context.\n\
213 Check whether the context where the stream is located is the same as the current context."},213 Check whether the context where the stream is located is the same as the current context."},
214 {107004, "The model is not in the current context.\n\214 {107004, "The model is not in the current context.\n\
215 Check whether the loaded model is consistent with the current context."},215 Check whether the loaded model is consistent with the current context."},
216 {107005, "The stream is not in the current model.\n\216 {107005, "The stream is not in the current model.\n\
217 Check whether the stream has been bound to the model."},217 Check whether the stream has been bound to the model."},
218 {107006, "The event timestamp is invalid.\n\218 {107006, "The event timestamp is invalid.\n\
219 Check whether the event is created."},219 Check whether the event is created."},
220 {107007, "Invert the event timestamp.\n\220 {107007, "Invert the event timestamp.\n\
221 Check whether the event is created."},221 Check whether the event is created."},
222 {107008, "The memory address is not aligned.\n\222 {107008, "The memory address is not aligned.\n\
223 Check whether the applied memory addresses are aligned. For details about the restrictions on the memory \223 Check whether the applied memory addresses are aligned. For details about the restrictions on the memory \
224application interface, see Memory Management."},224application interface, see Memory Management."},
225 {107009, "Failed to open the file.\n\225 {107009, "Failed to open the file.\n\
226 Check whether the file exists."},226 Check whether the file exists."},
227 {107010, "Failed to write the file.\n\227 {107010, "Failed to write the file.\n\
228 Check whether the file exists or has the write permission."},228 Check whether the file exists or has the write permission."},
229 {107011, "The stream is not subscribed to or subscribed to repeatedly.\n\229 {107011, "The stream is not subscribed to or subscribed to repeatedly.\n\
230 Check whether the current stream is subscribed to or repeatedly subscribed to."},230 Check whether the current stream is subscribed to or repeatedly subscribed to."},
231 {107012, "The thread is not subscribed or subscribed repeatedly.\n\231 {107012, "The thread is not subscribed or subscribed repeatedly.\n\
232 Check whether the current thread subscribes to or subscribes to the thread repeatedly."},232 Check whether the current thread subscribes to or subscribes to the thread repeatedly."},
233 {107013, "The group is not set."},233 {107013, "The group is not set."},
234 {107014, "The corresponding group is not created.\n\234 {107014, "The corresponding group is not created.\n\
235 Check whether the group ID set when the interface is invoked is within the supported range. The value \235 Check whether the group ID set when the interface is invoked is within the supported range. The value \
236range of the group ID is [0, (Number of groups - 1)]."},236range of the group ID is [0, (Number of groups - 1)]."},
237 {107015, "The stream corresponding to the callback is not registered with the thread.\n\237 {107015, "The stream corresponding to the callback is not registered with the thread.\n\
238 Check whether the stream has been registered with the thread and whether the acl.rt.subscribe_report \238 Check whether the stream has been registered with the thread and whether the acl.rt.subscribe_report \
239interface is invoked."},239interface is invoked."},
240 {107016, "Invalid memory type.\n\240 {107016, "Invalid memory type.\n\
241 Check whether the memory type is valid."},241 Check whether the memory type is valid."},
242 {107017, "Invalid resource handle.\n\242 {107017, "Invalid resource handle.\n\
243 Check whether the input and used parameters are correct."},243 Check whether the input and used parameters are correct."},
244 {107018, "The memory type applied for is incorrect.\n\244 {107018, "The memory type applied for is incorrect.\n\
245 Check whether the input and used memory types are correct."},245 Check whether the input and used memory types are correct."},
246 {107019, "Task execution timed out.\n\246 {107019, "Task execution timed out.\n\
247 Re-execute the interface for delivering the task."},247 Re-execute the interface for delivering the task."},
248 {207000, "This feature is not supported.\n\248 {207000, "This feature is not supported.\n\
249 Rectify the fault based on the error information in the ascend log."},249 Rectify the fault based on the error information in the ascend log."},
250 {207001, "Failed to apply for memory.\n\250 {207001, "Failed to apply for memory.\n\
251 Check the remaining storage space in the hardware environment."},251 Check the remaining storage space in the hardware environment."},
252 {207002, "Failed to release the memory.\n\252 {207002, "Failed to release the memory.\n\
253 Rectify the fault based on the error information in the ascend log."},253 Rectify the fault based on the error information in the ascend log."},
254 {207003, "The operation of the aicore operator overflows.\n\254 {207003, "The operation of the aicore operator overflows.\n\
255 Check whether the corresponding aicore operator operation overflows."},255 Check whether the corresponding aicore operator operation overflows."},
256 {207004, "The device is unavailable.\n\256 {207004, "The device is unavailable.\n\
257 Check whether the device is running properly."},257 Check whether the device is running properly."},
258 {207005, "Failed to apply for memory.\n\258 {207005, "Failed to apply for memory.\n\
259 Check the remaining storage space in the hardware environment."},259 Check the remaining storage space in the hardware environment."},
260 {207006, "You do not have the operation permission.\n\260 {207006, "You do not have the operation permission.\n\
261 Check whether the permission of the user who runs the application is correct."},261 Check whether the permission of the user who runs the application is correct."},
262 {207007, "Event resources are insufficient.\n\262 {207007, "Event resources are insufficient.\n\
263 Check whether the number of events meets the requirements by referring to the description of the \263 Check whether the number of events meets the requirements by referring to the description of the \
264acl.rt.create_event interface."},264acl.rt.create_event interface."},
265 {207008, "Stream resources are insufficient.\n\265 {207008, "Stream resources are insufficient.\n\
266 Check whether the number of streams meets the requirements by referring to the description of the \266 Check whether the number of streams meets the requirements by referring to the description of the \
267acl.rt.create_stream interface."},267acl.rt.create_stream interface."},
268 {207009, "Notify resources in the system are insufficient.\n\268 {207009, "Notify resources in the system are insufficient.\n\
269 There are too many concurrent data preprocessing tasks or model inference consumes too many resources. \269 There are too many concurrent data preprocessing tasks or model inference consumes too many resources. \
270You are advised to reduce the number of concurrent tasks or uninstall some models."},270You are advised to reduce the number of concurrent tasks or uninstall some models."},
271 {207010, "Insufficient model resources.\n\271 {207010, "Insufficient model resources.\n\
272 You are advised to uninstall some models."},272 You are advised to uninstall some models."},
273 {207011, "Runtime internal resources are insufficient.\n\273 {207011, "Runtime internal resources are insufficient.\n\
274 Rectify the fault based on the error information in the ascend log."},274 Rectify the fault based on the error information in the ascend log."},
275 {207012, "The number of queues exceeds the upper limit.\n\275 {207012, "The number of queues exceeds the upper limit.\n\
276 Destroy unnecessary queues before creating new queues."},276 Destroy unnecessary queues before creating new queues."},
277 {207013, "The queue is empty.\n\277 {207013, "The queue is empty.\n\
278 Cannot obtain data from an empty queue. Add data to the queue and then obtain data."},278 Cannot obtain data from an empty queue. Add data to the queue and then obtain data."},
279 {207014, "The queue is full. \n\279 {207014, "The queue is full. \n\
280 You cannot add data to a queue that is full. Obtain data from the queue and then add data."},280 You cannot add data to a queue that is full. Obtain data from the queue and then add data."},
281 {207015, "The queue is initialized repeatedly. \n\281 {207015, "The queue is initialized repeatedly. \n\
282 You are advised to initialize the queue only once."},282 You are advised to initialize the queue only once."},
283 {207018, "The memory on the device is exhausted. \n\283 {207018, "The memory on the device is exhausted. \n\
284 Check the memory usage on the device and properly plan the memory usage based on the memory specifications \284 Check the memory usage on the device and properly plan the memory usage based on the memory specifications \
285on the device."},285on the device."},
286 {507000, "An internal error occurs in the runtime module on the host. \n\286 {507000, "An internal error occurs in the runtime module on the host. \n\
287 Rectify the fault based on the error information in the ascend log."},287 Rectify the fault based on the error information in the ascend log."},
288 {507001, "An internal error occurs in the task scheduler module on the device. \n\288 {507001, "An internal error occurs in the task scheduler module on the device. \n\
289 Rectify the fault based on the error information in the ascend log."},289 Rectify the fault based on the error information in the ascend log."},
290 {507002, "The number of tasks on the stream reaches the maximum. \n\290 {507002, "The number of tasks on the stream reaches the maximum. \n\
291 Rectify the fault based on the error information in the ascend log."},291 Rectify the fault based on the error information in the ascend log."},
292 {507003, "The number of tasks on the stream is empty. \n\292 {507003, "The number of tasks on the stream is empty. \n\
293 Rectify the fault based on the error information in the ascend log."},293 Rectify the fault based on the error information in the ascend log."},
294 {507004, "Not all tasks on the stream are executed. \n\294 {507004, "Not all tasks on the stream are executed. \n\
295 Rectify the fault based on the error information in the ascend log."},295 Rectify the fault based on the error information in the ascend log."},
296 {507005, "Task execution on the AI CPU is complete. \n\296 {507005, "Task execution on the AI CPU is complete. \n\
297 Rectify the fault based on the error information in the ascend log."},297 Rectify the fault based on the error information in the ascend log."},
298 {507006, "The event is not complete. \n\298 {507006, "The event is not complete. \n\
299 Rectify the fault based on the error information in the ascend log."},299 Rectify the fault based on the error information in the ascend log."},
300 {507007, "Failed to release the context. \n\300 {507007, "Failed to release the context. \n\
301 Rectify the fault based on the error information in the ascend log."},301 Rectify the fault based on the error information in the ascend log."},
302 {507008, "Failed to obtain the SOC version. \n\302 {507008, "Failed to obtain the SOC version. \n\
303 Rectify the fault based on the error information in the ascend log."},303 Rectify the fault based on the error information in the ascend log."},
304 {507009, "The task type is not supported. \n\304 {507009, "The task type is not supported. \n\
305 Rectify the fault based on the error information in the ascend log."},305 Rectify the fault based on the error information in the ascend log."},
306 {507010, "The task scheduler loses the heartbeat. \n\306 {507010, "The task scheduler loses the heartbeat. \n\
307 Rectify the fault based on the error information in the ascend log."},307 Rectify the fault based on the error information in the ascend log."},
308 {507011, "Model execution failed. \n\308 {507011, "Model execution failed. \n\
309 Rectify the fault based on the error information in the ascend log."},309 Rectify the fault based on the error information in the ascend log."},
310 {507012, "Failed to obtain the task scheduler message. \n\310 {507012, "Failed to obtain the task scheduler message. \n\
311 Rectify the fault based on the error information in the ascend log."},311 Rectify the fault based on the error information in the ascend log."},
312 {507013, "System Direct Memory Access (DMA) hardware execution error. \n\312 {507013, "System Direct Memory Access (DMA) hardware execution error. \n\
313 Rectify the fault based on the error information in the ascend log."},313 Rectify the fault based on the error information in the ascend log."},
314 {507014, "The aicore execution times out. \n\314 {507014, "The aicore execution times out. \n\
315 Rectify the fault based on the error information in the ascend log."},315 Rectify the fault based on the error information in the ascend log."},
316 {507015, "The aicore execution is abnormal. \n\316 {507015, "The aicore execution is abnormal. \n\
317 Rectify the fault based on the error information in the ascend log."},317 Rectify the fault based on the error information in the ascend log."},
318 {507016, "An exception occurs when the aicore trap is executed. \n\318 {507016, "An exception occurs when the aicore trap is executed. \n\
319 Rectify the fault based on the error information in the ascend log."},319 Rectify the fault based on the error information in the ascend log."},
320 {507017, "The aicpu execution times out. \n\320 {507017, "The aicpu execution times out. \n\
321 Rectify the fault based on the error information in the ascend log."},321 Rectify the fault based on the error information in the ascend log."},
322 {507018, "The aicpu execution is abnormal. \n\322 {507018, "The aicpu execution is abnormal. \n\
323 Rectify the fault based on the error information in the ascend log."},323 Rectify the fault based on the error information in the ascend log."},
324 {507019, "The AICPU does not send a response to the task scheduler after data dump. \n\324 {507019, "The AICPU does not send a response to the task scheduler after data dump. \n\
325 Rectify the fault based on the error information in the ascend log."},325 Rectify the fault based on the error information in the ascend log."},
326 {507020, "The AIPPU does not send a response to the task scheduler after executing the model. \n\326 {507020, "The AIPPU does not send a response to the task scheduler after executing the model. \n\
327 Rectify the fault based on the error information in the ascend log."},327 Rectify the fault based on the error information in the ascend log."},
328 {507021, "The profiling function is abnormal. \n\328 {507021, "The profiling function is abnormal. \n\
329 Rectify the fault based on the error information in the ascend log."},329 Rectify the fault based on the error information in the ascend log."},
330 {507022, "The communication between processes is abnormal. \n\330 {507022, "The communication between processes is abnormal. \n\
331 Rectify the fault based on the error information in the ascend log."},331 Rectify the fault based on the error information in the ascend log."},
332 {507023, "The model exits. \n\332 {507023, "The model exits. \n\
333 Rectify the fault based on the error information in the ascend log."},333 Rectify the fault based on the error information in the ascend log."},
334 {507024, "The operator is being deregistered. \n\334 {507024, "The operator is being deregistered. \n\
335 Rectify the fault based on the error information in the ascend log."},335 Rectify the fault based on the error information in the ascend log."},
336 {507025, "The ring buffer function is not initialized. \n\336 {507025, "The ring buffer function is not initialized. \n\
337 Rectify the fault based on the error information in the ascend log."},337 Rectify the fault based on the error information in the ascend log."},
338 {507026, "The ring buffer has no data. \n\338 {507026, "The ring buffer has no data. \n\
339 Rectify the fault based on the error information in the ascend log."},339 Rectify the fault based on the error information in the ascend log."},
340 {507027, "The kernel in RUNTIME is not registered. \n\340 {507027, "The kernel in RUNTIME is not registered. \n\
341 Rectify the fault based on the error information in the ascend log."},341 Rectify the fault based on the error information in the ascend log."},
342 {507028, "Repeatedly register the kernel inside the RUNTIME. \n\342 {507028, "Repeatedly register the kernel inside the RUNTIME. \n\
343 Rectify the fault based on the error information in the ascend log."},343 Rectify the fault based on the error information in the ascend log."},
344 {507029, "The debug function failed to be registered. \n\344 {507029, "The debug function failed to be registered. \n\
345 Rectify the fault based on the error information in the ascend log."},345 Rectify the fault based on the error information in the ascend log."},
346 {507030, "Deregistration of the debugging function fails. \n\346 {507030, "Deregistration of the debugging function fails. \n\
347 Rectify the fault based on the error information in the ascend log."},347 Rectify the fault based on the error information in the ascend log."},
348 {507031, "The tag is not in the current context. \n\348 {507031, "The tag is not in the current context. \n\
349 Rectify the fault based on the error information in the ascend log."},349 Rectify the fault based on the error information in the ascend log."},
350 {507032, "The number of registered programs exceeds the upper limit. \n\350 {507032, "The number of registered programs exceeds the upper limit. \n\
351 Rectify the fault based on the error information in the ascend log."},351 Rectify the fault based on the error information in the ascend log."},
352 {507033, "Failed to start the device. \n\352 {507033, "Failed to start the device. \n\
353 Rectify the fault based on the error information in the ascend log."},353 Rectify the fault based on the error information in the ascend log."},
354 {507034, "Vector core execution timed out. \n\354 {507034, "Vector core execution timed out. \n\
355 Rectify the fault based on the error information in the ascend log."},355 Rectify the fault based on the error information in the ascend log."},
356 {507035, "The vector core execution is abnormal. \n\356 {507035, "The vector core execution is abnormal. \n\
357 Rectify the fault based on the error information in the ascend log."},357 Rectify the fault based on the error information in the ascend log."},
358 {507036, "An exception occurs when vector core traps are executed. \n\358 {507036, "An exception occurs when vector core traps are executed. \n\
359 Rectify the fault based on the error information in the ascend log."},359 Rectify the fault based on the error information in the ascend log."},
360 {507037, "An exception occurred when applying for internal resources of the Runtime. \n\360 {507037, "An exception occurred when applying for internal resources of the Runtime. \n\
361 Rectify the fault based on the error information in the ascend log."},361 Rectify the fault based on the error information in the ascend log."},
362 {507038, "An error occurred when modifying the die mode, can not change the die mode. \n\362 {507038, "An error occurred when modifying the die mode, can not change the die mode. \n\
363 Rectify the fault based on the error information in the ascend log."},363 Rectify the fault based on the error information in the ascend log."},
364 {507039, "The die cannot be specified in single-die mode. \n\364 {507039, "The die cannot be specified in single-die mode. \n\
365 Rectify the fault based on the error information in the ascend log."},365 Rectify the fault based on the error information in the ascend log."},
366 {507040, "The specified die ID is incorrect. \n\366 {507040, "The specified die ID is incorrect. \n\
367 Rectify the fault based on the error information in the ascend log."},367 Rectify the fault based on the error information in the ascend log."},
368 {507041, "The die mode is not set. \n\368 {507041, "The die mode is not set. \n\
369 Rectify the fault based on the error information in the ascend log."},369 Rectify the fault based on the error information in the ascend log."},
370 {507042, "The aicore trap read out-of-bounds exception. \n\370 {507042, "The aicore trap read out-of-bounds exception. \n\
371 Rectify the fault based on the error information in the ascend log."},371 Rectify the fault based on the error information in the ascend log."},
372 {507043, "The aicore trap write out-of-bounds exception. \n\372 {507043, "The aicore trap write out-of-bounds exception. \n\
373 Rectify the fault based on the error information in the ascend log."},373 Rectify the fault based on the error information in the ascend log."},
374 {507044, "Vector core trap read out-of-bounds exception. \n\374 {507044, "Vector core trap read out-of-bounds exception. \n\
375 Rectify the fault based on the error information in the ascend log."},375 Rectify the fault based on the error information in the ascend log."},
376 {507045, "Vector core trap write out-of-bounds exception. \n\376 {507045, "Vector core trap write out-of-bounds exception. \n\
377 Rectify the fault based on the error information in the ascend log."},377 Rectify the fault based on the error information in the ascend log."},
378 {507046, "In the specified timeout waiting event, all tasks in the specified stream are not completed. \n\378 {507046, "In the specified timeout waiting event, all tasks in the specified stream are not completed. \n\
379 Rectify the fault based on the error information in the ascend log."},379 Rectify the fault based on the error information in the ascend log."},
380 {507047, "During the specified event synchronization waiting time, the event is not executed completely. \n\380 {507047, "During the specified event synchronization waiting time, the event is not executed completely. \n\
381 Rectify the fault based on the error information in the ascend log."},381 Rectify the fault based on the error information in the ascend log."},
382 {507048, "The execution of the internal task times out. \n\382 {507048, "The execution of the internal task times out. \n\
383 Rectify the fault based on the error information in the ascend log."},383 Rectify the fault based on the error information in the ascend log."},
384 {507049, "An exception occurs during the execution of an internal task. \n\384 {507049, "An exception occurs during the execution of an internal task. \n\
385 Rectify the fault based on the error information in the ascend log."},385 Rectify the fault based on the error information in the ascend log."},
386 {507050, "The trap of the internal task is abnormal. \n\386 {507050, "The trap of the internal task is abnormal. \n\
387 Rectify the fault based on the error information in the ascend log."},387 Rectify the fault based on the error information in the ascend log."},
388 {507051, "Messages fail to be sent during data enqueuing. \n\388 {507051, "Messages fail to be sent during data enqueuing. \n\
389 Rectify the fault based on the error information in the ascend log."},389 Rectify the fault based on the error information in the ascend log."},
390 {507052, "Memory copy fails during data enqueuing. \n\390 {507052, "Memory copy fails during data enqueuing. \n\
391 Rectify the fault based on the error information in the ascend log."},391 Rectify the fault based on the error information in the ascend log."},
392 {507899, "An internal error occurs in the Driver module. \n\392 {507899, "An internal error occurs in the Driver module. \n\
393 Rectify the fault based on the error information in the ascend log."},393 Rectify the fault based on the error information in the ascend log."},
394 {507900, "An internal error occurs on the AI CPU module. \n\394 {507900, "An internal error occurs on the AI CPU module. \n\
395 Rectify the fault based on the error information in the ascend log."},395 Rectify the fault based on the error information in the ascend log."},
396 {507901, "The internal host device communication (HDC) session is disconnected. \n\396 {507901, "The internal host device communication (HDC) session is disconnected. \n\
397 Rectify the fault based on the error information in the ascend log."},397 Rectify the fault based on the error information in the ascend log."},
398 }; /* aclError code */398 }; /* aclError code */
399};399};
400} /* c10_npu::acl */400} /* c10_npu::acl */
Mtorch_npu/csrc/core/npu/NpuVariables.cpp+0-1
@@ -115,4 +115,3 @@ bool IsAclnnOnly()
115 return GetSocVersion() >= SocVersion::Ascend950;115 return GetSocVersion() >= SocVersion::Ascend950;
116}116}
117} // namespace c10_npu117} // namespace c10_npu
118 
Mtorch_npu/csrc/core/npu/NpuVariables.h+0-1
@@ -45,4 +45,3 @@ bool IsBF16Supported();
45bool IsAclnnOnly();45bool IsAclnnOnly();
46} // namespace c10_npu46} // namespace c10_npu
47#endif47#endif
48 
Mtorch_npu/csrc/distributed/CMakeLists.txt+11-11
@@ -1,12 +1,12 @@
1if (DEFINED BUILD_LIBTORCH)1if (DEFINED BUILD_LIBTORCH)
2 FILE(GLOB _DIST_SRCS *.cpp)2 FILE(GLOB _DIST_SRCS *.cpp)
3 # Exclude Python binding files when building libtorch3 # Exclude Python binding files when building libtorch
4 list(REMOVE_ITEM _DIST_SRCS "${CMAKE_CURRENT_SOURCE_DIR}/Init.cpp")4 list(REMOVE_ITEM _DIST_SRCS "${CMAKE_CURRENT_SOURCE_DIR}/Init.cpp")
5else()5else()
6 FILE(GLOB _DIST_SRCS *.cpp rpc/*.cpp symm_mem/*.cpp)6 FILE(GLOB _DIST_SRCS *.cpp rpc/*.cpp symm_mem/*.cpp)
7endif()7endif()
8 8 
9LIST(APPEND DIST_SRCS ${_DIST_SRCS})9LIST(APPEND DIST_SRCS ${_DIST_SRCS})
10 10 
11# Pass to parent11# Pass to parent
12set(DIST_SRCS ${DIST_SRCS} PARENT_SCOPE)12set(DIST_SRCS ${DIST_SRCS} PARENT_SCOPE)
Mtorch_npu/csrc/distributed/HCCLUtils.cpp+311-311
@@ -1,311 +1,311 @@
1#include <filesystem>1#include <filesystem>
2#include <fstream>2#include <fstream>
3#include <string>3#include <string>
4 4 
5#include <torch/csrc/distributed/c10d/Utils.hpp>5#include <torch/csrc/distributed/c10d/Utils.hpp>
6 6 
7#include "torch_npu/csrc/core/npu/interface/HcclInterface.h"7#include "torch_npu/csrc/core/npu/interface/HcclInterface.h"
8#include "torch_npu/csrc/distributed/HCCLUtils.hpp"8#include "torch_npu/csrc/distributed/HCCLUtils.hpp"
9 9 
10 10 
11namespace c10d_npu {11namespace c10d_npu {
12bool isFileExists(const std::string& path)12bool isFileExists(const std::string& path)
13{13{
14 std::filesystem::path filePath(path);14 std::filesystem::path filePath(path);
15 15 
16 if (!filePath.is_absolute()) {16 if (!filePath.is_absolute()) {
17 TORCH_CHECK(false, "Path is not absolute.", DIST_ERROR(ErrCode::UNAVAIL))17 TORCH_CHECK(false, "Path is not absolute.", DIST_ERROR(ErrCode::UNAVAIL))
18 return false;18 return false;
19 }19 }
20 20 
21 if (std::filesystem::exists(filePath) && std::filesystem::is_regular_file(filePath)) {21 if (std::filesystem::exists(filePath) && std::filesystem::is_regular_file(filePath)) {
22 return true;22 return true;
23 } else {23 } else {
24 return false;24 return false;
25 }25 }
26}26}
27 27 
28bool checkFilePathReadable(const std::string& file)28bool checkFilePathReadable(const std::string& file)
29{29{
30 std::filesystem::path filePath(file);30 std::filesystem::path filePath(file);
31 31 
32 if (!std::filesystem::exists(filePath)) {32 if (!std::filesystem::exists(filePath)) {
33 return false;33 return false;
34 }34 }
35 35 
36 if (std::filesystem::is_symlink(filePath)) {36 if (std::filesystem::is_symlink(filePath)) {
37 return false;37 return false;
38 }38 }
39 39 
40 if (!std::filesystem::is_regular_file(filePath)) {40 if (!std::filesystem::is_regular_file(filePath)) {
41 return false;41 return false;
42 }42 }
43 43 
44 std::filesystem::perms perms = std::filesystem::status(filePath).permissions();44 std::filesystem::perms perms = std::filesystem::status(filePath).permissions();
45 if ((perms & std::filesystem::perms::owner_read) == std::filesystem::perms::owner_read) {45 if ((perms & std::filesystem::perms::owner_read) == std::filesystem::perms::owner_read) {
46 return true;46 return true;
47 }47 }
48 return false;48 return false;
49}49}
50 50 
51// HCCL DataType mapping51// HCCL DataType mapping
52std::map<at::ScalarType, HcclDataType> kScalarTypeToHcclDataType = {52std::map<at::ScalarType, HcclDataType> kScalarTypeToHcclDataType = {
53 {at::kByte, HCCL_DATA_TYPE_UINT8},53 {at::kByte, HCCL_DATA_TYPE_UINT8},
54 {at::kChar, HCCL_DATA_TYPE_INT8},54 {at::kChar, HCCL_DATA_TYPE_INT8},
55 {at::kShort, HCCL_DATA_TYPE_INT16},55 {at::kShort, HCCL_DATA_TYPE_INT16},
56 {at::kInt, HCCL_DATA_TYPE_INT32},56 {at::kInt, HCCL_DATA_TYPE_INT32},
57 {at::kLong, HCCL_DATA_TYPE_INT64},57 {at::kLong, HCCL_DATA_TYPE_INT64},
58 {at::kHalf, HCCL_DATA_TYPE_FP16},58 {at::kHalf, HCCL_DATA_TYPE_FP16},
59 {at::kFloat, HCCL_DATA_TYPE_FP32},59 {at::kFloat, HCCL_DATA_TYPE_FP32},
60 {at::ScalarType::UInt16, HCCL_DATA_TYPE_UINT16},60 {at::ScalarType::UInt16, HCCL_DATA_TYPE_UINT16},
61 {at::ScalarType::UInt32, HCCL_DATA_TYPE_UINT32},61 {at::ScalarType::UInt32, HCCL_DATA_TYPE_UINT32},
62 {at::ScalarType::UInt64, HCCL_DATA_TYPE_UINT64},62 {at::ScalarType::UInt64, HCCL_DATA_TYPE_UINT64},
63 {at::kDouble, HCCL_DATA_TYPE_FP64},63 {at::kDouble, HCCL_DATA_TYPE_FP64},
64 {at::kBool, HCCL_DATA_TYPE_UINT8},64 {at::kBool, HCCL_DATA_TYPE_UINT8},
65 {at::kBFloat16, HCCL_DATA_TYPE_BFP16},65 {at::kBFloat16, HCCL_DATA_TYPE_BFP16},
66 {at::ScalarType::Float8_e4m3fn, HCCL_DATA_TYPE_FP8E4M3},66 {at::ScalarType::Float8_e4m3fn, HCCL_DATA_TYPE_FP8E4M3},
67 {at::ScalarType::Float8_e5m2, HCCL_DATA_TYPE_FP8E5M2},67 {at::ScalarType::Float8_e5m2, HCCL_DATA_TYPE_FP8E5M2},
68};68};
69 69 
70std::map<HcclDataType, std::string> kHcclDataTypeToStringMap = {70std::map<HcclDataType, std::string> kHcclDataTypeToStringMap = {
71 {HCCL_DATA_TYPE_UINT8, "at::kByte/at::kBool"},71 {HCCL_DATA_TYPE_UINT8, "at::kByte/at::kBool"},
72 {HCCL_DATA_TYPE_INT8, "at::kChar"},72 {HCCL_DATA_TYPE_INT8, "at::kChar"},
73 {HCCL_DATA_TYPE_INT16, "at::kShort"},73 {HCCL_DATA_TYPE_INT16, "at::kShort"},
74 {HCCL_DATA_TYPE_INT32, "at::kInt"},74 {HCCL_DATA_TYPE_INT32, "at::kInt"},
75 {HCCL_DATA_TYPE_UINT16, "at::ScalarType::UInt16"},75 {HCCL_DATA_TYPE_UINT16, "at::ScalarType::UInt16"},
76 {HCCL_DATA_TYPE_UINT32, "at::ScalarType::UInt32"},76 {HCCL_DATA_TYPE_UINT32, "at::ScalarType::UInt32"},
77 {HCCL_DATA_TYPE_UINT64, "at::ScalarType::UInt64"},77 {HCCL_DATA_TYPE_UINT64, "at::ScalarType::UInt64"},
78 {HCCL_DATA_TYPE_INT64, "at::kLong"},78 {HCCL_DATA_TYPE_INT64, "at::kLong"},
79 {HCCL_DATA_TYPE_FP16, "at::kHalf"},79 {HCCL_DATA_TYPE_FP16, "at::kHalf"},
80 {HCCL_DATA_TYPE_FP32, "at::kFloat"},80 {HCCL_DATA_TYPE_FP32, "at::kFloat"},
81 {HCCL_DATA_TYPE_FP64, "at::kDouble"},81 {HCCL_DATA_TYPE_FP64, "at::kDouble"},
82 {HCCL_DATA_TYPE_BFP16, "at::kBFloat16"},82 {HCCL_DATA_TYPE_BFP16, "at::kBFloat16"},
83 {HCCL_DATA_TYPE_FP8E4M3, "at::ScalarType::Float8_e4m3fn"},83 {HCCL_DATA_TYPE_FP8E4M3, "at::ScalarType::Float8_e4m3fn"},
84 {HCCL_DATA_TYPE_FP8E5M2, "at::ScalarType::Float8_e5m2"},84 {HCCL_DATA_TYPE_FP8E5M2, "at::ScalarType::Float8_e5m2"},
85};85};
86 86 
87// Helper function that gets the data type and issues error if not supported87// Helper function that gets the data type and issues error if not supported
88HcclDataType getHcclDataType(at::ScalarType type)88HcclDataType getHcclDataType(at::ScalarType type)
89{89{
90 try {90 try {
91 return kScalarTypeToHcclDataType.at(type);91 return kScalarTypeToHcclDataType.at(type);
92 } catch (std::out_of_range& e) {92 } catch (std::out_of_range& e) {
93 throw std::runtime_error("Unsupported data type for HCCL process group" + DIST_ERROR(ErrCode::NOT_SUPPORT));93 throw std::runtime_error("Unsupported data type for HCCL process group" + DIST_ERROR(ErrCode::NOT_SUPPORT));
94 }94 }
95}95}
96 96 
97std::string getHcclDataTypeSerialString(HcclDataType type)97std::string getHcclDataTypeSerialString(HcclDataType type)
98{98{
99 const auto& iter = kHcclDataTypeToStringMap.find(type);99 const auto& iter = kHcclDataTypeToStringMap.find(type);
100 if (iter != kHcclDataTypeToStringMap.cend()) {100 if (iter != kHcclDataTypeToStringMap.cend()) {
101 return iter->second;101 return iter->second;
102 } else {102 } else {
103 TORCH_NPU_WARN_ONCE("Can not serialize undefined hccl data type.");103 TORCH_NPU_WARN_ONCE("Can not serialize undefined hccl data type.");
104 return "";104 return "";
105 }105 }
106}106}
107 107 
108bool isSupportHcclCommName()108bool isSupportHcclCommName()
109{109{
110 return at_npu::hccl::isHcclFeatureSupported(HcclCommConfigCapability::HCCL_COMM_CONFIG_COMM_NAME);110 return at_npu::hccl::isHcclFeatureSupported(HcclCommConfigCapability::HCCL_COMM_CONFIG_COMM_NAME);
111}111}
112 112 
113HCCLComm::HCCLComm(HcclComm hcclComm) : hcclComm_(hcclComm), hcclAsyncErr_(HCCL_SUCCESS),113HCCLComm::HCCLComm(HcclComm hcclComm) : hcclComm_(hcclComm), hcclAsyncErr_(HCCL_SUCCESS),
114 hcclCommType(0), p2pPeer(0) {}114 hcclCommType(0), p2pPeer(0) {}
115 115
116HCCLComm::~HCCLComm()116HCCLComm::~HCCLComm()
117{117{
118 destroyHcclComm();118 destroyHcclComm();
119}119}
120 120 
121std::shared_ptr<HCCLComm> HCCLComm::create(121std::shared_ptr<HCCLComm> HCCLComm::create(
122 int numRanks,122 int numRanks,
123 int rank,123 int rank,
124 HcclRootInfo& rootInfo)124 HcclRootInfo& rootInfo)
125{125{
126 auto comm = std::make_shared<HCCLComm>();126 auto comm = std::make_shared<HCCLComm>();
127 HCCL_CHECK_ERROR(hcclCommInitRootInfo(numRanks, &rootInfo, rank, &(comm->hcclComm_)));127 HCCL_CHECK_ERROR(hcclCommInitRootInfo(numRanks, &rootInfo, rank, &(comm->hcclComm_)));
128 c10_npu::NpuSysCtrl::GetInstance().RegisterReleaseFn([=]() ->void {comm->destroyHcclComm();},128 c10_npu::NpuSysCtrl::GetInstance().RegisterReleaseFn([=]() ->void {comm->destroyHcclComm();},
129 c10_npu::ReleasePriority::PriorityMiddle);129 c10_npu::ReleasePriority::PriorityMiddle);
130 return comm;130 return comm;
131}131}
132 132 
133std::shared_ptr<HCCLComm> HCCLComm::create_config(133std::shared_ptr<HCCLComm> HCCLComm::create_config(
134 int numRanks,134 int numRanks,
135 int rank,135 int rank,
136 HcclRootInfo& rootInfo,136 HcclRootInfo& rootInfo,
137 HcclCommConfig* config)137 HcclCommConfig* config)
138{138{
139 auto comm = std::make_shared<HCCLComm>();139 auto comm = std::make_shared<HCCLComm>();
140 HCCL_CHECK_ERROR(hcclCommInitRootInfoConfig(numRanks, &rootInfo, rank, config, &(comm->hcclComm_)));140 HCCL_CHECK_ERROR(hcclCommInitRootInfoConfig(numRanks, &rootInfo, rank, config, &(comm->hcclComm_)));
141 c10_npu::NpuSysCtrl::GetInstance().RegisterReleaseFn([=]() ->void {comm->destroyHcclComm();},141 c10_npu::NpuSysCtrl::GetInstance().RegisterReleaseFn([=]() ->void {comm->destroyHcclComm();},
142 c10_npu::ReleasePriority::PriorityMiddle);142 c10_npu::ReleasePriority::PriorityMiddle);
143 return comm;143 return comm;
144}144}
145 145 
146std::shared_ptr<HCCLComm> HCCLComm::createGlobalHcclComm(146std::shared_ptr<HCCLComm> HCCLComm::createGlobalHcclComm(
147 const char *clusterInfo,147 const char *clusterInfo,
148 uint32_t rank,148 uint32_t rank,
149 HcclCommConfig* config)149 HcclCommConfig* config)
150{150{
151 auto comm = std::make_shared<HCCLComm>();151 auto comm = std::make_shared<HCCLComm>();
152 if (hcclCommInitClusterInfoConfig(clusterInfo, rank, config, &(comm->hcclComm_)) != HCCL_SUCCESS) {152 if (hcclCommInitClusterInfoConfig(clusterInfo, rank, config, &(comm->hcclComm_)) != HCCL_SUCCESS) {
153 return nullptr;153 return nullptr;
154 }154 }
155 c10_npu::NpuSysCtrl::GetInstance().RegisterReleaseFn([=]() ->void {comm->destroyHcclComm();},155 c10_npu::NpuSysCtrl::GetInstance().RegisterReleaseFn([=]() ->void {comm->destroyHcclComm();},
156 c10_npu::ReleasePriority::PriorityMiddle);156 c10_npu::ReleasePriority::PriorityMiddle);
157 return comm;157 return comm;
158}158}
159 159 
160std::shared_ptr<HCCLComm> HCCLComm::createSubHcclComm(160std::shared_ptr<HCCLComm> HCCLComm::createSubHcclComm(
161 std::shared_ptr<HCCLComm> comm,161 std::shared_ptr<HCCLComm> comm,
162 uint32_t rankNum,162 uint32_t rankNum,
163 uint32_t *rankIds,163 uint32_t *rankIds,
164 uint64_t subCommId,164 uint64_t subCommId,
165 uint32_t subCommRankId,165 uint32_t subCommRankId,
166 HcclCommConfig* config)166 HcclCommConfig* config)
167{167{
168 auto subComm = std::make_shared<HCCLComm>();168 auto subComm = std::make_shared<HCCLComm>();
169 if (hcclCreateSubCommConfig(&(comm->hcclComm_), rankNum, rankIds, subCommId, subCommRankId,169 if (hcclCreateSubCommConfig(&(comm->hcclComm_), rankNum, rankIds, subCommId, subCommRankId,
170 config, &(subComm->hcclComm_)) != HCCL_SUCCESS) {170 config, &(subComm->hcclComm_)) != HCCL_SUCCESS) {
171 return nullptr;171 return nullptr;
172 }172 }
173 c10_npu::NpuSysCtrl::GetInstance().RegisterReleaseFn([=]() ->void {subComm->destroyHcclComm();},173 c10_npu::NpuSysCtrl::GetInstance().RegisterReleaseFn([=]() ->void {subComm->destroyHcclComm();},
174 c10_npu::ReleasePriority::PriorityMiddle);174 c10_npu::ReleasePriority::PriorityMiddle);
175 return subComm;175 return subComm;
176}176}
177 177 
178// Move constructable178// Move constructable
179HCCLComm::HCCLComm(HCCLComm&& other)179HCCLComm::HCCLComm(HCCLComm&& other)
180{180{
181 std::swap(hcclComm_, other.hcclComm_);181 std::swap(hcclComm_, other.hcclComm_);
182 std::swap(hcclAsyncErr_, other.hcclAsyncErr_);182 std::swap(hcclAsyncErr_, other.hcclAsyncErr_);
183 std::swap(hcclCommType, other.hcclCommType);183 std::swap(hcclCommType, other.hcclCommType);
184 std::swap(p2pPeer, other.p2pPeer);184 std::swap(p2pPeer, other.p2pPeer);
185}185}
186 186 
187// Move assignable187// Move assignable
188HCCLComm& HCCLComm::operator=(HCCLComm&& other)188HCCLComm& HCCLComm::operator=(HCCLComm&& other)
189{189{
190 std::swap(hcclComm_, other.hcclComm_);190 std::swap(hcclComm_, other.hcclComm_);
191 std::swap(hcclAsyncErr_, other.hcclAsyncErr_);191 std::swap(hcclAsyncErr_, other.hcclAsyncErr_);
192 std::swap(hcclCommType, other.hcclCommType);192 std::swap(hcclCommType, other.hcclCommType);
193 std::swap(p2pPeer, other.p2pPeer);193 std::swap(p2pPeer, other.p2pPeer);
194 return *this;194 return *this;
195}195}
196 196 
197void HCCLComm::destroyHcclComm()197void HCCLComm::destroyHcclComm()
198{198{
199 std::unique_lock<std::mutex> lock(mutex_);199 std::unique_lock<std::mutex> lock(mutex_);
200 if (hcclComm_) {200 if (hcclComm_) {
201 hcclCommDestroy(hcclComm_);201 hcclCommDestroy(hcclComm_);
202 hcclComm_ = nullptr;202 hcclComm_ = nullptr;
203 }203 }
204}204}
205 205 
206HcclResult HCCLComm::checkForHcclError()206HcclResult HCCLComm::checkForHcclError()
207{207{
208 std::unique_lock<std::mutex> lock(mutex_);208 std::unique_lock<std::mutex> lock(mutex_);
209#ifdef ENABLE_HCCL_ERROR_CHECKING209#ifdef ENABLE_HCCL_ERROR_CHECKING
210 if (hcclAsyncErr_ != HCCL_SUCCESS) {210 if (hcclAsyncErr_ != HCCL_SUCCESS) {
211 return hcclAsyncErr_;211 return hcclAsyncErr_;
212 }212 }
213 if (hcclComm_ != nullptr) {213 if (hcclComm_ != nullptr) {
214 HcclResult result = hcclGetCommAsyncError(hcclComm_, &hcclAsyncErr_);214 HcclResult result = hcclGetCommAsyncError(hcclComm_, &hcclAsyncErr_);
215 if (result != HCCL_SUCCESS) {215 if (result != HCCL_SUCCESS) {
216 std::string temp_str = std::string("Failed to get HCCL error code: ") + std::to_string(result);216 std::string temp_str = std::string("Failed to get HCCL error code: ") + std::to_string(result);
217 const char* errmsg = temp_str.c_str();217 const char* errmsg = temp_str.c_str();
218 ASCEND_LOGE("%s", errmsg);218 ASCEND_LOGE("%s", errmsg);
219 LOG(ERROR) << c10::str(errmsg);219 LOG(ERROR) << c10::str(errmsg);
220 return result; // return this error result instead of hcclAsyncErr_220 return result; // return this error result instead of hcclAsyncErr_
221 }221 }
222 }222 }
223 return hcclAsyncErr_;223 return hcclAsyncErr_;
224#else224#else
225 // Always return success, if error checks are disabled.225 // Always return success, if error checks are disabled.
226 return HCCL_SUCCESS;226 return HCCL_SUCCESS;
227#endif227#endif
228}228}
229 229 
230void DebugInfoWriter::write(const std::string &hcclTrace)230void DebugInfoWriter::write(const std::string &hcclTrace)
231{231{
232 // Open a file for writing. The ios::binary flag is used to write data as232 // Open a file for writing. The ios::binary flag is used to write data as
233 // binary.233 // binary.
234 std::ofstream file(filename_, std::ios::binary);234 std::ofstream file(filename_, std::ios::binary);
235 235 
236 // Check if the file was opened successfully.236 // Check if the file was opened successfully.
237 if (!file.is_open()) {237 if (!file.is_open()) {
238 LOG(ERROR) << "Error opening file for writing HCCLPG debug info: "238 LOG(ERROR) << "Error opening file for writing HCCLPG debug info: "
239 << filename_;239 << filename_;
240 return;240 return;
241 }241 }
242 242 
243 file.write(hcclTrace.data(), hcclTrace.size());243 file.write(hcclTrace.data(), hcclTrace.size());
244 LOG(INFO) << "Finished writing HCCLPG debug info to " << filename_;244 LOG(INFO) << "Finished writing HCCLPG debug info to " << filename_;
245}245}
246 246 
247DebugInfoWriter &DebugInfoWriter::getWriter(int rank)247DebugInfoWriter &DebugInfoWriter::getWriter(int rank)
248{248{
249 if (writer_ == nullptr) {249 if (writer_ == nullptr) {
250 std::string fileNamePrefix = c10d::getCvarString(250 std::string fileNamePrefix = c10d::getCvarString(
251 {"TORCH_HCCL_DEBUG_INFO_TEMP_FILE"}, "/tmp/hccl_trace_rank_");251 {"TORCH_HCCL_DEBUG_INFO_TEMP_FILE"}, "/tmp/hccl_trace_rank_");
252 // Using std::unique_ptr here to auto-delete the writer object252 // Using std::unique_ptr here to auto-delete the writer object
253 // when the pointer itself is destroyed.253 // when the pointer itself is destroyed.
254 std::unique_ptr<DebugInfoWriter> writerPtr(254 std::unique_ptr<DebugInfoWriter> writerPtr(
255 new DebugInfoWriter(fileNamePrefix, rank));255 new DebugInfoWriter(fileNamePrefix, rank));
256 DebugInfoWriter::registerWriter(std::move(writerPtr));256 DebugInfoWriter::registerWriter(std::move(writerPtr));
257 }257 }
258 return *writer_;258 return *writer_;
259}259}
260 260 
261void DebugInfoWriter::registerWriter(std::unique_ptr<DebugInfoWriter> writer)261void DebugInfoWriter::registerWriter(std::unique_ptr<DebugInfoWriter> writer)
262{262{
263 TORCH_CHECK_WITH(263 TORCH_CHECK_WITH(
264 DistBackendError,264 DistBackendError,
265 !hasWriterRegistered_.load(),265 !hasWriterRegistered_.load(),
266 "debugInfoWriter already registered");266 "debugInfoWriter already registered");
267 hasWriterRegistered_.store(true);267 hasWriterRegistered_.store(true);
268 writer_ = std::move(writer);268 writer_ = std::move(writer);
269}269}
270 270 
271std::unique_ptr<DebugInfoWriter> DebugInfoWriter::writer_ = nullptr;271std::unique_ptr<DebugInfoWriter> DebugInfoWriter::writer_ = nullptr;
272std::atomic<bool> DebugInfoWriter::hasWriterRegistered_(false);272std::atomic<bool> DebugInfoWriter::hasWriterRegistered_(false);
273 273 
274struct HcclBufferNameKey {274struct HcclBufferNameKey {
275 c10::DeviceIndex device_index;275 c10::DeviceIndex device_index;
276 std::string name;276 std::string name;
277 bool operator<(const HcclBufferNameKey& other) const277 bool operator<(const HcclBufferNameKey& other) const
278 {278 {
279 if (device_index != other.device_index) {279 if (device_index != other.device_index) {
280 return device_index < other.device_index;280 return device_index < other.device_index;
281 }281 }
282 return name < other.name; // sort by name if device_index is the same282 return name < other.name; // sort by name if device_index is the same
283 }283 }
284};284};
285 285 
286struct HcclBufferNameStreamMap {286struct HcclBufferNameStreamMap {
287 std::map<HcclBufferNameKey, c10_npu::NPUStream> map;287 std::map<HcclBufferNameKey, c10_npu::NPUStream> map;
288 std::mutex mutex;288 std::mutex mutex;
289} g_BufferNameStreamMap = {};289} g_BufferNameStreamMap = {};
290 290 
291c10::optional<c10_npu::NPUStream> getHcclStreamByBufferName(const std::string &name, c10::DeviceIndex device_index)291c10::optional<c10_npu::NPUStream> getHcclStreamByBufferName(const std::string &name, c10::DeviceIndex device_index)
292{292{
293 std::unique_lock<std::mutex> lock(g_BufferNameStreamMap.mutex);293 std::unique_lock<std::mutex> lock(g_BufferNameStreamMap.mutex);
294 auto &map = g_BufferNameStreamMap.map;294 auto &map = g_BufferNameStreamMap.map;
295 auto it = map.find({device_index, name});295 auto it = map.find({device_index, name});
296 if (it == map.end()) {296 if (it == map.end()) {
297 return {};297 return {};
298 }298 }
299 return it->second;299 return it->second;
300}300}
301 301 
302bool setHcclStreamByBufferName(const std::string &name, c10::DeviceIndex device_index, c10_npu::NPUStream steam)302bool setHcclStreamByBufferName(const std::string &name, c10::DeviceIndex device_index, c10_npu::NPUStream steam)
303{303{
304 HcclBufferNameKey key = {device_index, name};304 HcclBufferNameKey key = {device_index, name};
305 std::unique_lock<std::mutex> lock(g_BufferNameStreamMap.mutex);305 std::unique_lock<std::mutex> lock(g_BufferNameStreamMap.mutex);
306 auto &map = g_BufferNameStreamMap.map;306 auto &map = g_BufferNameStreamMap.map;
307 auto pair = map.insert({key, steam});307 auto pair = map.insert({key, steam});
308 return pair.second;308 return pair.second;
309}309}
310 310 
311} // namespace c10d_npu311} // namespace c10d_npu
Mtorch_npu/csrc/distributed/HcclCompile.h+496-496
@@ -1,496 +1,496 @@
1#pragma once1#pragma once
2 2 
3#include <c10/util/CallOnce.h>3#include <c10/util/CallOnce.h>
4#include "torch_npu/csrc/core/npu/NPUException.h"4#include "torch_npu/csrc/core/npu/NPUException.h"
5#include "torch_npu/csrc/core/npu/register/FunctionLoader.h"5#include "torch_npu/csrc/core/npu/register/FunctionLoader.h"
6#include "torch_npu/csrc/core/npu/NpuVariables.h"6#include "torch_npu/csrc/core/npu/NpuVariables.h"
7 7 
8namespace c10d_npu {8namespace c10d_npu {
9#undef TORCH_NPU_LOAD_FUNC9#undef TORCH_NPU_LOAD_FUNC
10#define TORCH_NPU_LOAD_FUNC(funcName) \10#define TORCH_NPU_LOAD_FUNC(funcName) \
11 TORCH_NPU_REGISTER_FUNCTION(libhccl, funcName)11 TORCH_NPU_REGISTER_FUNCTION(libhccl, funcName)
12 12 
13#undef TORCH_NPU_GET_FUNC13#undef TORCH_NPU_GET_FUNC
14#define TORCH_NPU_GET_FUNC(funcName) \14#define TORCH_NPU_GET_FUNC(funcName) \
15 TORCH_NPU_GET_FUNCTION(libhccl, funcName)15 TORCH_NPU_GET_FUNCTION(libhccl, funcName)
16 16 
17TORCH_NPU_REGISTER_LIBRARY(libhccl)17TORCH_NPU_REGISTER_LIBRARY(libhccl)
18TORCH_NPU_LOAD_FUNC(HcclAlltoAllV)18TORCH_NPU_LOAD_FUNC(HcclAlltoAllV)
19TORCH_NPU_LOAD_FUNC(HcclAllGatherV)19TORCH_NPU_LOAD_FUNC(HcclAllGatherV)
20TORCH_NPU_LOAD_FUNC(HcclReduceScatterV)20TORCH_NPU_LOAD_FUNC(HcclReduceScatterV)
21TORCH_NPU_LOAD_FUNC(HcclReduce)21TORCH_NPU_LOAD_FUNC(HcclReduce)
22TORCH_NPU_LOAD_FUNC(HcclGetCommAsyncError)22TORCH_NPU_LOAD_FUNC(HcclGetCommAsyncError)
23TORCH_NPU_LOAD_FUNC(HcclScatter)23TORCH_NPU_LOAD_FUNC(HcclScatter)
24TORCH_NPU_LOAD_FUNC(HcclBatchSendRecv)24TORCH_NPU_LOAD_FUNC(HcclBatchSendRecv)
25TORCH_NPU_LOAD_FUNC(HcclAlltoAll)25TORCH_NPU_LOAD_FUNC(HcclAlltoAll)
26TORCH_NPU_LOAD_FUNC(HcclCommInitRootInfoConfig)26TORCH_NPU_LOAD_FUNC(HcclCommInitRootInfoConfig)
27TORCH_NPU_LOAD_FUNC(HcclGetCommConfigCapability)27TORCH_NPU_LOAD_FUNC(HcclGetCommConfigCapability)
28TORCH_NPU_LOAD_FUNC(HcclCommInitClusterInfoConfig)28TORCH_NPU_LOAD_FUNC(HcclCommInitClusterInfoConfig)
29TORCH_NPU_LOAD_FUNC(HcclCreateSubCommConfig)29TORCH_NPU_LOAD_FUNC(HcclCreateSubCommConfig)
30TORCH_NPU_LOAD_FUNC(HcclCommWorkingDevNicSet)30TORCH_NPU_LOAD_FUNC(HcclCommWorkingDevNicSet)
31TORCH_NPU_LOAD_FUNC(HcclCommRegister)31TORCH_NPU_LOAD_FUNC(HcclCommRegister)
32TORCH_NPU_LOAD_FUNC(HcclCommDeregister)32TORCH_NPU_LOAD_FUNC(HcclCommDeregister)
33TORCH_NPU_LOAD_FUNC(HcclCommExchangeMem)33TORCH_NPU_LOAD_FUNC(HcclCommExchangeMem)
34TORCH_NPU_LOAD_FUNC(HcclGetRootInfo)34TORCH_NPU_LOAD_FUNC(HcclGetRootInfo)
35TORCH_NPU_LOAD_FUNC(HcclCommDestroy)35TORCH_NPU_LOAD_FUNC(HcclCommDestroy)
36TORCH_NPU_LOAD_FUNC(HcclSend)36TORCH_NPU_LOAD_FUNC(HcclSend)
37TORCH_NPU_LOAD_FUNC(HcclRecv)37TORCH_NPU_LOAD_FUNC(HcclRecv)
38TORCH_NPU_LOAD_FUNC(HcclAllReduce)38TORCH_NPU_LOAD_FUNC(HcclAllReduce)
39TORCH_NPU_LOAD_FUNC(HcclBroadcast)39TORCH_NPU_LOAD_FUNC(HcclBroadcast)
40TORCH_NPU_LOAD_FUNC(HcclAllGather)40TORCH_NPU_LOAD_FUNC(HcclAllGather)
41TORCH_NPU_LOAD_FUNC(HcclReduceScatter)41TORCH_NPU_LOAD_FUNC(HcclReduceScatter)
42TORCH_NPU_LOAD_FUNC(HcclCommInitAll)42TORCH_NPU_LOAD_FUNC(HcclCommInitAll)
43TORCH_NPU_LOAD_FUNC(HcclCommInitRootInfo)43TORCH_NPU_LOAD_FUNC(HcclCommInitRootInfo)
44 44 
45TORCH_NPU_REGISTER_LIBRARY(libhcomm)45TORCH_NPU_REGISTER_LIBRARY(libhcomm)
46TORCH_NPU_REGISTER_FUNCTION(libhcomm, HcclGroupStart)46TORCH_NPU_REGISTER_FUNCTION(libhcomm, HcclGroupStart)
47TORCH_NPU_REGISTER_FUNCTION(libhcomm, HcclGroupEnd)47TORCH_NPU_REGISTER_FUNCTION(libhcomm, HcclGroupEnd)
48 48 
49extern HcclResult hcclGetRootInfo(HcclRootInfo *rootInfo)49extern HcclResult hcclGetRootInfo(HcclRootInfo *rootInfo)
50{50{
51 using HcclGetRootInfoFunc = HcclResult(*)(HcclRootInfo *);51 using HcclGetRootInfoFunc = HcclResult(*)(HcclRootInfo *);
52 static HcclGetRootInfoFunc func = nullptr;52 static HcclGetRootInfoFunc func = nullptr;
53 if (func == nullptr) {53 if (func == nullptr) {
54 func = (HcclGetRootInfoFunc)TORCH_NPU_GET_FUNC(HcclGetRootInfo)54 func = (HcclGetRootInfoFunc)TORCH_NPU_GET_FUNC(HcclGetRootInfo)
55 }55 }
56 TORCH_CHECK(func, "Failed to find function ", "HcclGetRootInfo", DIST_ERROR(ErrCode::NOT_FOUND));56 TORCH_CHECK(func, "Failed to find function ", "HcclGetRootInfo", DIST_ERROR(ErrCode::NOT_FOUND));
57 auto ret = func(rootInfo);57 auto ret = func(rootInfo);
58 return ret;58 return ret;
59}59}
60 60 
61extern HcclResult hcclCommDestroy(HcclComm comm)61extern HcclResult hcclCommDestroy(HcclComm comm)
62{62{
63 using HcclCommDestroyFunc = HcclResult(*)(HcclComm);63 using HcclCommDestroyFunc = HcclResult(*)(HcclComm);
64 static HcclCommDestroyFunc func = nullptr;64 static HcclCommDestroyFunc func = nullptr;
65 if (func == nullptr) {65 if (func == nullptr) {
66 func = (HcclCommDestroyFunc)TORCH_NPU_GET_FUNC(HcclCommDestroy)66 func = (HcclCommDestroyFunc)TORCH_NPU_GET_FUNC(HcclCommDestroy)
67 }67 }
68 TORCH_CHECK(func, "Failed to find function ", "HcclCommDestroy", DIST_ERROR(ErrCode::NOT_FOUND));68 TORCH_CHECK(func, "Failed to find function ", "HcclCommDestroy", DIST_ERROR(ErrCode::NOT_FOUND));
69 auto ret = func(comm);69 auto ret = func(comm);
70 return ret;70 return ret;
71}71}
72 72 
73extern HcclResult hcclSend(void *sendBuf, uint64_t count, HcclDataType dataType, uint32_t destRank,73extern HcclResult hcclSend(void *sendBuf, uint64_t count, HcclDataType dataType, uint32_t destRank,
74 HcclComm comm, aclrtStream stream)74 HcclComm comm, aclrtStream stream)
75{75{
76 using HcclSendFunc = HcclResult(*)(76 using HcclSendFunc = HcclResult(*)(
77 void *, uint64_t, HcclDataType, uint32_t, HcclComm, aclrtStream);77 void *, uint64_t, HcclDataType, uint32_t, HcclComm, aclrtStream);
78 static HcclSendFunc func = nullptr;78 static HcclSendFunc func = nullptr;
79 if (func == nullptr) {79 if (func == nullptr) {
80 func = (HcclSendFunc)TORCH_NPU_GET_FUNC(HcclSend)80 func = (HcclSendFunc)TORCH_NPU_GET_FUNC(HcclSend)
81 }81 }
82 TORCH_CHECK(func, "Failed to find function ", "HcclSend", DIST_ERROR(ErrCode::NOT_FOUND));82 TORCH_CHECK(func, "Failed to find function ", "HcclSend", DIST_ERROR(ErrCode::NOT_FOUND));
83 auto ret = func(sendBuf, count, dataType, destRank, comm, stream);83 auto ret = func(sendBuf, count, dataType, destRank, comm, stream);
84 return ret;84 return ret;
85}85}
86 86 
87extern HcclResult hcclRecv(void *recvBuf, uint64_t count, HcclDataType dataType, uint32_t srcRank,87extern HcclResult hcclRecv(void *recvBuf, uint64_t count, HcclDataType dataType, uint32_t srcRank,
88 HcclComm comm, aclrtStream stream)88 HcclComm comm, aclrtStream stream)
89{89{
90 using HcclRecvFunc = HcclResult(*)(90 using HcclRecvFunc = HcclResult(*)(
91 void *, uint64_t, HcclDataType, uint32_t, HcclComm, aclrtStream);91 void *, uint64_t, HcclDataType, uint32_t, HcclComm, aclrtStream);
92 static HcclRecvFunc func = nullptr;92 static HcclRecvFunc func = nullptr;
93 if (func == nullptr) {93 if (func == nullptr) {
94 func = (HcclRecvFunc)TORCH_NPU_GET_FUNC(HcclRecv)94 func = (HcclRecvFunc)TORCH_NPU_GET_FUNC(HcclRecv)
95 }95 }
96 TORCH_CHECK(func, "Failed to find function ", "HcclRecv", DIST_ERROR(ErrCode::NOT_FOUND));96 TORCH_CHECK(func, "Failed to find function ", "HcclRecv", DIST_ERROR(ErrCode::NOT_FOUND));
97 auto ret = func(recvBuf, count, dataType, srcRank, comm, stream);97 auto ret = func(recvBuf, count, dataType, srcRank, comm, stream);
98 return ret;98 return ret;
99}99}
100 100 
101extern HcclResult hcclCommInitAll(uint32_t ndev, int32_t *devices, HcclComm *comms)101extern HcclResult hcclCommInitAll(uint32_t ndev, int32_t *devices, HcclComm *comms)
102{102{
103 using HcclCommInitAllFunc = HcclResult(*)(103 using HcclCommInitAllFunc = HcclResult(*)(
104 uint32_t, int32_t *, HcclComm *);104 uint32_t, int32_t *, HcclComm *);
105 static HcclCommInitAllFunc func = nullptr;105 static HcclCommInitAllFunc func = nullptr;
106 if (func == nullptr) {106 if (func == nullptr) {
107 func = (HcclCommInitAllFunc)TORCH_NPU_GET_FUNC(HcclCommInitAll)107 func = (HcclCommInitAllFunc)TORCH_NPU_GET_FUNC(HcclCommInitAll)
108 }108 }
109 TORCH_CHECK(func, "Failed to find function ", "HcclCommInitAll", DIST_ERROR(ErrCode::NOT_FOUND));109 TORCH_CHECK(func, "Failed to find function ", "HcclCommInitAll", DIST_ERROR(ErrCode::NOT_FOUND));
110 auto ret = func(ndev, devices, comms);110 auto ret = func(ndev, devices, comms);
111 return ret;111 return ret;
112}112}
113 113 
114extern HcclResult hcclAllGather(void *sendBuf, void *recvBuf, uint64_t sendCount, HcclDataType dataType,114extern HcclResult hcclAllGather(void *sendBuf, void *recvBuf, uint64_t sendCount, HcclDataType dataType,
115 HcclComm comm, aclrtStream stream)115 HcclComm comm, aclrtStream stream)
116{116{
117 using HcclAllGatherFunc = HcclResult(*)(117 using HcclAllGatherFunc = HcclResult(*)(
118 void *, void *, uint64_t, HcclDataType, HcclComm, aclrtStream);118 void *, void *, uint64_t, HcclDataType, HcclComm, aclrtStream);
119 static HcclAllGatherFunc func = nullptr;119 static HcclAllGatherFunc func = nullptr;
120 if (func == nullptr) {120 if (func == nullptr) {
121 func = (HcclAllGatherFunc)TORCH_NPU_GET_FUNC(HcclAllGather)121 func = (HcclAllGatherFunc)TORCH_NPU_GET_FUNC(HcclAllGather)
122 }122 }
123 TORCH_CHECK(func, "Failed to find function ", "HcclAllGather", DIST_ERROR(ErrCode::NOT_FOUND));123 TORCH_CHECK(func, "Failed to find function ", "HcclAllGather", DIST_ERROR(ErrCode::NOT_FOUND));
124 auto ret = func(sendBuf, recvBuf, sendCount, dataType, comm, stream);124 auto ret = func(sendBuf, recvBuf, sendCount, dataType, comm, stream);
125 return ret;125 return ret;
126}126}
127 127 
128extern HcclResult hcclAllReduce(void *sendBuf, void *recvBuf, uint64_t count, HcclDataType dataType,128extern HcclResult hcclAllReduce(void *sendBuf, void *recvBuf, uint64_t count, HcclDataType dataType,
129 HcclReduceOp op, HcclComm comm, aclrtStream stream)129 HcclReduceOp op, HcclComm comm, aclrtStream stream)
130{130{
131 using HcclAllReduceFunc = HcclResult(*)(131 using HcclAllReduceFunc = HcclResult(*)(
132 void *, void *, uint64_t, HcclDataType, HcclReduceOp, HcclComm, aclrtStream);132 void *, void *, uint64_t, HcclDataType, HcclReduceOp, HcclComm, aclrtStream);
133 static HcclAllReduceFunc func = nullptr;133 static HcclAllReduceFunc func = nullptr;
134 if (func == nullptr) {134 if (func == nullptr) {
135 func = (HcclAllReduceFunc)TORCH_NPU_GET_FUNC(HcclAllReduce)135 func = (HcclAllReduceFunc)TORCH_NPU_GET_FUNC(HcclAllReduce)
136 }136 }
137 TORCH_CHECK(func, "Failed to find function ", "HcclAllReduce", DIST_ERROR(ErrCode::NOT_FOUND));137 TORCH_CHECK(func, "Failed to find function ", "HcclAllReduce", DIST_ERROR(ErrCode::NOT_FOUND));
138 auto ret = func(sendBuf, recvBuf, count, dataType, op, comm, stream);138 auto ret = func(sendBuf, recvBuf, count, dataType, op, comm, stream);
139 return ret;139 return ret;
140}140}
141 141 
142extern HcclResult hcclBroadcast(void *buf, uint64_t count, HcclDataType dataType, uint32_t root, HcclComm comm,142extern HcclResult hcclBroadcast(void *buf, uint64_t count, HcclDataType dataType, uint32_t root, HcclComm comm,
143 aclrtStream stream)143 aclrtStream stream)
144{144{
145 using HcclBroadcastFunc = HcclResult(*)(145 using HcclBroadcastFunc = HcclResult(*)(
146 void *, uint64_t, HcclDataType, uint32_t, HcclComm, aclrtStream);146 void *, uint64_t, HcclDataType, uint32_t, HcclComm, aclrtStream);
147 static HcclBroadcastFunc func = nullptr;147 static HcclBroadcastFunc func = nullptr;
148 if (func == nullptr) {148 if (func == nullptr) {
149 func = (HcclBroadcastFunc)TORCH_NPU_GET_FUNC(HcclBroadcast)149 func = (HcclBroadcastFunc)TORCH_NPU_GET_FUNC(HcclBroadcast)
150 }150 }
151 TORCH_CHECK(func, "Failed to find function ", "HcclBroadcast", DIST_ERROR(ErrCode::NOT_FOUND));151 TORCH_CHECK(func, "Failed to find function ", "HcclBroadcast", DIST_ERROR(ErrCode::NOT_FOUND));
152 auto ret = func(buf, count, dataType, root, comm, stream);152 auto ret = func(buf, count, dataType, root, comm, stream);
153 return ret;153 return ret;
154}154}
155 155 
156extern HcclResult hcclCommInitRootInfo(uint32_t nRanks, const HcclRootInfo *rootInfo, uint32_t rank, HcclComm *comm)156extern HcclResult hcclCommInitRootInfo(uint32_t nRanks, const HcclRootInfo *rootInfo, uint32_t rank, HcclComm *comm)
157{157{
158 using HcclCommInitRootInfoFunc = HcclResult(*)(158 using HcclCommInitRootInfoFunc = HcclResult(*)(
159 uint32_t, const HcclRootInfo *, uint32_t, HcclComm *);159 uint32_t, const HcclRootInfo *, uint32_t, HcclComm *);
160 static HcclCommInitRootInfoFunc func = nullptr;160 static HcclCommInitRootInfoFunc func = nullptr;
161 if (func == nullptr) {161 if (func == nullptr) {
162 func = (HcclCommInitRootInfoFunc)TORCH_NPU_GET_FUNC(HcclCommInitRootInfo)162 func = (HcclCommInitRootInfoFunc)TORCH_NPU_GET_FUNC(HcclCommInitRootInfo)
163 }163 }
164 TORCH_CHECK(func, "Failed to find function ", "HcclCommInitRootInfo", DIST_ERROR(ErrCode::NOT_FOUND));164 TORCH_CHECK(func, "Failed to find function ", "HcclCommInitRootInfo", DIST_ERROR(ErrCode::NOT_FOUND));
165 auto ret = func(nRanks, rootInfo, rank, comm);165 auto ret = func(nRanks, rootInfo, rank, comm);
166 return ret;166 return ret;
167}167}
168 168 
169extern HcclResult hcclReduceScatter(void *sendBuf, void *recvBuf, uint64_t recvCount, HcclDataType dataType,169extern HcclResult hcclReduceScatter(void *sendBuf, void *recvBuf, uint64_t recvCount, HcclDataType dataType,
170 HcclReduceOp op, HcclComm comm, aclrtStream stream)170 HcclReduceOp op, HcclComm comm, aclrtStream stream)
171{171{
172 using HcclReduceScatterFunc = HcclResult(*)(172 using HcclReduceScatterFunc = HcclResult(*)(
173 void *, void *, uint64_t, HcclDataType, HcclReduceOp, HcclComm, aclrtStream);173 void *, void *, uint64_t, HcclDataType, HcclReduceOp, HcclComm, aclrtStream);
174 static HcclReduceScatterFunc func = nullptr;174 static HcclReduceScatterFunc func = nullptr;
175 if (func == nullptr) {175 if (func == nullptr) {
176 func = (HcclReduceScatterFunc)TORCH_NPU_GET_FUNC(HcclReduceScatter);176 func = (HcclReduceScatterFunc)TORCH_NPU_GET_FUNC(HcclReduceScatter);
177 }177 }
178 TORCH_CHECK(func, "Failed to find function ", "HcclReduceScatter", DIST_ERROR(ErrCode::NOT_FOUND));178 TORCH_CHECK(func, "Failed to find function ", "HcclReduceScatter", DIST_ERROR(ErrCode::NOT_FOUND));
179 auto ret = func(sendBuf, recvBuf, recvCount, dataType, op, comm, stream);179 auto ret = func(sendBuf, recvBuf, recvCount, dataType, op, comm, stream);
180 return ret;180 return ret;
181}181}
182 182 
183extern HcclResult hcclAlltoAllV(const void *sendBuf, const void *sendCounts, const void *sdispls,183extern HcclResult hcclAlltoAllV(const void *sendBuf, const void *sendCounts, const void *sdispls,
184 HcclDataType sendType, const void *recvBuf, const void *recvCounts, const void *rdispls,184 HcclDataType sendType, const void *recvBuf, const void *recvCounts, const void *rdispls,
185 HcclDataType recvType, HcclComm comm, aclrtStream stream)185 HcclDataType recvType, HcclComm comm, aclrtStream stream)
186{186{
187 using HcclAlltoAllVFunc = HcclResult(*)(187 using HcclAlltoAllVFunc = HcclResult(*)(
188 const void *, const void *, const void *, HcclDataType,188 const void *, const void *, const void *, HcclDataType,
189 const void *, const void *, const void *, HcclDataType,189 const void *, const void *, const void *, HcclDataType,
190 HcclComm, aclrtStream);190 HcclComm, aclrtStream);
191 static HcclAlltoAllVFunc func = nullptr;191 static HcclAlltoAllVFunc func = nullptr;
192 if (func == nullptr) {192 if (func == nullptr) {
193 func = (HcclAlltoAllVFunc)TORCH_NPU_GET_FUNC(HcclAlltoAllV);193 func = (HcclAlltoAllVFunc)TORCH_NPU_GET_FUNC(HcclAlltoAllV);
194 }194 }
195 TORCH_CHECK(func, "Failed to find function ", "HcclAlltoAllV", DIST_ERROR(ErrCode::NOT_FOUND));195 TORCH_CHECK(func, "Failed to find function ", "HcclAlltoAllV", DIST_ERROR(ErrCode::NOT_FOUND));
196 auto ret = func(sendBuf, sendCounts, sdispls, sendType,196 auto ret = func(sendBuf, sendCounts, sdispls, sendType,
197 recvBuf, recvCounts, rdispls, recvType, comm, stream);197 recvBuf, recvCounts, rdispls, recvType, comm, stream);
198 return ret;198 return ret;
199}199}
200 200 
201extern HcclResult hcclAllGatherV(const void *sendBuf, uint64_t sendCount,201extern HcclResult hcclAllGatherV(const void *sendBuf, uint64_t sendCount,
202 const void *recvBuf, const void *recvCounts, const void *rdispls,202 const void *recvBuf, const void *recvCounts, const void *rdispls,
203 HcclDataType dataType, HcclComm comm, aclrtStream stream)203 HcclDataType dataType, HcclComm comm, aclrtStream stream)
204{204{
205 using HcclAllGatherVFunc = HcclResult(*)(205 using HcclAllGatherVFunc = HcclResult(*)(
206 const void *, uint64_t,206 const void *, uint64_t,
207 const void *, const void *, const void *,207 const void *, const void *, const void *,
208 HcclDataType, HcclComm, aclrtStream);208 HcclDataType, HcclComm, aclrtStream);
209 static HcclAllGatherVFunc func = nullptr;209 static HcclAllGatherVFunc func = nullptr;
210 if (func == nullptr) {210 if (func == nullptr) {
211 func = (HcclAllGatherVFunc)TORCH_NPU_GET_FUNC(HcclAllGatherV);211 func = (HcclAllGatherVFunc)TORCH_NPU_GET_FUNC(HcclAllGatherV);
212 }212 }
213 TORCH_CHECK(func, "Failed to find function ", "HcclAllGatherV", DIST_ERROR(ErrCode::NOT_FOUND));213 TORCH_CHECK(func, "Failed to find function ", "HcclAllGatherV", DIST_ERROR(ErrCode::NOT_FOUND));
214 auto ret = func(sendBuf, sendCount, recvBuf, recvCounts, rdispls, dataType, comm, stream);214 auto ret = func(sendBuf, sendCount, recvBuf, recvCounts, rdispls, dataType, comm, stream);
215 return ret;215 return ret;
216}216}
217 217 
218extern HcclResult hcclReduceScatterV(const void *sendBuf, const void *sendCounts, const void *sdispls,218extern HcclResult hcclReduceScatterV(const void *sendBuf, const void *sendCounts, const void *sdispls,
219 const void *recvBuf, uint64_t recvCount,219 const void *recvBuf, uint64_t recvCount,
220 HcclDataType dataType, HcclReduceOp op, HcclComm comm, aclrtStream stream)220 HcclDataType dataType, HcclReduceOp op, HcclComm comm, aclrtStream stream)
221{221{
222 using HcclReduceScatterVFunc = HcclResult(*)(222 using HcclReduceScatterVFunc = HcclResult(*)(
223 const void *, const void *, const void *,223 const void *, const void *, const void *,
224 const void *, uint64_t,224 const void *, uint64_t,
225 HcclDataType, HcclReduceOp, HcclComm, aclrtStream);225 HcclDataType, HcclReduceOp, HcclComm, aclrtStream);
226 static HcclReduceScatterVFunc func = nullptr;226 static HcclReduceScatterVFunc func = nullptr;
227 if (func == nullptr) {227 if (func == nullptr) {
228 func = (HcclReduceScatterVFunc)TORCH_NPU_GET_FUNC(HcclReduceScatterV);228 func = (HcclReduceScatterVFunc)TORCH_NPU_GET_FUNC(HcclReduceScatterV);
229 }229 }
230 TORCH_CHECK(func, "Failed to find function ", "HcclReduceScatterV", DIST_ERROR(ErrCode::NOT_FOUND));230 TORCH_CHECK(func, "Failed to find function ", "HcclReduceScatterV", DIST_ERROR(ErrCode::NOT_FOUND));
231 auto ret = func(sendBuf, sendCounts, sdispls, recvBuf, recvCount, dataType, op, comm, stream);231 auto ret = func(sendBuf, sendCounts, sdispls, recvBuf, recvCount, dataType, op, comm, stream);
232 return ret;232 return ret;
233}233}
234 234 
235extern HcclResult hcclReduce(void *sendBuf, void *recvBuf, uint64_t count, HcclDataType sendType,235extern HcclResult hcclReduce(void *sendBuf, void *recvBuf, uint64_t count, HcclDataType sendType,
236 HcclReduceOp op, uint32_t root, HcclComm comm, aclrtStream stream)236 HcclReduceOp op, uint32_t root, HcclComm comm, aclrtStream stream)
237{237{
238 using HcclReduceVFunc = HcclResult(*)(238 using HcclReduceVFunc = HcclResult(*)(
239 void *, void *, uint64_t, HcclDataType, HcclReduceOp, uint32_t, HcclComm, aclrtStream);239 void *, void *, uint64_t, HcclDataType, HcclReduceOp, uint32_t, HcclComm, aclrtStream);
240 static HcclReduceVFunc func = nullptr;240 static HcclReduceVFunc func = nullptr;
241 if (func == nullptr) {241 if (func == nullptr) {
242 func = (HcclReduceVFunc)TORCH_NPU_GET_FUNC(HcclReduce);242 func = (HcclReduceVFunc)TORCH_NPU_GET_FUNC(HcclReduce);
243 }243 }
244 TORCH_CHECK(func, "Failed to find function ", "HcclReduce", DIST_ERROR(ErrCode::NOT_FOUND));244 TORCH_CHECK(func, "Failed to find function ", "HcclReduce", DIST_ERROR(ErrCode::NOT_FOUND));
245 auto ret = func(sendBuf, recvBuf, count, sendType, op, root, comm, stream);245 auto ret = func(sendBuf, recvBuf, count, sendType, op, root, comm, stream);
246 return ret;246 return ret;
247}247}
248 248 
249HcclResult hcclGetCommAsyncError(HcclComm comm, HcclResult* asyncError)249HcclResult hcclGetCommAsyncError(HcclComm comm, HcclResult* asyncError)
250{250{
251 using HcclGetCommAsyncErrorVFunc = HcclResult(*)(HcclComm, HcclResult*);251 using HcclGetCommAsyncErrorVFunc = HcclResult(*)(HcclComm, HcclResult*);
252 static HcclGetCommAsyncErrorVFunc func = nullptr;252 static HcclGetCommAsyncErrorVFunc func = nullptr;
253 if (func == nullptr) {253 if (func == nullptr) {
254 func = (HcclGetCommAsyncErrorVFunc)TORCH_NPU_GET_FUNC(HcclGetCommAsyncError);254 func = (HcclGetCommAsyncErrorVFunc)TORCH_NPU_GET_FUNC(HcclGetCommAsyncError);
255 }255 }
256 TORCH_CHECK(func, "Failed to find function ", "HcclGetCommAsyncError", DIST_ERROR(ErrCode::NOT_FOUND));256 TORCH_CHECK(func, "Failed to find function ", "HcclGetCommAsyncError", DIST_ERROR(ErrCode::NOT_FOUND));
257 auto ret = func(comm, asyncError);257 auto ret = func(comm, asyncError);
258 return ret;258 return ret;
259}259}
260 260 
261HcclResult hcclScatter(void *sendBuf, void *recvBuf, uint64_t count, HcclDataType dataType, uint32_t root,261HcclResult hcclScatter(void *sendBuf, void *recvBuf, uint64_t count, HcclDataType dataType, uint32_t root,
262 HcclComm comm, aclrtStream stream)262 HcclComm comm, aclrtStream stream)
263{263{
264 using HcclScatterVFunc = HcclResult(*)(void *, void *, uint64_t, HcclDataType, uint32_t, HcclComm, aclrtStream);264 using HcclScatterVFunc = HcclResult(*)(void *, void *, uint64_t, HcclDataType, uint32_t, HcclComm, aclrtStream);
265 static HcclScatterVFunc func = nullptr;265 static HcclScatterVFunc func = nullptr;
266 if (func == nullptr) {266 if (func == nullptr) {
267 func = (HcclScatterVFunc)TORCH_NPU_GET_FUNC(HcclScatter);267 func = (HcclScatterVFunc)TORCH_NPU_GET_FUNC(HcclScatter);
268 }268 }
269 TORCH_CHECK(func, "Failed to find function ", "HcclScatter", DIST_ERROR(ErrCode::NOT_FOUND));269 TORCH_CHECK(func, "Failed to find function ", "HcclScatter", DIST_ERROR(ErrCode::NOT_FOUND));
270 auto ret = func(sendBuf, recvBuf, count, dataType, root, comm, stream);270 auto ret = func(sendBuf, recvBuf, count, dataType, root, comm, stream);
271 return ret;271 return ret;
272}272}
273 273 
274HcclResult hcclBatchIsendIrecv(void* sendRecvInfo, uint32_t itemNum, HcclComm comm, aclrtStream stream)274HcclResult hcclBatchIsendIrecv(void* sendRecvInfo, uint32_t itemNum, HcclComm comm, aclrtStream stream)
275{275{
276 using HcclBatchIsendIrecvVFunc = HcclResult(*)(276 using HcclBatchIsendIrecvVFunc = HcclResult(*)(
277 void *, uint32_t, HcclComm, aclrtStream);277 void *, uint32_t, HcclComm, aclrtStream);
278 static HcclBatchIsendIrecvVFunc func = nullptr;278 static HcclBatchIsendIrecvVFunc func = nullptr;
279 if (func == nullptr) {279 if (func == nullptr) {
280 func = (HcclBatchIsendIrecvVFunc)TORCH_NPU_GET_FUNC(HcclBatchSendRecv);280 func = (HcclBatchIsendIrecvVFunc)TORCH_NPU_GET_FUNC(HcclBatchSendRecv);
281 }281 }
282 TORCH_CHECK(func, "Failed to find function ", "HcclBatchSendRecv", DIST_ERROR(ErrCode::NOT_FOUND));282 TORCH_CHECK(func, "Failed to find function ", "HcclBatchSendRecv", DIST_ERROR(ErrCode::NOT_FOUND));
283 auto ret = func(sendRecvInfo, itemNum, comm, stream);283 auto ret = func(sendRecvInfo, itemNum, comm, stream);
284 return ret;284 return ret;
285}285}
286 286 
287HcclResult hcclAlltoAll(const void *sendBuf, uint64_t sendCount, HcclDataType sendType,287HcclResult hcclAlltoAll(const void *sendBuf, uint64_t sendCount, HcclDataType sendType,
288 const void *recvBuf, uint64_t recvCount, HcclDataType recvType,288 const void *recvBuf, uint64_t recvCount, HcclDataType recvType,
289 HcclComm comm, aclrtStream stream)289 HcclComm comm, aclrtStream stream)
290{290{
291 using HcclAlltoAllFunc = HcclResult(*)(291 using HcclAlltoAllFunc = HcclResult(*)(
292 const void *, uint64_t, HcclDataType,292 const void *, uint64_t, HcclDataType,
293 const void *, uint64_t, HcclDataType,293 const void *, uint64_t, HcclDataType,
294 HcclComm, aclrtStream);294 HcclComm, aclrtStream);
295 static HcclAlltoAllFunc func = nullptr;295 static HcclAlltoAllFunc func = nullptr;
296 if (func == nullptr) {296 if (func == nullptr) {
297 func = (HcclAlltoAllFunc)TORCH_NPU_GET_FUNC(HcclAlltoAll);297 func = (HcclAlltoAllFunc)TORCH_NPU_GET_FUNC(HcclAlltoAll);
298 }298 }
299 TORCH_CHECK(func, "Failed to find function ", "HcclAlltoAll", DIST_ERROR(ErrCode::NOT_FOUND));299 TORCH_CHECK(func, "Failed to find function ", "HcclAlltoAll", DIST_ERROR(ErrCode::NOT_FOUND));
300 auto ret = func(sendBuf, sendCount, sendType,300 auto ret = func(sendBuf, sendCount, sendType,
301 recvBuf, recvCount, recvType, comm, stream);301 recvBuf, recvCount, recvType, comm, stream);
302 return ret;302 return ret;
303}303}
304 304 
305bool hcclCommInitRootInfoConfigExist()305bool hcclCommInitRootInfoConfigExist()
306{306{
307 static c10::once_flag flag;307 static c10::once_flag flag;
308 static bool exist = false;308 static bool exist = false;
309 c10::call_once(flag, [&]() {309 c10::call_once(flag, [&]() {
310 auto func = TORCH_NPU_GET_FUNC(HcclCommInitRootInfoConfig)310 auto func = TORCH_NPU_GET_FUNC(HcclCommInitRootInfoConfig)
311 if (func != nullptr) {311 if (func != nullptr) {
312 exist = true;312 exist = true;
313 }313 }
314 });314 });
315 return exist;315 return exist;
316}316}
317 317 
318bool hcclAllGatherVExist()318bool hcclAllGatherVExist()
319{319{
320 static c10::once_flag flag;320 static c10::once_flag flag;
321 static bool exist = false;321 static bool exist = false;
322 c10::call_once(flag, [&]() {322 c10::call_once(flag, [&]() {
323 auto func = TORCH_NPU_GET_FUNC(HcclAllGatherV)323 auto func = TORCH_NPU_GET_FUNC(HcclAllGatherV)
324 if (func != nullptr &&324 if (func != nullptr &&
325 c10_npu::GetSocVersion() >= c10_npu::SocVersion::Ascend310P1 &&325 c10_npu::GetSocVersion() >= c10_npu::SocVersion::Ascend310P1 &&
326 c10_npu::GetSocVersion() < c10_npu::SocVersion::Ascend310B1) {326 c10_npu::GetSocVersion() < c10_npu::SocVersion::Ascend310B1) {
327 exist = true;327 exist = true;
328 }328 }
329 });329 });
330 return exist;330 return exist;
331}331}
332 332 
333bool hcclReduceScatterVExist()333bool hcclReduceScatterVExist()
334{334{
335 static c10::once_flag flag;335 static c10::once_flag flag;
336 static bool exist = false;336 static bool exist = false;
337 c10::call_once(flag, [&]() {337 c10::call_once(flag, [&]() {
338 auto func = TORCH_NPU_GET_FUNC(HcclReduceScatterV)338 auto func = TORCH_NPU_GET_FUNC(HcclReduceScatterV)
339 if (func != nullptr &&339 if (func != nullptr &&
340 ((c10_npu::GetSocVersion() >= c10_npu::SocVersion::Ascend310P1 &&340 ((c10_npu::GetSocVersion() >= c10_npu::SocVersion::Ascend310P1 &&
341 c10_npu::GetSocVersion() < c10_npu::SocVersion::Ascend310B1) ||341 c10_npu::GetSocVersion() < c10_npu::SocVersion::Ascend310B1) ||
342 c10_npu::GetSocVersion() == c10_npu::SocVersion::Ascend950)) {342 c10_npu::GetSocVersion() == c10_npu::SocVersion::Ascend950)) {
343 exist = true;343 exist = true;
344 }344 }
345 });345 });
346 return exist;346 return exist;
347}347}
348 348 
349HcclResult hcclCommInitRootInfoConfig(uint32_t nRanks, const HcclRootInfo *rootInfo, uint32_t rank, HcclCommConfig* config, HcclComm *comm)349HcclResult hcclCommInitRootInfoConfig(uint32_t nRanks, const HcclRootInfo *rootInfo, uint32_t rank, HcclCommConfig* config, HcclComm *comm)
350{350{
351 using HcclCommInitRootInfoConfigFunc = HcclResult(*)(351 using HcclCommInitRootInfoConfigFunc = HcclResult(*)(
352 uint32_t, const HcclRootInfo *, uint32_t, HcclCommConfig*, HcclComm *);352 uint32_t, const HcclRootInfo *, uint32_t, HcclCommConfig*, HcclComm *);
353 static HcclCommInitRootInfoConfigFunc func = nullptr;353 static HcclCommInitRootInfoConfigFunc func = nullptr;
354 if (func == nullptr) {354 if (func == nullptr) {
355 func = (HcclCommInitRootInfoConfigFunc)TORCH_NPU_GET_FUNC(HcclCommInitRootInfoConfig)355 func = (HcclCommInitRootInfoConfigFunc)TORCH_NPU_GET_FUNC(HcclCommInitRootInfoConfig)
356 }356 }
357 TORCH_CHECK(func, "Failed to find function ", "HcclCommInitRootInfoConfig", DIST_ERROR(ErrCode::NOT_FOUND));357 TORCH_CHECK(func, "Failed to find function ", "HcclCommInitRootInfoConfig", DIST_ERROR(ErrCode::NOT_FOUND));
358 auto ret = func(nRanks, rootInfo, rank, config, comm);358 auto ret = func(nRanks, rootInfo, rank, config, comm);
359 return ret;359 return ret;
360}360}
361 361 
362bool isHcclFeatureSupported(HcclCommConfigCapability configParameter)362bool isHcclFeatureSupported(HcclCommConfigCapability configParameter)
363{363{
364 using HcclGetCommConfigCapabilityFunc = uint32_t(*)();364 using HcclGetCommConfigCapabilityFunc = uint32_t(*)();
365 static HcclGetCommConfigCapabilityFunc func = (HcclGetCommConfigCapabilityFunc) TORCH_NPU_GET_FUNC(365 static HcclGetCommConfigCapabilityFunc func = (HcclGetCommConfigCapabilityFunc) TORCH_NPU_GET_FUNC(
366 HcclGetCommConfigCapability);366 HcclGetCommConfigCapability);
367 if (func == nullptr) {367 if (func == nullptr) {
368 return false;368 return false;
369 }369 }
370 return configParameter < func();370 return configParameter < func();
371}371}
372 372 
373bool hcclCommInitClusterInfoConfigExist()373bool hcclCommInitClusterInfoConfigExist()
374{374{
375 const static bool isClusterInitExist = []() -> bool {375 const static bool isClusterInitExist = []() -> bool {
376 auto func = TORCH_NPU_GET_FUNC(HcclCommInitClusterInfoConfig)376 auto func = TORCH_NPU_GET_FUNC(HcclCommInitClusterInfoConfig)
377 return func != nullptr;377 return func != nullptr;
378 }();378 }();
379 return isClusterInitExist;379 return isClusterInitExist;
380}380}
381 381 
382HcclResult hcclCommInitClusterInfoConfig(const char *clusterInfo, uint32_t rank, HcclCommConfig *config, HcclComm *comm)382HcclResult hcclCommInitClusterInfoConfig(const char *clusterInfo, uint32_t rank, HcclCommConfig *config, HcclComm *comm)
383{383{
384 using HcclCommInitClusterInfoConfigFunc = HcclResult(*)(const char *, uint32_t, HcclCommConfig *, HcclComm *);384 using HcclCommInitClusterInfoConfigFunc = HcclResult(*)(const char *, uint32_t, HcclCommConfig *, HcclComm *);
385 static HcclCommInitClusterInfoConfigFunc func = nullptr;385 static HcclCommInitClusterInfoConfigFunc func = nullptr;
386 if (func == nullptr) {386 if (func == nullptr) {
387 func = (HcclCommInitClusterInfoConfigFunc)TORCH_NPU_GET_FUNC(HcclCommInitClusterInfoConfig)387 func = (HcclCommInitClusterInfoConfigFunc)TORCH_NPU_GET_FUNC(HcclCommInitClusterInfoConfig)
388 }388 }
389 TORCH_CHECK(func, "Failed to find function ", "HcclCommInitClusterInfoConfig", DIST_ERROR(ErrCode::NOT_FOUND));389 TORCH_CHECK(func, "Failed to find function ", "HcclCommInitClusterInfoConfig", DIST_ERROR(ErrCode::NOT_FOUND));
390 auto ret = func(clusterInfo, rank, config, comm);390 auto ret = func(clusterInfo, rank, config, comm);
391 return ret;391 return ret;
392}392}
393 393 
394bool hcclCreateSubCommConfigExist()394bool hcclCreateSubCommConfigExist()
395{395{
396 const static bool isCreateSubCommExist = []() -> bool {396 const static bool isCreateSubCommExist = []() -> bool {
397 auto func = TORCH_NPU_GET_FUNC(HcclCreateSubCommConfig)397 auto func = TORCH_NPU_GET_FUNC(HcclCreateSubCommConfig)
398 return func != nullptr;398 return func != nullptr;
399 }();399 }();
400 return isCreateSubCommExist;400 return isCreateSubCommExist;
401}401}
402 402 
403HcclResult hcclCreateSubCommConfig(HcclComm *comm, uint32_t rankNum, uint32_t *rankIds, uint64_t subCommId, uint32_t subCommRankId,403HcclResult hcclCreateSubCommConfig(HcclComm *comm, uint32_t rankNum, uint32_t *rankIds, uint64_t subCommId, uint32_t subCommRankId,
404 HcclCommConfig* config, HcclComm *subComm)404 HcclCommConfig* config, HcclComm *subComm)
405{405{
406 using HcclCreateSubCommConfigFunc = HcclResult(*)(HcclComm *, uint32_t, uint32_t *, uint64_t, uint32_t, HcclCommConfig *, HcclComm *);406 using HcclCreateSubCommConfigFunc = HcclResult(*)(HcclComm *, uint32_t, uint32_t *, uint64_t, uint32_t, HcclCommConfig *, HcclComm *);
407 static HcclCreateSubCommConfigFunc func = nullptr;407 static HcclCreateSubCommConfigFunc func = nullptr;
408 if (func == nullptr) {408 if (func == nullptr) {
409 func = (HcclCreateSubCommConfigFunc)TORCH_NPU_GET_FUNC(HcclCreateSubCommConfig)409 func = (HcclCreateSubCommConfigFunc)TORCH_NPU_GET_FUNC(HcclCreateSubCommConfig)
410 }410 }
411 TORCH_CHECK(func, "Failed to find function ", "HcclCreateSubCommConfig", DIST_ERROR(ErrCode::NOT_FOUND));411 TORCH_CHECK(func, "Failed to find function ", "HcclCreateSubCommConfig", DIST_ERROR(ErrCode::NOT_FOUND));
412 auto ret = func(comm, rankNum, rankIds, subCommId, subCommRankId, config, subComm);412 auto ret = func(comm, rankNum, rankIds, subCommId, subCommRankId, config, subComm);
413 return ret;413 return ret;
414}414}
415 415 
416bool hcclCommWorkingDevNicSetExist()416bool hcclCommWorkingDevNicSetExist()
417{417{
418 const static bool isHcclCommWorkingDevNicSetExist = []() -> bool {418 const static bool isHcclCommWorkingDevNicSetExist = []() -> bool {
419 auto func = TORCH_NPU_GET_FUNC(HcclCommWorkingDevNicSet)419 auto func = TORCH_NPU_GET_FUNC(HcclCommWorkingDevNicSet)
420 return func != nullptr;420 return func != nullptr;
421 }();421 }();
422 return isHcclCommWorkingDevNicSetExist;422 return isHcclCommWorkingDevNicSetExist;
423}423}
424 424 
425HcclResult hcclCommWorkingDevNicSet(HcclComm comm, uint32_t *ranks, bool *useBackup, uint32_t nRanks)425HcclResult hcclCommWorkingDevNicSet(HcclComm comm, uint32_t *ranks, bool *useBackup, uint32_t nRanks)
426{426{
427 using HcclCommWorkingDevNicSetFunc = HcclResult(*)(HcclComm, uint32_t *, bool *, uint32_t);427 using HcclCommWorkingDevNicSetFunc = HcclResult(*)(HcclComm, uint32_t *, bool *, uint32_t);
428 static HcclCommWorkingDevNicSetFunc func = nullptr;428 static HcclCommWorkingDevNicSetFunc func = nullptr;
429 if (func == nullptr) {429 if (func == nullptr) {
430 func = (HcclCommWorkingDevNicSetFunc)TORCH_NPU_GET_FUNC(HcclCommWorkingDevNicSet)430 func = (HcclCommWorkingDevNicSetFunc)TORCH_NPU_GET_FUNC(HcclCommWorkingDevNicSet)
431 }431 }
432 TORCH_CHECK(func, "Failed to find function ", "HcclCommWorkingDevNicSet", DIST_ERROR(ErrCode::NOT_FOUND));432 TORCH_CHECK(func, "Failed to find function ", "HcclCommWorkingDevNicSet", DIST_ERROR(ErrCode::NOT_FOUND));
433 auto ret = func(comm, ranks, useBackup, nRanks);433 auto ret = func(comm, ranks, useBackup, nRanks);
434 return ret;434 return ret;
435}435}
436 436 
437HcclResult hcclCommRegister(HcclComm comm, void *addr, uint64_t size, void **handle, uint32_t flag)437HcclResult hcclCommRegister(HcclComm comm, void *addr, uint64_t size, void **handle, uint32_t flag)
438{438{
439 using HcclCommRegisterFunc = HcclResult(*)(HcclComm, void *, uint64_t, void **, uint32_t);439 using HcclCommRegisterFunc = HcclResult(*)(HcclComm, void *, uint64_t, void **, uint32_t);
440 static HcclCommRegisterFunc func = nullptr;440 static HcclCommRegisterFunc func = nullptr;
441 if (func == nullptr) {441 if (func == nullptr) {
442 func = (HcclCommRegisterFunc)TORCH_NPU_GET_FUNC(HcclCommRegister)442 func = (HcclCommRegisterFunc)TORCH_NPU_GET_FUNC(HcclCommRegister)
443 }443 }
444 TORCH_CHECK(func, "Failed to find function ", "HcclCommRegister", DIST_ERROR(ErrCode::NOT_FOUND));444 TORCH_CHECK(func, "Failed to find function ", "HcclCommRegister", DIST_ERROR(ErrCode::NOT_FOUND));
445 auto ret = func(comm, addr, size, handle, flag);445 auto ret = func(comm, addr, size, handle, flag);
446 return ret;446 return ret;
447}447}
448 448 
449HcclResult hcclCommDeregister(HcclComm comm, void *handle)449HcclResult hcclCommDeregister(HcclComm comm, void *handle)
450{450{
451 using HcclCommDeregisterFunc = HcclResult(*)(HcclComm, void *);451 using HcclCommDeregisterFunc = HcclResult(*)(HcclComm, void *);
452 static HcclCommDeregisterFunc func = nullptr;452 static HcclCommDeregisterFunc func = nullptr;
453 if (func == nullptr) {453 if (func == nullptr) {
454 func = (HcclCommDeregisterFunc)TORCH_NPU_GET_FUNC(HcclCommDeregister)454 func = (HcclCommDeregisterFunc)TORCH_NPU_GET_FUNC(HcclCommDeregister)
455 }455 }
456 TORCH_CHECK(func, "Failed to find function ", "HcclCommDeregister", DIST_ERROR(ErrCode::NOT_FOUND));456 TORCH_CHECK(func, "Failed to find function ", "HcclCommDeregister", DIST_ERROR(ErrCode::NOT_FOUND));
457 auto ret = func(comm, handle);457 auto ret = func(comm, handle);
458 return ret;458 return ret;
459}459}
460 460 
461HcclResult hcclCommExchangeMem(HcclComm comm, void *windowHandle, uint32_t *peerRanks, uint32_t peerRankNum)461HcclResult hcclCommExchangeMem(HcclComm comm, void *windowHandle, uint32_t *peerRanks, uint32_t peerRankNum)
462{462{
463 using HcclCommExchangeMemFunc = HcclResult(*)(HcclComm, void *, uint32_t *, uint32_t);463 using HcclCommExchangeMemFunc = HcclResult(*)(HcclComm, void *, uint32_t *, uint32_t);
464 static HcclCommExchangeMemFunc func = nullptr;464 static HcclCommExchangeMemFunc func = nullptr;
465 if (func == nullptr) {465 if (func == nullptr) {
466 func = (HcclCommExchangeMemFunc)TORCH_NPU_GET_FUNC(HcclCommExchangeMem)466 func = (HcclCommExchangeMemFunc)TORCH_NPU_GET_FUNC(HcclCommExchangeMem)
467 }467 }
468 TORCH_CHECK(func, "Failed to find function ", "HcclCommExchangeMem", DIST_ERROR(ErrCode::NOT_FOUND));468 TORCH_CHECK(func, "Failed to find function ", "HcclCommExchangeMem", DIST_ERROR(ErrCode::NOT_FOUND));
469 auto ret = func(comm, windowHandle, peerRanks, peerRankNum);469 auto ret = func(comm, windowHandle, peerRanks, peerRankNum);
470 return ret;470 return ret;
471}471}
472 472 
473HcclResult hcclGroupStart()473HcclResult hcclGroupStart()
474{474{
475 using hcclGroupStartFunc = HcclResult(*)();475 using hcclGroupStartFunc = HcclResult(*)();
476 static hcclGroupStartFunc func = nullptr;476 static hcclGroupStartFunc func = nullptr;
477 if (func == nullptr) {477 if (func == nullptr) {
478 func = (hcclGroupStartFunc)TORCH_NPU_GET_FUNCTION(libhcomm, HcclGroupStart)478 func = (hcclGroupStartFunc)TORCH_NPU_GET_FUNCTION(libhcomm, HcclGroupStart)
479 }479 }
480 TORCH_CHECK(func, "Failed to find function ", "HcclGroupStart", DIST_ERROR(ErrCode::NOT_FOUND));480 TORCH_CHECK(func, "Failed to find function ", "HcclGroupStart", DIST_ERROR(ErrCode::NOT_FOUND));
481 auto ret = func();481 auto ret = func();
482 return ret;482 return ret;
483}483}
484 484 
485HcclResult hcclGroupEnd()485HcclResult hcclGroupEnd()
486{486{
487 using hcclGroupEndFunc = HcclResult(*)();487 using hcclGroupEndFunc = HcclResult(*)();
488 static hcclGroupEndFunc func = nullptr;488 static hcclGroupEndFunc func = nullptr;
489 if (func == nullptr) {489 if (func == nullptr) {
490 func = (hcclGroupEndFunc)TORCH_NPU_GET_FUNCTION(libhcomm, HcclGroupEnd)490 func = (hcclGroupEndFunc)TORCH_NPU_GET_FUNCTION(libhcomm, HcclGroupEnd)
491 }491 }
492 TORCH_CHECK(func, "Failed to find function ", "HcclGroupEnd", DIST_ERROR(ErrCode::NOT_FOUND));492 TORCH_CHECK(func, "Failed to find function ", "HcclGroupEnd", DIST_ERROR(ErrCode::NOT_FOUND));
493 auto ret = func();493 auto ret = func();
494 return ret;494 return ret;
495}495}
496} // namespace c10d_npu496} // namespace c10d_npu
Mtorch_npu/csrc/distributed/Init.cpp+614-614
@@ -1,614 +1,614 @@
1#include <deque>1#include <deque>
2 2 
3#include <torch/custom_class.h>3#include <torch/custom_class.h>
4#include <torch/csrc/python_headers.h>4#include <torch/csrc/python_headers.h>
5#include <c10/util/intrusive_ptr.h>5#include <c10/util/intrusive_ptr.h>
6#include <c10/util/irange.h>6#include <c10/util/irange.h>
7#include <c10d/ProcessGroup.hpp>7#include <c10d/ProcessGroup.hpp>
8#include <c10d/comm.hpp>8#include <c10d/comm.hpp>
9#include <c10d/Work.hpp>9#include <c10d/Work.hpp>
10#include <pybind11/chrono.h>10#include <pybind11/chrono.h>
11 11 
12#include <torch/csrc/Exceptions.h>12#include <torch/csrc/Exceptions.h>
13#include <ATen/core/functional.h>13#include <ATen/core/functional.h>
14#include <torch/csrc/jit/python/pybind_utils.h>14#include <torch/csrc/jit/python/pybind_utils.h>
15#include <torch/csrc/utils/object_ptr.h>15#include <torch/csrc/utils/object_ptr.h>
16#include <torch/csrc/utils/pybind.h>16#include <torch/csrc/utils/pybind.h>
17#include <torch/csrc/utils/tensor_flatten.h>17#include <torch/csrc/utils/tensor_flatten.h>
18#include <torch/csrc/distributed/c10d/python_comm_hook.h>18#include <torch/csrc/distributed/c10d/python_comm_hook.h>
19 19 
20#include "torch_npu/csrc/distributed/rpc/init.h"20#include "torch_npu/csrc/distributed/rpc/init.h"
21#include "torch_npu/csrc/distributed/ProcessGroupHCCL.hpp"21#include "torch_npu/csrc/distributed/ProcessGroupHCCL.hpp"
22#include "torch_npu/csrc/distributed/ProcessGroupLCCL.hpp"22#include "torch_npu/csrc/distributed/ProcessGroupLCCL.hpp"
23#include "torch_npu/csrc/distributed/reducer.hpp"23#include "torch_npu/csrc/distributed/reducer.hpp"
24#include "torch_npu/csrc/distributed/ParallelTcpStore.hpp"24#include "torch_npu/csrc/distributed/ParallelTcpStore.hpp"
25#include "torch_npu/csrc/aten/NPUNativeFunctions.h"25#include "torch_npu/csrc/aten/NPUNativeFunctions.h"
26#include "torch_npu/csrc/aten/CustomFunctions.h"26#include "torch_npu/csrc/aten/CustomFunctions.h"
27#include "torch_npu/csrc/core/NPUBridge.h"27#include "torch_npu/csrc/core/NPUBridge.h"
28#include "torch_npu/csrc/distributed/Init.h"28#include "torch_npu/csrc/distributed/Init.h"
29 29 
30 30 
31namespace {31namespace {
32 32 
33// Wrapper to ensure GIL is released before destructing ProcessGroupGloo33// Wrapper to ensure GIL is released before destructing ProcessGroupGloo
34template <typename T>34template <typename T>
35class IntrusivePtrNoGilDestructor {35class IntrusivePtrNoGilDestructor {
36 c10::intrusive_ptr<T> impl_;36 c10::intrusive_ptr<T> impl_;
37 37 
38public:38public:
39 IntrusivePtrNoGilDestructor() = default;39 IntrusivePtrNoGilDestructor() = default;
40 IntrusivePtrNoGilDestructor(const IntrusivePtrNoGilDestructor&) = default;40 IntrusivePtrNoGilDestructor(const IntrusivePtrNoGilDestructor&) = default;
41 IntrusivePtrNoGilDestructor(IntrusivePtrNoGilDestructor&&) = default;41 IntrusivePtrNoGilDestructor(IntrusivePtrNoGilDestructor&&) = default;
42 IntrusivePtrNoGilDestructor& operator=(const IntrusivePtrNoGilDestructor&) =42 IntrusivePtrNoGilDestructor& operator=(const IntrusivePtrNoGilDestructor&) =
43 default;43 default;
44 IntrusivePtrNoGilDestructor& operator=(IntrusivePtrNoGilDestructor&&) =44 IntrusivePtrNoGilDestructor& operator=(IntrusivePtrNoGilDestructor&&) =
45 default;45 default;
46 IntrusivePtrNoGilDestructor(c10::intrusive_ptr<T> impl)46 IntrusivePtrNoGilDestructor(c10::intrusive_ptr<T> impl)
47 : impl_(std::move(impl)) {}47 : impl_(std::move(impl)) {}
48 explicit IntrusivePtrNoGilDestructor(T* impl)48 explicit IntrusivePtrNoGilDestructor(T* impl)
49 : impl_(c10::intrusive_ptr<T>::unsafe_steal_from_new(impl)) {}49 : impl_(c10::intrusive_ptr<T>::unsafe_steal_from_new(impl)) {}
50 ~IntrusivePtrNoGilDestructor() {50 ~IntrusivePtrNoGilDestructor() {
51 if (impl_) {51 if (impl_) {
52 if (PyGILState_Check() != 0) {52 if (PyGILState_Check() != 0) {
53 pybind11::gil_scoped_release release;53 pybind11::gil_scoped_release release;
54 impl_.reset();54 impl_.reset();
55 } else {55 } else {
56 impl_.reset();56 impl_.reset();
57 }57 }
58 }58 }
59 }59 }
60 T& operator*() const noexcept {60 T& operator*() const noexcept {
61 return *impl_;61 return *impl_;
62 }62 }
63 T* operator->() const noexcept {63 T* operator->() const noexcept {
64 return impl_.get();64 return impl_.get();
65 }65 }
66 C10_NODISCARD T* get() const noexcept {66 C10_NODISCARD T* get() const noexcept {
67 return impl_.get();67 return impl_.get();
68 }68 }
69 void reset() noexcept {69 void reset() noexcept {
70 impl_.reset();70 impl_.reset();
71 }71 }
72 operator bool() const noexcept {72 operator bool() const noexcept {
73 return impl_;73 return impl_;
74 }74 }
75};75};
76 76 
77} // anonymous namespace77} // anonymous namespace
78 78 
79PYBIND11_DECLARE_HOLDER_TYPE(T, IntrusivePtrNoGilDestructor<T>, true);79PYBIND11_DECLARE_HOLDER_TYPE(T, IntrusivePtrNoGilDestructor<T>, true);
80 80 
81 81 
82namespace torch_npu {82namespace torch_npu {
83namespace distributed {83namespace distributed {
84 84 
85template <typename T>85template <typename T>
86using shared_ptr_class_ = py::class_<T, std::shared_ptr<T>>;86using shared_ptr_class_ = py::class_<T, std::shared_ptr<T>>;
87 87 
88template <typename T>88template <typename T>
89using intrusive_ptr_class_ = py::class_<T, c10::intrusive_ptr<T>>;89using intrusive_ptr_class_ = py::class_<T, c10::intrusive_ptr<T>>;
90 90 
91template <typename T>91template <typename T>
92using intrusive_ptr_no_gil_destructor_class_ =92using intrusive_ptr_no_gil_destructor_class_ =
93 py::class_<T, IntrusivePtrNoGilDestructor<T>>;93 py::class_<T, IntrusivePtrNoGilDestructor<T>>;
94 94 
95 95 
96class BroadcastWork {96class BroadcastWork {
97public:97public:
98 inline std::vector<at::Tensor> cast_tensors(at::TensorList tensors) const98 inline std::vector<at::Tensor> cast_tensors(at::TensorList tensors) const
99 {99 {
100 static auto cast_back_to_ori_format = [](const at::Tensor &t) {100 static auto cast_back_to_ori_format = [](const at::Tensor &t) {
101 return at_npu::native::custom_ops::npu_format_cast(t, torch_npu::NPUBridge::GetNpuStorageImpl(t)->npu_desc_.origin_format_);101 return at_npu::native::custom_ops::npu_format_cast(t, torch_npu::NPUBridge::GetNpuStorageImpl(t)->npu_desc_.origin_format_);
102 };102 };
103 return c10::fmap(tensors, cast_back_to_ori_format);103 return c10::fmap(tensors, cast_back_to_ori_format);
104 }104 }
105 105 
106 BroadcastWork(106 BroadcastWork(
107 const c10::intrusive_ptr<c10d::ProcessGroup>& process_group,107 const c10::intrusive_ptr<c10d::ProcessGroup>& process_group,
108 std::vector<at::Tensor> bucket_tensors,108 std::vector<at::Tensor> bucket_tensors,
109 int root_rank = 0)109 int root_rank = 0)
110 : bucket_tensors_(std::move(bucket_tensors)),110 : bucket_tensors_(std::move(bucket_tensors)),
111 cast_tensors_(cast_tensors(bucket_tensors_)),111 cast_tensors_(cast_tensors(bucket_tensors_)),
112 flat_tensor_({torch::utils::flatten_dense_tensors(cast_tensors_)}) {112 flat_tensor_({torch::utils::flatten_dense_tensors(cast_tensors_)}) {
113 c10d::BroadcastOptions broadcastOptions;113 c10d::BroadcastOptions broadcastOptions;
114 broadcastOptions.rootRank = root_rank;114 broadcastOptions.rootRank = root_rank;
115 work_ = process_group->broadcast(flat_tensor_, broadcastOptions);115 work_ = process_group->broadcast(flat_tensor_, broadcastOptions);
116 }116 }
117 117 
118 void finish()118 void finish()
119 {119 {
120 work_->wait();120 work_->wait();
121 auto output_tensors = torch::utils::unflatten_dense_tensors(121 auto output_tensors = torch::utils::unflatten_dense_tensors(
122 flat_tensor_.front(), cast_tensors_);122 flat_tensor_.front(), cast_tensors_);
123 TORCH_INTERNAL_ASSERT(output_tensors.size() == bucket_tensors_.size(), DIST_ERROR(ErrCode::PARAM));123 TORCH_INTERNAL_ASSERT(output_tensors.size() == bucket_tensors_.size(), DIST_ERROR(ErrCode::PARAM));
124 for (const auto i : c10::irange(output_tensors.size())) {124 for (const auto i : c10::irange(output_tensors.size())) {
125 bucket_tensors_[i].copy_(output_tensors[i], true);125 bucket_tensors_[i].copy_(output_tensors[i], true);
126 }126 }
127 }127 }
128 128 
129protected:129protected:
130 // The list of tensors to broadcast. They are guaranteed to be130 // The list of tensors to broadcast. They are guaranteed to be
131 // placed on the same device and have the same dtype.131 // placed on the same device and have the same dtype.
132 std::vector<at::Tensor> bucket_tensors_;132 std::vector<at::Tensor> bucket_tensors_;
133 // Some tensors with format, such as FRACTAL_Z, 5HD, may be padded to133 // Some tensors with format, such as FRACTAL_Z, 5HD, may be padded to
134 // keep alignment with 16*16 cube kernel which will modify storage as134 // keep alignment with 16*16 cube kernel which will modify storage as
135 // input tensor for cat operation during flatten to a buffer tensor.135 // input tensor for cat operation during flatten to a buffer tensor.
136 // So, it needs to cast all bucket tensors to tensors with format HCHW136 // So, it needs to cast all bucket tensors to tensors with format HCHW
137 std::vector<at::Tensor> cast_tensors_;137 std::vector<at::Tensor> cast_tensors_;
138 // The vector with a single flattened tensor containing the contents138 // The vector with a single flattened tensor containing the contents
139 // of the tensors in bucket_tensors_. It must be stored in a vector139 // of the tensors in bucket_tensors_. It must be stored in a vector
140 // because c10d::ProcessGroup::broadcast takes a vector argument.140 // because c10d::ProcessGroup::broadcast takes a vector argument.
141 std::vector<at::Tensor> flat_tensor_;141 std::vector<at::Tensor> flat_tensor_;
142 142 
143private:143private:
144 144 
145 // The broadcast work that is kicked off upon construction.145 // The broadcast work that is kicked off upon construction.
146 c10::intrusive_ptr<c10d::Work> work_;146 c10::intrusive_ptr<c10d::Work> work_;
147};147};
148 148 
149// Broadcast many tensors to all processes in the process group.149// Broadcast many tensors to all processes in the process group.
150void broadcast_coalesced(150void broadcast_coalesced(
151 c10::intrusive_ptr<c10d::ProcessGroup> process_group,151 c10::intrusive_ptr<c10d::ProcessGroup> process_group,
152 at::TensorList tensors,152 at::TensorList tensors,
153 size_t buffer_size,153 size_t buffer_size,
154 int rank)154 int rank)
155{155{
156 // Coalesce tensors into buckets taking into account the maximum buffer size.156 // Coalesce tensors into buckets taking into account the maximum buffer size.
157 // This routine is multi-device aware, so the tensors can be split across157 // This routine is multi-device aware, so the tensors can be split across
158 // multiple devices and can contain a mix of CPU and CUDA tensors.158 // multiple devices and can contain a mix of CPU and CUDA tensors.
159 std::vector<std::vector<size_t>> buckets;159 std::vector<std::vector<size_t>> buckets;
160 std::tie(buckets, std::ignore) =160 std::tie(buckets, std::ignore) =
161 c10d_npu::compute_bucket_assignment_by_size(tensors.vec(), {buffer_size});161 c10d_npu::compute_bucket_assignment_by_size(tensors.vec(), {buffer_size});
162 162 
163 // Returns tensor at specified index in input tensor list.163 // Returns tensor at specified index in input tensor list.
164 const auto lookup = [&tensors](size_t index) { return tensors[index]; };164 const auto lookup = [&tensors](size_t index) { return tensors[index]; };
165 165 
166 // We maintain a maximum of 2 in flight broadcast operations to avoid166 // We maintain a maximum of 2 in flight broadcast operations to avoid
167 // allocating too much memory (in case the specified tensors are very large).167 // allocating too much memory (in case the specified tensors are very large).
168 std::deque<BroadcastWork> in_flight;168 std::deque<BroadcastWork> in_flight;
169 constexpr auto max_in_flight = 2;169 constexpr auto max_in_flight = 2;
170 for (const auto& bucket : buckets) {170 for (const auto& bucket : buckets) {
171 if (in_flight.size() >= max_in_flight) {171 if (in_flight.size() >= max_in_flight) {
172 in_flight.front().finish();172 in_flight.front().finish();
173 in_flight.pop_front();173 in_flight.pop_front();
174 }174 }
175 in_flight.emplace_back(process_group, c10::fmap(bucket, lookup), rank);175 in_flight.emplace_back(process_group, c10::fmap(bucket, lookup), rank);
176 }176 }
177 177 
178 while (!in_flight.empty()) {178 while (!in_flight.empty()) {
179 in_flight.front().finish();179 in_flight.front().finish();
180 in_flight.pop_front();180 in_flight.pop_front();
181 }181 }
182}182}
183 183 
184// Called from DDP's Python API to create a c10d Python comm hook object.184// Called from DDP's Python API to create a c10d Python comm hook object.
185// The input state and callable comm_hook are Python objects. It later calls185// The input state and callable comm_hook are Python objects. It later calls
186// register_comm_hook function of the reducer input to register the hook.186// register_comm_hook function of the reducer input to register the hook.
187void _register_comm_hook(187void _register_comm_hook(
188 c10d_npu::Reducer& reducer,188 c10d_npu::Reducer& reducer,
189 py::object state,189 py::object state,
190 py::object comm_hook)190 py::object comm_hook)
191{191{
192 reducer.register_comm_hook(std::make_unique<::c10d::PythonCommHook>(192 reducer.register_comm_hook(std::make_unique<::c10d::PythonCommHook>(
193 std::move(state), std::move(comm_hook)));193 std::move(state), std::move(comm_hook)));
194}194}
195 195 
196// Called from DDP's Python API to create a c10d C++ comm hook.196// Called from DDP's Python API to create a c10d C++ comm hook.
197// The input is an enum hook type. It later calls register_builtin_comm_hook197// The input is an enum hook type. It later calls register_builtin_comm_hook
198// function of the reducer input to set the hook type.198// function of the reducer input to set the hook type.
199void _register_builtin_comm_hook(199void _register_builtin_comm_hook(
200 c10d_npu::Reducer& reducer,200 c10d_npu::Reducer& reducer,
201 ::c10d::BuiltinCommHookType comm_hook_type)201 ::c10d::BuiltinCommHookType comm_hook_type)
202{202{
203 reducer.register_builtin_comm_hook(comm_hook_type);203 reducer.register_builtin_comm_hook(comm_hook_type);
204}204}
205 205 
206PyObject* c10d_npu_init(PyObject* _unused, PyObject* noargs)206PyObject* c10d_npu_init(PyObject* _unused, PyObject* noargs)
207{207{
208 auto torch_npu_C_module = THPObjectPtr(PyImport_ImportModule("torch_npu._C"));208 auto torch_npu_C_module = THPObjectPtr(PyImport_ImportModule("torch_npu._C"));
209 if (!torch_npu_C_module) {209 if (!torch_npu_C_module) {
210 throw python_error();210 throw python_error();
211 }211 }
212 auto torch_npu_C_m = py::handle(torch_npu_C_module).cast<py::module>();212 auto torch_npu_C_m = py::handle(torch_npu_C_module).cast<py::module>();
213 213
214 auto m =214 auto m =
215 torch_npu_C_m.def_submodule("_distributed_c10d", "distributed c10d bindings");215 torch_npu_C_m.def_submodule("_distributed_c10d", "distributed c10d bindings");
216 auto module = py::handle(m).cast<py::module>();216 auto module = py::handle(m).cast<py::module>();
217 217 
218 module.def("_compute_bucket_assignment_by_size",218 module.def("_compute_bucket_assignment_by_size",
219 [](const std::vector<at::Tensor>& tensors,219 [](const std::vector<at::Tensor>& tensors,
220 const std::vector<size_t>& bucket_size_limits,220 const std::vector<size_t>& bucket_size_limits,
221 const std::vector<bool>& expect_sparse_gradient,221 const std::vector<bool>& expect_sparse_gradient,
222 const std::vector<int64_t>& tensor_indices,222 const std::vector<int64_t>& tensor_indices,
223 const c10::optional<std::shared_ptr<::c10d::Logger>>& logger) {223 const c10::optional<std::shared_ptr<::c10d::Logger>>& logger) {
224 if (logger.has_value()) {224 if (logger.has_value()) {
225 std::weak_ptr<::c10d::Logger> logger_weakref = logger.value();225 std::weak_ptr<::c10d::Logger> logger_weakref = logger.value();
226 return ::c10d_npu::compute_bucket_assignment_by_size(tensors, bucket_size_limits, expect_sparse_gradient, tensor_indices, {logger_weakref});226 return ::c10d_npu::compute_bucket_assignment_by_size(tensors, bucket_size_limits, expect_sparse_gradient, tensor_indices, {logger_weakref});
227 } else {227 } else {
228 return ::c10d_npu::compute_bucket_assignment_by_size(tensors, bucket_size_limits, expect_sparse_gradient, tensor_indices, {});228 return ::c10d_npu::compute_bucket_assignment_by_size(tensors, bucket_size_limits, expect_sparse_gradient, tensor_indices, {});
229 }229 }
230 },230 },
231 py::arg("tensors"),231 py::arg("tensors"),
232 py::arg("bucket_size"),232 py::arg("bucket_size"),
233 py::arg("expect_sparse_gradient") = std::vector<bool>(),233 py::arg("expect_sparse_gradient") = std::vector<bool>(),
234 py::arg("tensor_indices") = std::vector<int64_t>(),234 py::arg("tensor_indices") = std::vector<int64_t>(),
235 py::arg("logger") = c10::optional<std::shared_ptr<::c10d::Logger>>{},235 py::arg("logger") = c10::optional<std::shared_ptr<::c10d::Logger>>{},
236 py::call_guard<py::gil_scoped_release>());236 py::call_guard<py::gil_scoped_release>());
237 237 
238 module.def("_verify_params_across_processes",238 module.def("_verify_params_across_processes",
239 [](const c10::intrusive_ptr<::c10d::ProcessGroup>& process_group,239 [](const c10::intrusive_ptr<::c10d::ProcessGroup>& process_group,
240 const std::vector<at::Tensor>& params,240 const std::vector<at::Tensor>& params,
241 const c10::optional<std::shared_ptr<::c10d::Logger>>& logger) {241 const c10::optional<std::shared_ptr<::c10d::Logger>>& logger) {
242 if (logger.has_value()) {242 if (logger.has_value()) {
243 std::weak_ptr<::c10d::Logger> logger_weakref = logger.value();243 std::weak_ptr<::c10d::Logger> logger_weakref = logger.value();
244 c10d_npu::verify_params_across_processes(process_group, params, {logger_weakref});244 c10d_npu::verify_params_across_processes(process_group, params, {logger_weakref});
245 } else {245 } else {
246 c10d_npu::verify_params_across_processes(process_group, params, {});246 c10d_npu::verify_params_across_processes(process_group, params, {});
247 }247 }
248 },248 },
249 py::arg("process_group"),249 py::arg("process_group"),
250 py::arg("params"),250 py::arg("params"),
251 py::arg("logger") = c10::optional<std::shared_ptr<::c10d::Logger>>{},251 py::arg("logger") = c10::optional<std::shared_ptr<::c10d::Logger>>{},
252 py::call_guard<py::gil_scoped_release>());252 py::call_guard<py::gil_scoped_release>());
253 253 
254 module254 module
255 .def("_register_comm_hook",255 .def("_register_comm_hook",
256 &_register_comm_hook,256 &_register_comm_hook,
257 py::arg("reducer"),257 py::arg("reducer"),
258 py::arg("state"),258 py::arg("state"),
259 py::arg("comm_hook"),259 py::arg("comm_hook"),
260 py::call_guard<py::gil_scoped_release>())260 py::call_guard<py::gil_scoped_release>())
261 .def("_register_builtin_comm_hook",261 .def("_register_builtin_comm_hook",
262 &_register_builtin_comm_hook,262 &_register_builtin_comm_hook,
263 py::arg("reducer"),263 py::arg("reducer"),
264 py::arg("comm_hook_type"));264 py::arg("comm_hook_type"));
265 265 
266 module.def("_broadcast_coalesced",266 module.def("_broadcast_coalesced",
267 // Define a lambda such that the pybind11 prototype can take a std::vector267 // Define a lambda such that the pybind11 prototype can take a std::vector
268 // for the tensor list argument, but still pass it to the underlying268 // for the tensor list argument, but still pass it to the underlying
269 // function as a c10::ArrayRef.269 // function as a c10::ArrayRef.
270 [](c10::intrusive_ptr<::c10d::ProcessGroup> process_group,270 [](c10::intrusive_ptr<::c10d::ProcessGroup> process_group,
271 std::vector<at::Tensor> tensors, // NOLINT271 std::vector<at::Tensor> tensors, // NOLINT
272 size_t buffer_size,272 size_t buffer_size,
273 int rank) {273 int rank) {
274 torch_npu::distributed::broadcast_coalesced(274 torch_npu::distributed::broadcast_coalesced(
275 std::move(process_group), tensors, buffer_size, rank);275 std::move(process_group), tensors, buffer_size, rank);
276 },276 },
277 py::arg("process_group"),277 py::arg("process_group"),
278 py::arg("tensors"),278 py::arg("tensors"),
279 py::arg("buffer_size"),279 py::arg("buffer_size"),
280 // The source of truth rank to broadcast the tensors from.280 // The source of truth rank to broadcast the tensors from.
281 py::arg("src") = 0,281 py::arg("src") = 0,
282 py::call_guard<py::gil_scoped_release>());282 py::call_guard<py::gil_scoped_release>());
283 283 
284 module.def("_is_support_hccl_comm_name", &c10d_npu::isSupportHcclCommName);284 module.def("_is_support_hccl_comm_name", &c10d_npu::isSupportHcclCommName);
285 285 
286 shared_ptr_class_<c10d_npu::Reducer>(module, "Reducer")286 shared_ptr_class_<c10d_npu::Reducer>(module, "Reducer")
287 .def(py::init<287 .def(py::init<
288 std::vector<at::Tensor>,288 std::vector<at::Tensor>,
289 std::vector<std::vector<size_t>>,289 std::vector<std::vector<size_t>>,
290 std::vector<size_t>,290 std::vector<size_t>,
291 c10::intrusive_ptr<::c10d::ProcessGroup>,291 c10::intrusive_ptr<::c10d::ProcessGroup>,
292 std::vector<bool>,292 std::vector<bool>,
293 int64_t,293 int64_t,
294 bool,294 bool,
295 bool,295 bool,
296 std::unordered_map<size_t, std::string>,296 std::unordered_map<size_t, std::string>,
297 int64_t>(),297 int64_t>(),
298 py::arg("params"),298 py::arg("params"),
299 py::arg("bucket_indices"),299 py::arg("bucket_indices"),
300 py::arg("per_bucket_size_limits"),300 py::arg("per_bucket_size_limits"),
301 py::arg("process_group"),301 py::arg("process_group"),
302 py::arg("expect_sparse_gradients") = std::vector<bool>(),302 py::arg("expect_sparse_gradients") = std::vector<bool>(),
303 py::arg("bucket_bytes_cap") = ::c10d::kDefaultBucketBytesCap,303 py::arg("bucket_bytes_cap") = ::c10d::kDefaultBucketBytesCap,
304 py::arg("find_unused_parameters") = false,304 py::arg("find_unused_parameters") = false,
305 py::arg("gradient_as_bucket_view") = false,305 py::arg("gradient_as_bucket_view") = false,
306 py::arg("param_to_name_mapping") =306 py::arg("param_to_name_mapping") =
307 std::unordered_map<size_t, std::string>(),307 std::unordered_map<size_t, std::string>(),
308 py::arg("first_bucket_bytes_cap") = ::c10d::kDefaultFirstBucketBytes,308 py::arg("first_bucket_bytes_cap") = ::c10d::kDefaultFirstBucketBytes,
309 py::call_guard<py::gil_scoped_release>())309 py::call_guard<py::gil_scoped_release>())
310 .def("prepare_for_forward",310 .def("prepare_for_forward",
311 &c10d_npu::Reducer::prepare_for_forward,311 &c10d_npu::Reducer::prepare_for_forward,
312 py::call_guard<py::gil_scoped_release>())312 py::call_guard<py::gil_scoped_release>())
313 .def("prepare_for_backward",313 .def("prepare_for_backward",
314 &c10d_npu::Reducer::prepare_for_backward,314 &c10d_npu::Reducer::prepare_for_backward,
315 py::call_guard<py::gil_scoped_release>())315 py::call_guard<py::gil_scoped_release>())
316 .def("prepare_for_backward",316 .def("prepare_for_backward",
317 [](c10d_npu::Reducer& reducer, const at::Tensor& output)317 [](c10d_npu::Reducer& reducer, const at::Tensor& output)
318 -> void { reducer.prepare_for_backward({output}); },318 -> void { reducer.prepare_for_backward({output}); },
319 py::call_guard<py::gil_scoped_release>())319 py::call_guard<py::gil_scoped_release>())
320 .def("get_backward_stats", &c10d_npu::Reducer::get_backward_stats)320 .def("get_backward_stats", &c10d_npu::Reducer::get_backward_stats)
321 .def("_install_post_backward_futures", [](::c10d_npu::Reducer& reducer, const std::vector<std::shared_ptr<torch::jit::PythonFutureWrapper>>& futs) {321 .def("_install_post_backward_futures", [](::c10d_npu::Reducer& reducer, const std::vector<std::shared_ptr<torch::jit::PythonFutureWrapper>>& futs) {
322 c10::List<c10::intrusive_ptr<c10::ivalue::Future>> futures(c10::FutureType::create(c10::TensorType::get()));322 c10::List<c10::intrusive_ptr<c10::ivalue::Future>> futures(c10::FutureType::create(c10::TensorType::get()));
323 for (const auto &fut : futs) {323 for (const auto &fut : futs) {
324 futures.push_back(fut->fut);324 futures.push_back(fut->fut);
325 }325 }
326 reducer.install_futures(std::move(futures));326 reducer.install_futures(std::move(futures));
327 },327 },
328 py::call_guard<py::gil_scoped_release>())328 py::call_guard<py::gil_scoped_release>())
329 .def("_rebuild_buckets",329 .def("_rebuild_buckets",
330 &::c10d_npu::Reducer::rebuild_buckets,330 &::c10d_npu::Reducer::rebuild_buckets,
331 py::call_guard<py::gil_scoped_release>())331 py::call_guard<py::gil_scoped_release>())
332 .def("_get_zeros_like_grad_buckets",332 .def("_get_zeros_like_grad_buckets",
333 [](::c10d_npu::Reducer& reducer) {333 [](::c10d_npu::Reducer& reducer) {
334 return reducer.get_grad_buckets(true);334 return reducer.get_grad_buckets(true);
335 },335 },
336 py::call_guard<py::gil_scoped_release>())336 py::call_guard<py::gil_scoped_release>())
337 .def("_push_all_rebuilt_params",337 .def("_push_all_rebuilt_params",
338 &::c10d_npu::Reducer::push_rebuilt_params_for_all_indices,338 &::c10d_npu::Reducer::push_rebuilt_params_for_all_indices,
339 py::call_guard<py::gil_scoped_release>())339 py::call_guard<py::gil_scoped_release>())
340 .def("_set_forward_pass_work_handle",340 .def("_set_forward_pass_work_handle",
341 &::c10d_npu::Reducer::set_forward_pass_work_handle,341 &::c10d_npu::Reducer::set_forward_pass_work_handle,
342 py::call_guard<py::gil_scoped_release>())342 py::call_guard<py::gil_scoped_release>())
343 .def("_get_local_used_map",343 .def("_get_local_used_map",
344 &::c10d_npu::Reducer::get_local_used_map_on_device)344 &::c10d_npu::Reducer::get_local_used_map_on_device)
345 .def("_set_ddp_runtime_logging_sample_rate",345 .def("_set_ddp_runtime_logging_sample_rate",
346 &::c10d_npu::Reducer::set_ddp_runtime_logging_sample_rate,346 &::c10d_npu::Reducer::set_ddp_runtime_logging_sample_rate,
347 py::arg("sample_rate"),347 py::arg("sample_rate"),
348 py::call_guard<py::gil_scoped_release>())348 py::call_guard<py::gil_scoped_release>())
349 .def("_set_static_graph",349 .def("_set_static_graph",
350 &::c10d_npu::Reducer::set_static_graph,350 &::c10d_npu::Reducer::set_static_graph,
351 py::call_guard<py::gil_scoped_release>())351 py::call_guard<py::gil_scoped_release>())
352 .def("_ddp_graph_static",352 .def("_ddp_graph_static",
353 &::c10d_npu::Reducer::ddp_graph_static,353 &::c10d_npu::Reducer::ddp_graph_static,
354 py::call_guard<py::gil_scoped_release>())354 py::call_guard<py::gil_scoped_release>())
355 .def("_delay_all_reduce",355 .def("_delay_all_reduce",
356 &::c10d_npu::Reducer::delay_all_reduce,356 &::c10d_npu::Reducer::delay_all_reduce,
357 py::call_guard<py::gil_scoped_release>())357 py::call_guard<py::gil_scoped_release>())
358 .def("_run_comm_hook",358 .def("_run_comm_hook",
359 [](::c10d_npu::Reducer& reducer, ::c10d::GradBucket& bucket)359 [](::c10d_npu::Reducer& reducer, ::c10d::GradBucket& bucket)
360 -> std::shared_ptr<torch::jit::PythonFutureWrapper> {360 -> std::shared_ptr<torch::jit::PythonFutureWrapper> {
361 c10::intrusive_ptr<c10::ivalue::Future> fut =361 c10::intrusive_ptr<c10::ivalue::Future> fut =
362 reducer.run_comm_hook(bucket);362 reducer.run_comm_hook(bucket);
363 return std::make_shared<torch::jit::PythonFutureWrapper>(fut);363 return std::make_shared<torch::jit::PythonFutureWrapper>(fut);
364 },364 },
365 py::call_guard<py::gil_scoped_release>())365 py::call_guard<py::gil_scoped_release>())
366 .def("set_logger",366 .def("set_logger",
367 [](::c10d_npu::Reducer& reducer,367 [](::c10d_npu::Reducer& reducer,
368 const std::shared_ptr<::c10d::Logger> logger) {368 const std::shared_ptr<::c10d::Logger> logger) {
369 std::weak_ptr<::c10d::Logger> logger_weakref = logger;369 std::weak_ptr<::c10d::Logger> logger_weakref = logger;
370 reducer.set_logger(logger_weakref);370 reducer.set_logger(logger_weakref);
371 });371 });
372 372 
373 py::module_ dist = py::module_::import("torch._C._distributed_c10d");373 py::module_ dist = py::module_::import("torch._C._distributed_c10d");
374 auto processGroupHCCL = intrusive_ptr_no_gil_destructor_class_<::c10d_npu::ProcessGroupHCCL>(374 auto processGroupHCCL = intrusive_ptr_no_gil_destructor_class_<::c10d_npu::ProcessGroupHCCL>(
375 module, "ProcessGroupHCCL", dist.attr("Backend"))375 module, "ProcessGroupHCCL", dist.attr("Backend"))
376 .def(py::init<const c10::intrusive_ptr<::c10d::Store>&,376 .def(py::init<const c10::intrusive_ptr<::c10d::Store>&,
377 int,377 int,
378 int,378 int,
379 c10::intrusive_ptr<::c10d_npu::ProcessGroupHCCL::Options>>(),379 c10::intrusive_ptr<::c10d_npu::ProcessGroupHCCL::Options>>(),
380 py::call_guard<py::gil_scoped_release>())380 py::call_guard<py::gil_scoped_release>())
381 .def(py::init([](const c10::intrusive_ptr<::c10d::Store>& store,381 .def(py::init([](const c10::intrusive_ptr<::c10d::Store>& store,
382 int rank,382 int rank,
383 int size,383 int size,
384 const std::chrono::milliseconds& timeout) {384 const std::chrono::milliseconds& timeout) {
385 auto options = ::c10d_npu::ProcessGroupHCCL::Options::create();385 auto options = ::c10d_npu::ProcessGroupHCCL::Options::create();
386 options->is_high_priority_stream = false;386 options->is_high_priority_stream = false;
387 options->timeout = timeout;387 options->timeout = timeout;
388 return c10::make_intrusive<::c10d_npu::ProcessGroupHCCL>(388 return c10::make_intrusive<::c10d_npu::ProcessGroupHCCL>(
389 store, rank, size, options);389 store, rank, size, options);
390 }),390 }),
391 py::arg("store"),391 py::arg("store"),
392 py::arg("rank"),392 py::arg("rank"),
393 py::arg("size"),393 py::arg("size"),
394 py::arg("timeout") = kProcessGroupDefaultTimeout,394 py::arg("timeout") = kProcessGroupDefaultTimeout,
395 py::call_guard<py::gil_scoped_release>())395 py::call_guard<py::gil_scoped_release>())
396 .def("get_hccl_comm", &::c10d_npu::ProcessGroupHCCL::getHcclComm)396 .def("get_hccl_comm", &::c10d_npu::ProcessGroupHCCL::getHcclComm)
397 .def("_set_hccl_comm_name", &::c10d_npu::ProcessGroupHCCL::setHcclCommName)397 .def("_set_hccl_comm_name", &::c10d_npu::ProcessGroupHCCL::setHcclCommName)
398 .def("resume_hccl_comm", &::c10d_npu::ProcessGroupHCCL::resumeHcclComm)398 .def("resume_hccl_comm", &::c10d_npu::ProcessGroupHCCL::resumeHcclComm)
399 .def("_set_switch_nic_comm",399 .def("_set_switch_nic_comm",
400 &::c10d_npu::ProcessGroupHCCL::setSwitchNicComm,400 &::c10d_npu::ProcessGroupHCCL::setSwitchNicComm,
401 py::arg("rankid"),401 py::arg("rankid"),
402 py::arg("nRanks"),402 py::arg("nRanks"),
403 py::arg("ranks") = std::vector<uint32_t>{},403 py::arg("ranks") = std::vector<uint32_t>{},
404 py::arg("useBackup") = std::vector<bool>{})404 py::arg("useBackup") = std::vector<bool>{})
405 .def("abort_hccl_comm", &::c10d_npu::ProcessGroupHCCL::abortAndClearHcclComm)405 .def("abort_hccl_comm", &::c10d_npu::ProcessGroupHCCL::abortAndClearHcclComm)
406 .def("_delete_tcpstore_key", &::c10d_npu::ProcessGroupHCCL::deleteTCPStoreKey)406 .def("_delete_tcpstore_key", &::c10d_npu::ProcessGroupHCCL::deleteTCPStoreKey)
407 .def("set_watchdog_status", &::c10d_npu::ProcessGroupHCCL::setWatchdogStatus)407 .def("set_watchdog_status", &::c10d_npu::ProcessGroupHCCL::setWatchdogStatus)
408 .def("clear_workmeta_list", &::c10d_npu::ProcessGroupHCCL::clearWorkMetaList)408 .def("clear_workmeta_list", &::c10d_npu::ProcessGroupHCCL::clearWorkMetaList)
409 .def("get_hccl_comm_name",409 .def("get_hccl_comm_name",
410 [](::c10d_npu::ProcessGroupHCCL &pg, int rankid, py::args args, py::kwargs kwargs)410 [](::c10d_npu::ProcessGroupHCCL &pg, int rankid, py::args args, py::kwargs kwargs)
411 -> std::string {411 -> std::string {
412 bool init_comm = true;412 bool init_comm = true;
413 if (kwargs.contains("init_comm")) {413 if (kwargs.contains("init_comm")) {
414 init_comm = py::cast<bool>(kwargs["init_comm"]);414 init_comm = py::cast<bool>(kwargs["init_comm"]);
415 }415 }
416 return pg.getHcclCommName(rankid, init_comm);416 return pg.getHcclCommName(rankid, init_comm);
417 })417 })
418 .def("_get_stream_id", &::c10d_npu::ProcessGroupHCCL::getStreamId,418 .def("_get_stream_id", &::c10d_npu::ProcessGroupHCCL::getStreamId,
419 py::arg("p2p") = false,419 py::arg("p2p") = false,
420 py::arg("peer") = -1)420 py::arg("peer") = -1)
421 .def("get_coll_stream_id", &::c10d_npu::ProcessGroupHCCL::getCollNpuStreamId,421 .def("get_coll_stream_id", &::c10d_npu::ProcessGroupHCCL::getCollNpuStreamId,
422 py::arg("device"))422 py::arg("device"))
423 .def("get_p2p_stream_id", &::c10d_npu::ProcessGroupHCCL::getP2PStreamId,423 .def("get_p2p_stream_id", &::c10d_npu::ProcessGroupHCCL::getP2PStreamId,
424 py::arg("device"),424 py::arg("device"),
425 py::arg("peer"),425 py::arg("peer"),
426 py::arg("is_batched"))426 py::arg("is_batched"))
427 .def("_window_register_and_exchange", &::c10d_npu::ProcessGroupHCCL::windowRegisterAndExchange,427 .def("_window_register_and_exchange", &::c10d_npu::ProcessGroupHCCL::windowRegisterAndExchange,
428 py::arg("window_size"),428 py::arg("window_size"),
429 py::arg("peer_ranks"))429 py::arg("peer_ranks"))
430 .def("_get_window_mem", &::c10d_npu::ProcessGroupHCCL::getWindowMem)430 .def("_get_window_mem", &::c10d_npu::ProcessGroupHCCL::getWindowMem)
431 .def_property_readonly("options", &::c10d_npu::ProcessGroupHCCL::getOptions)431 .def_property_readonly("options", &::c10d_npu::ProcessGroupHCCL::getOptions)
432 .def("batch_isend_irecv",432 .def("batch_isend_irecv",
433 [](::c10d_npu::ProcessGroupHCCL &pg, std::vector<std::string> &op_type,433 [](::c10d_npu::ProcessGroupHCCL &pg, std::vector<std::string> &op_type,
434 std::vector<at::Tensor> &tensors,434 std::vector<at::Tensor> &tensors,
435 std::vector<int64_t> remote_rank_list)435 std::vector<int64_t> remote_rank_list)
436 -> c10::intrusive_ptr<c10d::Work> {436 -> c10::intrusive_ptr<c10d::Work> {
437 return pg.batch_isend_irecv(op_type, tensors, remote_rank_list);437 return pg.batch_isend_irecv(op_type, tensors, remote_rank_list);
438 },438 },
439 py::call_guard<py::gil_scoped_release>())439 py::call_guard<py::gil_scoped_release>())
440 .def("reduce_scatter_tensor_uneven",440 .def("reduce_scatter_tensor_uneven",
441 &::c10d_npu::ProcessGroupHCCL::_reduce_scatter_base_uneven,441 &::c10d_npu::ProcessGroupHCCL::_reduce_scatter_base_uneven,
442 py::arg("output"),442 py::arg("output"),
443 py::arg("input"),443 py::arg("input"),
444 py::arg("input_split_sizes") = std::vector<int64_t>{},444 py::arg("input_split_sizes") = std::vector<int64_t>{},
445 py::arg("opts") = ::c10d::ReduceScatterOptions(),445 py::arg("opts") = ::c10d::ReduceScatterOptions(),
446 py::call_guard<py::gil_scoped_release>())446 py::call_guard<py::gil_scoped_release>())
447 .def("all_gather_into_tensor_uneven",447 .def("all_gather_into_tensor_uneven",
448 &::c10d_npu::ProcessGroupHCCL::_allgather_base_uneven,448 &::c10d_npu::ProcessGroupHCCL::_allgather_base_uneven,
449 py::arg("output"),449 py::arg("output"),
450 py::arg("input"),450 py::arg("input"),
451 py::arg("output_split_sizes") = std::vector<int64_t>{},451 py::arg("output_split_sizes") = std::vector<int64_t>{},
452 py::arg("opts") = ::c10d::AllgatherOptions(),452 py::arg("opts") = ::c10d::AllgatherOptions(),
453 py::call_guard<py::gil_scoped_release>())453 py::call_guard<py::gil_scoped_release>())
454 .def("_set_default_timeout",454 .def("_set_default_timeout",
455 &::c10d_npu::ProcessGroupHCCL::setTimeout,455 &::c10d_npu::ProcessGroupHCCL::setTimeout,
456 py::arg("timeout"),456 py::arg("timeout"),
457 py::call_guard<py::gil_scoped_release>())457 py::call_guard<py::gil_scoped_release>())
458 .def("_add_ephemeral_timeout",458 .def("_add_ephemeral_timeout",
459 &::c10d_npu::ProcessGroupHCCL::addEphemeralTimeout,459 &::c10d_npu::ProcessGroupHCCL::addEphemeralTimeout,
460 py::arg("timeout"),460 py::arg("timeout"),
461 py::call_guard<py::gil_scoped_release>());461 py::call_guard<py::gil_scoped_release>());
462 462 
463 intrusive_ptr_class_<::c10d_npu::ProcessGroupHCCL::Options>(463 intrusive_ptr_class_<::c10d_npu::ProcessGroupHCCL::Options>(
464 processGroupHCCL,464 processGroupHCCL,
465 "Options",465 "Options",
466 dist.attr("Backend").attr("Options"))466 dist.attr("Backend").attr("Options"))
467 .def(py::init<>())467 .def(py::init<>())
468 .def_readwrite("op_timeout", &::c10d_npu::ProcessGroupHCCL::Options::opTimeout)468 .def_readwrite("op_timeout", &::c10d_npu::ProcessGroupHCCL::Options::opTimeout)
469 .def_readwrite("is_high_priority_stream",469 .def_readwrite("is_high_priority_stream",
470 &::c10d_npu::ProcessGroupHCCL::Options::is_high_priority_stream)470 &::c10d_npu::ProcessGroupHCCL::Options::is_high_priority_stream)
471 .def_readwrite("global_ranks_in_group",471 .def_readwrite("global_ranks_in_group",
472 &::c10d_npu::ProcessGroupHCCL::Options::global_ranks_in_group)472 &::c10d_npu::ProcessGroupHCCL::Options::global_ranks_in_group)
473 .def_readwrite("hccl_config", &::c10d_npu::ProcessGroupHCCL::Options::hccl_config)473 .def_readwrite("hccl_config", &::c10d_npu::ProcessGroupHCCL::Options::hccl_config)
474 .def_readwrite("group_id",474 .def_readwrite("group_id",
475 &::c10d_npu::ProcessGroupHCCL::Options::group_id);475 &::c10d_npu::ProcessGroupHCCL::Options::group_id);
476 476
477 // bind for ProcessGroupLCCL477 // bind for ProcessGroupLCCL
478 auto processGroupLCCL = intrusive_ptr_no_gil_destructor_class_<::c10d_npu::ProcessGroupLCCL>(478 auto processGroupLCCL = intrusive_ptr_no_gil_destructor_class_<::c10d_npu::ProcessGroupLCCL>(
479 module, "ProcessGroupLCCL", dist.attr("Backend"))479 module, "ProcessGroupLCCL", dist.attr("Backend"))
480 .def(py::init<const c10::intrusive_ptr<::c10d::Store>&, int, int>(),480 .def(py::init<const c10::intrusive_ptr<::c10d::Store>&, int, int>(),
481 py::call_guard<py::gil_scoped_release>());481 py::call_guard<py::gil_scoped_release>());
482 482 
483 auto cDist = py::module_::import("torch._C._distributed_c10d");483 auto cDist = py::module_::import("torch._C._distributed_c10d");
484 auto parallelStore = intrusive_ptr_no_gil_destructor_class_<::c10d::ParallelTcpStore>(484 auto parallelStore = intrusive_ptr_no_gil_destructor_class_<::c10d::ParallelTcpStore>(
485 module, "ParallelStore", cDist.attr("Store"), R"(485 module, "ParallelStore", cDist.attr("Store"), R"(
486A TCP-Parallel-Epoll-based distributed key-value store implementation. The server store holds486A TCP-Parallel-Epoll-based distributed key-value store implementation. The server store holds
487the data, while the client stores can connect to the server store over TCP and487the data, while the client stores can connect to the server store over TCP and
488perform actions such as :meth:`~torch.distributed.store.set` to insert a key-value488perform actions such as :meth:`~torch.distributed.store.set` to insert a key-value
489pair, :meth:`~torch.distributed.store.get` to retrieve a key-value pair, etc. There489pair, :meth:`~torch.distributed.store.get` to retrieve a key-value pair, etc. There
490should always be one server store initialized because the client store(s) will wait for490should always be one server store initialized because the client store(s) will wait for
491the server to establish a connection.491the server to establish a connection.
492 492 
493Arguments:493Arguments:
494 host_name (str): The hostname or IP Address the server store should run on.494 host_name (str): The hostname or IP Address the server store should run on.
495 port (int): The port on which the server store should listen for incoming requests.495 port (int): The port on which the server store should listen for incoming requests.
496 world_size (int, optional): The total number of store users (number of clients + 1 for the server). Default is -1 (a negative value indicates a non-fixed number of store users).496 world_size (int, optional): The total number of store users (number of clients + 1 for the server). Default is -1 (a negative value indicates a non-fixed number of store users).
497 agentRun(bool): The client(worker), agentRun is False. The agent(proxy), agentRun is True.497 agentRun(bool): The client(worker), agentRun is False. The agent(proxy), agentRun is True.
498 agentPid(int): Generally, a single `torch_run` is launched on a node. If multiple `torch_run` are launched on a node, the agentPid refers to the process ID (PID) of each `torch_run`.498 agentPid(int): Generally, a single `torch_run` is launched on a node. If multiple `torch_run` are launched on a node, the agentPid refers to the process ID (PID) of each `torch_run`.
499 The pid transmit to the worker through environment variable and is used for local socket communication.499 The pid transmit to the worker through environment variable and is used for local socket communication.
500 is_master (bool, optional): True when initializing the server store and False for client stores. Default is False.500 is_master (bool, optional): True when initializing the server store and False for client stores. Default is False.
501 enableTiered(bool, optional): parallel tcpstore tiered optimization, if True, The agent adds a proxy role, the worker on the node connects to the proxy via Unix Domain Socket.501 enableTiered(bool, optional): parallel tcpstore tiered optimization, if True, The agent adds a proxy role, the worker on the node connects to the proxy via Unix Domain Socket.
502 and the proxy connects to the server via TCP, completing the establishment and communication of the connection., Default is False.502 and the proxy connects to the server via TCP, completing the establishment and communication of the connection., Default is False.
503 timeout (timedelta, optional): Timeout used by the store during initialization and for methods such as :meth:`~torch.distributed.store.get` and :meth:`~torch.distributed.store.wait`. Default is timedelta(seconds=300)503 timeout (timedelta, optional): Timeout used by the store during initialization and for methods such as :meth:`~torch.distributed.store.get` and :meth:`~torch.distributed.store.wait`. Default is timedelta(seconds=300)
504 wait_for_worker (bool, optional): Whether to wait for all the workers to connect with the server store. This is only applicable when world_size is a fixed value. Default is True.504 wait_for_worker (bool, optional): Whether to wait for all the workers to connect with the server store. This is only applicable when world_size is a fixed value. Default is True.
505 505 
506--enable_tiered_parallel_tcpstore = "false":506--enable_tiered_parallel_tcpstore = "false":
507Example::507Example::
508 >>> import torch_npu.distributed as dist508 >>> import torch_npu.distributed as dist
509 >>> from datetime import timedelta509 >>> from datetime import timedelta
510 >>> # Run on process 1 (server)510 >>> # Run on process 1 (server)
511 >>> server_store = dist.ParallelStore("127.0.0.1", 1234, 2, True, 100, True, timedelta(seconds=30))511 >>> server_store = dist.ParallelStore("127.0.0.1", 1234, 2, True, 100, True, timedelta(seconds=30))
512 >>> # Run on process 2 (client)512 >>> # Run on process 2 (client)
513 >>> client_store = dist.ParallelStore("127.0.0.1", 1234, 2, False, 100, False)513 >>> client_store = dist.ParallelStore("127.0.0.1", 1234, 2, False, 100, False)
514 >>> # Use any of the store methods from either the client or server after initialization514 >>> # Use any of the store methods from either the client or server after initialization
515 >>> server_store.set("first_key", "first_value")515 >>> server_store.set("first_key", "first_value")
516 >>> client_store.get("first_key")516 >>> client_store.get("first_key")
517 517 
518--enable_tiered_parallel_tcpstore = "true":518--enable_tiered_parallel_tcpstore = "true":
519Example::519Example::
520 >>> import torch_npu.distributed as dist520 >>> import torch_npu.distributed as dist
521 >>> from datetime import timedelta521 >>> from datetime import timedelta
522 >>> # Run on process 1 (server proxy)522 >>> # Run on process 1 (server proxy)
523 >>> server_store = dist.ParallelStore("127.0.0.1", 1234, 2, True, 100, True, True, timedelta(seconds=30))523 >>> server_store = dist.ParallelStore("127.0.0.1", 1234, 2, True, 100, True, True, timedelta(seconds=30))
524 >>> # Run on process 2 (client)524 >>> # Run on process 2 (client)
525 >>> client_store = dist.ParallelStore("127.0.0.1", 1234, 2, False, 100, False, True)525 >>> client_store = dist.ParallelStore("127.0.0.1", 1234, 2, False, 100, False, True)
526 >>> # Use any of the store methods from either the client or server and proxy after initialization526 >>> # Use any of the store methods from either the client or server and proxy after initialization
527 >>> server_store.set("first_key", "first_value")527 >>> server_store.set("first_key", "first_value")
528 >>> client_store.get("first_key")528 >>> client_store.get("first_key")
529 )")529 )")
530 530 
531 .def(py::init([](const std::string &host,531 .def(py::init([](const std::string &host,
532 uint16_t port,532 uint16_t port,
533 int worldSize,533 int worldSize,
534 bool agentRun,534 bool agentRun,
535 uint32_t agentPid,535 uint32_t agentPid,
536 bool isServer,536 bool isServer,
537 bool enableTiered,537 bool enableTiered,
538 std::chrono::milliseconds timeout,538 std::chrono::milliseconds timeout,
539 bool waitWorkers,539 bool waitWorkers,
540 bool multiTenant) {540 bool multiTenant) {
541 c10::optional<std::size_t> numWorkers = c10::nullopt;541 c10::optional<std::size_t> numWorkers = c10::nullopt;
542 if (worldSize > -1) {542 if (worldSize > -1) {
543 numWorkers = static_cast<std::size_t>(worldSize);543 numWorkers = static_cast<std::size_t>(worldSize);
544 }544 }
545 ::c10d::TCPStoreOptions opts{ port, isServer, numWorkers, waitWorkers, timeout, multiTenant };545 ::c10d::TCPStoreOptions opts{ port, isServer, numWorkers, waitWorkers, timeout, multiTenant };
546 return c10::make_intrusive <::c10d::ParallelTcpStore>(host, agentRun, agentPid, enableTiered, opts);546 return c10::make_intrusive <::c10d::ParallelTcpStore>(host, agentRun, agentPid, enableTiered, opts);
547 }),547 }),
548 py::arg("host") = "127.0.0.1",548 py::arg("host") = "127.0.0.1",
549 py::arg("port") = 29500,549 py::arg("port") = 29500,
550 py::arg("world_size") = -1,550 py::arg("world_size") = -1,
551 py::arg("agent_run") = false,551 py::arg("agent_run") = false,
552 py::arg("agent_pid") = -1,552 py::arg("agent_pid") = -1,
553 py::arg("is_server") = false,553 py::arg("is_server") = false,
554 py::arg("enable_tiered") = false,554 py::arg("enable_tiered") = false,
555 py::arg("timeout") = std::chrono::milliseconds(300000),555 py::arg("timeout") = std::chrono::milliseconds(300000),
556 py::arg("wait_workers") = true,556 py::arg("wait_workers") = true,
557 py::arg("multi_tenant") = false);557 py::arg("multi_tenant") = false);
558 558 
559 module.def("_dump_hccl_trace_json",559 module.def("_dump_hccl_trace_json",
560 [](std::optional<bool> includeCollectives,560 [](std::optional<bool> includeCollectives,
561 std::optional<bool> onlyActive) {561 std::optional<bool> onlyActive) {
562 return py::bytes(::c10d_npu::dump_hccl_trace_json(562 return py::bytes(::c10d_npu::dump_hccl_trace_json(
563 includeCollectives.value_or(true), onlyActive.value_or(false)));563 includeCollectives.value_or(true), onlyActive.value_or(false)));
564 },564 },
565 py::arg("includeCollectives") = std::optional<bool>(),565 py::arg("includeCollectives") = std::optional<bool>(),
566 py::arg("onlyActive") = std::optional<bool>(),566 py::arg("onlyActive") = std::optional<bool>(),
567 R"(567 R"(
568 Arguments:568 Arguments:
569 includeCollectives(bool, optional): Whether to include collective work traces. Default is True.569 includeCollectives(bool, optional): Whether to include collective work traces. Default is True.
570 onlyActive (bool, optional): Whether to only include active collective work traces. Default is False.570 onlyActive (bool, optional): Whether to only include active collective work traces. Default is False.
571 Returns:571 Returns:
572 Stringified json work traces.572 Stringified json work traces.
573 Default settings return everything - i.e. contains HCCL comm dumps and collective traces.573 Default settings return everything - i.e. contains HCCL comm dumps and collective traces.
574 )");574 )");
575 module.def("_dump_hccl_trace",575 module.def("_dump_hccl_trace",
576 [](std::optional<bool> includeCollectives,576 [](std::optional<bool> includeCollectives,
577 std::optional<bool> includeStackTraces,577 std::optional<bool> includeStackTraces,
578 std::optional<bool> onlyActive) {578 std::optional<bool> onlyActive) {
579 return py::bytes(::c10d_npu::dump_hccl_trace(579 return py::bytes(::c10d_npu::dump_hccl_trace(
580 includeCollectives.value_or(true),580 includeCollectives.value_or(true),
581 includeStackTraces.value_or(true),581 includeStackTraces.value_or(true),
582 onlyActive.value_or(false)));582 onlyActive.value_or(false)));
583 },583 },
584 py::arg("includeCollectives") = std::optional<bool>(),584 py::arg("includeCollectives") = std::optional<bool>(),
585 py::arg("includeStackTraces") = std::optional<bool>(),585 py::arg("includeStackTraces") = std::optional<bool>(),
586 py::arg("onlyActive") = std::optional<bool>(),586 py::arg("onlyActive") = std::optional<bool>(),
587 R"(587 R"(
588 Arguments:588 Arguments:
589 includeCollectives(bool, optional): Whether to include collective work traces. Default is True.589 includeCollectives(bool, optional): Whether to include collective work traces. Default is True.
590 includeStackTraces(bool, optional): Whether to include stacktraces in the collective work traces. Default is True.590 includeStackTraces(bool, optional): Whether to include stacktraces in the collective work traces. Default is True.
591 onlyActive (bool, optional): Whether to only include active collective work traces. Default is False.591 onlyActive (bool, optional): Whether to only include active collective work traces. Default is False.
592 Returns:592 Returns:
593 Stringified pickle work traces.593 Stringified pickle work traces.
594 Default settings return everything - i.e. contains HCCL comm dumps and collective traces.594 Default settings return everything - i.e. contains HCCL comm dumps and collective traces.
595 )");595 )");
596 596 
597 Py_RETURN_TRUE;597 Py_RETURN_TRUE;
598}598}
599 599 
600// c10d methods on torch._C600// c10d methods on torch._C
601static PyMethodDef methods[] = { // NOLINT601static PyMethodDef methods[] = { // NOLINT
602 {"_c10d_npu_init", c10d_npu_init, METH_NOARGS, nullptr},602 {"_c10d_npu_init", c10d_npu_init, METH_NOARGS, nullptr},
603#ifdef USE_RPC_FRAMEWORK603#ifdef USE_RPC_FRAMEWORK
604 {"_rpc_npu_init", rpc::rpc_npu_init, METH_NOARGS, nullptr},604 {"_rpc_npu_init", rpc::rpc_npu_init, METH_NOARGS, nullptr},
605#endif605#endif
606 {nullptr, nullptr, 0, nullptr}};606 {nullptr, nullptr, 0, nullptr}};
607 607 
608PyMethodDef* python_functions()608PyMethodDef* python_functions()
609{609{
610 return methods;610 return methods;
611}611}
612 612 
613} // namespace distributed613} // namespace distributed
614} // namespace torch_npu614} // namespace torch_npu
Mtorch_npu/csrc/distributed/Init.h+11-11
@@ -1,12 +1,12 @@
1#pragma once1#pragma once
2 2 
3#include <torch/csrc/python_headers.h>3#include <torch/csrc/python_headers.h>
4#include "torch_npu/csrc/core/npu/NPUMacros.h"4#include "torch_npu/csrc/core/npu/NPUMacros.h"
5 5 
6namespace torch_npu {6namespace torch_npu {
7namespace distributed {7namespace distributed {
8 8 
9TORCH_NPU_API PyMethodDef* python_functions();9TORCH_NPU_API PyMethodDef* python_functions();
10 10 
11} // namespace distributed11} // namespace distributed
12} // namespace torch_npu12} // namespace torch_npu
Mtorch_npu/csrc/distributed/default_comm_hooks.cpp+57-57
@@ -1,57 +1,57 @@
1#include <c10d/default_comm_hooks.hpp>1#include <c10d/default_comm_hooks.hpp>
2#include <c10/core/ScalarType.h>2#include <c10/core/ScalarType.h>
3#include <c10/util/Exception.h>3#include <c10/util/Exception.h>
4 4 
5#include <c10d/ProcessGroup.hpp>5#include <c10d/ProcessGroup.hpp>
6#include <c10d/comm.hpp>6#include <c10d/comm.hpp>
7#include <torch/torch.h>7#include <torch/torch.h>
8 8 
9#include "torch_npu/csrc/core/npu/NPUException.h"9#include "torch_npu/csrc/core/npu/NPUException.h"
10 10 
11namespace c10d {11namespace c10d {
12 12 
13c10::intrusive_ptr<c10::ivalue::Future> AllReduceCommHook::runHook(13c10::intrusive_ptr<c10::ivalue::Future> AllReduceCommHook::runHook(
14 GradBucket& bucket)14 GradBucket& bucket)
15{15{
16 std::vector<at::Tensor> tensors = {bucket.getBufferRef()};16 std::vector<at::Tensor> tensors = {bucket.getBufferRef()};
17 // Apply the division first to avoid overflow, especially for FP16.17 // Apply the division first to avoid overflow, especially for FP16.
18 tensors[0] /= state_->getSize();18 tensors[0] /= state_->getSize();
19 return state_->allreduce(tensors)->getFuture();19 return state_->allreduce(tensors)->getFuture();
20}20}
21 21 
22c10::intrusive_ptr<c10::ivalue::Future> FP16CompressCommHook::runHook(22c10::intrusive_ptr<c10::ivalue::Future> FP16CompressCommHook::runHook(
23 GradBucket& bucket)23 GradBucket& bucket)
24{24{
25 auto compressed_tensor = bucket.getBufferRef().to(torch::kFloat16);25 auto compressed_tensor = bucket.getBufferRef().to(torch::kFloat16);
26 // Apply the division first to avoid overflow.26 // Apply the division first to avoid overflow.
27 compressed_tensor /= state_->getSize();27 compressed_tensor /= state_->getSize();
28 std::vector<at::Tensor> tensors = {compressed_tensor};28 std::vector<at::Tensor> tensors = {compressed_tensor};
29 29 
30 auto allreduce_fut = state_->allreduce(tensors)->getFuture();30 auto allreduce_fut = state_->allreduce(tensors)->getFuture();
31 auto decompressed_tensor = bucket.getBufferRef();31 auto decompressed_tensor = bucket.getBufferRef();
32 auto decompress = [decompressed_tensor](c10::ivalue::Future& allreduce_fut) {32 auto decompress = [decompressed_tensor](c10::ivalue::Future& allreduce_fut) {
33 auto result = allreduce_fut.value();33 auto result = allreduce_fut.value();
34 TORCH_INTERNAL_ASSERT(34 TORCH_INTERNAL_ASSERT(
35 result.isTensorList(),35 result.isTensorList(),
36 "ProcessGroup::allreduce should return TensorList", DIST_ERROR(ErrCode::INTERNAL));36 "ProcessGroup::allreduce should return TensorList", DIST_ERROR(ErrCode::INTERNAL));
37 37 
38 auto reduce_tensor = result.toTensorVector()[0];38 auto reduce_tensor = result.toTensorVector()[0];
39 TORCH_INTERNAL_ASSERT_DEBUG_ONLY(39 TORCH_INTERNAL_ASSERT_DEBUG_ONLY(
40 reduce_tensor.scalar_type() == at::ScalarType::Half,40 reduce_tensor.scalar_type() == at::ScalarType::Half,
41 "Expected reduced tensor to be fp16 in FP16CompressHook, but got type ",41 "Expected reduced tensor to be fp16 in FP16CompressHook, but got type ",
42 reduce_tensor.scalar_type(), DIST_ERROR(ErrCode::TYPE)42 reduce_tensor.scalar_type(), DIST_ERROR(ErrCode::TYPE)
43 );43 );
44 decompressed_tensor.copy_(reduce_tensor);44 decompressed_tensor.copy_(reduce_tensor);
45 return c10::IValue(decompressed_tensor);45 return c10::IValue(decompressed_tensor);
46 };46 };
47 47 
48 return allreduce_fut->then(decompress, allreduce_fut->elementType());48 return allreduce_fut->then(decompress, allreduce_fut->elementType());
49}49}
50 50 
51c10::intrusive_ptr<c10::ivalue::Future> _AllReduceBySumCommHook::runHook(GradBucket& bucket)51c10::intrusive_ptr<c10::ivalue::Future> _AllReduceBySumCommHook::runHook(GradBucket& bucket)
52{52{
53 std::vector<at::Tensor> tensors = {bucket.getBufferRef()};53 std::vector<at::Tensor> tensors = {bucket.getBufferRef()};
54 return state_->allreduce(tensors)->getFuture();54 return state_->allreduce(tensors)->getFuture();
55}55}
56 56 
57} // namespace c10d57} // namespace c10d
Mtorch_npu/csrc/distributed/default_comm_hooks.hpp+48-48
@@ -1,48 +1,48 @@
1#pragma once1#pragma once
2 2 
3#include <c10d/ProcessGroup.hpp>3#include <c10d/ProcessGroup.hpp>
4#include <c10d/comm.hpp>4#include <c10d/comm.hpp>
5 5 
6namespace c10d {6namespace c10d {
7 7 
8enum class BuiltinCommHookType {8enum class BuiltinCommHookType {
9 ALLREDUCE = 1,9 ALLREDUCE = 1,
10 FP16_COMPRESS = 2,10 FP16_COMPRESS = 2,
11};11};
12 12 
13class AllReduceCommHook : public CppCommHookInterface<c10::intrusive_ptr<ProcessGroup>> {13class AllReduceCommHook : public CppCommHookInterface<c10::intrusive_ptr<ProcessGroup>> {
14public:14public:
15 explicit AllReduceCommHook(c10::intrusive_ptr<ProcessGroup> state)15 explicit AllReduceCommHook(c10::intrusive_ptr<ProcessGroup> state)
16 : CppCommHookInterface<c10::intrusive_ptr<ProcessGroup>>(state) {}16 : CppCommHookInterface<c10::intrusive_ptr<ProcessGroup>>(state) {}
17 17 
18 ~AllReduceCommHook() override = default;18 ~AllReduceCommHook() override = default;
19 19 
20 c10::intrusive_ptr<c10::ivalue::Future> runHook(GradBucket& bucket) override;20 c10::intrusive_ptr<c10::ivalue::Future> runHook(GradBucket& bucket) override;
21};21};
22 22 
23class FP16CompressCommHook : public CppCommHookInterface<c10::intrusive_ptr<ProcessGroup>> {23class FP16CompressCommHook : public CppCommHookInterface<c10::intrusive_ptr<ProcessGroup>> {
24public:24public:
25 explicit FP16CompressCommHook(c10::intrusive_ptr<ProcessGroup> state)25 explicit FP16CompressCommHook(c10::intrusive_ptr<ProcessGroup> state)
26 : CppCommHookInterface<c10::intrusive_ptr<ProcessGroup>>(state) {}26 : CppCommHookInterface<c10::intrusive_ptr<ProcessGroup>>(state) {}
27 27 
28 ~FP16CompressCommHook() override = default;28 ~FP16CompressCommHook() override = default;
29 29 
30 c10::intrusive_ptr<c10::ivalue::Future> runHook(GradBucket& bucket) override;30 c10::intrusive_ptr<c10::ivalue::Future> runHook(GradBucket& bucket) override;
31};31};
32 32 
33// Almost same as AllReduceCommHook, but without division inside the hook.33// Almost same as AllReduceCommHook, but without division inside the hook.
34// This enables the optimization of fusing copy and division and saves one scan34// This enables the optimization of fusing copy and division and saves one scan
35// over all the input parameters, when no communication hook is provided by the user.35// over all the input parameters, when no communication hook is provided by the user.
36// Only used internally and not released as a public built-in communication hook.36// Only used internally and not released as a public built-in communication hook.
37class _AllReduceBySumCommHook37class _AllReduceBySumCommHook
38 : public CppCommHookInterface<c10::intrusive_ptr<ProcessGroup>> {38 : public CppCommHookInterface<c10::intrusive_ptr<ProcessGroup>> {
39public:39public:
40 explicit _AllReduceBySumCommHook(c10::intrusive_ptr<ProcessGroup> state)40 explicit _AllReduceBySumCommHook(c10::intrusive_ptr<ProcessGroup> state)
41 : CppCommHookInterface<c10::intrusive_ptr<ProcessGroup>>(state) {}41 : CppCommHookInterface<c10::intrusive_ptr<ProcessGroup>>(state) {}
42 42 
43 ~_AllReduceBySumCommHook() override = default;43 ~_AllReduceBySumCommHook() override = default;
44 44 
45 c10::intrusive_ptr<c10::ivalue::Future> runHook(GradBucket& bucket) override;45 c10::intrusive_ptr<c10::ivalue::Future> runHook(GradBucket& bucket) override;
46};46};
47 47 
48} // namespace c10d48} // namespace c10d
Mtorch_npu/csrc/distributed/reducer.cpp+2161-2161
Mtorch_npu/csrc/distributed/reducer.hpp+622-622
@@ -1,622 +1,622 @@
1#pragma once1#pragma once
2 2 
3#include <atomic>3#include <atomic>
4#include <memory>4#include <memory>
5#include <mutex>5#include <mutex>
6#include <tuple>6#include <tuple>
7#include <unordered_map>7#include <unordered_map>
8#include <vector>8#include <vector>
9 9 
10#include <ATen/core/ivalue_inl.h>10#include <ATen/core/ivalue_inl.h>
11#include <c10/macros/Macros.h>11#include <c10/macros/Macros.h>
12#include <c10/util/ApproximateClock.h>12#include <c10/util/ApproximateClock.h>
13#include <c10/util/intrusive_ptr.h>13#include <c10/util/intrusive_ptr.h>
14#include <c10d/ProcessGroup.hpp>14#include <c10d/ProcessGroup.hpp>
15#include <c10d/Utils.hpp>15#include <c10d/Utils.hpp>
16#include <c10d/Work.hpp>16#include <c10d/Work.hpp>
17#include <c10d/comm.hpp>17#include <c10d/comm.hpp>
18#include <c10d/default_comm_hooks.hpp>18#include <c10d/default_comm_hooks.hpp>
19#include <torch/csrc/autograd/function.h>19#include <torch/csrc/autograd/function.h>
20#include <torch/csrc/autograd/profiler.h>20#include <torch/csrc/autograd/profiler.h>
21#include <torch/csrc/autograd/variable.h>21#include <torch/csrc/autograd/variable.h>
22#ifndef _WIN3222#ifndef _WIN32
23#include <torch/csrc/distributed/autograd/context/context.h>23#include <torch/csrc/distributed/autograd/context/context.h>
24#endif24#endif
25#include <c10d/logger.hpp>25#include <c10d/logger.hpp>
26#include <c10d/debug.h>26#include <c10d/debug.h>
27 27 
28namespace c10d_npu {28namespace c10d_npu {
29 29 
30constexpr int kDefaultFirstBucketBytes = int(1024 * 1024);30constexpr int kDefaultFirstBucketBytes = int(1024 * 1024);
31constexpr int kDefaultBucketBytesCap = int(25 * 1024 * 1024);31constexpr int kDefaultBucketBytesCap = int(25 * 1024 * 1024);
32// Collect runtime stats once for every kDDPRuntimeLoggingSampleRate iterations.32// Collect runtime stats once for every kDDPRuntimeLoggingSampleRate iterations.
33constexpr int kDDPRuntimeLoggingSampleRate = 100;33constexpr int kDDPRuntimeLoggingSampleRate = 100;
34constexpr int kUnsetTime = -1;34constexpr int kUnsetTime = -1;
35 35 
36inline int64_t current_time_in_nanos()36inline int64_t current_time_in_nanos()
37{37{
38 return c10::getTime();38 return c10::getTime();
39}39}
40 40 
41// Forward declaration41// Forward declaration
42class Logger;42class Logger;
43 43 
44class TORCH_API Timer {44class TORCH_API Timer {
45private:45private:
46 // The timestamp of forward call start time in each iteration.46 // The timestamp of forward call start time in each iteration.
47 int64_t forward_start_time = kUnsetTime;47 int64_t forward_start_time = kUnsetTime;
48 // The timestamp of backward computation start and end time in each48 // The timestamp of backward computation start and end time in each
49 // iteration.49 // iteration.
50 int64_t backward_compute_start_time = kUnsetTime;50 int64_t backward_compute_start_time = kUnsetTime;
51 int64_t backward_compute_end_time = kUnsetTime;51 int64_t backward_compute_end_time = kUnsetTime;
52 // The timestamp of first communication call start time in each iteration.52 // The timestamp of first communication call start time in each iteration.
53 int64_t backward_comm_start_time = kUnsetTime;53 int64_t backward_comm_start_time = kUnsetTime;
54 // The timestamp of last communication call end time in each iteration.54 // The timestamp of last communication call end time in each iteration.
55 int64_t backward_comm_end_time = kUnsetTime;55 int64_t backward_comm_end_time = kUnsetTime;
56public:56public:
57 enum class Event {57 enum class Event {
58 kForwardStart,58 kForwardStart,
59 kBackwardComputeStart,59 kBackwardComputeStart,
60 kBackwardComputeEnd,60 kBackwardComputeEnd,
61 kBackwardCommStart,61 kBackwardCommStart,
62 kBackwardCommEnd,62 kBackwardCommEnd,
63 };63 };
64 64 
65 // Record the current event, i.e., mark it as having occurred now. Default65 // Record the current event, i.e., mark it as having occurred now. Default
66 // CPU implementation.66 // CPU implementation.
67 virtual void record(Event event) {67 virtual void record(Event event) {
68 getTimeRef(event) = current_time_in_nanos();68 getTimeRef(event) = current_time_in_nanos();
69 }69 }
70 70 
71 // Return the difference between when two events occurred, in nanoseconds.71 // Return the difference between when two events occurred, in nanoseconds.
72 // Or nullopt if one of them hasn't been recorded.72 // Or nullopt if one of them hasn't been recorded.
73 virtual c10::optional<int64_t> measureDifference(Event start, Event end) = 0;73 virtual c10::optional<int64_t> measureDifference(Event start, Event end) = 0;
74 74 
75 virtual ~Timer() = default;75 virtual ~Timer() = default;
76 76 
77 // Return host-side timestamp, or nullopt if it has not yet been recorded.77 // Return host-side timestamp, or nullopt if it has not yet been recorded.
78 c10::optional<int64_t> getTimestamp(Event event) {78 c10::optional<int64_t> getTimestamp(Event event) {
79 auto time = getTimeRef(event);79 auto time = getTimeRef(event);
80 if (time == kUnsetTime) {80 if (time == kUnsetTime) {
81 return c10::nullopt;81 return c10::nullopt;
82 } else {82 } else {
83 return time;83 return time;
84 }84 }
85 }85 }
86 86 
87 // Return host-side time member variable corresponding to the given event.87 // Return host-side time member variable corresponding to the given event.
88 int64_t& getTimeRef(Event event) {88 int64_t& getTimeRef(Event event) {
89 switch (event) {89 switch (event) {
90 case Event::kForwardStart:90 case Event::kForwardStart:
91 return forward_start_time;91 return forward_start_time;
92 case Event::kBackwardComputeStart:92 case Event::kBackwardComputeStart:
93 return backward_compute_start_time;93 return backward_compute_start_time;
94 case Event::kBackwardComputeEnd:94 case Event::kBackwardComputeEnd:
95 return backward_compute_end_time;95 return backward_compute_end_time;
96 case Event::kBackwardCommStart:96 case Event::kBackwardCommStart:
97 return backward_comm_start_time;97 return backward_comm_start_time;
98 case Event::kBackwardCommEnd:98 case Event::kBackwardCommEnd:
99 return backward_comm_end_time;99 return backward_comm_end_time;
100 default:100 default:
101 TORCH_INTERNAL_ASSERT(false);101 TORCH_INTERNAL_ASSERT(false);
102 }102 }
103 }103 }
104};104};
105 105 
106// Local accumulator type for a single bucket.106// Local accumulator type for a single bucket.
107struct BucketAccumulator {107struct BucketAccumulator {
108 std::vector<size_t> indices;108 std::vector<size_t> indices;
109 size_t size = 0;109 size_t size = 0;
110 size_t size_limit = 0;110 size_t size_limit = 0;
111};111};
112 112 
113C10_DECLARE_TYPED_REGISTRY(TimerRegistry, c10::DeviceType, Timer, std::unique_ptr, c10::Device);113C10_DECLARE_TYPED_REGISTRY(TimerRegistry, c10::DeviceType, Timer, std::unique_ptr, c10::Device);
114 114 
115class Reducer {115class Reducer {
116public:116public:
117 // The constructor takes a list of variables for every model replica.117 // The constructor takes a list of variables for every model replica.
118 // The bucket assignment for this reducer is specified as a list of118 // The bucket assignment for this reducer is specified as a list of
119 // buckets, each of which is specified as a list of indices into the119 // buckets, each of which is specified as a list of indices into the
120 // variables list for **a single replica** (i.e. `variables[0]`).120 // variables list for **a single replica** (i.e. `variables[0]`).
121 explicit Reducer(121 explicit Reducer(
122 std::vector<at::Tensor> params,122 std::vector<at::Tensor> params,
123 std::vector<std::vector<size_t>> bucket_indices,123 std::vector<std::vector<size_t>> bucket_indices,
124 std::vector<size_t> per_bucket_size_limits,124 std::vector<size_t> per_bucket_size_limits,
125 c10::intrusive_ptr<c10d::ProcessGroup> process_group,125 c10::intrusive_ptr<c10d::ProcessGroup> process_group,
126 std::vector<bool> expect_sparse_gradients,126 std::vector<bool> expect_sparse_gradients,
127 int64_t bucket_bytes_cap,127 int64_t bucket_bytes_cap,
128 bool find_unused_parameters,128 bool find_unused_parameters,
129 bool gradient_as_bucket_view,129 bool gradient_as_bucket_view,
130 std::unordered_map<size_t, std::string> paramNames,130 std::unordered_map<size_t, std::string> paramNames,
131 int64_t first_bucket_bytes_cap);131 int64_t first_bucket_bytes_cap);
132 132 
133 ~Reducer() noexcept(false);133 ~Reducer() noexcept(false);
134 134 
135 // To (re-)initialize bucket assignment, pass a list of buckets, each135 // To (re-)initialize bucket assignment, pass a list of buckets, each
136 // of which is specified by a list of indices in the variables list.136 // of which is specified by a list of indices in the variables list.
137 // This function performs validation that the variables within a bucket137 // This function performs validation that the variables within a bucket
138 // all live on the same device and have the same dimensionality.138 // all live on the same device and have the same dimensionality.
139 void initialize_buckets(139 void initialize_buckets(
140 std::vector<std::vector<size_t>> bucket_indices,140 std::vector<std::vector<size_t>> bucket_indices,
141 std::vector<size_t> per_bucket_sizes);141 std::vector<size_t> per_bucket_sizes);
142 142 
143 // This function is called when the forward function has produced an output,143 // This function is called when the forward function has produced an output,
144 // and the user wishes to reduce gradients in the backwards pass.144 // and the user wishes to reduce gradients in the backwards pass.
145 // If they don't, and wish to accumulate gradients before reducing them,145 // If they don't, and wish to accumulate gradients before reducing them,
146 // a call to this function can simply be omitted.146 // a call to this function can simply be omitted.
147 void prepare_for_backward(const std::vector<at::Tensor>& outputs);147 void prepare_for_backward(const std::vector<at::Tensor>& outputs);
148 148 
149 // Called at the begginning of forward() inside DistributedDataParallel,149 // Called at the begginning of forward() inside DistributedDataParallel,
150 // right now it caputures the starting time of forward in each iteration.150 // right now it caputures the starting time of forward in each iteration.
151 void prepare_for_forward();151 void prepare_for_forward();
152 152 
153 // Returns the relative time in nanoseconds when gradients were ready,153 // Returns the relative time in nanoseconds when gradients were ready,
154 // with respect to the time `prepare_for_backward` was called. The154 // with respect to the time `prepare_for_backward` was called. The
155 // vector is for parameters for a single model replica.155 // vector is for parameters for a single model replica.
156 std::vector<int64_t> get_backward_stats() const156 std::vector<int64_t> get_backward_stats() const
157 {157 {
158 return backward_stats_;158 return backward_stats_;
159 }159 }
160 160 
161 // Registers a hook to the reducer. The hook is `CommHookInterface`161 // Registers a hook to the reducer. The hook is `CommHookInterface`
162 // type to allow both Python and CPP hooks. This function can only162 // type to allow both Python and CPP hooks. This function can only
163 // be called once before calling backward.163 // be called once before calling backward.
164 // Cannot combine with the call of `register_builtin_comm_hook`.164 // Cannot combine with the call of `register_builtin_comm_hook`.
165 void register_comm_hook(std::unique_ptr<c10d::CommHookInterface> iface);165 void register_comm_hook(std::unique_ptr<c10d::CommHookInterface> iface);
166 166 
167 // Registers a built-in C++ comm hook to the reducer. This function can only167 // Registers a built-in C++ comm hook to the reducer. This function can only
168 // be called once before calling backward.168 // be called once before calling backward.
169 // Cannot combine with the call of `register_comm_hook`.169 // Cannot combine with the call of `register_comm_hook`.
170 void register_builtin_comm_hook(c10d::BuiltinCommHookType comm_hook_type);170 void register_builtin_comm_hook(c10d::BuiltinCommHookType comm_hook_type);
171 171 
172 // Runs allreduce or installed communication hook given GradBucket instance.172 // Runs allreduce or installed communication hook given GradBucket instance.
173 c10::intrusive_ptr<c10::ivalue::Future> run_comm_hook(173 c10::intrusive_ptr<c10::ivalue::Future> run_comm_hook(
174 c10d::GradBucket& grad_bucket);174 c10d::GradBucket& grad_bucket);
175 175 
176 // Runs default allreduce hook.176 // Runs default allreduce hook.
177 c10::intrusive_ptr<c10::ivalue::Future> run_allreduce_hook(177 c10::intrusive_ptr<c10::ivalue::Future> run_allreduce_hook(
178 c10d::GradBucket& grad_bucket);178 c10d::GradBucket& grad_bucket);
179 179 
180 // Returns gradient buckets in sequential order of buckets_. This is the order180 // Returns gradient buckets in sequential order of buckets_. This is the order
181 // in which buckets are reduced across processes. If return_zero_tensors=true,181 // in which buckets are reduced across processes. If return_zero_tensors=true,
182 // will return zero tensors of the same shape instead of the true tensors.182 // will return zero tensors of the same shape instead of the true tensors.
183 std::vector<c10d::GradBucket> get_grad_buckets(183 std::vector<c10d::GradBucket> get_grad_buckets(
184 bool return_zero_tensors = true) const;184 bool return_zero_tensors = true) const;
185 185 
186 // Rebuild buckets based on rebuilt_params_ and rebuilt_param_indices_186 // Rebuild buckets based on rebuilt_params_ and rebuilt_param_indices_
187 // according to when tensors received grads in the backward pass.187 // according to when tensors received grads in the backward pass.
188 bool rebuild_buckets();188 bool rebuild_buckets();
189 189 
190 // Install futures that should be awaited at end of backwards. Currently these190 // Install futures that should be awaited at end of backwards. Currently these
191 // are only used by user-defined custom buffer reduction hooks, but can be generalized191 // are only used by user-defined custom buffer reduction hooks, but can be generalized
192 // to any user-originating futures that need to be awaited.192 // to any user-originating futures that need to be awaited.
193 void install_futures(c10::List<c10::intrusive_ptr<c10::ivalue::Future>> futs);193 void install_futures(c10::List<c10::intrusive_ptr<c10::ivalue::Future>> futs);
194 194 
195 // Returns true if we should rebuild buckets, else false. We only rebuild195 // Returns true if we should rebuild buckets, else false. We only rebuild
196 // buckets once after the first iteration and never rebuild them if196 // buckets once after the first iteration and never rebuild them if
197 // find_unused_parameters_.197 // find_unused_parameters_.
198 inline bool should_rebuild_buckets() const198 inline bool should_rebuild_buckets() const
199 {199 {
200 return (static_graph_ || !find_unused_parameters_) && !has_rebuilt_bucket_;200 return (static_graph_ || !find_unused_parameters_) && !has_rebuilt_bucket_;
201 }201 }
202 202 
203 // Pushes all parameters to be rebuilt.203 // Pushes all parameters to be rebuilt.
204 void push_rebuilt_params_for_all_indices();204 void push_rebuilt_params_for_all_indices();
205 205 
206 // Creates and sets ForwardPassWorkHandle given a ProcessGroup::Work and the206 // Creates and sets ForwardPassWorkHandle given a ProcessGroup::Work and the
207 // corresponding tensor being reduced.207 // corresponding tensor being reduced.
208 void set_forward_pass_work_handle(208 void set_forward_pass_work_handle(
209 c10::intrusive_ptr<c10d::Work> forwardPassWorkHandle,209 c10::intrusive_ptr<c10d::Work> forwardPassWorkHandle,
210 bool useStaticWorldSize);210 bool useStaticWorldSize);
211 211 
212 // Retrieve on-device tensors used to track locally unused parameters. It is212 // Retrieve on-device tensors used to track locally unused parameters. It is
213 // a tensor where index i = 1 if the Variable with that index has been used.213 // a tensor where index i = 1 if the Variable with that index has been used.
214 at::Tensor get_local_used_map_on_device() const;214 at::Tensor get_local_used_map_on_device() const;
215 215 
216 // An function for users to set sample_rate of collecting216 // An function for users to set sample_rate of collecting
217 // runtime stats. The time stats will be recorded for the217 // runtime stats. The time stats will be recorded for the
218 // first 10 iterations, after 10 iteratons time stats will be218 // first 10 iterations, after 10 iteratons time stats will be
219 // recorded once every "sample_rate" training iterations.219 // recorded once every "sample_rate" training iterations.
220 void set_ddp_runtime_logging_sample_rate(int sample_rate);220 void set_ddp_runtime_logging_sample_rate(int sample_rate);
221 221 
222 // Specify the training graph is static.222 // Specify the training graph is static.
223 void set_static_graph();223 void set_static_graph();
224 224 
225 // Delay all reduce to be after all gradients' calculation is complete.225 // Delay all reduce to be after all gradients' calculation is complete.
226 void delay_all_reduce();226 void delay_all_reduce();
227 227 
228 // Weak reference to associated DDP logger. The reference is weak to avoid228 // Weak reference to associated DDP logger. The reference is weak to avoid
229 // refcycle between reducer and logger.229 // refcycle between reducer and logger.
230 void set_logger(std::weak_ptr<c10d::Logger> logger);230 void set_logger(std::weak_ptr<c10d::Logger> logger);
231 231 
232 // When graph is not explicitly set by user as static and has unused232 // When graph is not explicitly set by user as static and has unused
233 // parameters, this will return whether the graph has been static until the233 // parameters, this will return whether the graph has been static until the
234 // current iteration, which means unused params set has not changed.234 // current iteration, which means unused params set has not changed.
235 bool ddp_graph_static();235 bool ddp_graph_static();
236 236 
237protected:237protected:
238 // Forward declaration.238 // Forward declaration.
239 struct Bucket;239 struct Bucket;
240 240 
241 void push_rebuilt_params(const size_t& index);241 void push_rebuilt_params(const size_t& index);
242 242 
243 // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)243 // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)
244 mutable std::mutex mutex_;244 mutable std::mutex mutex_;
245 // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)245 // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)
246 const std::vector<at::Tensor> params_;246 const std::vector<at::Tensor> params_;
247 // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)247 // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)
248 const c10::intrusive_ptr<::c10d::ProcessGroup> process_group_;248 const c10::intrusive_ptr<::c10d::ProcessGroup> process_group_;
249 // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)249 // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)
250 std::vector<bool> expect_sparse_gradients_;250 std::vector<bool> expect_sparse_gradients_;
251 251 
252 std::vector<std::shared_ptr<torch::autograd::Node>>252 std::vector<std::shared_ptr<torch::autograd::Node>>
253 grad_accumulators_; // NOLINT(cppcoreguidelines-non-private-member-variables-in-classes)253 grad_accumulators_; // NOLINT(cppcoreguidelines-non-private-member-variables-in-classes)
254 // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)254 // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)
255 std::unordered_map<torch::autograd::Node*, size_t> gradAccToVariableMap_;255 std::unordered_map<torch::autograd::Node*, size_t> gradAccToVariableMap_;
256 std::vector<std::pair<uintptr_t, std::shared_ptr<torch::autograd::Node>>>256 std::vector<std::pair<uintptr_t, std::shared_ptr<torch::autograd::Node>>>
257 hooks_; // NOLINT(cppcoreguidelines-non-private-member-variables-in-classes)257 hooks_; // NOLINT(cppcoreguidelines-non-private-member-variables-in-classes)
258 258 
259 // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)259 // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)
260 bool expect_autograd_hooks_;260 bool expect_autograd_hooks_;
261 // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)261 // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)
262 bool require_finalize_;262 bool require_finalize_;
263 // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)263 // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)
264 size_t next_bucket_;264 size_t next_bucket_;
265 265 
266 // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)266 // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)
267 bool has_marked_unused_parameters_;267 bool has_marked_unused_parameters_;
268 // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)268 // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)
269 const bool find_unused_parameters_;269 const bool find_unused_parameters_;
270 // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)270 // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)
271 const bool gradient_as_bucket_view_;271 const bool gradient_as_bucket_view_;
272 // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)272 // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)
273 std::vector<size_t> unused_parameters_;273 std::vector<size_t> unused_parameters_;
274 // Previous iteration's unused params, used for checking if unused parameters274 // Previous iteration's unused params, used for checking if unused parameters
275 // change between iterations. Only filled during the first backwards call.275 // change between iterations. Only filled during the first backwards call.
276 // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)276 // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)
277 std::vector<size_t> prev_iteration_unused_parameters_;277 std::vector<size_t> prev_iteration_unused_parameters_;
278 // Whether graph is static or not. When user does not explicitly set static278 // Whether graph is static or not. When user does not explicitly set static
279 // graph, the only possible dynamism is set of unused parameters changing279 // graph, the only possible dynamism is set of unused parameters changing
280 // between iterations which is tracked by this flag.280 // between iterations which is tracked by this flag.
281 // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)281 // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)
282 bool ddp_graph_static_{true};282 bool ddp_graph_static_{true};
283 // Locally used parameter maps indicating if parameters are used locally283 // Locally used parameter maps indicating if parameters are used locally
284 // during the current iteration or no_sync session if no_sync is on.284 // during the current iteration or no_sync session if no_sync is on.
285 // Each map is a one-dim int32 tensor of number of parameters. These tensors285 // Each map is a one-dim int32 tensor of number of parameters. These tensors
286 // are marked in autograd_hook to indicate the corresponding param has been286 // are marked in autograd_hook to indicate the corresponding param has been
287 // used, and get allreduced in the end of backward step of current iteration287 // used, and get allreduced in the end of backward step of current iteration
288 // or no_sync session for figuring out the globally unused parameters.288 // or no_sync session for figuring out the globally unused parameters.
289 //289 //
290 // local_used_map_: CPU tensor for bookkeeping locally used params290 // local_used_map_: CPU tensor for bookkeeping locally used params
291 // local_used_map_dev_: dev tensor for reducing globally unused params291 // local_used_map_dev_: dev tensor for reducing globally unused params
292 at::Tensor local_used_map_;292 at::Tensor local_used_map_;
293 at::Tensor local_used_map_dev_;293 at::Tensor local_used_map_dev_;
294 // Indicate that reduction is done and D2H copy is done as well.294 // Indicate that reduction is done and D2H copy is done as well.
295 bool local_used_map_reduced_;295 bool local_used_map_reduced_;
296 296 
297 // Weak pointer to associated DDP logger.297 // Weak pointer to associated DDP logger.
298 std::weak_ptr<c10d::Logger> logger_;298 std::weak_ptr<c10d::Logger> logger_;
299 // List of futures installed by Reducer::install_futures that should be awaited299 // List of futures installed by Reducer::install_futures that should be awaited
300 // at the end of backwards pass.300 // at the end of backwards pass.
301 c10::optional<c10::List<c10::intrusive_ptr<c10::ivalue::Future>>> installed_futures_{c10::nullopt};301 c10::optional<c10::List<c10::intrusive_ptr<c10::ivalue::Future>>> installed_futures_{c10::nullopt};
302 302 
303 // Work handle for allreduce on local_used_map_303 // Work handle for allreduce on local_used_map_
304 c10::intrusive_ptr<c10d::Work> local_used_work_;304 c10::intrusive_ptr<c10d::Work> local_used_work_;
305 305 
306 void mark_variable_ready_dense(size_t variable_index);306 void mark_variable_ready_dense(size_t variable_index);
307 307 
308 void mark_variable_ready_sparse(size_t variable_index);308 void mark_variable_ready_sparse(size_t variable_index);
309 309 
310 void mark_variable_ready(size_t variable_index);310 void mark_variable_ready(size_t variable_index);
311 311 
312 void autograd_hook(size_t index);312 void autograd_hook(size_t index);
313 313 
314 void mark_bucket_ready(size_t bucket_index);314 void mark_bucket_ready(size_t bucket_index);
315 315 
316 void finalize_bucket_dense(Bucket& replica);316 void finalize_bucket_dense(Bucket& replica);
317 317 
318 void finalize_backward();318 void finalize_backward();
319 319 
320 // Returns list of model parameters corresponding to the given bucket.320 // Returns list of model parameters corresponding to the given bucket.
321 // bucket_index is a key to cache after buckets are rebuilt, after which this321 // bucket_index is a key to cache after buckets are rebuilt, after which this
322 // mapping never changes.322 // mapping never changes.
323 std::vector<at::Tensor> get_variables_for_bucket(323 std::vector<at::Tensor> get_variables_for_bucket(
324 size_t bucket_index, const Bucket& bucket) const;324 size_t bucket_index, const Bucket& bucket) const;
325 325 
326 // Asserts that the reduction for the previous iteration has finished before326 // Asserts that the reduction for the previous iteration has finished before
327 // rebuilding buckets or kicking off the next one.327 // rebuilding buckets or kicking off the next one.
328 void ensure_prior_reduction_finished();328 void ensure_prior_reduction_finished();
329 329 
330 // Broadcast rebuilt buckets from rank 0 to other ranks before initializing330 // Broadcast rebuilt buckets from rank 0 to other ranks before initializing
331 // the buckets331 // the buckets
332 void sync_bucket_indices(std::vector<std::vector<size_t>>& bucket_indices);332 void sync_bucket_indices(std::vector<std::vector<size_t>>& bucket_indices);
333 333 
334 // We'd like to use DistAutogradContext::GradCallback here but dist autograd334 // We'd like to use DistAutogradContext::GradCallback here but dist autograd
335 // doesn't exist under Windows. So we just directly use the concrete type but335 // doesn't exist under Windows. So we just directly use the concrete type but
336 // to preserve and enforce our original intent we do a static assert when dist336 // to preserve and enforce our original intent we do a static assert when dist
337 // autograd is available.337 // autograd is available.
338 using GradCallback = std::function<bool(at::Tensor&)>;338 using GradCallback = std::function<bool(at::Tensor&)>;
339#ifndef _WIN32339#ifndef _WIN32
340 static_assert(340 static_assert(
341 std::is_same<341 std::is_same<
342 GradCallback,342 GradCallback,
343 torch::distributed::autograd::DistAutogradContext::GradCallback>::343 torch::distributed::autograd::DistAutogradContext::GradCallback>::
344 value,344 value,
345 "");345 "");
346#endif346#endif
347 void runGradCallbackForVariable(at::Tensor& variable, GradCallback&& cb);347 void runGradCallbackForVariable(at::Tensor& variable, GradCallback&& cb);
348 348 
349 // A bucket replica represents [1..N] gradients to be reduced,349 // A bucket replica represents [1..N] gradients to be reduced,
350 // with the same dtype, on the same device.350 // with the same dtype, on the same device.
351 //351 //
352 // Batching gradients together before reducing them can result in lower352 // Batching gradients together before reducing them can result in lower
353 // overhead and/or faster time to completion. Only gradients of the same type353 // overhead and/or faster time to completion. Only gradients of the same type
354 // and on the same device can be batched. The tensor that represents the354 // and on the same device can be batched. The tensor that represents the
355 // flattened gradient uses the same type and is placed on the same device.355 // flattened gradient uses the same type and is placed on the same device.
356 // Buckets are filled as the gradients they hold are computed (triggered by356 // Buckets are filled as the gradients they hold are computed (triggered by
357 // autograd hooks). Buckets are reduced in a predetermined order that is357 // autograd hooks). Buckets are reduced in a predetermined order that is
358 // identical across processes.358 // identical across processes.
359 struct BucketReplica {359 struct BucketReplica {
360 // Flattened (1 dimensional) contents of bucket.360 // Flattened (1 dimensional) contents of bucket.
361 at::Tensor contents;361 at::Tensor contents;
362 362 
363 // Views into contents for each grad. Each view will be created with363 // Views into contents for each grad. Each view will be created with
364 // layout (sizes + strides) matching the grad's expected layout364 // layout (sizes + strides) matching the grad's expected layout
365 // ("Gradient Layout Contract" in torch/csrc/autograd/AccumulateGrad.h).365 // ("Gradient Layout Contract" in torch/csrc/autograd/AccumulateGrad.h).
366 // `bucket_views_in[i].copy_(grad)` and366 // `bucket_views_in[i].copy_(grad)` and
367 // `grad.copy_(bucket_views_out[i])`367 // `grad.copy_(bucket_views_out[i])`
368 // provide convenient ways to move grad data in/out of contents.368 // provide convenient ways to move grad data in/out of contents.
369 // The reason we keep two states for bucket_views is that if DDP369 // The reason we keep two states for bucket_views is that if DDP
370 // communication hook was registered, `bucket_views_out` could be370 // communication hook was registered, `bucket_views_out` could be
371 // re-initialized with the value of hook's `future_work`. We still need to371 // re-initialized with the value of hook's `future_work`. We still need to
372 // keep a separate view reference to replica's original contents for372 // keep a separate view reference to replica's original contents for
373 // `bucket_views_in[i].copy_(grad)` call.373 // `bucket_views_in[i].copy_(grad)` call.
374 std::vector<at::Tensor> bucket_views_in;374 std::vector<at::Tensor> bucket_views_in;
375 std::vector<at::Tensor> bucket_views_out;375 std::vector<at::Tensor> bucket_views_out;
376 376 
377 // Variables that contribute to this bucket replica. Use refcounted value377 // Variables that contribute to this bucket replica. Use refcounted value
378 // here so that we can easily unflatten the bucket contents into the378 // here so that we can easily unflatten the bucket contents into the
379 // participating variables after reduction has completed.379 // participating variables after reduction has completed.
380 std::vector<at::Tensor> variables;380 std::vector<at::Tensor> variables;
381 381 
382 // Per-variable offset/length into the flat bucket contents tensor and grad382 // Per-variable offset/length into the flat bucket contents tensor and grad
383 // bucket.383 // bucket.
384 std::vector<size_t> offsets;384 std::vector<size_t> offsets;
385 std::vector<size_t> lengths;385 std::vector<size_t> lengths;
386 386 
387 // Per-variable sizes into the grad bucekt.387 // Per-variable sizes into the grad bucekt.
388 std::vector<c10::IntArrayRef> sizes_vec;388 std::vector<c10::IntArrayRef> sizes_vec;
389 389 
390 // Number of tensors to be added before this bucket is complete.390 // Number of tensors to be added before this bucket is complete.
391 // This is reset to `variables.size()` every iteration.391 // This is reset to `variables.size()` every iteration.
392 size_t pending;392 size_t pending;
393 };393 };
394 394 
395 // This function is called inside `initialize_buckets`, it initializes both395 // This function is called inside `initialize_buckets`, it initializes both
396 // bucket_views_in and bucket_views_out into the contents tensor for each396 // bucket_views_in and bucket_views_out into the contents tensor for each
397 // variable's grad. Views serve as entry points to copy_ each grad's data397 // variable's grad. Views serve as entry points to copy_ each grad's data
398 // in/out of the flat contents tensor.398 // in/out of the flat contents tensor.
399 void initialize_bucket_views(BucketReplica& replica, at::Tensor& contents);399 void initialize_bucket_views(BucketReplica& replica, at::Tensor& contents);
400 400 
401 // This function is called inside `finalize_backward`, it happens only if401 // This function is called inside `finalize_backward`, it happens only if
402 // DDP communication hook was registered to recreate just bucket_views_out402 // DDP communication hook was registered to recreate just bucket_views_out
403 // with the result of `future_work`.403 // with the result of `future_work`.
404 void populate_bucket_views_out(BucketReplica& replica, at::Tensor& tensor) const;404 void populate_bucket_views_out(BucketReplica& replica, at::Tensor& tensor) const;
405 405 
406 // If gradient_as_bucket_view_ is false, after allreduce buckets,406 // If gradient_as_bucket_view_ is false, after allreduce buckets,
407 // copy bucket results back to grads.407 // copy bucket results back to grads.
408 void copy_bucket_to_grad(408 void copy_bucket_to_grad(
409 at::Tensor& variable,409 at::Tensor& variable,
410 Reducer::BucketReplica& replica,410 Reducer::BucketReplica& replica,
411 size_t intra_bucket_index,411 size_t intra_bucket_index,
412 bool global_unused);412 bool global_unused);
413 // Check layout of grad and bucket_view before copying the grad to bucket.413 // Check layout of grad and bucket_view before copying the grad to bucket.
414 void check_grad_layout(const at::Tensor& grad, const at::Tensor& bucket_view);414 void check_grad_layout(const at::Tensor& grad, const at::Tensor& bucket_view);
415 // If gradient_as_bucket_view_ is false, before allreduce buckets,415 // If gradient_as_bucket_view_ is false, before allreduce buckets,
416 // copy grads to buckets.416 // copy grads to buckets.
417 void copy_grad_to_bucket(const at::Tensor& grad, at::Tensor& bucket_view);417 void copy_grad_to_bucket(const at::Tensor& grad, at::Tensor& bucket_view);
418 // A bucket holds N bucket replicas (1 per model replica).418 // A bucket holds N bucket replicas (1 per model replica).
419 //419 //
420 // If every bucket in this struct is ready, the reduction can be kicked off.420 // If every bucket in this struct is ready, the reduction can be kicked off.
421 // One bucket per replica. Reduction is kicked off when every bucket is ready.421 // One bucket per replica. Reduction is kicked off when every bucket is ready.
422 //422 //
423 struct Bucket {423 struct Bucket {
424 std::vector<BucketReplica> replicas;424 std::vector<BucketReplica> replicas;
425 425 
426 // Global indices of participating variables in the bucket426 // Global indices of participating variables in the bucket
427 std::vector<size_t> variable_indices;427 std::vector<size_t> variable_indices;
428 428 
429 // Number of replicas to be marked done before this bucket is ready.429 // Number of replicas to be marked done before this bucket is ready.
430 size_t pending;430 size_t pending;
431 431 
432 // Keep work handle around when this set of buckets is being reduced.432 // Keep work handle around when this set of buckets is being reduced.
433 c10::intrusive_ptr<c10d::Work> work;433 c10::intrusive_ptr<c10d::Work> work;
434 434 
435 // Keep future work handle around DDP comm hook.435 // Keep future work handle around DDP comm hook.
436 // If no hook is registered, a temporary vanilla allreduce hook will be436 // If no hook is registered, a temporary vanilla allreduce hook will be
437 // used.437 // used.
438 c10::intrusive_ptr<at::ivalue::Future> future_work;438 c10::intrusive_ptr<at::ivalue::Future> future_work;
439 439 
440 // If this bucket should expect a single sparse gradient.440 // If this bucket should expect a single sparse gradient.
441 // Implies: replicas[i].variables.size() == 1.441 // Implies: replicas[i].variables.size() == 1.
442 bool expect_sparse_gradient = false;442 bool expect_sparse_gradient = false;
443 // "Limit" of cumulative parameter sizes that this bucket manages. It is443 // "Limit" of cumulative parameter sizes that this bucket manages. It is
444 // actually a soft limit because we don't shard parameters across buckets444 // actually a soft limit because we don't shard parameters across buckets
445 // so a single parameter may push it over the cap.445 // so a single parameter may push it over the cap.
446 size_t bucket_size_limit;446 size_t bucket_size_limit;
447 };447 };
448 448 
449 std::vector<Bucket> buckets_;449 std::vector<Bucket> buckets_;
450 450 
451 // A variable locator locates a particular variable in the bucket451 // A variable locator locates a particular variable in the bucket
452 // structure. The `bucket_index` field points to the bucket in the `buckets_`452 // structure. The `bucket_index` field points to the bucket in the `buckets_`
453 // vector. The `intra_bucket_index` field points to the index of the variable453 // vector. The `intra_bucket_index` field points to the index of the variable
454 // in any of the vector fields in the bucket replica.454 // in any of the vector fields in the bucket replica.
455 struct VariableLocator {455 struct VariableLocator {
456 // Index into the `buckets_` variable.456 // Index into the `buckets_` variable.
457 size_t bucket_index;457 size_t bucket_index;
458 // Index of parameter in single bucket replica.458 // Index of parameter in single bucket replica.
459 size_t intra_bucket_index;459 size_t intra_bucket_index;
460 460 
461 VariableLocator() = default;461 VariableLocator() = default;
462 462 
463 VariableLocator(size_t bucket_index_, size_t intra_bucket_index_)463 VariableLocator(size_t bucket_index_, size_t intra_bucket_index_)
464 {464 {
465 bucket_index = bucket_index_;465 bucket_index = bucket_index_;
466 intra_bucket_index = intra_bucket_index_;466 intra_bucket_index = intra_bucket_index_;
467 }467 }
468 };468 };
469 469 
470 // Map the index of a variable to its location in the bucket structure.470 // Map the index of a variable to its location in the bucket structure.
471 std::vector<VariableLocator> variable_locators_;471 std::vector<VariableLocator> variable_locators_;
472 472 
473 // track the number of iterations to synchronize grads in training so far.473 // track the number of iterations to synchronize grads in training so far.
474 long num_iterations_;474 long num_iterations_;
475 // track the number of buckets that have been ready for475 // track the number of buckets that have been ready for
476 // communication calls like allReduce or communication hooks.476 // communication calls like allReduce or communication hooks.
477 int num_buckets_ready_;477 int num_buckets_ready_;
478 478 
479 // Timing information.479 // Timing information.
480 int64_t backward_compute_start_time_ = -1;480 int64_t backward_compute_start_time_ = -1;
481 std::unique_ptr<Timer> timer_;481 std::unique_ptr<Timer> timer_;
482 482 
483 // We collect the relative timestamp of every gradient being ready483 // We collect the relative timestamp of every gradient being ready
484 // when executing autograd. This can be used to derive a timeline of484 // when executing autograd. This can be used to derive a timeline of
485 // the point in time buckets were ready, or ideal bucket assignment/ordering.485 // the point in time buckets were ready, or ideal bucket assignment/ordering.
486 std::vector<int64_t> backward_stats_;486 std::vector<int64_t> backward_stats_;
487 487 
488 bool should_collect_runtime_stats();488 bool should_collect_runtime_stats();
489 void record_forward_compute_start_time();489 void record_forward_compute_start_time();
490 void record_backward_compute_start_time();490 void record_backward_compute_start_time();
491 void record_backward_compute_end_time();491 void record_backward_compute_end_time();
492 void record_backward_comm_start_time();492 void record_backward_comm_start_time();
493 void record_backward_comm_end_time();493 void record_backward_comm_end_time();
494 494 
495 int get_ddp_runtime_logging_sample_rate() const;495 int get_ddp_runtime_logging_sample_rate() const;
496 int ddp_runtime_logging_sample_rate_ = kDDPRuntimeLoggingSampleRate;496 int ddp_runtime_logging_sample_rate_ = kDDPRuntimeLoggingSampleRate;
497 497 
498 bool is_multi_device_module_ = false;498 bool is_multi_device_module_ = false;
499 499 
500 // Following variables are to help build dynamic bucket order500 // Following variables are to help build dynamic bucket order
501 bool has_rebuilt_bucket_;501 bool has_rebuilt_bucket_;
502 std::vector<at::Tensor> rebuilt_params_;502 std::vector<at::Tensor> rebuilt_params_;
503 std::vector<int64_t> rebuilt_param_indices_;503 std::vector<int64_t> rebuilt_param_indices_;
504 const int64_t bucket_bytes_cap_;504 const int64_t bucket_bytes_cap_;
505 505 
506#ifndef _WIN32506#ifndef _WIN32
507 struct RpcContext {507 struct RpcContext {
508 using ContextPtr = torch::distributed::autograd::ContextPtr;508 using ContextPtr = torch::distributed::autograd::ContextPtr;
509 // The shared_ptr is to hold the context instance.509 // The shared_ptr is to hold the context instance.
510 ContextPtr context_ptr_holder;510 ContextPtr context_ptr_holder;
511 std::atomic<ContextPtr::element_type*> context_ptr{nullptr};511 std::atomic<ContextPtr::element_type*> context_ptr{nullptr};
512 512 
513 void set(ContextPtr&& new_context_ptr);513 void set(ContextPtr&& new_context_ptr);
514 };514 };
515 RpcContext rpc_context_;515 RpcContext rpc_context_;
516#endif516#endif
517 517 
518 // A struct containing work handle and tensor for allreduce scheduled in518 // A struct containing work handle and tensor for allreduce scheduled in
519 // forward pass, if applicable.519 // forward pass, if applicable.
520 struct ForwardPassAllreduceWork {520 struct ForwardPassAllreduceWork {
521 c10::intrusive_ptr<c10d::Work> workHandle;521 c10::intrusive_ptr<c10d::Work> workHandle;
522 at::Tensor resultTensor;522 at::Tensor resultTensor;
523 // whether we should divide by the initial world_size or the no. of523 // whether we should divide by the initial world_size or the no. of
524 // remaining DDP ranks.524 // remaining DDP ranks.
525 bool useStaticWorldSize = false;525 bool useStaticWorldSize = false;
526 };526 };
527 527 
528 // Handle for the currently scheduled allreduce in the forward pass, if528 // Handle for the currently scheduled allreduce in the forward pass, if
529 // applicable.529 // applicable.
530 ForwardPassAllreduceWork forwardPassWorkHandle_;530 ForwardPassAllreduceWork forwardPassWorkHandle_;
531 531 
532 // Division factor for reduction of gradients.532 // Division factor for reduction of gradients.
533 // Equal to the process group size, with an exception of handling uneven533 // Equal to the process group size, with an exception of handling uneven
534 // input.534 // input.
535 int div_factor_;535 int div_factor_;
536 536 
537 bool static_graph_;537 bool static_graph_;
538 538 
539 // Key: size_t (index), Value: the number of times that a variable's539 // Key: size_t (index), Value: the number of times that a variable's
540 // autograd_hook() should be triggered before marking this variable's grad as540 // autograd_hook() should be triggered before marking this variable's grad as
541 // ready for communication. Map will not change after 1st iteration.541 // ready for communication. Map will not change after 1st iteration.
542 std::unordered_map<size_t, int> numGradHooksTriggeredMap_;542 std::unordered_map<size_t, int> numGradHooksTriggeredMap_;
543 // Key: size_t (index), Value: the number of times that a variable's543 // Key: size_t (index), Value: the number of times that a variable's
544 // autograd_hook() are left to be triggered before marking this variable's544 // autograd_hook() are left to be triggered before marking this variable's
545 // grad as ready for communication. Map will change after 1st iteration to545 // grad as ready for communication. Map will change after 1st iteration to
546 // track a grad is ready for communication or not.546 // track a grad is ready for communication or not.
547 std::unordered_map<size_t, int> numGradHooksTriggeredMapPerIteration_;547 std::unordered_map<size_t, int> numGradHooksTriggeredMapPerIteration_;
548 548 
549private:549private:
550 // reset counting for buckets before backward starts550 // reset counting for buckets before backward starts
551 void reset_bucket_counting();551 void reset_bucket_counting();
552 // search unused parameters beore backward starts552 // search unused parameters beore backward starts
553 void search_unused_parameters(553 void search_unused_parameters(
554 const std::vector<torch::autograd::Variable>& outputs);554 const std::vector<torch::autograd::Variable>& outputs);
555 void set_divide_factor();555 void set_divide_factor();
556 // kick off all reduce for the ready bucket556 // kick off all reduce for the ready bucket
557 void all_reduce_bucket(Bucket& bucket);557 void all_reduce_bucket(Bucket& bucket);
558 // kick off all reduce to local used map, it can help find global unused558 // kick off all reduce to local used map, it can help find global unused
559 // parameters559 // parameters
560 void all_reduce_local_used_map();560 void all_reduce_local_used_map();
561 // initialize locally used parameter maps561 // initialize locally used parameter maps
562 void initialize_local_used_map();562 void initialize_local_used_map();
563 // get current cuda stream563 // get current cuda stream
564 const c10::Stream get_current_stream();564 const c10::Stream get_current_stream();
565 bool dynamic_graph_find_unused() const;565 bool dynamic_graph_find_unused() const;
566 bool static_graph_first_iteration() const;566 bool static_graph_first_iteration() const;
567 bool static_graph_after_first_iteration() const;567 bool static_graph_after_first_iteration() const;
568 568 
569 // comm_hook_ is used to access the DDP communication hook if registered.569 // comm_hook_ is used to access the DDP communication hook if registered.
570 std::unique_ptr<c10d::CommHookInterface> comm_hook_;570 std::unique_ptr<c10d::CommHookInterface> comm_hook_;
571 // Debug level setting. It is parsed once when Reducer is constructed, and571 // Debug level setting. It is parsed once when Reducer is constructed, and
572 // remains the same across a single invocation of DDP training.572 // remains the same across a single invocation of DDP training.
573 c10d::DebugLevel ddp_debug_level_;573 c10d::DebugLevel ddp_debug_level_;
574 // Mapping of variable index to fully qualified name of model to notify users574 // Mapping of variable index to fully qualified name of model to notify users
575 // about errors when certain parameters do not get gradient.575 // about errors when certain parameters do not get gradient.
576 std::unordered_map<size_t, std::string> param_names_;576 std::unordered_map<size_t, std::string> param_names_;
577 // Variable indices stored sequentially in order of when the gradient is ready577 // Variable indices stored sequentially in order of when the gradient is ready
578 // for the current backwards pass.578 // for the current backwards pass.
579 std::vector<int> grad_ready_order_indices_;579 std::vector<int> grad_ready_order_indices_;
580 // Bytes capacity of first bucket, can be configured by user580 // Bytes capacity of first bucket, can be configured by user
581 int64_t first_bucket_bytes_cap_;581 int64_t first_bucket_bytes_cap_;
582 // Per iteration set of parameter indices that have been marked ready.582 // Per iteration set of parameter indices that have been marked ready.
583 std::unordered_set<size_t> perIterationReadyParams_;583 std::unordered_set<size_t> perIterationReadyParams_;
584 // Retrieves parameter names that have not been marked as ready as part of584 // Retrieves parameter names that have not been marked as ready as part of
585 // previous iteration.585 // previous iteration.
586 std::vector<std::string> getUnmarkedParamsForIteration();586 std::vector<std::string> getUnmarkedParamsForIteration();
587 // Retrives parameter indices that have not been marked as ready as part of587 // Retrives parameter indices that have not been marked as ready as part of
588 // previous iteration.588 // previous iteration.
589 std::vector<size_t> getUnmarkedParamIndicesForIteration();589 std::vector<size_t> getUnmarkedParamIndicesForIteration();
590 // Raises appropriate error if mark_variable_ready is called on the same590 // Raises appropriate error if mark_variable_ready is called on the same
591 // variable twice, which is unexpected.591 // variable twice, which is unexpected.
592 void checkAndRaiseMarkedTwiceError(size_t curVariableIndex);592 void checkAndRaiseMarkedTwiceError(size_t curVariableIndex);
593 // Retrieves parameter corresponding to the given VariableIndex.593 // Retrieves parameter corresponding to the given VariableIndex.
594 at::Tensor& get_param_from_index(size_t index);594 at::Tensor& get_param_from_index(size_t index);
595 595 
596 // Cached bucket index to model parameter mapping. Populated after buckets596 // Cached bucket index to model parameter mapping. Populated after buckets
597 // are rebuilt after which this mapping is static.597 // are rebuilt after which this mapping is static.
598 mutable std::unordered_map<size_t, std::vector<at::Tensor>> cached_variables_for_bucket_;598 mutable std::unordered_map<size_t, std::vector<at::Tensor>> cached_variables_for_bucket_;
599 599 
600 friend class Logger;600 friend class Logger;
601};601};
602 602 
603// This is equivalent to take_tensors but returns indices into the603// This is equivalent to take_tensors but returns indices into the
604// tensor list argument for bucket assignment. Also, it is aware604// tensor list argument for bucket assignment. Also, it is aware
605// of device placement and will not allow buckets to span devices.605// of device placement and will not allow buckets to span devices.
606// The index of tensors[i] assigned to bucket is tensor_indices[i],606// The index of tensors[i] assigned to bucket is tensor_indices[i],
607// when tensor_indices is empty, the index of tensors[i] assigned to607// when tensor_indices is empty, the index of tensors[i] assigned to
608// bucket is i.608// bucket is i.
609std::tuple<std::vector<std::vector<size_t>>, std::vector<size_t>> compute_bucket_assignment_by_size(609std::tuple<std::vector<std::vector<size_t>>, std::vector<size_t>> compute_bucket_assignment_by_size(
610 const std::vector<at::Tensor>& tensors,610 const std::vector<at::Tensor>& tensors,
611 const std::vector<size_t>& bucket_size,611 const std::vector<size_t>& bucket_size,
612 const std::vector<bool>& expect_sparse_gradient = {},612 const std::vector<bool>& expect_sparse_gradient = {},
613 const std::vector<int64_t>& tensor_indices = {},613 const std::vector<int64_t>& tensor_indices = {},
614 const c10::optional<std::weak_ptr<c10d::Logger>>& logger = {});614 const c10::optional<std::weak_ptr<c10d::Logger>>& logger = {});
615 615 
616// Verify models across all processes are the same as model on rank 0 with616// Verify models across all processes are the same as model on rank 0 with
617// respect to no. of params and matching dtype/size/layout.617// respect to no. of params and matching dtype/size/layout.
618void verify_params_across_processes(618void verify_params_across_processes(
619 const c10::intrusive_ptr<c10d::ProcessGroup>& process_group,619 const c10::intrusive_ptr<c10d::ProcessGroup>& process_group,
620 const std::vector<at::Tensor>& params,620 const std::vector<at::Tensor>& params,
621 const c10::optional<std::weak_ptr<c10d::Logger>>& logger);621 const c10::optional<std::weak_ptr<c10d::Logger>>& logger);
622} // namespace c10d_npu622} // namespace c10d_npu
Mtorch_npu/csrc/framework/CMakeLists.txt+11-11
@@ -1,12 +1,12 @@
1FILE(GLOB _FRAMEWORK_SRCS1FILE(GLOB _FRAMEWORK_SRCS
2 *.cpp2 *.cpp
3 aoe/*.cpp3 aoe/*.cpp
4 autograd/*.cpp4 autograd/*.cpp
5 contiguous/*.cpp5 contiguous/*.cpp
6 interface/*.cpp6 interface/*.cpp
7 utils/*.cpp)7 utils/*.cpp)
8 8 
9LIST(APPEND FRAMEWORK_SRCS ${_FRAMEWORK_SRCS})9LIST(APPEND FRAMEWORK_SRCS ${_FRAMEWORK_SRCS})
10 10 
11# Pass to parent11# Pass to parent
12set(FRAMEWORK_SRCS ${FRAMEWORK_SRCS} PARENT_SCOPE)12set(FRAMEWORK_SRCS ${FRAMEWORK_SRCS} PARENT_SCOPE)
Mtorch_npu/csrc/framework/StorageDescHelper.cpp+0-1
@@ -311,4 +311,3 @@ int64_t StorageDescHelper::GetValidMemorySize(const at::Tensor &tensor)
311 311 
312} // namespace native312} // namespace native
313} // namespace at_npu313} // namespace at_npu
314 
Mtorch_npu/csrc/framework/contiguous/ReshapeOpt.cpp+0-1
@@ -87,4 +87,3 @@ bool CanUseMemcpyForOtherFormat(const at::Tensor &tensor)
87 87 
88} // namespace native88} // namespace native
89} // namespace at_npu89} // namespace at_npu
90 
Mtorch_npu/csrc/framework/interface/LibAscendHal.h+0-1
@@ -8,4 +8,3 @@ bool isSyscntEnable();
8} // namespace native8} // namespace native
9} // namespace torchat_npu_npu9} // namespace torchat_npu_npu
10#endif10#endif
11 
Mtorch_npu/csrc/npu/CMakeLists.txt+5-5
@@ -1,6 +1,6 @@
1FILE(GLOB _NPU_SRCS *.cpp)1FILE(GLOB _NPU_SRCS *.cpp)
2 2 
3LIST(APPEND NPU_SRCS ${_NPU_SRCS})3LIST(APPEND NPU_SRCS ${_NPU_SRCS})
4 4 
5# Pass to parent5# Pass to parent
6set(NPU_SRCS ${NPU_SRCS} PARENT_SCOPE)6set(NPU_SRCS ${NPU_SRCS} PARENT_SCOPE)
Mtorch_npu/csrc/profiler/CMakeLists.txt+5-5
@@ -1,6 +1,6 @@
1FILE(GLOB _PROF_SRCS *.cpp unwind/*.cpp python/*.cpp)1FILE(GLOB _PROF_SRCS *.cpp unwind/*.cpp python/*.cpp)
2 2 
3LIST(APPEND PROF_SRCS ${_PROF_SRCS})3LIST(APPEND PROF_SRCS ${_PROF_SRCS})
4 4 
5# Pass to parent5# Pass to parent
6set(PROF_SRCS ${PROF_SRCS} PARENT_SCOPE)6set(PROF_SRCS ${PROF_SRCS} PARENT_SCOPE)
Mtorch_npu/csrc/utils/TensorType.cpp+347-347
@@ -1,347 +1,347 @@
1#include <c10/core/DeviceType.h>1#include <c10/core/DeviceType.h>
2#include <torch/csrc/autograd/utils/wrap_outputs.h>2#include <torch/csrc/autograd/utils/wrap_outputs.h>
3 3 
4#include "torch_npu/csrc/utils/TensorType.h"4#include "torch_npu/csrc/utils/TensorType.h"
5#include "torch_npu/csrc/utils/LazyInit.h"5#include "torch_npu/csrc/utils/LazyInit.h"
6 6 
7namespace torch_npu {7namespace torch_npu {
8namespace utils {8namespace utils {
9using namespace at;9using namespace at;
10using namespace torch::autograd;10using namespace torch::autograd;
11 11 
12std::vector<std::pair<Backend, ScalarType>> all_declared_types_npu()12std::vector<std::pair<Backend, ScalarType>> all_declared_types_npu()
13{13{
14 std::vector<std::pair<Backend, ScalarType>> ret;14 std::vector<std::pair<Backend, ScalarType>> ret;
15 // can't easily iterate over enum classes, does not support BFloat16 now15 // can't easily iterate over enum classes, does not support BFloat16 now
16 std::vector<Backend> backends = { c10::Backend::PrivateUse1 };16 std::vector<Backend> backends = { c10::Backend::PrivateUse1 };
17 std::vector<ScalarType> scalar_types = { ScalarType::Byte, ScalarType::Char, ScalarType::Double,17 std::vector<ScalarType> scalar_types = { ScalarType::Byte, ScalarType::Char, ScalarType::Double,
18 ScalarType::Float, ScalarType::Int, ScalarType::Long,18 ScalarType::Float, ScalarType::Int, ScalarType::Long,
19 ScalarType::Short, ScalarType::Half, ScalarType::Bool,19 ScalarType::Short, ScalarType::Half, ScalarType::Bool,
20 ScalarType::BFloat16 };20 ScalarType::BFloat16 };
21 21 
22 for (auto &backend : backends) {22 for (auto &backend : backends) {
23 for (auto &scalar_type : scalar_types) {23 for (auto &scalar_type : scalar_types) {
24 ret.emplace_back(std::make_pair(backend, scalar_type));24 ret.emplace_back(std::make_pair(backend, scalar_type));
25 }25 }
26 }26 }
27 27 
28 return ret;28 return ret;
29}29}
30 30 
31struct PyTensorType {31struct PyTensorType {
32 PyTypeObject py_type;32 PyTypeObject py_type;
33 THPDtype *dtype;33 THPDtype *dtype;
34 THPLayout *layout;34 THPLayout *layout;
35 bool is_npu;35 bool is_npu;
36 char name[64];36 char name[64];
37 int backend;37 int backend;
38 int scalar_type;38 int scalar_type;
39 39 
40 Backend get_backend() const40 Backend get_backend() const
41 {41 {
42 return static_cast<Backend>(backend);42 return static_cast<Backend>(backend);
43 }43 }
44 44 
45 DispatchKey get_dispatch_key() const45 DispatchKey get_dispatch_key() const
46 {46 {
47 return backendToDispatchKey(static_cast<Backend>(backend));47 return backendToDispatchKey(static_cast<Backend>(backend));
48 }48 }
49 49 
50 ScalarType get_scalar_type() const50 ScalarType get_scalar_type() const
51 {51 {
52 return static_cast<ScalarType>(scalar_type);52 return static_cast<ScalarType>(scalar_type);
53 }53 }
54};54};
55 55 
56static_assert(std::is_standard_layout<PyTensorType>::value, "PyTensorType must be standard layout");56static_assert(std::is_standard_layout<PyTensorType>::value, "PyTensorType must be standard layout");
57 57 
58static void py_bind_tensor_types(const std::vector<PyTensorType> &tensor_types);58static void py_bind_tensor_types(const std::vector<PyTensorType> &tensor_types);
59 59 
60static PyObject *Tensor_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)60static PyObject *Tensor_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
61{61{
62 HANDLE_TH_ERRORS62 HANDLE_TH_ERRORS
63 auto &tensor_type = *((PyTensorType *)type);63 auto &tensor_type = *((PyTensorType *)type);
64 if (tensor_type.is_npu) {64 if (tensor_type.is_npu) {
65 TORCH_NPU_WARN_ONCE("Warning: The torch.npu.*DtypeTensor constructors are no longer recommended. "65 TORCH_NPU_WARN_ONCE("Warning: The torch.npu.*DtypeTensor constructors are no longer recommended. "
66 "It's best to use methods such as torch.tensor(data, dtype=*, device='npu') "66 "It's best to use methods such as torch.tensor(data, dtype=*, device='npu') "
67 "to create tensors.");67 "to create tensors.");
68 }68 }
69 TORCH_CHECK_TYPE(!tensor_type.is_npu || c10_npu::device_count() != 0, "type ", tensor_type.name,69 TORCH_CHECK_TYPE(!tensor_type.is_npu || c10_npu::device_count() != 0, "type ", tensor_type.name,
70 " not available. Torch not compiled with npu enabled.", PTA_ERROR(ErrCode::TYPE))70 " not available. Torch not compiled with npu enabled.", PTA_ERROR(ErrCode::TYPE))
71 torch_npu::utils::npu_lazy_init();71 torch_npu::utils::npu_lazy_init();
72 return THPVariable_Wrap(72 return THPVariable_Wrap(
73 torch::utils::legacy_tensor_ctor(tensor_type.get_dispatch_key(), tensor_type.get_scalar_type(), args, kwargs));73 torch::utils::legacy_tensor_ctor(tensor_type.get_dispatch_key(), tensor_type.get_scalar_type(), args, kwargs));
74 END_HANDLE_TH_ERRORS74 END_HANDLE_TH_ERRORS
75}75}
76 76 
77static PyObject *Tensor_instancecheck(PyObject *_self, PyObject *arg)77static PyObject *Tensor_instancecheck(PyObject *_self, PyObject *arg)
78{78{
79 HANDLE_TH_ERRORS79 HANDLE_TH_ERRORS
80 auto self = (PyTensorType *)_self;80 auto self = (PyTensorType *)_self;
81 if (THPVariable_Check(arg)) {81 if (THPVariable_Check(arg)) {
82 const auto &var = THPVariable_Unpack(arg);82 const auto &var = THPVariable_Unpack(arg);
83 83 
84 if (legacyExtractDispatchKey(var.key_set()) == self->get_dispatch_key() &&84 if (legacyExtractDispatchKey(var.key_set()) == self->get_dispatch_key() &&
85 var.scalar_type() == static_cast<ScalarType>(self->scalar_type)) {85 var.scalar_type() == static_cast<ScalarType>(self->scalar_type)) {
86 Py_RETURN_TRUE;86 Py_RETURN_TRUE;
87 }87 }
88 }88 }
89 Py_RETURN_FALSE;89 Py_RETURN_FALSE;
90 END_HANDLE_TH_ERRORS90 END_HANDLE_TH_ERRORS
91}91}
92 92 
93PyObject *Tensor_dtype(PyTensorType *self, void *unused)93PyObject *Tensor_dtype(PyTensorType *self, void *unused)
94{94{
95 return torch::autograd::utils::wrap(self->dtype);95 return torch::autograd::utils::wrap(self->dtype);
96}96}
97 97 
98PyObject *Tensor_layout(PyTensorType *self, void *unused)98PyObject *Tensor_layout(PyTensorType *self, void *unused)
99{99{
100 return torch::autograd::utils::wrap(self->layout);100 return torch::autograd::utils::wrap(self->layout);
101}101}
102 102 
103PyObject *Tensor_is_npu(PyTensorType *self, void *unused)103PyObject *Tensor_is_npu(PyTensorType *self, void *unused)
104{104{
105 if (self->is_npu) {105 if (self->is_npu) {
106 Py_RETURN_TRUE;106 Py_RETURN_TRUE;
107 } else {107 } else {
108 Py_RETURN_FALSE;108 Py_RETURN_FALSE;
109 }109 }
110}110}
111 111 
112PyObject *Tensor_is_sparse(PyTensorType *self, void *unused)112PyObject *Tensor_is_sparse(PyTensorType *self, void *unused)
113{113{
114 if (self->layout->layout == at::Layout::Strided) {114 if (self->layout->layout == at::Layout::Strided) {
115 Py_RETURN_FALSE;115 Py_RETURN_FALSE;
116 } else {116 } else {
117 Py_RETURN_TRUE;117 Py_RETURN_TRUE;
118 }118 }
119}119}
120 120 
121static struct PyMethodDef metaclass_methods[] = {121static struct PyMethodDef metaclass_methods[] = {
122 {"__instancecheck__", Tensor_instancecheck, METH_O, nullptr},122 {"__instancecheck__", Tensor_instancecheck, METH_O, nullptr},
123 {nullptr}123 {nullptr}
124};124};
125 125 
126using getter = PyObject *(*)(PyObject *, void *);126using getter = PyObject *(*)(PyObject *, void *);
127 127 
128static struct PyGetSetDef metaclass_properties[] = {128static struct PyGetSetDef metaclass_properties[] = {
129 {"dtype", (getter)Tensor_dtype, nullptr, nullptr, nullptr},129 {"dtype", (getter)Tensor_dtype, nullptr, nullptr, nullptr},
130 {"layout", (getter)Tensor_layout, nullptr, nullptr, nullptr},130 {"layout", (getter)Tensor_layout, nullptr, nullptr, nullptr},
131 {"is_npu", (getter)Tensor_is_npu, nullptr, nullptr, nullptr},131 {"is_npu", (getter)Tensor_is_npu, nullptr, nullptr, nullptr},
132 {"is_sparse", (getter)Tensor_is_sparse, nullptr, nullptr, nullptr},132 {"is_sparse", (getter)Tensor_is_sparse, nullptr, nullptr, nullptr},
133 {nullptr}133 {nullptr}
134};134};
135 135 
136static PyTypeObject metaclass = {136static PyTypeObject metaclass = {
137 PyVarObject_HEAD_INIT(nullptr, 0) "torch.tensortype", /* tp_name */137 PyVarObject_HEAD_INIT(nullptr, 0) "torch.tensortype", /* tp_name */
138 sizeof(PyTypeObject) /* tp_basicsize */138 sizeof(PyTypeObject) /* tp_basicsize */
139};139};
140 140 
141static void py_initialize_metaclass(PyTypeObject &metaclass)141static void py_initialize_metaclass(PyTypeObject &metaclass)
142{142{
143 metaclass.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE;143 metaclass.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE;
144 metaclass.tp_methods = metaclass_methods;144 metaclass.tp_methods = metaclass_methods;
145 metaclass.tp_getset = metaclass_properties;145 metaclass.tp_getset = metaclass_properties;
146 metaclass.tp_base = &PyType_Type;146 metaclass.tp_base = &PyType_Type;
147 if (PyType_Ready(&metaclass) < 0) {147 if (PyType_Ready(&metaclass) < 0) {
148 throw python_error();148 throw python_error();
149 }149 }
150}150}
151 151 
152static PyTypeObject tensor_type_prototype = {152static PyTypeObject tensor_type_prototype = {
153 PyVarObject_HEAD_INIT(&metaclass, 0) nullptr, /* tp_name */153 PyVarObject_HEAD_INIT(&metaclass, 0) nullptr, /* tp_name */
154 sizeof(PyTensorType) /* tp_basicsize */154 sizeof(PyTensorType) /* tp_basicsize */
155};155};
156 156 
157static void py_initialize_tensor_type(PyTypeObject &type, const char *name, PyObject *tp_dict)157static void py_initialize_tensor_type(PyTypeObject &type, const char *name, PyObject *tp_dict)
158{158{
159 // NOTE: we don't use the typical static declaration of PyTypeObject because159 // NOTE: we don't use the typical static declaration of PyTypeObject because
160 // we need to initialize as many types as there are VariableType instances.160 // we need to initialize as many types as there are VariableType instances.
161 // We copy the basic object fields from a prototype definition and initialize161 // We copy the basic object fields from a prototype definition and initialize
162 // the remaining fields below.162 // the remaining fields below.
163 memcpy(&type, &tensor_type_prototype, sizeof(PyTypeObject));163 memcpy(&type, &tensor_type_prototype, sizeof(PyTypeObject));
164 // Subclassing from torch.<ScalarType>Tensor isn't supported.164 // Subclassing from torch.<ScalarType>Tensor isn't supported.
165 // (Py_TPFLAGS_BASETYPE omitted). Subclassing torch.Tensor still allowed.165 // (Py_TPFLAGS_BASETYPE omitted). Subclassing torch.Tensor still allowed.
166 type.tp_flags = Py_TPFLAGS_DEFAULT;166 type.tp_flags = Py_TPFLAGS_DEFAULT;
167 type.tp_name = name;167 type.tp_name = name;
168 type.tp_new = Tensor_new;168 type.tp_new = Tensor_new;
169 if (PyType_Ready(&type) < 0) {169 if (PyType_Ready(&type) < 0) {
170 throw python_error();170 throw python_error();
171 }171 }
172 if (PyDict_Merge(type.tp_dict, tp_dict, 0) < 0) {172 if (PyDict_Merge(type.tp_dict, tp_dict, 0) < 0) {
173 throw python_error();173 throw python_error();
174 }174 }
175}175}
176 176 
177static std::string get_module(Backend backend)177static std::string get_module(Backend backend)
178{178{
179 switch (backend) {179 switch (backend) {
180 case Backend::CPU:180 case Backend::CPU:
181 return "torch";181 return "torch";
182 case Backend::CUDA:182 case Backend::CUDA:
183 return "torch.cuda";183 return "torch.cuda";
184 case Backend::SparseCPU:184 case Backend::SparseCPU:
185 return "torch.sparse";185 return "torch.sparse";
186 case Backend::SparseCUDA:186 case Backend::SparseCUDA:
187 return "torch.cuda.sparse";187 return "torch.cuda.sparse";
188 case Backend::PrivateUse1:188 case Backend::PrivateUse1:
189 return "torch." + c10::get_privateuse1_backend();189 return "torch." + c10::get_privateuse1_backend();
190 default:190 default:
191 AT_ERROR("invalid backend: ", c10::toString(backend));191 AT_ERROR("invalid backend: ", c10::toString(backend));
192 }192 }
193}193}
194 194 
195static std::string get_name(Backend backend, ScalarType scalarType)195static std::string get_name(Backend backend, ScalarType scalarType)
196{196{
197 std::ostringstream ss;197 std::ostringstream ss;
198 ss << get_module(backend) << "." << toString(scalarType) << "Tensor";198 ss << get_module(backend) << "." << toString(scalarType) << "Tensor";
199 return ss.str();199 return ss.str();
200}200}
201 201 
202static void set_type(PyTensorType &type_obj, Backend backend, ScalarType scalarType)202static void set_type(PyTensorType &type_obj, Backend backend, ScalarType scalarType)
203{203{
204 // This field is lazily initialized from backend and scalar_type204 // This field is lazily initialized from backend and scalar_type
205 type_obj.backend = static_cast<int>(backend);205 type_obj.backend = static_cast<int>(backend);
206 type_obj.scalar_type = static_cast<int>(scalarType);206 type_obj.scalar_type = static_cast<int>(scalarType);
207 type_obj.layout = torch::getTHPLayout(c10::layout_from_backend(backend));207 type_obj.layout = torch::getTHPLayout(c10::layout_from_backend(backend));
208 type_obj.dtype = torch::getTHPDtype(scalarType);208 type_obj.dtype = torch::getTHPDtype(scalarType);
209 type_obj.is_npu = (backend == c10::Backend::PrivateUse1);209 type_obj.is_npu = (backend == c10::Backend::PrivateUse1);
210}210}
211 211 
212static void set_name(PyTensorType &type_obj, const std::string &name)212static void set_name(PyTensorType &type_obj, const std::string &name)
213{213{
214 size_t n = sizeof(type_obj.name);214 size_t n = sizeof(type_obj.name);
215 strncpy(type_obj.name, name.c_str(), n);215 strncpy(type_obj.name, name.c_str(), n);
216 type_obj.name[n - 1] = '\0';216 type_obj.name[n - 1] = '\0';
217}217}
218 218 
219static THPObjectPtr get_tensor_dict()219static THPObjectPtr get_tensor_dict()
220{220{
221 auto torch = THPObjectPtr(PyImport_ImportModule("torch"));221 auto torch = THPObjectPtr(PyImport_ImportModule("torch"));
222 if (!torch) {222 if (!torch) {
223 throw python_error();223 throw python_error();
224 }224 }
225 225 
226 auto tensor_class = THPObjectPtr(PyObject_GetAttrString(torch, "Tensor"));226 auto tensor_class = THPObjectPtr(PyObject_GetAttrString(torch, "Tensor"));
227 if (!tensor_class) {227 if (!tensor_class) {
228 throw python_error();228 throw python_error();
229 }229 }
230 230 
231 auto tensor_type = (PyTypeObject *)tensor_class.get();231 auto tensor_type = (PyTypeObject *)tensor_class.get();
232 TORCH_CHECK(tensor_type->tp_base, "missing base type for Tensor", PTA_ERROR(ErrCode::TYPE));232 TORCH_CHECK(tensor_type->tp_base, "missing base type for Tensor", PTA_ERROR(ErrCode::TYPE));
233 233 
234 auto res = THPObjectPtr(PyDict_New());234 auto res = THPObjectPtr(PyDict_New());
235 if (!res) {235 if (!res) {
236 throw python_error();236 throw python_error();
237 }237 }
238 238 
239 if (PyDict_Merge(res.get(), tensor_type->tp_dict, 0) < 0) {239 if (PyDict_Merge(res.get(), tensor_type->tp_dict, 0) < 0) {
240 throw python_error();240 throw python_error();
241 }241 }
242 if (PyDict_Merge(res.get(), tensor_type->tp_base->tp_dict, 0) < 0) {242 if (PyDict_Merge(res.get(), tensor_type->tp_base->tp_dict, 0) < 0) {
243 throw python_error();243 throw python_error();
244 }244 }
245 245 
246 return res;246 return res;
247}247}
248 248 
249static std::vector<PyTensorType> tensor_types;249static std::vector<PyTensorType> tensor_types;
250 250 
251static void initialize_npu_aten_types(std::vector<PyTensorType> &tensor_types)251static void initialize_npu_aten_types(std::vector<PyTensorType> &tensor_types)
252{252{
253 // only initialize npu types253 // only initialize npu types
254 auto declared_types = all_declared_types_npu();254 auto declared_types = all_declared_types_npu();
255 tensor_types.resize(declared_types.size());255 tensor_types.resize(declared_types.size());
256 256 
257 for (size_t i = 0, end = declared_types.size(); i != end; i++) {257 for (size_t i = 0, end = declared_types.size(); i != end; i++) {
258 auto &tensor_type = tensor_types[i];258 auto &tensor_type = tensor_types[i];
259 Backend backend = declared_types[i].first;259 Backend backend = declared_types[i].first;
260 ScalarType scalar_type = declared_types[i].second;260 ScalarType scalar_type = declared_types[i].second;
261 set_type(tensor_type, backend, scalar_type);261 set_type(tensor_type, backend, scalar_type);
262 set_name(tensor_type, get_name(backend, scalar_type));262 set_name(tensor_type, get_name(backend, scalar_type));
263 }263 }
264}264}
265 265 
266void _initialize_python_bindings()266void _initialize_python_bindings()
267{267{
268 // Initialize the at::Type* pointers, name, and properties of the PyTensorType268 // Initialize the at::Type* pointers, name, and properties of the PyTensorType
269 // vector. After this call, the vector must not be resized.269 // vector. After this call, the vector must not be resized.
270 initialize_npu_aten_types(tensor_types);270 initialize_npu_aten_types(tensor_types);
271 271 
272 // Initialize the Python metaclass for the torch.FloatTensor, etc. types.272 // Initialize the Python metaclass for the torch.FloatTensor, etc. types.
273 // The metaclass handles __instancecheck__ checks and binds the dtype property273 // The metaclass handles __instancecheck__ checks and binds the dtype property
274 // on the type objects.274 // on the type objects.
275 py_initialize_metaclass(metaclass);275 py_initialize_metaclass(metaclass);
276 276 
277 // Get the tp_dict of the Variable class. We copy function definitions277 // Get the tp_dict of the Variable class. We copy function definitions
278 // onto each Tensor type object so that they can be accessed via e.g.278 // onto each Tensor type object so that they can be accessed via e.g.
279 // `torch.npu.FloatTensor.add`.279 // `torch.npu.FloatTensor.add`.
280 auto tensor_dict = get_tensor_dict();280 auto tensor_dict = get_tensor_dict();
281 281 
282 // Initialize each Python type object torch.npu.FloatTensor, torch.npu.DoubleTensor, etc.282 // Initialize each Python type object torch.npu.FloatTensor, torch.npu.DoubleTensor, etc.
283 for (auto &tensor_type : tensor_types) {283 for (auto &tensor_type : tensor_types) {
284 py_initialize_tensor_type(tensor_type.py_type, tensor_type.name, tensor_dict.get());284 py_initialize_tensor_type(tensor_type.py_type, tensor_type.name, tensor_dict.get());
285 }285 }
286 286 
287 // Add the type objects to their corresponding modules. e.g. torch.npu.FloatTensor287 // Add the type objects to their corresponding modules. e.g. torch.npu.FloatTensor
288 // is added to the `torch_npu` module as `FloatTensor`. Also add all the type288 // is added to the `torch_npu` module as `FloatTensor`. Also add all the type
289 // objects to the set torch_npu._tensor_classes.289 // objects to the set torch_npu._tensor_classes.
290 py_bind_tensor_types(tensor_types);290 py_bind_tensor_types(tensor_types);
291}291}
292 292 
293static void py_bind_tensor_types(const std::vector<PyTensorType> &tensor_types)293static void py_bind_tensor_types(const std::vector<PyTensorType> &tensor_types)
294{294{
295 auto torch_module = THPObjectPtr(PyImport_ImportModule("torch"));295 auto torch_module = THPObjectPtr(PyImport_ImportModule("torch"));
296 if (!torch_module) {296 if (!torch_module) {
297 throw python_error();297 throw python_error();
298 }298 }
299 299 
300 auto tensor_classes = THPObjectPtr(PyObject_GetAttrString(torch_module.get(), "_tensor_classes"));300 auto tensor_classes = THPObjectPtr(PyObject_GetAttrString(torch_module.get(), "_tensor_classes"));
301 if (!tensor_classes) {301 if (!tensor_classes) {
302 throw python_error();302 throw python_error();
303 }303 }
304 304 
305 for (auto &tensor_type : tensor_types) {305 for (auto &tensor_type : tensor_types) {
306 auto name = std::string(tensor_type.name);306 auto name = std::string(tensor_type.name);
307 auto idx = name.rfind('.');307 auto idx = name.rfind('.');
308 auto type_name = name.substr(idx + 1);308 auto type_name = name.substr(idx + 1);
309 auto module_name = name.substr(0, idx);309 auto module_name = name.substr(0, idx);
310 310 
311 auto module_obj = THPObjectPtr(PyImport_ImportModule(module_name.c_str()));311 auto module_obj = THPObjectPtr(PyImport_ImportModule(module_name.c_str()));
312 if (!module_obj) {312 if (!module_obj) {
313 throw python_error();313 throw python_error();
314 }314 }
315 315 
316 PyObject *type_obj = (PyObject *)&tensor_type;316 PyObject *type_obj = (PyObject *)&tensor_type;
317 Py_INCREF(type_obj);317 Py_INCREF(type_obj);
318 if (PyModule_AddObject(module_obj.get(), type_name.c_str(), type_obj) < 0) {318 if (PyModule_AddObject(module_obj.get(), type_name.c_str(), type_obj) < 0) {
319 throw python_error();319 throw python_error();
320 }320 }
321 if (PySet_Add(tensor_classes.get(), type_obj) < 0) {321 if (PySet_Add(tensor_classes.get(), type_obj) < 0) {
322 throw python_error();322 throw python_error();
323 }323 }
324 }324 }
325}325}
326 326 
327// Callback for python part. Used for additional initialization of python classes327// Callback for python part. Used for additional initialization of python classes
328static PyObject *THPModule_initExtension(PyObject *_unused, PyObject *noargs)328static PyObject *THPModule_initExtension(PyObject *_unused, PyObject *noargs)
329{329{
330 HANDLE_TH_ERRORS330 HANDLE_TH_ERRORS
331 _initialize_python_bindings();331 _initialize_python_bindings();
332 Py_RETURN_NONE;332 Py_RETURN_NONE;
333 END_HANDLE_TH_ERRORS333 END_HANDLE_TH_ERRORS
334}334}
335 335 
336// autograd methods on torch._C336// autograd methods on torch._C
337static PyMethodDef TorchNpuExtensionMethods[] = {337static PyMethodDef TorchNpuExtensionMethods[] = {
338 {"_initExtension", (PyCFunction)THPModule_initExtension, METH_NOARGS, nullptr},338 {"_initExtension", (PyCFunction)THPModule_initExtension, METH_NOARGS, nullptr},
339 {nullptr, nullptr, 0, nullptr}339 {nullptr, nullptr, 0, nullptr}
340};340};
341 341 
342PyMethodDef *npu_extension_functions()342PyMethodDef *npu_extension_functions()
343{343{
344 return TorchNpuExtensionMethods;344 return TorchNpuExtensionMethods;
345}345}
346}346}
347}347}
Mtorch_npu/csrc/utils/TensorType.h+16-16
@@ -1,16 +1,16 @@
1#include <torch/csrc/utils/tensor_new.h>1#include <torch/csrc/utils/tensor_new.h>
2 2 
3#include "torch_npu/csrc/core/npu/NPUMacros.h"3#include "torch_npu/csrc/core/npu/NPUMacros.h"
4#include "torch_npu/csrc/core/npu/NPUFunctions.h"4#include "torch_npu/csrc/core/npu/NPUFunctions.h"
5 5 
6namespace torch_npu {6namespace torch_npu {
7namespace utils {7namespace utils {
8 8 
9// Initializes the Python tensor type objects: torch.npu.FloatTensor,9// Initializes the Python tensor type objects: torch.npu.FloatTensor,
10// torch.npu.DoubleTensor, etc. and binds them in their containing modules.10// torch.npu.DoubleTensor, etc. and binds them in their containing modules.
11void _initialize_python_bindings();11void _initialize_python_bindings();
12 12 
13TORCH_NPU_API PyMethodDef* npu_extension_functions();13TORCH_NPU_API PyMethodDef* npu_extension_functions();
14 14 
15}15}
16}16}
Mtorch_npu/distributed/__init__.py+30-30
@@ -1,30 +1,30 @@
1__all__ = [1__all__ = [
2 "is_hccl_available", "reinit_process_group", "reduce_scatter_tensor_uneven", "all_gather_into_tensor_uneven"2 "is_hccl_available", "reinit_process_group", "reduce_scatter_tensor_uneven", "all_gather_into_tensor_uneven"
3]3]
4 4 
5from torch.distributed import _make_nccl_premul_sum as _make_hccl_premul_sum5from torch.distributed import _make_nccl_premul_sum as _make_hccl_premul_sum
6 6 
7import torch_npu7import torch_npu
8 8 
9 9 
10def is_available():10def is_available():
11 """11 """
12 Returns ``True`` if the distributed package is available. Otherwise,12 Returns ``True`` if the distributed package is available. Otherwise,
13 ``torch.distributed`` does not expose any other APIs. Currently,13 ``torch.distributed`` does not expose any other APIs. Currently,
14 ``torch.distributed`` is available on Linux, MacOS and Windows. Set14 ``torch.distributed`` is available on Linux, MacOS and Windows. Set
15 ``USE_DISTRIBUTED=1`` to enable it when building PyTorch from source.15 ``USE_DISTRIBUTED=1`` to enable it when building PyTorch from source.
16 Currently, the default value is ``USE_DISTRIBUTED=1`` for Linux and Windows,16 Currently, the default value is ``USE_DISTRIBUTED=1`` for Linux and Windows,
17 ``USE_DISTRIBUTED=0`` for MacOS.17 ``USE_DISTRIBUTED=0`` for MacOS.
18 """18 """
19 return hasattr(torch_npu._C, "_c10d_npu_init")19 return hasattr(torch_npu._C, "_c10d_npu_init")
20 20 
21 21 
22from torch_npu._C._distributed_c10d import (22from torch_npu._C._distributed_c10d import (
23 ParallelStore,23 ParallelStore,
24 _verify_params_across_processes,24 _verify_params_across_processes,
25 _is_support_hccl_comm_name,25 _is_support_hccl_comm_name,
26)26)
27 27 
28 28 
29from torch_npu.distributed import fsdp, tensor, nn29from torch_npu.distributed import fsdp, tensor, nn
30from .distributed_c10d import is_hccl_available, reinit_process_group, _reduce_scatter_tensor_uneven as reduce_scatter_tensor_uneven, _all_gather_into_tensor_uneven as all_gather_into_tensor_uneven30from .distributed_c10d import is_hccl_available, reinit_process_group, _reduce_scatter_tensor_uneven as reduce_scatter_tensor_uneven, _all_gather_into_tensor_uneven as all_gather_into_tensor_uneven
Mtorch_npu/dynamo/trace_rule.py+99-100
@@ -1,100 +1,99 @@
1import torch1import torch
2from torch._dynamo.variables import TorchInGraphFunctionVariable2from torch._dynamo.variables import TorchInGraphFunctionVariable
3from torch._dynamo.trace_rules import manual_torch_name_rule_map, SkipFunctionVariable3from torch._dynamo.trace_rules import manual_torch_name_rule_map, SkipFunctionVariable
4import torch._dynamo.variables.torch as torch_module4import torch._dynamo.variables.torch as torch_module
5from torch._dynamo.utils import common_constant_types5from torch._dynamo.utils import common_constant_types
6import torch_npu6import torch_npu
7 7 
8__all__ = []8__all__ = []
9 9 
10torch_non_c_binding_in_graph_functions_npu = dict.fromkeys(10torch_non_c_binding_in_graph_functions_npu = dict.fromkeys(
11 [11 [
12 "torch.npu.current_stream",12 "torch.npu.current_stream",
13 "torch.npu.default_stream",13 "torch.npu.default_stream",
14 "torch.npu.stream",14 "torch.npu.stream",
15 "torch.npu.set_stream",15 "torch.npu.set_stream",
16 "torch_npu.npu.utils.synchronize",16 "torch_npu.npu.utils.synchronize",
17 "torch.npu.current_device",17 "torch.npu.current_device",
18 "torch.npu.get_device_capability",18 "torch.npu.get_device_capability",
19 "torch.npu.get_device_properties",19 "torch.npu.get_device_properties",
20 "torch.npu.graphs.graph_pool_handle",20 "torch.npu.graphs.graph_pool_handle",
21 "torch.npu.ipc_collect",21 "torch.npu.ipc_collect",
22 "torch.npu.is_available",22 "torch.npu.is_available",
23 "torch.npu.memory._dump_snapshot",23 "torch.npu.memory._dump_snapshot",
24 "torch.npu.memory._free_mutex",24 "torch.npu.memory._free_mutex",
25 "torch.npu.memory._record_memory_history_impl",25 "torch.npu.memory._record_memory_history_impl",
26 "torch.npu.memory._set_allocator_settings",26 "torch.npu.memory._set_allocator_settings",
27 "torch.npu.memory.empty_cache",27 "torch.npu.memory.empty_cache",
28 "torch.npu.mem_get_info",28 "torch.npu.mem_get_info",
29 "torch.npu.memory.reset_accumulated_host_memory_stats",29 "torch.npu.memory.reset_accumulated_host_memory_stats",
30 "torch.npu.memory.reset_accumulated_memory_stats",30 "torch.npu.memory.reset_accumulated_memory_stats",
31 "torch.npu.memory.reset_max_memory_allocated",31 "torch.npu.memory.reset_max_memory_allocated",
32 "torch.npu.memory.reset_max_memory_cached",32 "torch.npu.memory.reset_max_memory_cached",
33 "torch.npu.memory.reset_peak_host_memory_stats",33 "torch.npu.memory.reset_peak_host_memory_stats",
34 "torch.npu.memory.reset_peak_memory_stats",34 "torch.npu.memory.reset_peak_memory_stats",
35 "torch.npu.memory.get_per_process_memory_fraction",35 "torch.npu.memory.get_per_process_memory_fraction",
36 "torch.npu.memory.set_per_process_memory_fraction",36 "torch.npu.memory.set_per_process_memory_fraction",
37 "torch.npu.random.manual_seed_all",37 "torch.npu.random.manual_seed_all",
38 "torch.npu.random.manual_seed",38 "torch.npu.random.manual_seed",
39 "torch.npu.random.seed_all",39 "torch.npu.random.seed_all",
40 "torch.npu.random.seed",40 "torch.npu.random.seed",
41 "torch.npu.set_sync_debug_mode",41 "torch.npu.set_sync_debug_mode",
42 "torch.npu._set_rng_state_offset",42 "torch.npu._set_rng_state_offset",
43 "torch.npu._get_generator", 43 "torch.npu._get_generator",
44 "torch.npu._memory_viz._frames_fmt", 44 "torch.npu._memory_viz._frames_fmt",
45 "torch.npu._memory_viz._frame_fmt", 45 "torch.npu._memory_viz._frame_fmt",
46 "torch.npu.amp.autocast_mode.custom_bwd", 46 "torch.npu.amp.autocast_mode.custom_bwd",
47 "torch.npu.amp.autocast_mode.custom_fwd", 47 "torch.npu.amp.autocast_mode.custom_fwd",
48 "torch.npu.is_initialized",48 "torch.npu.is_initialized",
49 "torch.npu._get_current_allocator",49 "torch.npu._get_current_allocator",
50 "torch.npu.is_bf16_supported",50 "torch.npu.is_bf16_supported",
51 "torch.npu.memory._get_current_allocator",51 "torch.npu.memory._get_current_allocator",
52 ],52 ],
53 TorchInGraphFunctionVariable,53 TorchInGraphFunctionVariable,
54)54)
55 55 
56torch_c_binding_in_graph_functions_npu = dict.fromkeys(56torch_c_binding_in_graph_functions_npu = dict.fromkeys(
57 [57 [
58 "torch_npu._C._npu_changeCurrentAllocator",58 "torch_npu._C._npu_changeCurrentAllocator",
59 "torch_npu._C._npu_npuCachingAllocator_set_allocator_settings",59 "torch_npu._C._npu_npuCachingAllocator_set_allocator_settings",
60 "torch_npu._C._npu_emptyCache",60 "torch_npu._C._npu_emptyCache",
61 "torch_npu._C._npu_getAllocator",61 "torch_npu._C._npu_getAllocator",
62 "torch_npu._C._npu_getCheckpointState",62 "torch_npu._C._npu_getCheckpointState",
63 "torch_npu._C._npu_getCurrentStream",63 "torch_npu._C._npu_getCurrentStream",
64 "torch_npu._C._npu_getDefaultStream",64 "torch_npu._C._npu_getDefaultStream",
65 "torch_npu._C._npu_init",65 "torch_npu._C._npu_init",
66 "torch_npu._C._npu_ipc_collect",66 "torch_npu._C._npu_ipc_collect",
67 "torch_npu._C._npu_resetAccumulatedHostMemoryStats",67 "torch_npu._C._npu_resetAccumulatedHostMemoryStats",
68 "torch_npu._C._npu_resetPeakHostMemoryStats",68 "torch_npu._C._npu_resetPeakHostMemoryStats",
69 "torch_npu._C._npu_resetPeakMemoryStats",69 "torch_npu._C._npu_resetPeakMemoryStats",
70 "torch_npu._C._npu_set_sync_debug_mode",70 "torch_npu._C._npu_set_sync_debug_mode",
71 "torch_npu._C._npu_setDevice",71 "torch_npu._C._npu_setDevice",
72 "torch_npu._C._npu_getMemoryFraction",72 "torch_npu._C._npu_getMemoryFraction",
73 "torch_npu._C._npu_setMemoryFraction",73 "torch_npu._C._npu_setMemoryFraction",
74 "torch_npu._C._npu_synchronize",74 "torch_npu._C._npu_synchronize",
75 "torch_npu._C._npu_resetAccumulatedMemoryStats",75 "torch_npu._C._npu_resetAccumulatedMemoryStats",
76 "torch_npu._C._npu_hasPrimaryContext",76 "torch_npu._C._npu_hasPrimaryContext",
77 "torch_npu._C._npu_setStream",77 "torch_npu._C._npu_setStream",
78 ],78 ],
79 TorchInGraphFunctionVariable,79 TorchInGraphFunctionVariable,
80)80)
81 81 
82skip_functions_npu = dict.fromkeys(82skip_functions_npu = dict.fromkeys(
83 [83 [
84 "torch.npu.set_device",84 "torch.npu.set_device",
85 ],85 ],
86 SkipFunctionVariable86 SkipFunctionVariable
87)87)
88 88 
89 89 
90def _patch_npu_trace_rules():90def _patch_npu_trace_rules():
91 torch._dynamo.trace_rules.clear_lru_cache()91 torch._dynamo.trace_rules.clear_lru_cache()
92 torch._dynamo.trace_rules.torch_name_rule_map.append(torch_non_c_binding_in_graph_functions_npu)92 torch._dynamo.trace_rules.torch_name_rule_map.append(torch_non_c_binding_in_graph_functions_npu)
93 torch._dynamo.trace_rules.torch_name_rule_map.append(torch_c_binding_in_graph_functions_npu)93 torch._dynamo.trace_rules.torch_name_rule_map.append(torch_c_binding_in_graph_functions_npu)
94 torch._dynamo.trace_rules.torch_name_rule_map.append(skip_functions_npu)94 torch._dynamo.trace_rules.torch_name_rule_map.append(skip_functions_npu)
95 torch_module.constant_fold_functions[torch.npu.current_device] = True95 torch_module.constant_fold_functions[torch.npu.current_device] = True
96 torch_module.constant_fold_functions[torch.npu.get_device_properties] = True96 torch_module.constant_fold_functions[torch.npu.get_device_properties] = True
97 torch_module.constant_fold_functions_need_guards[torch.npu.current_device] = True97 torch_module.constant_fold_functions_need_guards[torch.npu.current_device] = True
98 torch_module.constant_fold_functions[torch.npu.is_available] = True98 torch_module.constant_fold_functions[torch.npu.is_available] = True
99 common_constant_types.add(torch_npu._C._NPUDeviceProperties)99 common_constant_types.add(torch_npu._C._NPUDeviceProperties)
100 
Mtorch_npu/npu/amp/__init__.py+5-5
@@ -1,6 +1,6 @@
1__all__ = [1__all__ = [
2 "autocast", "GradScaler", "custom_fwd", "custom_bwd"2 "autocast", "GradScaler", "custom_fwd", "custom_bwd"
3]3]
4 4 
5from .autocast_mode import autocast, custom_fwd, custom_bwd # noqa: F4015from .autocast_mode import autocast, custom_fwd, custom_bwd # noqa: F401
O
OopenLiBingCI5月17日

此条代码评论区间+2+5

【openlibing.ci】识别到代码检查告警抑制注释,匹配工具:flake8,请Committer检视其合理性。

likedislike
6from .grad_scaler import GradScaler # noqa: F4016from .grad_scaler import GradScaler # noqa: F401
Mtorch_npu/npu/amp/autocast_mode.py+97-97
@@ -1,98 +1,98 @@
1__all__ = ["autocast", "custom_fwd", "custom_bwd"]1__all__ = ["autocast", "custom_fwd", "custom_bwd"]
2 2 
3 3 
4import functools4import functools
5import collections5import collections
6from typing import Any6from typing import Any
7from typing_extensions import deprecated7from typing_extensions import deprecated
8 8 
9try:9try:
10 import numpy as np10 import numpy as np
11 11 
12 HAS_NUMPY = True12 HAS_NUMPY = True
13except ModuleNotFoundError:13except ModuleNotFoundError:
14 np = None # type: ignore[assignment]14 np = None # type: ignore[assignment]
15 15 
16import torch16import torch
17import torch_npu17import torch_npu
O
OopenLiBingCI5月17日

此条代码评论区间+12+17

【openlibing.ci】识别到代码检查告警抑制注释,匹配工具:mypy,请Committer检视其合理性。

likedislike
18from torch_npu.utils._error_code import ErrCode, pta_error18from torch_npu.utils._error_code import ErrCode, pta_error
19 19 
20 20 
21class autocast(torch.amp.autocast_mode.autocast):21class autocast(torch.amp.autocast_mode.autocast):
22 r"""22 r"""
23 See :class:`torch.autocast`.23 See :class:`torch.autocast`.
24 ``torch.npu.amp.autocast(args...)`` is equivalent to ``torch.autocast("npu", args...)``24 ``torch.npu.amp.autocast(args...)`` is equivalent to ``torch.autocast("npu", args...)``
25 """25 """
26 26 
27 def __init__(self, enabled: bool = True, dtype: torch.dtype = torch.float16, cache_enabled: bool = True):27 def __init__(self, enabled: bool = True, dtype: torch.dtype = torch.float16, cache_enabled: bool = True):
28 if torch._jit_internal.is_scripting():28 if torch._jit_internal.is_scripting():
29 self._enabled = enabled29 self._enabled = enabled
30 self.device = "npu"30 self.device = "npu"
31 self.fast_dtype = dtype31 self.fast_dtype = dtype
32 return32 return
33 super().__init__("npu", enabled=enabled, dtype=dtype, cache_enabled=cache_enabled)33 super().__init__("npu", enabled=enabled, dtype=dtype, cache_enabled=cache_enabled)
34 34 
35 def __enter__(self):35 def __enter__(self):
36 if torch._jit_internal.is_scripting():36 if torch._jit_internal.is_scripting():
37 return self37 return self
38 return super().__enter__()38 return super().__enter__()
39 39 
40 def __exit__(self, exc_type: Any, exc_val: Any, exc_tb: Any): # type: ignore[override]40 def __exit__(self, exc_type: Any, exc_val: Any, exc_tb: Any): # type: ignore[override]
41 if torch._jit_internal.is_scripting():41 if torch._jit_internal.is_scripting():
42 return None42 return None
O
OopenLiBingCI5月17日

此条代码评论区间+37+42

【openlibing.ci】识别到代码检查告警抑制注释,匹配工具:mypy,请Committer检视其合理性。

likedislike
43 return super().__exit__(exc_type, exc_val, exc_tb)43 return super().__exit__(exc_type, exc_val, exc_tb)
44 44 
45 def __call__(self, func):45 def __call__(self, func):
46 if torch._jit_internal.is_scripting():46 if torch._jit_internal.is_scripting():
47 return func47 return func
48 return super().__call__(func)48 return super().__call__(func)
49 49 
50 50 
51# Casts Tensors and containers of Tensors. Special-cases passthroughs for strings and np.ndarrays, which51# Casts Tensors and containers of Tensors. Special-cases passthroughs for strings and np.ndarrays, which
52# may be falsely detected as "Iterables."52# may be falsely detected as "Iterables."
53def _cast(value, dtype):53def _cast(value, dtype):
54 if isinstance(value, torch.Tensor):54 if isinstance(value, torch.Tensor):
55 is_eligible = (value.is_floating_point() and value.device.type == 'npu' and (value.dtype is not torch.float64))55 is_eligible = (value.is_floating_point() and value.device.type == 'npu' and (value.dtype is not torch.float64))
56 return value.to(dtype) if is_eligible else value56 return value.to(dtype) if is_eligible else value
57 elif isinstance(value, (str, bytes)):57 elif isinstance(value, (str, bytes)):
58 return value58 return value
59 elif HAS_NUMPY and isinstance(value, np.ndarray):59 elif HAS_NUMPY and isinstance(value, np.ndarray):
60 return value60 return value
61 elif isinstance(value, collections.abc.Mapping):61 elif isinstance(value, collections.abc.Mapping):
62 return {_cast(k, dtype): _cast(v, dtype) for k, v in value.items()}62 return {_cast(k, dtype): _cast(v, dtype) for k, v in value.items()}
63 elif isinstance(value, collections.abc.Iterable):63 elif isinstance(value, collections.abc.Iterable):
64 iterable = map(lambda v: _cast(v, dtype), value)64 iterable = map(lambda v: _cast(v, dtype), value)
65 if isinstance(value, list) or isinstance(value, tuple):65 if isinstance(value, list) or isinstance(value, tuple):
66 return type(value)(iterable)66 return type(value)(iterable)
67 else:67 else:
68 return iterable68 return iterable
69 else:69 else:
70 return value70 return value
71 71 
72 72 
73@deprecated(73@deprecated(
74 "`torch_npu.npu.amp.custom_fwd(args...)` is deprecated. "74 "`torch_npu.npu.amp.custom_fwd(args...)` is deprecated. "
75 "Please use `torch.amp.custom_fwd(args..., device_type='npu')` instead.",75 "Please use `torch.amp.custom_fwd(args..., device_type='npu')` instead.",
76 category=FutureWarning,76 category=FutureWarning,
77)77)
78def custom_fwd(fwd=None, *, cast_inputs=None):78def custom_fwd(fwd=None, *, cast_inputs=None):
79 """79 """
80 ``torch_npu.npu.amp.custom_fwd(args...)`` is deprecated. Please use80 ``torch_npu.npu.amp.custom_fwd(args...)`` is deprecated. Please use
81 ``torch.amp.custom_fwd(args..., device_type='npu')`` instead.81 ``torch.amp.custom_fwd(args..., device_type='npu')`` instead.
82 """82 """
83 return functools.partial(torch.amp.custom_fwd, device_type="npu")(83 return functools.partial(torch.amp.custom_fwd, device_type="npu")(
84 fwd=fwd, cast_inputs=cast_inputs84 fwd=fwd, cast_inputs=cast_inputs
85 )85 )
86 86 
87 87 
88@deprecated(88@deprecated(
89 "`torch_npu.npu.amp.custom_bwd(args...)` is deprecated. "89 "`torch_npu.npu.amp.custom_bwd(args...)` is deprecated. "
90 "Please use `torch.amp.custom_bwd(args..., device_type='npu')` instead.",90 "Please use `torch.amp.custom_bwd(args..., device_type='npu')` instead.",
91 category=FutureWarning,91 category=FutureWarning,
92)92)
93def custom_bwd(bwd):93def custom_bwd(bwd):
94 """94 """
95 ``torch_npu.npu.amp.custom_bwd(args...)`` is deprecated. Please use95 ``torch_npu.npu.amp.custom_bwd(args...)`` is deprecated. Please use
96 ``torch.amp.custom_bwd(args..., device_type='npu')`` instead.96 ``torch.amp.custom_bwd(args..., device_type='npu')`` instead.
97 """97 """
98 return functools.partial(torch.amp.custom_bwd, device_type="npu")(bwd)98 return functools.partial(torch.amp.custom_bwd, device_type="npu")(bwd)
Mtorch_npu/npu/amp/common.py+5-5
@@ -1,5 +1,5 @@
1import torch_npu1import torch_npu
2 2 
3 3 
4def amp_definitely_not_available():4def amp_definitely_not_available():
5 return not torch_npu.npu.is_available()5 return not torch_npu.npu.is_available()
Mtorch_npu/npu/amp/grad_scaler.py+505-505
@@ -1,505 +1,505 @@
1import warnings1import warnings
2from collections import defaultdict2from collections import defaultdict
3import collections.abc as container_abcs3import collections.abc as container_abcs
4from typing import List4from typing import List
5 5 
6import torch6import torch
7import torch.distributed as dist7import torch.distributed as dist
8from torch.amp.grad_scaler import _MultiDeviceReplicator, OptState, _refresh_per_optimizer_state8from torch.amp.grad_scaler import _MultiDeviceReplicator, OptState, _refresh_per_optimizer_state
9from torch.amp.grad_scaler import GradScaler as BaseGradScaler9from torch.amp.grad_scaler import GradScaler as BaseGradScaler
10import torch_npu10import torch_npu
11from torch_npu.utils._error_code import ErrCode, pta_error11from torch_npu.utils._error_code import ErrCode, pta_error
12from .common import amp_definitely_not_available12from .common import amp_definitely_not_available
13 13 
14 14 
15class _NpuMultiDeviceReplicator(_MultiDeviceReplicator):15class _NpuMultiDeviceReplicator(_MultiDeviceReplicator):
16 """16 """
17 Lazily serves copies of a tensor to requested devices. Copies are cached per-device.17 Lazily serves copies of a tensor to requested devices. Copies are cached per-device.
18 """18 """
19 19 
20 def __init__(self, master_tensor: torch.Tensor) -> None:20 def __init__(self, master_tensor: torch.Tensor) -> None:
21 if not master_tensor.is_npu:21 if not master_tensor.is_npu:
22 raise ValueError("Device type of master_tensor should be npu." + pta_error(ErrCode.VALUE))22 raise ValueError("Device type of master_tensor should be npu." + pta_error(ErrCode.VALUE))
23 self.master = master_tensor23 self.master = master_tensor
24 self._per_device_tensors = {}24 self._per_device_tensors = {}
25 25 
26 26 
27class GradScaler(BaseGradScaler):27class GradScaler(BaseGradScaler):
28 """28 """
29 An instance ``scaler`` of :class:`GradScaler` helps perform the steps of gradient scaling29 An instance ``scaler`` of :class:`GradScaler` helps perform the steps of gradient scaling
30 conveniently.30 conveniently.
31 31 
32 * ``scaler.scale(loss)`` multiplies a given loss by ``scaler``'s current scale factor.32 * ``scaler.scale(loss)`` multiplies a given loss by ``scaler``'s current scale factor.
33 * ``scaler.step(optimizer)`` safely unscales gradients and calls ``optimizer.step()``.33 * ``scaler.step(optimizer)`` safely unscales gradients and calls ``optimizer.step()``.
34 * ``scaler.update()`` updates ``scaler``'s scale factor.34 * ``scaler.update()`` updates ``scaler``'s scale factor.
35 35 
36 Example::36 Example::
37 37 
38 # Creates a GradScaler once at the beginning of training.38 # Creates a GradScaler once at the beginning of training.
39 scaler = GradScaler()39 scaler = GradScaler()
40 40 
41 for epoch in epochs:41 for epoch in epochs:
42 for input, target in data:42 for input, target in data:
43 optimizer.zero_grad()43 optimizer.zero_grad()
44 output = model(input)44 output = model(input)
45 loss = loss_fn(output, target)45 loss = loss_fn(output, target)
46 46 
47 # Scales loss. Calls backward() on scaled loss to create scaled gradients.47 # Scales loss. Calls backward() on scaled loss to create scaled gradients.
48 scaler.scale(loss).backward()48 scaler.scale(loss).backward()
49 49 
50 # scaler.step() first unscales gradients of the optimizer's params.50 # scaler.step() first unscales gradients of the optimizer's params.
51 # If gradients don't contain infs/NaNs, optimizer.step() is then called,51 # If gradients don't contain infs/NaNs, optimizer.step() is then called,
52 # otherwise, optimizer.step() is skipped.52 # otherwise, optimizer.step() is skipped.
53 scaler.step(optimizer)53 scaler.step(optimizer)
54 54 
55 # Updates the scale for next iteration.55 # Updates the scale for next iteration.
56 scaler.update()56 scaler.update()
57 57 
58 See the :ref:`Automatic Mixed Precision examples<amp-examples>` for usage58 See the :ref:`Automatic Mixed Precision examples<amp-examples>` for usage
59 (along with autocasting) in more complex cases like gradient clipping, gradient accumulation, gradient penalty,59 (along with autocasting) in more complex cases like gradient clipping, gradient accumulation, gradient penalty,
60 and multiple losses/optimizers.60 and multiple losses/optimizers.
61 61 
62 ``scaler`` dynamically estimates the scale factor each iteration. To minimize gradient underflow,62 ``scaler`` dynamically estimates the scale factor each iteration. To minimize gradient underflow,
63 a large scale factor should be used. However, ``float16`` values can "overflow" (become inf or NaN) if63 a large scale factor should be used. However, ``float16`` values can "overflow" (become inf or NaN) if
64 the scale factor is too large. Therefore, the optimal scale factor is the largest factor that can be used64 the scale factor is too large. Therefore, the optimal scale factor is the largest factor that can be used
65 without incurring inf or NaN gradient values.65 without incurring inf or NaN gradient values.
66 ``scaler`` approximates the optimal scale factor over time by checking the gradients for infs and NaNs during every66 ``scaler`` approximates the optimal scale factor over time by checking the gradients for infs and NaNs during every
67 ``scaler.step(optimizer)`` (or optional separate ``scaler.unscale_(optimizer)``, see :meth:`unscale_`).67 ``scaler.step(optimizer)`` (or optional separate ``scaler.unscale_(optimizer)``, see :meth:`unscale_`).
68 68 
69 * If infs/NaNs are found, ``scaler.step(optimizer)`` skips the underlying ``optimizer.step()`` (so the params69 * If infs/NaNs are found, ``scaler.step(optimizer)`` skips the underlying ``optimizer.step()`` (so the params
70 themselves remain uncorrupted) and ``update()`` multiplies the scale by ``backoff_factor``.70 themselves remain uncorrupted) and ``update()`` multiplies the scale by ``backoff_factor``.
71 71 
72 * If no infs/NaNs are found, ``scaler.step(optimizer)`` runs the underlying ``optimizer.step()`` as usual.72 * If no infs/NaNs are found, ``scaler.step(optimizer)`` runs the underlying ``optimizer.step()`` as usual.
73 If ``growth_interval`` unskipped iterations occur consecutively, ``update()`` multiplies the scale by73 If ``growth_interval`` unskipped iterations occur consecutively, ``update()`` multiplies the scale by
74 ``growth_factor``.74 ``growth_factor``.
75 75 
76 The scale factor often causes infs/NaNs to appear in gradients for the first few iterations as its76 The scale factor often causes infs/NaNs to appear in gradients for the first few iterations as its
77 value calibrates. ``scaler.step`` will skip the underlying ``optimizer.step()`` for these77 value calibrates. ``scaler.step`` will skip the underlying ``optimizer.step()`` for these
78 iterations. After that, step skipping should occur rarely (once every few hundred or thousand iterations).78 iterations. After that, step skipping should occur rarely (once every few hundred or thousand iterations).
79 79 
80 Args:80 Args:
81 init_scale (float, optional, default=2.**16): Initial scale factor.81 init_scale (float, optional, default=2.**16): Initial scale factor.
82 growth_factor (float, optional, default=2.0): Factor by which the scale is multiplied during82 growth_factor (float, optional, default=2.0): Factor by which the scale is multiplied during
83 :meth:`update` if no inf/NaN gradients occur for ``growth_interval`` consecutive iterations.83 :meth:`update` if no inf/NaN gradients occur for ``growth_interval`` consecutive iterations.
84 backoff_factor (float, optional, default=0.5): Factor by which the scale is multiplied during84 backoff_factor (float, optional, default=0.5): Factor by which the scale is multiplied during
85 :meth:`update` if inf/NaN gradients occur in an iteration.85 :meth:`update` if inf/NaN gradients occur in an iteration.
86 growth_interval (int, optional, default=2000): Number of consecutive iterations without inf/NaN gradients86 growth_interval (int, optional, default=2000): Number of consecutive iterations without inf/NaN gradients
87 that must occur for the scale to be multiplied by ``growth_factor``.87 that must occur for the scale to be multiplied by ``growth_factor``.
88 dynamic (bool, optional, default=True): If ``False``, use static loss scale.88 dynamic (bool, optional, default=True): If ``False``, use static loss scale.
89 enabled (bool, optional, default=True): If ``False``, disables gradient scaling. :meth:`step` simply89 enabled (bool, optional, default=True): If ``False``, disables gradient scaling. :meth:`step` simply
90 invokes the underlying ``optimizer.step()``, and other methods become no-ops.90 invokes the underlying ``optimizer.step()``, and other methods become no-ops.
91 """91 """
92 92 
93 def __init__(self,93 def __init__(self,
94 init_scale=2. ** 16,94 init_scale=2. ** 16,
95 growth_factor=2.0,95 growth_factor=2.0,
96 backoff_factor=0.5,96 backoff_factor=0.5,
97 growth_interval=2000,97 growth_interval=2000,
98 dynamic=True,98 dynamic=True,
99 enabled=True):99 enabled=True):
100 if enabled and amp_definitely_not_available():100 if enabled and amp_definitely_not_available():
101 warnings.warn("torch_npu.amp.GradScaler is enabled, but NPU is not available. Disabling.")101 warnings.warn("torch_npu.amp.GradScaler is enabled, but NPU is not available. Disabling.")
102 self._enabled = False102 self._enabled = False
103 else:103 else:
104 self._enabled = enabled104 self._enabled = enabled
105 105 
106 if self._enabled:106 if self._enabled:
107 if growth_factor <= 1.0:107 if growth_factor <= 1.0:
108 raise ValueError("The growth factor must be > 1.0." + pta_error(ErrCode.VALUE))108 raise ValueError("The growth factor must be > 1.0." + pta_error(ErrCode.VALUE))
109 if backoff_factor >= 1.0:109 if backoff_factor >= 1.0:
110 raise ValueError("The backoff factor must be < 1.0." + pta_error(ErrCode.VALUE))110 raise ValueError("The backoff factor must be < 1.0." + pta_error(ErrCode.VALUE))
111 111 
112 self._init_scale = init_scale112 self._init_scale = init_scale
113 # self._scale will be lazily initialized during the first call to scale()113 # self._scale will be lazily initialized during the first call to scale()
114 self._scale = None114 self._scale = None
115 self._growth_factor = growth_factor115 self._growth_factor = growth_factor
116 self._backoff_factor = backoff_factor116 self._backoff_factor = backoff_factor
117 self._growth_interval = growth_interval117 self._growth_interval = growth_interval
118 self._dynamic = dynamic118 self._dynamic = dynamic
119 self._init_growth_tracker = 0119 self._init_growth_tracker = 0
120 # self._growth_tracker will be lazily initialized during the first call to scale()120 # self._growth_tracker will be lazily initialized during the first call to scale()
121 self._growth_tracker = None121 self._growth_tracker = None
122 self._per_optimizer_states = defaultdict(_refresh_per_optimizer_state)122 self._per_optimizer_states = defaultdict(_refresh_per_optimizer_state)
123 self._has_overflow = False123 self._has_overflow = False
124 self._clear_overflow_flag = False124 self._clear_overflow_flag = False
125 self._dist_initialized = False125 self._dist_initialized = False
126 self._dist_overflow_count = None126 self._dist_overflow_count = None
127 127 
128 def _lazy_init_scale_growth_tracker(self, dev):128 def _lazy_init_scale_growth_tracker(self, dev):
129 if self._growth_tracker is not None:129 if self._growth_tracker is not None:
130 raise RuntimeError("_growth_tracker initialized before _scale" + pta_error(ErrCode.VALUE))130 raise RuntimeError("_growth_tracker initialized before _scale" + pta_error(ErrCode.VALUE))
131 131 
132 self._scale = torch.full((), self._init_scale, dtype=torch.float32).pin_memory().to(dev, non_blocking=True)132 self._scale = torch.full((), self._init_scale, dtype=torch.float32).pin_memory().to(dev, non_blocking=True)
133 self._growth_tracker = torch.full((), self._init_growth_tracker, dtype=torch.int32)133 self._growth_tracker = torch.full((), self._init_growth_tracker, dtype=torch.int32)
134 self._growth_tracker = self._growth_tracker.pin_memory().to(dev, non_blocking=True)134 self._growth_tracker = self._growth_tracker.pin_memory().to(dev, non_blocking=True)
135 135 
136 def _lazy_init_dist_flag_and_dist_overflow_count(self):136 def _lazy_init_dist_flag_and_dist_overflow_count(self):
137 if self._dist_overflow_count is not None:137 if self._dist_overflow_count is not None:
138 raise RuntimeError("_dist_overflow_count initialized before _scale" + pta_error(ErrCode.VALUE))138 raise RuntimeError("_dist_overflow_count initialized before _scale" + pta_error(ErrCode.VALUE))
139 try:139 try:
140 if dist.is_initialized():140 if dist.is_initialized():
141 self._dist_initialized = True141 self._dist_initialized = True
142 except AttributeError as err:142 except AttributeError as err:
143 print("torch.distributed has no attribute is_initialized")143 print("torch.distributed has no attribute is_initialized")
144 144 
145 self._dist_overflow_count = torch.Tensor([0.]).to('npu')145 self._dist_overflow_count = torch.Tensor([0.]).to('npu')
146 146 
147 def scale(self, outputs):147 def scale(self, outputs):
148 """148 """
149 Multiplies ('scales') a tensor or list of tensors by the scale factor.149 Multiplies ('scales') a tensor or list of tensors by the scale factor.
150 150 
151 Returns scaled outputs. If this instance of :class:`GradScaler` is not enabled, outputs are returned151 Returns scaled outputs. If this instance of :class:`GradScaler` is not enabled, outputs are returned
152 unmodified.152 unmodified.
153 153 
154 Args:154 Args:
155 outputs (Tensor or iterable of Tensors): Outputs to scale.155 outputs (Tensor or iterable of Tensors): Outputs to scale.
156 """156 """
157 if not self._enabled:157 if not self._enabled:
158 return outputs158 return outputs
159 159 
160 if self._dist_overflow_count is None:160 if self._dist_overflow_count is None:
161 self._lazy_init_dist_flag_and_dist_overflow_count()161 self._lazy_init_dist_flag_and_dist_overflow_count()
162 if self._dist_overflow_count is None:162 if self._dist_overflow_count is None:
163 raise RuntimeError("_dist_overflow_count is None." + pta_error(ErrCode.VALUE))163 raise RuntimeError("_dist_overflow_count is None." + pta_error(ErrCode.VALUE))
164 164 
165 if self._dynamic and not self._clear_overflow_flag:165 if self._dynamic and not self._clear_overflow_flag:
166 if not torch_npu.npu.utils.is_support_inf_nan():166 if not torch_npu.npu.utils.is_support_inf_nan():
167 GradScaler.clear_npu_overflow_flag()167 GradScaler.clear_npu_overflow_flag()
168 self._clear_overflow_flag = True168 self._clear_overflow_flag = True
169 169 
170 # Short-circuit for the common case.170 # Short-circuit for the common case.
171 if isinstance(outputs, torch.Tensor):171 if isinstance(outputs, torch.Tensor):
172 if not outputs.is_npu:172 if not outputs.is_npu:
173 raise ValueError("Device type of outputs should be npu." + pta_error(ErrCode.VALUE))173 raise ValueError("Device type of outputs should be npu." + pta_error(ErrCode.VALUE))
174 if self._scale is None:174 if self._scale is None:
175 self._lazy_init_scale_growth_tracker(outputs.device)175 self._lazy_init_scale_growth_tracker(outputs.device)
176 if self._scale is None:176 if self._scale is None:
177 raise RuntimeError("_scale is None." + pta_error(ErrCode.VALUE))177 raise RuntimeError("_scale is None." + pta_error(ErrCode.VALUE))
178 return outputs * self._scale.to(device=outputs.device, non_blocking=True)178 return outputs * self._scale.to(device=outputs.device, non_blocking=True)
179 179 
180 # Invoke the more complex machinery only if we're treating multiple outputs.180 # Invoke the more complex machinery only if we're treating multiple outputs.
181 stash: List[_NpuMultiDeviceReplicator] = [] # holds a reference that can be overwritten by apply_scale181 stash: List[_NpuMultiDeviceReplicator] = [] # holds a reference that can be overwritten by apply_scale
182 182 
183 def apply_scale(val):183 def apply_scale(val):
184 if isinstance(val, torch.Tensor):184 if isinstance(val, torch.Tensor):
185 if not val.is_npu:185 if not val.is_npu:
186 raise ValueError("Device type of val should be npu." + pta_error(ErrCode.VALUE))186 raise ValueError("Device type of val should be npu." + pta_error(ErrCode.VALUE))
187 if len(stash) == 0:187 if len(stash) == 0:
188 if self._scale is None:188 if self._scale is None:
189 self._lazy_init_scale_growth_tracker(val.device)189 self._lazy_init_scale_growth_tracker(val.device)
190 if self._scale is None:190 if self._scale is None:
191 raise RuntimeError("_scale is None." + pta_error(ErrCode.VALUE))191 raise RuntimeError("_scale is None." + pta_error(ErrCode.VALUE))
192 stash.append(_NpuMultiDeviceReplicator(self._scale))192 stash.append(_NpuMultiDeviceReplicator(self._scale))
193 return val * stash[0].get(val.device)193 return val * stash[0].get(val.device)
194 elif isinstance(val, container_abcs.Iterable):194 elif isinstance(val, container_abcs.Iterable):
195 iterable = map(apply_scale, val)195 iterable = map(apply_scale, val)
196 if isinstance(val, list) or isinstance(val, tuple):196 if isinstance(val, list) or isinstance(val, tuple):
197 return type(val)(iterable)197 return type(val)(iterable)
198 else:198 else:
199 return iterable199 return iterable
200 else:200 else:
201 raise TypeError("outputs must be a Tensor or an iterable of Tensors" + pta_error(ErrCode.TYPE))201 raise TypeError("outputs must be a Tensor or an iterable of Tensors" + pta_error(ErrCode.TYPE))
202 202 
203 return apply_scale(outputs)203 return apply_scale(outputs)
204 204 
205 def _unscale_grads_(self, optimizer, inv_scale, found_inf, allow_fp16):205 def _unscale_grads_(self, optimizer, inv_scale, found_inf, allow_fp16):
206 per_device_found_inf = _NpuMultiDeviceReplicator(found_inf)206 per_device_found_inf = _NpuMultiDeviceReplicator(found_inf)
207 per_device_inv_scale = _NpuMultiDeviceReplicator(inv_scale)207 per_device_inv_scale = _NpuMultiDeviceReplicator(inv_scale)
208 208 
209 # To set up _amp_foreach_non_finite_check_and_unscale_, split grads by device and dtype.209 # To set up _amp_foreach_non_finite_check_and_unscale_, split grads by device and dtype.
210 # There could be hundreds of grads, so we'd like to iterate through them just once.210 # There could be hundreds of grads, so we'd like to iterate through them just once.
211 # However, we don't know their devices or dtypes in advance.211 # However, we don't know their devices or dtypes in advance.
212 212 
213 # Google says mypy struggles with defaultdicts type annotations.213 # Google says mypy struggles with defaultdicts type annotations.
214 per_device_and_dtype_grads = defaultdict(lambda: defaultdict(list))214 per_device_and_dtype_grads = defaultdict(lambda: defaultdict(list))
215 with torch.no_grad():215 with torch.no_grad():
216 if hasattr(optimizer, 'is_fused_optimizer'):216 if hasattr(optimizer, 'is_fused_optimizer'):
217 if not optimizer.is_params_grads_combined:217 if not optimizer.is_params_grads_combined:
218 optimizer._maybe_init_combined_params_and_grads()218 optimizer._maybe_init_combined_params_and_grads()
219 219 
220 device = found_inf.device220 device = found_inf.device
221 for grads_combined_one_dtype in optimizer.grads_all_group_combined:221 for grads_combined_one_dtype in optimizer.grads_all_group_combined:
222 if grads_combined_one_dtype is None:222 if grads_combined_one_dtype is None:
223 continue223 continue
224 if self._dynamic:224 if self._dynamic:
225 torch._amp_foreach_non_finite_check_and_unscale_(225 torch._amp_foreach_non_finite_check_and_unscale_(
226 [grads_combined_one_dtype],226 [grads_combined_one_dtype],
227 per_device_found_inf.get(device),227 per_device_found_inf.get(device),
228 per_device_inv_scale.get(device))228 per_device_inv_scale.get(device))
229 if per_device_found_inf.get(device).item() > 0:229 if per_device_found_inf.get(device).item() > 0:
230 self._has_overflow = True230 self._has_overflow = True
231 else:231 else:
232 grads_combined_one_dtype.mul_(232 grads_combined_one_dtype.mul_(
233 per_device_inv_scale.get(device))233 per_device_inv_scale.get(device))
234 else:234 else:
235 for group in optimizer.param_groups:235 for group in optimizer.param_groups:
236 for param in group["params"]:236 for param in group["params"]:
237 if param.grad is None:237 if param.grad is None:
238 continue238 continue
239 if (not allow_fp16) and param.grad.dtype == torch.float16:239 if (not allow_fp16) and param.grad.dtype == torch.float16:
240 raise TypeError("Attempting to unscale FP16 gradients." + pta_error(ErrCode.TYPE))240 raise TypeError("Attempting to unscale FP16 gradients." + pta_error(ErrCode.TYPE))
241 if param.grad.is_sparse:241 if param.grad.is_sparse:
242 # is_coalesced() == False means the sparse grad has values with duplicate indices.242 # is_coalesced() == False means the sparse grad has values with duplicate indices.
243 # coalesce() deduplicates indices and adds all values that have the same index.243 # coalesce() deduplicates indices and adds all values that have the same index.
244 # For scaled fp16 values, there's a good chance coalescing will cause overflow,244 # For scaled fp16 values, there's a good chance coalescing will cause overflow,
245 # so we should check the coalesced _values().245 # so we should check the coalesced _values().
246 if param.grad.dtype == torch.float16:246 if param.grad.dtype == torch.float16:
247 param.grad = param.grad.coalesce()247 param.grad = param.grad.coalesce()
248 to_unscale = param.grad._values()248 to_unscale = param.grad._values()
249 else:249 else:
250 to_unscale = param.grad250 to_unscale = param.grad
251 251 
252 per_device_and_dtype_grads[to_unscale.device][to_unscale.dtype].append(to_unscale)252 per_device_and_dtype_grads[to_unscale.device][to_unscale.dtype].append(to_unscale)
253 253 
254 for device, per_dtype_grads in per_device_and_dtype_grads.items():254 for device, per_dtype_grads in per_device_and_dtype_grads.items():
255 for grads in per_dtype_grads.values():255 for grads in per_dtype_grads.values():
256 if self._dynamic:256 if self._dynamic:
257 torch._amp_foreach_non_finite_check_and_unscale_(grads,257 torch._amp_foreach_non_finite_check_and_unscale_(grads,
258 per_device_found_inf.get(device),258 per_device_found_inf.get(device),
259 per_device_inv_scale.get(device))259 per_device_inv_scale.get(device))
260 if per_device_found_inf.get(device).item() > 0:260 if per_device_found_inf.get(device).item() > 0:
261 self._has_overflow = True261 self._has_overflow = True
262 else:262 else:
263 for grad in grads:263 for grad in grads:
264 grad.mul_(per_device_inv_scale.get(device))264 grad.mul_(per_device_inv_scale.get(device))
265 265 
266 self._sync_dist_overflow_count()266 self._sync_dist_overflow_count()
267 if self._has_overflow:267 if self._has_overflow:
268 per_device_found_inf.get(found_inf.device).add_(1)268 per_device_found_inf.get(found_inf.device).add_(1)
269 else:269 else:
270 per_device_found_inf.get(found_inf.device)270 per_device_found_inf.get(found_inf.device)
271 271 
272 return per_device_found_inf._per_device_tensors272 return per_device_found_inf._per_device_tensors
273 273 
274 def unscale_(self, optimizer):274 def unscale_(self, optimizer):
275 """275 """
276 Divides ("unscales") the optimizer's gradient tensors by the scale factor.276 Divides ("unscales") the optimizer's gradient tensors by the scale factor.
277 277 
278 :meth:`unscale_` is optional, serving cases where you need to278 :meth:`unscale_` is optional, serving cases where you need to
279 :ref:`modify or inspect gradients<working-with-unscaled-gradients>`279 :ref:`modify or inspect gradients<working-with-unscaled-gradients>`
280 between the backward pass(es) and :meth:`step`.280 between the backward pass(es) and :meth:`step`.
281 If :meth:`unscale_` is not called explicitly, gradients will be unscaled automatically during :meth:`step`.281 If :meth:`unscale_` is not called explicitly, gradients will be unscaled automatically during :meth:`step`.
282 282 
283 Simple example, using :meth:`unscale_` to enable clipping of unscaled gradients::283 Simple example, using :meth:`unscale_` to enable clipping of unscaled gradients::
284 284 
285 ...285 ...
286 scaler.scale(loss).backward()286 scaler.scale(loss).backward()
287 scaler.unscale_(optimizer)287 scaler.unscale_(optimizer)
288 torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm)288 torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm)
289 scaler.step(optimizer)289 scaler.step(optimizer)
290 scaler.update()290 scaler.update()
291 291 
292 Args:292 Args:
293 optimizer (torch.optim.Optimizer): Optimizer that owns the gradients to be unscaled.293 optimizer (torch.optim.Optimizer): Optimizer that owns the gradients to be unscaled.
294 294 
295 .. note::295 .. note::
296 :meth:`unscale_` does not incur a CPU-NPU sync.296 :meth:`unscale_` does not incur a CPU-NPU sync.
297 297 
298 .. warning::298 .. warning::
299 :meth:`unscale_` should only be called once per optimizer per :meth:`step` call,299 :meth:`unscale_` should only be called once per optimizer per :meth:`step` call,
300 and only after all gradients for that optimizer's assigned parameters have been accumulated.300 and only after all gradients for that optimizer's assigned parameters have been accumulated.
301 Calling :meth:`unscale_` twice for a given optimizer between each :meth:`step` triggers a RuntimeError.301 Calling :meth:`unscale_` twice for a given optimizer between each :meth:`step` triggers a RuntimeError.
302 302 
303 .. warning::303 .. warning::
304 :meth:`unscale_` may unscale sparse gradients out of place, replacing the ``.grad`` attribute.304 :meth:`unscale_` may unscale sparse gradients out of place, replacing the ``.grad`` attribute.
305 """305 """
306 if not self._enabled:306 if not self._enabled:
307 return307 return
308 308 
309 self._check_scale_growth_tracker("unscale_")309 self._check_scale_growth_tracker("unscale_")
310 310 
311 optimizer_state = self._per_optimizer_states[id(optimizer)]311 optimizer_state = self._per_optimizer_states[id(optimizer)]
312 312 
313 if optimizer_state["stage"] is OptState.UNSCALED:313 if optimizer_state["stage"] is OptState.UNSCALED:
314 raise RuntimeError("unscale_() has already been called on this optimizer since the last update()." +314 raise RuntimeError("unscale_() has already been called on this optimizer since the last update()." +
315 pta_error(ErrCode.INTERNAL))315 pta_error(ErrCode.INTERNAL))
316 elif optimizer_state["stage"] is OptState.STEPPED:316 elif optimizer_state["stage"] is OptState.STEPPED:
317 raise RuntimeError("unscale_() is being called after step()." +317 raise RuntimeError("unscale_() is being called after step()." +
318 pta_error(ErrCode.INTERNAL))318 pta_error(ErrCode.INTERNAL))
319 319 
320 # FP32 division can be imprecise for certain compile options, so we carry out the reciprocal in FP64.320 # FP32 division can be imprecise for certain compile options, so we carry out the reciprocal in FP64.
321 if self._scale is None:321 if self._scale is None:
322 raise RuntimeError("_scale is None." + pta_error(ErrCode.VALUE))322 raise RuntimeError("_scale is None." + pta_error(ErrCode.VALUE))
323 inv_scale = self._scale.float().reciprocal()323 inv_scale = self._scale.float().reciprocal()
324 found_inf = torch.full((), 0.0, dtype=torch.float32).pin_memory().to(self._scale.device, non_blocking=True)324 found_inf = torch.full((), 0.0, dtype=torch.float32).pin_memory().to(self._scale.device, non_blocking=True)
325 325 
326 optimizer_state["found_inf_per_device"] = self._unscale_grads_(optimizer, inv_scale, found_inf, False)326 optimizer_state["found_inf_per_device"] = self._unscale_grads_(optimizer, inv_scale, found_inf, False)
327 optimizer_state["stage"] = OptState.UNSCALED327 optimizer_state["stage"] = OptState.UNSCALED
328 328 
329 def _maybe_opt_step(self, optimizer, optimizer_state, *args, **kwargs):329 def _maybe_opt_step(self, optimizer, optimizer_state, *args, **kwargs):
330 retval = None330 retval = None
331 if not sum(v.item() for v in optimizer_state["found_inf_per_device"].values()) and not self._has_overflow:331 if not sum(v.item() for v in optimizer_state["found_inf_per_device"].values()) and not self._has_overflow:
332 retval = optimizer.step(*args, **kwargs)332 retval = optimizer.step(*args, **kwargs)
333 else:333 else:
334 print("Gradient overflow. Skipping step")334 print("Gradient overflow. Skipping step")
335 return retval335 return retval
336 336 
337 def step(self, optimizer, *args, **kwargs):337 def step(self, optimizer, *args, **kwargs):
338 """338 """
339 :meth:`step` carries out the following two operations:339 :meth:`step` carries out the following two operations:
340 340 
341 1. Internally invokes ``unscale_(optimizer)`` (unless :meth:`unscale_` was explicitly called for ``optimizer``341 1. Internally invokes ``unscale_(optimizer)`` (unless :meth:`unscale_` was explicitly called for ``optimizer``
342 earlier in the iteration). As part of the :meth:`unscale_`, gradients are checked for infs/NaNs.342 earlier in the iteration). As part of the :meth:`unscale_`, gradients are checked for infs/NaNs.
343 2. If no inf/NaN gradients are found, invokes ``optimizer.step()`` using the unscaled343 2. If no inf/NaN gradients are found, invokes ``optimizer.step()`` using the unscaled
344 gradients. Otherwise, ``optimizer.step()`` is skipped to avoid corrupting the params.344 gradients. Otherwise, ``optimizer.step()`` is skipped to avoid corrupting the params.
345 345 
346 ``*args`` and ``**kwargs`` are forwarded to ``optimizer.step()``.346 ``*args`` and ``**kwargs`` are forwarded to ``optimizer.step()``.
347 347 
348 Returns the return value of ``optimizer.step(*args, **kwargs)``.348 Returns the return value of ``optimizer.step(*args, **kwargs)``.
349 349 
350 Args:350 Args:
351 optimizer (torch.optim.Optimizer): Optimizer that applies the gradients.351 optimizer (torch.optim.Optimizer): Optimizer that applies the gradients.
352 args: Any arguments.352 args: Any arguments.
353 kwargs: Any keyword arguments.353 kwargs: Any keyword arguments.
354 354 
355 .. warning::355 .. warning::
356 Closure use is not currently supported.356 Closure use is not currently supported.
357 """357 """
358 if (not self._enabled):358 if (not self._enabled):
359 return optimizer.step(*args, **kwargs)359 return optimizer.step(*args, **kwargs)
360 360 
361 if "closure" in kwargs:361 if "closure" in kwargs:
362 raise RuntimeError("Closure use is not currently supported if GradScaler is enabled." +362 raise RuntimeError("Closure use is not currently supported if GradScaler is enabled." +
363 pta_error(ErrCode.NOT_SUPPORT))363 pta_error(ErrCode.NOT_SUPPORT))
364 364 
365 self._check_scale_growth_tracker("step")365 self._check_scale_growth_tracker("step")
366 366 
367 optimizer_state = self._per_optimizer_states[id(optimizer)]367 optimizer_state = self._per_optimizer_states[id(optimizer)]
368 368 
369 if optimizer_state["stage"] is OptState.STEPPED:369 if optimizer_state["stage"] is OptState.STEPPED:
370 raise RuntimeError("step() has already been called since the last update()." +370 raise RuntimeError("step() has already been called since the last update()." +
371 pta_error(ErrCode.INTERNAL))371 pta_error(ErrCode.INTERNAL))
372 372 
373 retval = None373 retval = None
374 374 
375 if (hasattr(optimizer, "_step_supports_amp_scaling") and optimizer._step_supports_amp_scaling):375 if (hasattr(optimizer, "_step_supports_amp_scaling") and optimizer._step_supports_amp_scaling):
376 # This optimizer has customized scale-handling logic, so we can call optimizer.step() directly.376 # This optimizer has customized scale-handling logic, so we can call optimizer.step() directly.
377 # The contract with custom optimizers is that their step() should accept an additional,377 # The contract with custom optimizers is that their step() should accept an additional,
378 # optional grad_scaler kwarg. We append self to the kwargs so the custom optimizer has full information:378 # optional grad_scaler kwarg. We append self to the kwargs so the custom optimizer has full information:
379 # it can query its own state, invoke unscale_ on itself, etc379 # it can query its own state, invoke unscale_ on itself, etc
380 retval = optimizer.step(*args, **dict(kwargs, grad_scaler=self))380 retval = optimizer.step(*args, **dict(kwargs, grad_scaler=self))
381 optimizer_state["stage"] = OptState.STEPPED381 optimizer_state["stage"] = OptState.STEPPED
382 return retval382 return retval
383 383 
384 if optimizer_state["stage"] is OptState.READY:384 if optimizer_state["stage"] is OptState.READY:
385 self.unscale_(optimizer)385 self.unscale_(optimizer)
386 386 
387 if len(optimizer_state["found_inf_per_device"]) <= 0:387 if len(optimizer_state["found_inf_per_device"]) <= 0:
388 raise RuntimeError("No inf checks were recorded for this optimizer." + pta_error(ErrCode.INTERNAL))388 raise RuntimeError("No inf checks were recorded for this optimizer." + pta_error(ErrCode.INTERNAL))
389 389 
390 if self._dynamic:390 if self._dynamic:
391 retval = self._maybe_opt_step(optimizer, optimizer_state, *args, **kwargs)391 retval = self._maybe_opt_step(optimizer, optimizer_state, *args, **kwargs)
392 optimizer_state["stage"] = OptState.STEPPED392 optimizer_state["stage"] = OptState.STEPPED
393 return retval393 return retval
394 394 
395 retval = optimizer.step(*args, **kwargs)395 retval = optimizer.step(*args, **kwargs)
396 optimizer_state["stage"] = OptState.STEPPED396 optimizer_state["stage"] = OptState.STEPPED
397 397 
398 return retval398 return retval
399 399 
400 def update(self, new_scale=None):400 def update(self, new_scale=None):
401 """401 """
402 Updates the scale factor.402 Updates the scale factor.
403 403 
404 If any optimizer steps were skipped the scale is multiplied by ``backoff_factor``404 If any optimizer steps were skipped the scale is multiplied by ``backoff_factor``
405 to reduce it. If ``growth_interval`` unskipped iterations occurred consecutively,405 to reduce it. If ``growth_interval`` unskipped iterations occurred consecutively,
406 the scale is multiplied by ``growth_factor`` to increase it.406 the scale is multiplied by ``growth_factor`` to increase it.
407 407 
408 Passing ``new_scale`` sets the scale directly.408 Passing ``new_scale`` sets the scale directly.
409 409 
410 Args:410 Args:
411 new_scale (float or :class:`torch.npu.FloatTensor`, optional, default=None): New scale factor.411 new_scale (float or :class:`torch.npu.FloatTensor`, optional, default=None): New scale factor.
412 412 
413 .. warning::413 .. warning::
414 :meth:`update` should only be called at the end of the iteration, after ``scaler.step(optimizer)`` has414 :meth:`update` should only be called at the end of the iteration, after ``scaler.step(optimizer)`` has
415 been invoked for all optimizers used this iteration.415 been invoked for all optimizers used this iteration.
416 """416 """
417 if not self._enabled:417 if not self._enabled:
418 return418 return
419 419 
420 _scale, _ = self._check_scale_growth_tracker("update")420 _scale, _ = self._check_scale_growth_tracker("update")
421 421 
422 if new_scale is not None:422 if new_scale is not None:
423 # Accept a new user-defined scale.423 # Accept a new user-defined scale.
424 if isinstance(new_scale, float):424 if isinstance(new_scale, float):
425 self._scale = torch.full((), new_scale, dtype=torch.float32)425 self._scale = torch.full((), new_scale, dtype=torch.float32)
426 self._scale = self._scale.pin_memory().to(_scale.device, non_blocking=True)426 self._scale = self._scale.pin_memory().to(_scale.device, non_blocking=True)
427 else:427 else:
428 reason = "new_scale should be a float or a 1-element torch.npu.FloatTensor with requires_grad=False."428 reason = "new_scale should be a float or a 1-element torch.npu.FloatTensor with requires_grad=False."
429 if not isinstance(new_scale, torch.npu.FloatTensor): # type: ignore[attr-defined]429 if not isinstance(new_scale, torch.npu.FloatTensor): # type: ignore[attr-defined]
430 raise TypeError(reason + pta_error(ErrCode.TYPE))430 raise TypeError(reason + pta_error(ErrCode.TYPE))
431 if new_scale.numel() != 1:431 if new_scale.numel() != 1:
O
OopenLiBingCI5月17日

此条代码评论区间+427+431

【openlibing.ci】识别到代码检查告警抑制注释,匹配工具:mypy,请Committer检视其合理性。

likedislike
432 raise ValueError(reason + pta_error(ErrCode.VALUE))432 raise ValueError(reason + pta_error(ErrCode.VALUE))
433 if new_scale.requires_grad:433 if new_scale.requires_grad:
434 raise ValueError(reason + pta_error(ErrCode.VALUE))434 raise ValueError(reason + pta_error(ErrCode.VALUE))
435 self._scale = new_scale435 self._scale = new_scale
436 elif self._dynamic:436 elif self._dynamic:
437 self._npu_update_scale()437 self._npu_update_scale()
438 438 
439 # To prepare for next iteration, clear the data collected from optimizers this iteration.439 # To prepare for next iteration, clear the data collected from optimizers this iteration.
440 self._per_optimizer_states = defaultdict(_refresh_per_optimizer_state)440 self._per_optimizer_states = defaultdict(_refresh_per_optimizer_state)
441 self._has_overflow = False441 self._has_overflow = False
442 self._clear_overflow_flag = False442 self._clear_overflow_flag = False
443 443 
444 def state_dict(self):444 def state_dict(self):
445 state = super(GradScaler, self).state_dict()445 state = super(GradScaler, self).state_dict()
446 if self._enabled:446 if self._enabled:
447 state["dynamic"] = self._dynamic447 state["dynamic"] = self._dynamic
448 return state448 return state
449 449 
450 def load_state_dict(self, state_dict):450 def load_state_dict(self, state_dict):
451 if not self._enabled:451 if not self._enabled:
452 return452 return
453 453 
454 if len(state_dict) == 0:454 if len(state_dict) == 0:
455 raise RuntimeError("The source state dict is empty, possibly because it was saved "455 raise RuntimeError("The source state dict is empty, possibly because it was saved "
456 "from a disabled instance of GradScaler." + pta_error(ErrCode.VALUE))456 "from a disabled instance of GradScaler." + pta_error(ErrCode.VALUE))
457 457 
458 super(GradScaler, self).load_state_dict(state_dict)458 super(GradScaler, self).load_state_dict(state_dict)
459 self._dynamic = state_dict["dynamic"]459 self._dynamic = state_dict["dynamic"]
460 460 
461 @staticmethod461 @staticmethod
462 def get_npu_overflow_flag():462 def get_npu_overflow_flag():
463 float_status = torch.zeros(8).pin_memory().to('npu', non_blocking=True)463 float_status = torch.zeros(8).pin_memory().to('npu', non_blocking=True)
464 result = torch_npu.npu_get_float_status(float_status)464 result = torch_npu.npu_get_float_status(float_status)
465 if (result.cpu()[0] != 0):465 if (result.cpu()[0] != 0):
466 return True466 return True
467 else:467 else:
468 return False468 return False
469 469 
470 @staticmethod470 @staticmethod
471 def clear_npu_overflow_flag():471 def clear_npu_overflow_flag():
472 float_status = torch.zeros(8).pin_memory().to('npu', non_blocking=True)472 float_status = torch.zeros(8).pin_memory().to('npu', non_blocking=True)
473 result = torch_npu.npu_clear_float_status(float_status)473 result = torch_npu.npu_clear_float_status(float_status)
474 474 
475 def _sync_dist_overflow_count(self):475 def _sync_dist_overflow_count(self):
476 if torch_npu.npu.utils.is_support_inf_nan():476 if torch_npu.npu.utils.is_support_inf_nan():
477 return477 return
478 if self._dynamic and self._dist_initialized:478 if self._dynamic and self._dist_initialized:
479 if self._has_overflow:479 if self._has_overflow:
480 self._dist_overflow_count.add_(1)480 self._dist_overflow_count.add_(1)
481 dist.all_reduce(self._dist_overflow_count)481 dist.all_reduce(self._dist_overflow_count)
482 self._dist_overflow_count.zero_()482 self._dist_overflow_count.zero_()
483 else:483 else:
484 dist.all_reduce(self._dist_overflow_count)484 dist.all_reduce(self._dist_overflow_count)
485 if self._dist_overflow_count.item() != 0:485 if self._dist_overflow_count.item() != 0:
486 self._has_overflow = True486 self._has_overflow = True
487 self._dist_overflow_count.zero_()487 self._dist_overflow_count.zero_()
488 488 
489 def _npu_update_scale(self):489 def _npu_update_scale(self):
490 if self._has_overflow:490 if self._has_overflow:
491 self._scale.mul_(self._backoff_factor)491 self._scale.mul_(self._backoff_factor)
492 self._growth_tracker.zero_()492 self._growth_tracker.zero_()
493 print(("Loss scaler reducing loss scale "493 print(("Loss scaler reducing loss scale "
494 "to {}").format(self._scale.item()))494 "to {}").format(self._scale.item()))
495 else:495 else:
496 # Entering this branch means we just carried out a successful step,496 # Entering this branch means we just carried out a successful step,
497 # so growth_tracker is incremented before comparing to growth_interval.497 # so growth_tracker is incremented before comparing to growth_interval.
498 self._growth_tracker.add_(1)498 self._growth_tracker.add_(1)
499 if self._growth_tracker.item() == self._growth_interval:499 if self._growth_tracker.item() == self._growth_interval:
500 new_scale = self._scale * self._growth_factor500 new_scale = self._scale * self._growth_factor
501 if not torch.isinf(new_scale):501 if not torch.isinf(new_scale):
502 self._scale = new_scale502 self._scale = new_scale
503 self._growth_tracker.zero_()503 self._growth_tracker.zero_()
504 print(("Loss scaler increasing loss scale "504 print(("Loss scaler increasing loss scale "
505 "to {}").format(self._scale.item()))505 "to {}").format(self._scale.item()))
Mtorch_npu/testing/common_distributed.py+110-110
@@ -1,110 +1,110 @@
1import unittest1import unittest
2from functools import wraps2from functools import wraps
3from typing import (3from typing import (
4 Tuple,4 Tuple,
5 Dict,5 Dict,
6 Any,6 Any,
7)7)
8from collections import namedtuple8from collections import namedtuple
9import sys9import sys
10import os10import os
11from contextlib import contextmanager11from contextlib import contextmanager
12import torch12import torch
13import torch.distributed as dist13import torch.distributed as dist
14import torch_npu14import torch_npu
15 15 
16 16 
17TestSkip = namedtuple('TestSkip', 'exit_code, message')17TestSkip = namedtuple('TestSkip', 'exit_code, message')
18TEST_SKIPS = {18TEST_SKIPS = {
19 "multi-npu": TestSkip(75, "Multi-NPU condition not satisfied"),19 "multi-npu": TestSkip(75, "Multi-NPU condition not satisfied"),
20 "multi-npu-1": TestSkip(75, "Need at least 1 ASCEND devices"),20 "multi-npu-1": TestSkip(75, "Need at least 1 ASCEND devices"),
21 "multi-npu-2": TestSkip(75, "Need at least 2 ASCEND devices"),21 "multi-npu-2": TestSkip(75, "Need at least 2 ASCEND devices"),
22 "multi-npu-3": TestSkip(75, "Need at least 3 ASCEND devices"),22 "multi-npu-3": TestSkip(75, "Need at least 3 ASCEND devices"),
23 "multi-npu-4": TestSkip(75, "Need at least 4 ASCEND devices"),23 "multi-npu-4": TestSkip(75, "Need at least 4 ASCEND devices"),
24 "multi-npu-5": TestSkip(75, "Need at least 5 ASCEND devices"),24 "multi-npu-5": TestSkip(75, "Need at least 5 ASCEND devices"),
25 "multi-npu-6": TestSkip(75, "Need at least 6 ASCEND devices"),25 "multi-npu-6": TestSkip(75, "Need at least 6 ASCEND devices"),
26 "multi-npu-7": TestSkip(75, "Need at least 7 ASCEND devices"),26 "multi-npu-7": TestSkip(75, "Need at least 7 ASCEND devices"),
27 "multi-npu-8": TestSkip(75, "Need at least 8 ASCEND devices"),27 "multi-npu-8": TestSkip(75, "Need at least 8 ASCEND devices"),
28 "hccl":TestSkip(76, "c10d not compiled with HCCL support"),28 "hccl":TestSkip(76, "c10d not compiled with HCCL support"),
29 "known_issues":TestSkip(77, "Test skipped due to known issues"),29 "known_issues":TestSkip(77, "Test skipped due to known issues"),
30}30}
31 31 
32 32 
33def skipIfUnsupportMultiNPU(npu_number_needed):33def skipIfUnsupportMultiNPU(npu_number_needed):
34 def skip_dec(func):34 def skip_dec(func):
35 @wraps(func)35 @wraps(func)
36 def wrapper(self, *args, **kwargs):36 def wrapper(self, *args, **kwargs):
37 if not torch.npu.is_available() or torch.npu.device_count() < npu_number_needed:37 if not torch.npu.is_available() or torch.npu.device_count() < npu_number_needed:
38 raise unittest.SkipTest(f"Multi-NPU {npu_number_needed} condition not satisfied")38 raise unittest.SkipTest(f"Multi-NPU {npu_number_needed} condition not satisfied")
39 return func(self, *args, **kwargs)39 return func(self, *args, **kwargs)
40 return wrapper40 return wrapper
41 return skip_dec41 return skip_dec
42 42 
43 43 
44def with_comms(func):44def with_comms(func):
45 if func is None:45 if func is None:
46 raise RuntimeError("Test function is None.")46 raise RuntimeError("Test function is None.")
47 47 
48 @wraps(func) # pyre-ignore[6]48 @wraps(func) # pyre-ignore[6]
49 def wrapper(49 def wrapper(
50 self, *args: Tuple[object], **kwargs: Dict[str, Any] # type: ignore[misc]50 self, *args: Tuple[object], **kwargs: Dict[str, Any] # type: ignore[misc]
51 ) -> None:51 ) -> None:
52 # if backend not specified, and npu available, then use hccl, else gloo52 # if backend not specified, and npu available, then use hccl, else gloo
O
OopenLiBingCI5月17日

此条代码评论区间+48+52

【openlibing.ci】识别到代码检查告警抑制注释,匹配工具:mypy,请Committer检视其合理性。

likedislike
53 if torch.npu.is_available() and torch.npu.device_count() >= self.world_size:53 if torch.npu.is_available() and torch.npu.device_count() >= self.world_size:
54 self.device_type = "npu"54 self.device_type = "npu"
55 else:55 else:
56 self.device_type = "cpu"56 self.device_type = "cpu"
57 57 
58 pg_backend = (58 pg_backend = (
59 "hccl" if self.device_type == "npu" else "gloo"59 "hccl" if self.device_type == "npu" else "gloo"
60 )60 )
61 if pg_backend == "hccl" and torch.npu.device_count() < self.world_size:61 if pg_backend == "hccl" and torch.npu.device_count() < self.world_size:
62 raise RuntimeError(TEST_SKIPS[f"multi-npu-{self.world_size}"].message)62 raise RuntimeError(TEST_SKIPS[f"multi-npu-{self.world_size}"].message)
63 63 
64 init_pg(backend=pg_backend, world_size=self.world_size, rank=self.rank, file_name=self.file_name)64 init_pg(backend=pg_backend, world_size=self.world_size, rank=self.rank, file_name=self.file_name)
65 65 
66 torch.npu.manual_seed(0)66 torch.npu.manual_seed(0)
67 torch.npu.initial_seed()67 torch.npu.initial_seed()
68 func(self, *args, **kwargs) # type: ignore[misc]68 func(self, *args, **kwargs) # type: ignore[misc]
69 self.destroy_pg()69 self.destroy_pg()
70 70 
71 return wrapper71 return wrapper
O
OopenLiBingCI5月17日

此条代码评论区间+66+71

【openlibing.ci】识别到代码检查告警抑制注释,匹配工具:mypy,请Committer检视其合理性。

likedislike
72 72 
73 73 
74def init_pg(backend: str = "hccl", world_size=1, rank=0, file_name="file://") -> None:74def init_pg(backend: str = "hccl", world_size=1, rank=0, file_name="file://") -> None:
75 if backend == "hccl" and torch.npu.device_count() < world_size:75 if backend == "hccl" and torch.npu.device_count() < world_size:
76 raise RuntimeError(TEST_SKIPS[f"multi-npu-{world_size}"].message)76 raise RuntimeError(TEST_SKIPS[f"multi-npu-{world_size}"].message)
77 77 
78 if backend not in ["hccl", "gloo"]:78 if backend not in ["hccl", "gloo"]:
79 raise RuntimeError(f"Backend {backend} not supported!")79 raise RuntimeError(f"Backend {backend} not supported!")
80 80 
81 dist.init_process_group(81 dist.init_process_group(
82 backend=backend,82 backend=backend,
83 world_size=world_size,83 world_size=world_size,
84 rank=rank, # pyre-ignore[16]84 rank=rank, # pyre-ignore[16]
85 init_method=f"file://{file_name}", # pyre-ignore[16]85 init_method=f"file://{file_name}", # pyre-ignore[16]
86 )86 )
87 87 
88 # set device for hccl pg for collectives88 # set device for hccl pg for collectives
89 if backend == "hccl":89 if backend == "hccl":
90 torch.npu.set_device(rank)90 torch.npu.set_device(rank)
91 91 
92 92 
93@contextmanager93@contextmanager
94def _dynamo_dist_per_rank_init(rank, world_size, init_pg_=True):94def _dynamo_dist_per_rank_init(rank, world_size, init_pg_=True):
95 # To avoid multiple inheritance from _dynamo.test_case.TestCase and MultiProcessTestCase,95 # To avoid multiple inheritance from _dynamo.test_case.TestCase and MultiProcessTestCase,
96 # Just manually implement the most important part of the dynamo behavior to reset/clear.96 # Just manually implement the most important part of the dynamo behavior to reset/clear.
97 torch_npu.npu.set_device(rank)97 torch_npu.npu.set_device(rank)
98 os.environ['MASTER_ADDR'] = 'localhost'98 os.environ['MASTER_ADDR'] = 'localhost'
99 os.environ['MASTER_PORT'] = '6789'99 os.environ['MASTER_PORT'] = '6789'
100 if init_pg_:100 if init_pg_:
101 dist.init_process_group(backend="hccl", rank=rank, world_size=world_size)101 dist.init_process_group(backend="hccl", rank=rank, world_size=world_size)
102 torch._dynamo.reset()102 torch._dynamo.reset()
103 torch._dynamo.utils.counters.clear()103 torch._dynamo.utils.counters.clear()
104 try:104 try:
105 yield105 yield
106 finally:106 finally:
107 torch._dynamo.reset()107 torch._dynamo.reset()
108 torch._dynamo.utils.counters.clear()108 torch._dynamo.utils.counters.clear()
109 if init_pg_:109 if init_pg_:
110 dist.destroy_process_group()110 dist.destroy_process_group()
Mtorch_npu/testing/decorator.py+142-142
@@ -1,142 +1,142 @@
1from functools import wraps, partialmethod1from functools import wraps, partialmethod
2 2 
3import os3import os
4import inspect4import inspect
5import itertools5import itertools
6import torch6import torch
7 7 
8 8 
9def feed_data(func, new_name, *args, **kwargs):9def feed_data(func, new_name, *args, **kwargs):
10 """10 """
11 This internal method decorator feeds the test data item to the test.11 This internal method decorator feeds the test data item to the test.
12 """12 """
13 @wraps(func)13 @wraps(func)
14 def wrapper(self):14 def wrapper(self):
15 return func(self, *args, **kwargs)15 return func(self, *args, **kwargs)
16 wrapper.__name__ = new_name16 wrapper.__name__ = new_name
17 wrapper.__wrapped__ = func17 wrapper.__wrapped__ = func
18 return wrapper18 return wrapper
19 19 
20 20 
21def instantiate_tests(arg=None, **kwargs):21def instantiate_tests(arg=None, **kwargs):
22 22 
23 def wrapper(cls):23 def wrapper(cls):
24 def gen_testcase(cls, func, name, key_list, func_args, value):24 def gen_testcase(cls, func, name, key_list, func_args, value):
25 new_kwargs = dict(device="npu") if "device" in func_args else {}25 new_kwargs = dict(device="npu") if "device" in func_args else {}
26 test_name = name26 test_name = name
27 for k, v in zip(key_list, value):27 for k, v in zip(key_list, value):
28 func_key = None28 func_key = None
29 if k == "format":29 if k == "format":
30 test_name += ("_" + str(v))30 test_name += ("_" + str(v))
31 elif k == "dtype":31 elif k == "dtype":
32 test_name += ("_" + str(v).split('.')[1])32 test_name += ("_" + str(v).split('.')[1])
33 for _func_key in func_args:33 for _func_key in func_args:
34 if k in _func_key:34 if k in _func_key:
35 if func_key is not None:35 if func_key is not None:
36 raise RuntimeError(f"Multiple matches for {k}")36 raise RuntimeError(f"Multiple matches for {k}")
37 func_key = _func_key37 func_key = _func_key
38 new_kwargs[func_key] = v38 new_kwargs[func_key] = v
39 setattr(cls, test_name, feed_data(func, test_name, **new_kwargs))39 setattr(cls, test_name, feed_data(func, test_name, **new_kwargs))
40 40 
41 for name, func in list(cls.__dict__.items()):41 for name, func in list(cls.__dict__.items()):
42 data = {}42 data = {}
43 if hasattr(func, "dtypes"):43 if hasattr(func, "dtypes"):
44 data['dtype'] = func.dtypes44 data['dtype'] = func.dtypes
45 if hasattr(func, "formats"):45 if hasattr(func, "formats"):
46 data['format'] = func.formats46 data['format'] = func.formats
47 47 
48 key_list = data.keys()48 key_list = data.keys()
49 if not key_list:49 if not key_list:
50 continue50 continue
51 51 
52 func_args = inspect.getfullargspec(func).args52 func_args = inspect.getfullargspec(func).args
53 value_list = [data.get(key) for key in key_list]53 value_list = [data.get(key) for key in key_list]
54 for value in itertools.product(*value_list):54 for value in itertools.product(*value_list):
55 gen_testcase(cls, func, name, key_list, func_args, value)55 gen_testcase(cls, func, name, key_list, func_args, value)
56 56 
57 delattr(cls, name)57 delattr(cls, name)
58 return cls58 return cls
59 59 
60 return wrapper(arg)60 return wrapper(arg)
61 61 
62 62 
63def gen_ops_testcase(cls, func, name, keys, value, op_info):63def gen_ops_testcase(cls, func, name, keys, value, op_info):
64 new_kwargs = {}64 new_kwargs = {}
65 test_name = f'{func.__name__}_{name}'65 test_name = f'{func.__name__}_{name}'
66 66 
67 for k, v in zip(keys, value):67 for k, v in zip(keys, value):
68 if k == "npu_format":68 if k == "npu_format":
69 test_name += ("_" + str(v))69 test_name += ("_" + str(v))
70 elif k == "dtype":70 elif k == "dtype":
71 test_name += ("_" + str(v).split('.')[1])71 test_name += ("_" + str(v).split('.')[1])
72 new_kwargs[k] = v72 new_kwargs[k] = v
73 73 
74 new_kwargs['op'] = op_info74 new_kwargs['op'] = op_info
75 new_func = partialmethod(func, **new_kwargs)75 new_func = partialmethod(func, **new_kwargs)
76 76 
77 setattr(cls, test_name, new_func)77 setattr(cls, test_name, new_func)
78 for decorator in op_info.get_decorators(cls.__name__, func.__name__, 'cpu', value[0], {}):78 for decorator in op_info.get_decorators(cls.__name__, func.__name__, 'cpu', value[0], {}):
79 setattr(cls, test_name, decorator(new_func))79 setattr(cls, test_name, decorator(new_func))
80 80 
81 81 
82def gen_op_input(testcase, func, op_info):82def gen_op_input(testcase, func, op_info):
83 data = {83 data = {
84 'dtype': func.dtypes if hasattr(func, "dtypes") else op_info.dtypesIfNPU, 84 'dtype': func.dtypes if hasattr(func, "dtypes") else op_info.dtypesIfNPU,
85 'npu_format': func.formats if hasattr(func, "formats") else op_info.formats85 'npu_format': func.formats if hasattr(func, "formats") else op_info.formats
86 }86 }
87 87 
88 if 'test_variant_consistency_eager' in testcase:88 if 'test_variant_consistency_eager' in testcase:
89 if torch.float32 in op_info.dtypesIfNPU:89 if torch.float32 in op_info.dtypesIfNPU:
90 data['dtype'] = {torch.float32}90 data['dtype'] = {torch.float32}
91 else:91 else:
92 data['dtype'] = {list(op_info.dtypesIfNPU)[-1]}92 data['dtype'] = {list(op_info.dtypesIfNPU)[-1]}
93 93 
94 return data94 return data
95 95 
96 96 
97def instantiate_ops_tests(op_db):97def instantiate_ops_tests(op_db):
98 98 
99 def wrapper(cls):99 def wrapper(cls):
100 testcases = [x for x in dir(cls) if x.startswith('test_')]100 testcases = [x for x in dir(cls) if x.startswith('test_')]
101 for testcase in testcases: 101 for testcase in testcases:
102 if hasattr(cls, testcase):102 if hasattr(cls, testcase):
103 func = getattr(cls, testcase)103 func = getattr(cls, testcase)
104 for op_info in op_db:104 for op_info in op_db:
105 data = gen_op_input(testcase, func, op_info)105 data = gen_op_input(testcase, func, op_info)
106 keys = data.keys()106 keys = data.keys()
107 values = [data.get(key) for key in keys]107 values = [data.get(key) for key in keys]
108 108 
109 for value in itertools.product(*values):109 for value in itertools.product(*values):
110 gen_ops_testcase(cls, func, op_info.name, keys, value, op_info)110 gen_ops_testcase(cls, func, op_info.name, keys, value, op_info)
111 111 
112 delattr(cls, testcase)112 delattr(cls, testcase)
113 113 
114 return cls114 return cls
115 115
116 return wrapper116 return wrapper
117 117 
118 118 
119class Dtypes(object):119class Dtypes(object):
120 120 
121 def __init__(self, *args):121 def __init__(self, *args):
122 if (args is None or len(args) == 0):122 if (args is None or len(args) == 0):
123 raise RuntimeError("No dtypes given")123 raise RuntimeError("No dtypes given")
124 if not all(isinstance(arg, torch.dtype) for arg in args):124 if not all(isinstance(arg, torch.dtype) for arg in args):
125 raise RuntimeError("Unknown dtype in {0}".format(str(args)))125 raise RuntimeError("Unknown dtype in {0}".format(str(args)))
126 self.args = args126 self.args = args
127 127 
128 def __call__(self, fn):128 def __call__(self, fn):
129 fn.dtypes = self.args129 fn.dtypes = self.args
130 return fn130 return fn
131 131 
132 132 
133class Formats(object):133class Formats(object):
134 134 
135 def __init__(self, *args):135 def __init__(self, *args):
136 if args is None or len(args) == 0:136 if args is None or len(args) == 0:
137 raise RuntimeError("No formats given")137 raise RuntimeError("No formats given")
138 self.args = args138 self.args = args
139 139 
140 def __call__(self, fn):140 def __call__(self, fn):
141 fn.formats = self.args141 fn.formats = self.args
142 return fn142 return fn
Mtorch_npu/utils/cpp_extension.py+60-60
@@ -1,60 +1,60 @@
1import os1import os
2import setuptools2import setuptools
3 3 
4import torch4import torch
5import torch.utils.cpp_extension as TorchExtension5import torch.utils.cpp_extension as TorchExtension
6 6 
7import torch_npu7import torch_npu
8 8 
9PYTORCH_NPU_INSTALL_PATH = os.path.dirname(os.path.realpath(torch_npu.__file__))9PYTORCH_NPU_INSTALL_PATH = os.path.dirname(os.path.realpath(torch_npu.__file__))
10 10 
11 11 
12def NpuExtension(name, sources, *args, **kwargs):12def NpuExtension(name, sources, *args, **kwargs):
13 r'''13 r'''
14 Creates a :class:`setuptools.Extension` for C++.14 Creates a :class:`setuptools.Extension` for C++.
15 15 
16 Convenience method that creates a :class:`setuptools.Extension` with the16 Convenience method that creates a :class:`setuptools.Extension` with the
17 bare minimum (but often sufficient) arguments to build a C++ extension.17 bare minimum (but often sufficient) arguments to build a C++ extension.
18 18 
19 All arguments are forwarded to the :class:`setuptools.Extension`19 All arguments are forwarded to the :class:`setuptools.Extension`
20 constructor.20 constructor.
21 21 
22 Example:22 Example:
23 >>> from setuptools import setup23 >>> from setuptools import setup
24 >>> from torch_npu.utils.cpp_extension import NpuExtension24 >>> from torch_npu.utils.cpp_extension import NpuExtension
25 >>> setup(25 >>> setup(
26 name='extension',26 name='extension',
27 ext_modules=[27 ext_modules=[
28 NpuExtension(28 NpuExtension(
29 name='extension',29 name='extension',
30 sources=['extension.cpp'],30 sources=['extension.cpp'],
31 extra_compile_args=['-g']),31 extra_compile_args=['-g']),
32 ],32 ],
33 cmdclass={33 cmdclass={
34 'build_ext': BuildExtension34 'build_ext': BuildExtension
35 })35 })
36 '''36 '''
37 37 
38 torch_npu_dir = PYTORCH_NPU_INSTALL_PATH38 torch_npu_dir = PYTORCH_NPU_INSTALL_PATH
39 include_dirs = kwargs.get('include_dirs', [])39 include_dirs = kwargs.get('include_dirs', [])
40 include_dirs.append(os.path.join(torch_npu_dir, 'include'))40 include_dirs.append(os.path.join(torch_npu_dir, 'include'))
41 include_dirs.append(os.path.join(torch_npu_dir, 'include', 'third_party', 'acl', 'inc'))41 include_dirs.append(os.path.join(torch_npu_dir, 'include', 'third_party', 'acl', 'inc'))
42 include_dirs.append(os.path.join(torch_npu_dir, 'include', 'third_party', 'hccl', 'inc'))42 include_dirs.append(os.path.join(torch_npu_dir, 'include', 'third_party', 'hccl', 'inc'))
43 include_dirs += TorchExtension.include_paths()43 include_dirs += TorchExtension.include_paths()
44 kwargs['include_dirs'] = include_dirs44 kwargs['include_dirs'] = include_dirs
45 45 
46 library_dirs = kwargs.get('library_dirs', [])46 library_dirs = kwargs.get('library_dirs', [])
47 library_dirs.append(os.path.join(torch_npu_dir, 'lib'))47 library_dirs.append(os.path.join(torch_npu_dir, 'lib'))
48 library_dirs += TorchExtension.library_paths()48 library_dirs += TorchExtension.library_paths()
49 kwargs['library_dirs'] = library_dirs49 kwargs['library_dirs'] = library_dirs
50 50 
51 libraries = kwargs.get('libraries', [])51 libraries = kwargs.get('libraries', [])
52 libraries.append('c10')52 libraries.append('c10')
53 libraries.append('torch')53 libraries.append('torch')
54 libraries.append('torch_cpu')54 libraries.append('torch_cpu')
55 libraries.append('torch_python')55 libraries.append('torch_python')
56 libraries.append('torch_npu')56 libraries.append('torch_npu')
57 kwargs['libraries'] = libraries57 kwargs['libraries'] = libraries
58 58 
59 kwargs['language'] = 'c++'59 kwargs['language'] = 'c++'
60 return setuptools.Extension(name, sources, *args, **kwargs)60 return setuptools.Extension(name, sources, *args, **kwargs)
Mtorch_npu/utils/flops_count.py+0-1
@@ -38,4 +38,3 @@ class FlopsCounter(_FlopsCounter):
38 super().__init__()38 super().__init__()
39 warnings.warn("torch_npu.utils.flops_count.FlopsCounter() will be deprecated. "39 warnings.warn("torch_npu.utils.flops_count.FlopsCounter() will be deprecated. "
40 "If necessary, please use torch_npu.utils.FlopsCounter().", FutureWarning)40 "If necessary, please use torch_npu.utils.FlopsCounter().", FutureWarning)
41 
Mtorch_npu/utils/syncbatchnorm.py+103-103
@@ -1,103 +1,103 @@
1import torch1import torch
2import torch.distributed as dist2import torch.distributed as dist
3from torch.autograd.function import Function3from torch.autograd.function import Function
4 4 
5import torch_npu5import torch_npu
6from torch_npu.utils._error_code import ErrCode, ops_error6from torch_npu.utils._error_code import ErrCode, ops_error
7 7 
8 8 
9__all__ = ["SyncBatchNorm"]9__all__ = ["SyncBatchNorm"]
10 10 
11 11 
12class SyncBatchNorm(Function):12class SyncBatchNorm(Function):
13 13 
14 @staticmethod14 @staticmethod
15 def forward(self, input_tensor, weight, bias, running_mean, running_var, eps, momentum, process_group, world_size):15 def forward(self, input_tensor, weight, bias, running_mean, running_var, eps, momentum, process_group, world_size):
16 input_tensor = input_tensor.contiguous()16 input_tensor = input_tensor.contiguous()
17 input_shape = input_tensor.shape17 input_shape = input_tensor.shape
18 input_tensor_ = input_tensor.reshape(input_shape[0], input_shape[1], 1, -1)18 input_tensor_ = input_tensor.reshape(input_shape[0], input_shape[1], 1, -1)
19 # calculate sum/sum_square for input.19 # calculate sum/sum_square for input.
20 sum_val, sum_square_val = torch_npu.batch_norm_reduce(input_tensor_, eps)20 sum_val, sum_square_val = torch_npu.batch_norm_reduce(input_tensor_, eps)
21 21 
22 count = torch.full((1,),22 count = torch.full((1,),
23 input_tensor.numel() // input_tensor.size(1),23 input_tensor.numel() // input_tensor.size(1),
24 dtype=sum_val.dtype,24 dtype=sum_val.dtype,
25 device=sum_val.device)25 device=sum_val.device)
26 26 
27 num_channels = input_tensor.shape[1]27 num_channels = input_tensor.shape[1]
28 # C, C, 1 -> (2C + 1)28 # C, C, 1 -> (2C + 1)
29 combined = torch.cat([sum_val, sum_square_val, count], dim=0)29 combined = torch.cat([sum_val, sum_square_val, count], dim=0)
30 # world_size * (2C + 1)30 # world_size * (2C + 1)
31 combined_list = [torch.empty_like(combined) for k in range(world_size)]31 combined_list = [torch.empty_like(combined) for k in range(world_size)]
32 dist.all_gather(combined_list, combined, process_group, async_op=False)32 dist.all_gather(combined_list, combined, process_group, async_op=False)
33 combined = torch.stack(combined_list, dim=0)33 combined = torch.stack(combined_list, dim=0)
34 # world_size * (2C + 1) -> world_size * C, world_size * C, world_size * 134 # world_size * (2C + 1) -> world_size * C, world_size * C, world_size * 1
35 sum_all, square_sum_all, count_all = torch.split(combined, num_channels, dim=1)35 sum_all, square_sum_all, count_all = torch.split(combined, num_channels, dim=1)
36 36 
37 size = count_all.view(-1).sum()37 size = count_all.view(-1).sum()
38 if size == 1:38 if size == 1:
39 raise ValueError('Expected more than 1 value per channel when training, got input size {}'.format(size) +39 raise ValueError('Expected more than 1 value per channel when training, got input size {}'.format(size) +
40 ops_error(ErrCode.VALUE))40 ops_error(ErrCode.VALUE))
41 41 
42 # calculate global mean & invstd42 # calculate global mean & invstd
43 mean, invstd = torch_npu.batch_norm_gather_stats_update(input_tensor,43 mean, invstd = torch_npu.batch_norm_gather_stats_update(input_tensor,
44 sum_all,44 sum_all,
45 square_sum_all,45 square_sum_all,
46 running_mean,46 running_mean,
47 running_var,47 running_var,
48 momentum,48 momentum,
49 eps,49 eps,
50 count_all.view(-1))50 count_all.view(-1))
51 51 
52 self.save_for_backward(input_tensor, weight, mean, invstd, count_all)52 self.save_for_backward(input_tensor, weight, mean, invstd, count_all)
53 self.process_group = process_group53 self.process_group = process_group
54 54 
55 # apply element-wise normalization55 # apply element-wise normalization
56 out = torch.batch_norm_elemt(input_tensor, weight, bias, mean, invstd, eps)56 out = torch.batch_norm_elemt(input_tensor, weight, bias, mean, invstd, eps)
57 return out57 return out
58 58 
59 @staticmethod59 @staticmethod
60 def backward(self, grad_output):60 def backward(self, grad_output):
61 if not grad_output.is_contiguous(memory_format=torch.channels_last):61 if not grad_output.is_contiguous(memory_format=torch.channels_last):
62 grad_output = grad_output.contiguous()62 grad_output = grad_output.contiguous()
63 saved_input, weight, mean, invstd, count_tensor = self.saved_tensors63 saved_input, weight, mean, invstd, count_tensor = self.saved_tensors
64 grad_input = grad_weight = grad_bias = None64 grad_input = grad_weight = grad_bias = None
65 process_group = self.process_group65 process_group = self.process_group
66 66 
67 # calculate local stats as well as grad_weight / grad_bias67 # calculate local stats as well as grad_weight / grad_bias
68 sum_dy, sum_dy_xmu, grad_weight, grad_bias = torch.batch_norm_backward_reduce(grad_output,68 sum_dy, sum_dy_xmu, grad_weight, grad_bias = torch.batch_norm_backward_reduce(grad_output,
69 saved_input,69 saved_input,
70 mean,70 mean,
71 invstd,71 invstd,
72 weight,72 weight,
73 self.needs_input_grad[0],73 self.needs_input_grad[0],
74 self.needs_input_grad[1],74 self.needs_input_grad[1],
75 self.needs_input_grad[2])75 self.needs_input_grad[2])
76 76 
77 if self.needs_input_grad[0]:77 if self.needs_input_grad[0]:
78 # synchronizing stats used to calculate input gradient.78 # synchronizing stats used to calculate input gradient.
79 num_channels = sum_dy.shape[0]79 num_channels = sum_dy.shape[0]
80 combined = torch.cat([sum_dy, sum_dy_xmu], dim=0)80 combined = torch.cat([sum_dy, sum_dy_xmu], dim=0)
81 torch.distributed.all_reduce(81 torch.distributed.all_reduce(
82 combined, torch.distributed.ReduceOp.SUM, process_group, async_op=False)82 combined, torch.distributed.ReduceOp.SUM, process_group, async_op=False)
83 sum_dy, sum_dy_xmu = torch.split(combined, num_channels)83 sum_dy, sum_dy_xmu = torch.split(combined, num_channels)
84 84 
85 # backward pass for gradient calculation85 # backward pass for gradient calculation
86 grad_input = torch.batch_norm_backward_elemt(grad_output,86 grad_input = torch.batch_norm_backward_elemt(grad_output,
87 saved_input,87 saved_input,
88 mean,88 mean,
89 invstd,89 invstd,
90 weight,90 weight,
91 sum_dy,91 sum_dy,
92 sum_dy_xmu,92 sum_dy_xmu,
93 count_tensor)93 count_tensor)
94 94 
95 # synchronizing of grad_weight / grad_bias is not needed as distributed95 # synchronizing of grad_weight / grad_bias is not needed as distributed
96 # training would handle all reduce.96 # training would handle all reduce.
97 if weight is None or not self.needs_input_grad[1]:97 if weight is None or not self.needs_input_grad[1]:
98 grad_weight = None98 grad_weight = None
99 99 
100 if weight is None or not self.needs_input_grad[2]:100 if weight is None or not self.needs_input_grad[2]:
101 grad_bias = None101 grad_bias = None
102 102 
103 return grad_input, grad_weight, grad_bias, None, None, None, None, None, None103 return grad_input, grad_weight, grad_bias, None, None, None, None, None, None
Mtorch_npu/utils/tensor_methods.py+88-88
@@ -1,88 +1,88 @@
1from functools import wraps1from functools import wraps
2 2 
3import torch3import torch
4 4 
5import torch_npu5import torch_npu
6from torch_npu.utils._error_code import ErrCode, pta_error6from torch_npu.utils._error_code import ErrCode, pta_error
7from torch_npu.utils.storage import _reduce_ex7from torch_npu.utils.storage import _reduce_ex
8 8 
9 9 
10__all__ = []10__all__ = []
11 11 
12 12 
13def _npu(self, *args, **kwargs):13def _npu(self, *args, **kwargs):
14 return torch_npu._C.npu(self, *args, **kwargs)14 return torch_npu._C.npu(self, *args, **kwargs)
15 15 
16 16 
17@property17@property
18def _is_npu(self):18def _is_npu(self):
19 return torch_npu._C.is_npu(self)19 return torch_npu._C.is_npu(self)
20 20 
21 21 
22class _NPUTensortypeCache(object):22class _NPUTensortypeCache(object):
23 init = False23 init = False
24 tensortype_list = []24 tensortype_list = []
25 tensortype_dict = {}25 tensortype_dict = {}
26 26 
27 @classmethod27 @classmethod
28 def tensortype_list_dict_init(cls):28 def tensortype_list_dict_init(cls):
29 if not cls.init:29 if not cls.init:
30 cls.tensortype_list += [30 cls.tensortype_list += [
31 torch_npu.npu.BoolTensor,31 torch_npu.npu.BoolTensor,
32 torch_npu.npu.ByteTensor,32 torch_npu.npu.ByteTensor,
33 torch_npu.npu.CharTensor,33 torch_npu.npu.CharTensor,
34 torch_npu.npu.DoubleTensor,34 torch_npu.npu.DoubleTensor,
35 torch_npu.npu.FloatTensor,35 torch_npu.npu.FloatTensor,
36 torch_npu.npu.HalfTensor,36 torch_npu.npu.HalfTensor,
37 torch_npu.npu.IntTensor,37 torch_npu.npu.IntTensor,
38 torch_npu.npu.LongTensor,38 torch_npu.npu.LongTensor,
39 torch_npu.npu.ShortTensor,39 torch_npu.npu.ShortTensor,
40 torch_npu.npu.BFloat16Tensor,40 torch_npu.npu.BFloat16Tensor,
41 ]41 ]
42 42 
43 cls.tensortype_str_list = [43 cls.tensortype_str_list = [
44 "torch_npu.npu.BoolTensor",44 "torch_npu.npu.BoolTensor",
45 "torch_npu.npu.ByteTensor",45 "torch_npu.npu.ByteTensor",
46 "torch_npu.npu.CharTensor",46 "torch_npu.npu.CharTensor",
47 "torch_npu.npu.DoubleTensor",47 "torch_npu.npu.DoubleTensor",
48 "torch_npu.npu.FloatTensor",48 "torch_npu.npu.FloatTensor",
49 "torch_npu.npu.HalfTensor",49 "torch_npu.npu.HalfTensor",
50 "torch_npu.npu.IntTensor",50 "torch_npu.npu.IntTensor",
51 "torch_npu.npu.LongTensor",51 "torch_npu.npu.LongTensor",
52 "torch_npu.npu.ShortTensor",52 "torch_npu.npu.ShortTensor",
53 "torch_npu.npu.BFloat16Tensor",53 "torch_npu.npu.BFloat16Tensor",
54 ]54 ]
55 55 
56 for tensortype, tensortype_str in zip(cls.tensortype_list, cls.tensortype_str_list):56 for tensortype, tensortype_str in zip(cls.tensortype_list, cls.tensortype_str_list):
57 cls.tensortype_dict[tensortype_str] = tensortype57 cls.tensortype_dict[tensortype_str] = tensortype
58 cls.tensortype_dict[tensortype_str.replace('torch_npu.', 'torch.')] = tensortype58 cls.tensortype_dict[tensortype_str.replace('torch_npu.', 'torch.')] = tensortype
59 59 
60 cls.init = True60 cls.init = True
61 61 
62 @classmethod62 @classmethod
63 def get_tensortype_list(cls):63 def get_tensortype_list(cls):
64 return cls.tensortype_list64 return cls.tensortype_list
65 65 
66 @classmethod66 @classmethod
67 def get_tensortype_dict(cls):67 def get_tensortype_dict(cls):
68 return cls.tensortype_dict68 return cls.tensortype_dict
69 69 
70 70 
71def _npu_type(self, dtype=None, non_blocking=False, **kwargs):71def _npu_type(self, dtype=None, non_blocking=False, **kwargs):
72 if dtype is None:72 if dtype is None:
73 return self.type_raw(dtype, non_blocking, **kwargs)73 return self.type_raw(dtype, non_blocking, **kwargs)
74 74
75 _NPUTensortypeCache.tensortype_list_dict_init()75 _NPUTensortypeCache.tensortype_list_dict_init()
76 if isinstance(dtype, str) and dtype in _NPUTensortypeCache.get_tensortype_dict():76 if isinstance(dtype, str) and dtype in _NPUTensortypeCache.get_tensortype_dict():
77 tensortype_class = _NPUTensortypeCache.get_tensortype_dict()[dtype]77 tensortype_class = _NPUTensortypeCache.get_tensortype_dict()[dtype]
78 return self.to(dtype=tensortype_class.dtype, device='npu', non_blocking=non_blocking)78 return self.to(dtype=tensortype_class.dtype, device='npu', non_blocking=non_blocking)
79 elif dtype in _NPUTensortypeCache.get_tensortype_list():79 elif dtype in _NPUTensortypeCache.get_tensortype_list():
80 return self.to(dtype=dtype.dtype, device='npu', non_blocking=non_blocking)80 return self.to(dtype=dtype.dtype, device='npu', non_blocking=non_blocking)
81 else:81 else:
82 return self.type_raw(dtype, non_blocking, **kwargs)82 return self.type_raw(dtype, non_blocking, **kwargs)
83 83 
84 84 
85def _add_tensor_methods():85def _add_tensor_methods():
86 torch.Tensor.type_raw = torch.Tensor.type86 torch.Tensor.type_raw = torch.Tensor.type
87 torch.Tensor.type = _npu_type87 torch.Tensor.type = _npu_type
88 torch.Tensor.__reduce_ex__ = _reduce_ex88 torch.Tensor.__reduce_ex__ = _reduce_ex