已合并
revert: 回退ordinary AICPU常量折叠迁移 #5239
pantong创建于 26 天前
revert: 回退ordinary AICPU常量折叠迁移 #5239
已合并
共 18 个文件变更+1410-39
| @@ -534,7 +534,7 @@ elseif (BUILD_OPEN_PROJECT OR ENABLE_OPEN_SRC) | |||
| 534 | if (NOT MDC_COMPILE_RUNTIME) | 534 | if (NOT MDC_COMPILE_RUNTIME) |
| 535 | add_custom_target(ge-compiler) | 535 | add_custom_target(ge-compiler) |
| 536 | add_dependencies(ge-compiler parser_common aicore_utils fusion_pass op_compile_adapter aicpu_engine_common fmk_parser ge_compiler | 536 | add_dependencies(ge-compiler parser_common aicore_utils fusion_pass op_compile_adapter aicpu_engine_common fmk_parser ge_compiler |
| 537 | - fmk_onnx_parser opskernel ge_runner slice llm_engine jit_exe _caffe_parser flow_graph aihac_autofusion | 537 | + fmk_onnx_parser opskernel ge_runner slice aicpu_const_folding llm_engine jit_exe _caffe_parser flow_graph aihac_autofusion |
| 538 | dflow_runner eager_style_graph_builder_base eager_style_graph_builder_base_static gen_esb | 538 | dflow_runner eager_style_graph_builder_base eager_style_graph_builder_base_static gen_esb |
| 539 | aihac_symbolizer ge_python llm_datadist_python_v1 dataflow_python ge_python_pass_bridge | 539 | aihac_symbolizer ge_python llm_datadist_python_v1 dataflow_python ge_python_pass_bridge |
| 540 | ge_python_custom_op_bridge func2graph) | 540 | ge_python_custom_op_bridge func2graph) |
| @@ -24,7 +24,7 @@ namespace ge { | |||
| 24 | namespace { | 24 | namespace { |
| 25 | const std::string kConstantFoldingName = "libconstant_folding_ops.so"; | 25 | const std::string kConstantFoldingName = "libconstant_folding_ops.so"; |
| 26 | const std::string kOpsHostCpuName = "libops_host_cpu.so"; | 26 | const std::string kOpsHostCpuName = "libops_host_cpu.so"; |
| 27 | -const std::string kOpConstantFoldingName = "libopconstant_folding.so"; | 27 | +const std::string kAicpuConstFoldingName = "libaicpu_const_folding.so"; |
| 28 | constexpr char kAicpuHostFindFunc[] = "AicpuHostFindFunc"; | 28 | constexpr char kAicpuHostFindFunc[] = "AicpuHostFindFunc"; |
| 29 | 29 | ||
| 30 | Status GetDataNumber(const GeTensorDesc &out_desc, uint64_t &data_num) { | 30 | Status GetDataNumber(const GeTensorDesc &out_desc, uint64_t &data_num) { |
| @@ -110,13 +110,28 @@ ge::Status HostCpuEngine::Initialize(const std::string &path_base) { | |||
| 110 | (void)LoadLib(constant_folding_name); | 110 | (void)LoadLib(constant_folding_name); |
| 111 | } | 111 | } |
| 112 | 112 | ||
| 113 | + // libops_host_cpu.so 中除 AICPU 注册的常量折叠算子之外, 还包含其他 | ||
| 114 | + // 通过 REGISTER_HOST_CPU_OP_BUILDER 注册的常量折叠算子, 必须先 dlopen | ||
| 115 | + // 让其 file-scope 静态注册先写入 op_type 路由, 但此时不调用其 Initialize, | ||
| 116 | + // 给后续的 libaicpu_const_folding.so Initialize 留出"后写覆盖"的机会 | ||
| 113 | std::string ops_host_cpu_name = lib_dir + "/" + kOpsHostCpuName; | 117 | std::string ops_host_cpu_name = lib_dir + "/" + kOpsHostCpuName; |
| 118 | + void *ops_host_cpu_handle = nullptr; | ||
| 114 | if (GetEngineRealPath(ops_host_cpu_name) == SUCCESS) { | 119 | if (GetEngineRealPath(ops_host_cpu_name) == SUCCESS) { |
| 115 | - (void)LoadLib(ops_host_cpu_name, true); | 120 | + ops_host_cpu_handle = DlopenLib(ops_host_cpu_name); |
| 121 | + if (ops_host_cpu_handle != nullptr) { | ||
| 122 | + GELOGI("Lib: %s has been opened (initialize deferred)", ops_host_cpu_name.c_str()); | ||
| 123 | + (void)lib_handles_.emplace_back(ops_host_cpu_handle); | ||
| 124 | + } | ||
| 116 | } | 125 | } |
| 117 | 126 | ||
| 118 | - // Load the opbase ordinary constant-folding router after the fused HostCPU library is initialized. | 127 | + // 后加载 libaicpu_const_folding.so 并执行 Initialize: 成功则 V2 wrapper 工厂 |
| 119 | - (void)LoadOpConstantFoldingLib(kOpConstantFoldingName, lib_dir); | 128 | + // 通过 last-write-wins 语义覆盖 libops_host_cpu.so 中同名 op_type 的注册项 |
| 129 | + // AICPU 路径不可用时, 回退执行 libops_host_cpu.so 的 Initialize, 注册 V1 wrapper | ||
| 130 | + // 兜底, 保证常量折叠链路可用 | ||
| 131 | + const bool aicpu_init_ok = (LoadLib(kAicpuConstFoldingName, true) == SUCCESS); | ||
| 132 | + if (!aicpu_init_ok && ops_host_cpu_handle != nullptr) { | ||
| 133 | + (void)InvokeLibInitialize(ops_host_cpu_handle, ops_host_cpu_name); | ||
| 134 | + } | ||
| 120 | 135 | ||
| 121 | initialized_ = true; | 136 | initialized_ = true; |
| 122 | return SUCCESS; | 137 | return SUCCESS; |
| @@ -248,13 +263,9 @@ Status HostCpuEngine::Run(const NodePtr &node, HostCpuOp &kernel, const std::vec | |||
| 248 | return SUCCESS; | 263 | return SUCCESS; |
| 249 | } | 264 | } |
| 250 | 265 | ||
| 251 | -void *HostCpuEngine::DlopenLib(const std::string &lib_path, bool global) const { | 266 | +void *HostCpuEngine::DlopenLib(const std::string &lib_path) const { |
| 252 | GELOGI("To invoke dlopen on lib: %s", lib_path.c_str()); | 267 | GELOGI("To invoke dlopen on lib: %s", lib_path.c_str()); |
| 253 | - // RTLD_LOCAL is the default when RTLD_GLOBAL is absent. | 268 | + constexpr uint32_t open_flag = static_cast<uint32_t>(MMPA_RTLD_NOW) | static_cast<uint32_t>(MMPA_RTLD_GLOBAL); |
| 254 | - uint32_t open_flag = static_cast<uint32_t>(MMPA_RTLD_NOW); | ||
| 255 | - if (global) { | ||
| 256 | - open_flag |= static_cast<uint32_t>(MMPA_RTLD_GLOBAL); | ||
| 257 | - } | ||
| 258 | auto handle = mmDlopen(lib_path.c_str(), static_cast<int32_t>(open_flag)); | 269 | auto handle = mmDlopen(lib_path.c_str(), static_cast<int32_t>(open_flag)); |
| 259 | if (handle == nullptr) { | 270 | if (handle == nullptr) { |
| 260 | const char_t *error = mmDlerror(); | 271 | const char_t *error = mmDlerror(); |
| @@ -306,30 +317,6 @@ Status HostCpuEngine::LoadLib(const std::string &lib_path, bool invoke_init) { | |||
| 306 | return SUCCESS; | 317 | return SUCCESS; |
| 307 | } | 318 | } |
| 308 | 319 | ||
| 309 | -Status HostCpuEngine::LoadOpConstantFoldingLib(const std::string &lib_path, const std::string &host_cpu_dir) { | ||
| 310 | - void *handle = DlopenLib(lib_path, false); | ||
| 311 | - if (handle == nullptr) { | ||
| 312 | - return INTERNAL_ERROR; | ||
| 313 | - } | ||
| 314 | - using InitFunc = int32_t (*)(const char *); | ||
| 315 | - const auto initialize = reinterpret_cast<InitFunc>(mmDlsym(handle, "ConstantFoldingInitialize")); | ||
| 316 | - if (initialize == nullptr) { | ||
| 317 | - const char_t *reason = mmDlerror(); | ||
| 318 | - reason = (reason == nullptr) ? "" : reason; | ||
| 319 | - GELOGW("[Find][ConstantFoldingInitialize] symbol not found in lib: %s, reason = %s", lib_path.c_str(), reason); | ||
| 320 | - (void)mmDlclose(handle); | ||
| 321 | - return INTERNAL_ERROR; | ||
| 322 | - } | ||
| 323 | - if (initialize(host_cpu_dir.c_str()) != 0) { | ||
| 324 | - GELOGW("[Invoke][ConstantFoldingInitialize] failed. path = %s", lib_path.c_str()); | ||
| 325 | - (void)mmDlclose(handle); | ||
| 326 | - return INTERNAL_ERROR; | ||
| 327 | - } | ||
| 328 | - GELOGI("Lib: %s has been opened", lib_path.c_str()); | ||
| 329 | - (void)lib_handles_.emplace_back(handle); | ||
| 330 | - return SUCCESS; | ||
| 331 | -} | ||
| 332 | - | ||
| 333 | Status HostCpuEngine::GetEngineRealPath(std::string &path) { | 320 | Status HostCpuEngine::GetEngineRealPath(std::string &path) { |
| 334 | const std::string real_path = RealPath(path.c_str()); | 321 | const std::string real_path = RealPath(path.c_str()); |
| 335 | if (real_path.empty()) { | 322 | if (real_path.empty()) { |
| @@ -50,14 +50,12 @@ class HostCpuEngine { | |||
| 50 | 50 | ||
| 51 | HostCpuEngine() = default; | 51 | HostCpuEngine() = default; |
| 52 | 52 | ||
| 53 | - void *DlopenLib(const std::string &lib_path, bool global = true) const; | 53 | + void *DlopenLib(const std::string &lib_path) const; |
| 54 | 54 | ||
| 55 | Status InvokeLibInitialize(void *handle, const std::string &lib_path) const; | 55 | Status InvokeLibInitialize(void *handle, const std::string &lib_path) const; |
| 56 | 56 | ||
| 57 | Status LoadLib(const std::string &lib_path, bool invoke_init = false); | 57 | Status LoadLib(const std::string &lib_path, bool invoke_init = false); |
| 58 | 58 | ||
| 59 | - Status LoadOpConstantFoldingLib(const std::string &lib_path, const std::string &host_cpu_dir); | ||
| 60 | - | ||
| 61 | static Status GetEngineRealPath(std::string &path); | 59 | static Status GetEngineRealPath(std::string &path); |
| 62 | 60 | ||
| 63 | static Status PrepareInputs(const ConstOpDescPtr &op_desc, const std::vector<ConstGeTensorPtr> &inputs, | 61 | static Status PrepareInputs(const ConstOpDescPtr &op_desc, const std::vector<ConstGeTensorPtr> &inputs, |
| @@ -76,7 +76,7 @@ if("ge-compiler" IN_LIST BUILD_COMPONENT) | |||
| 76 | install_public_packages(ge-compiler) | 76 | install_public_packages(ge-compiler) |
| 77 | if(NOT MDC_COMPILE_RUNTIME) | 77 | if(NOT MDC_COMPILE_RUNTIME) |
| 78 | install(TARGETS parser_common aicore_utils fusion_pass op_compile_adapter aicpu_engine_common fmk_parser ge_compiler fmk_onnx_parser opskernel ge_runner | 78 | install(TARGETS parser_common aicore_utils fusion_pass op_compile_adapter aicpu_engine_common fmk_parser ge_compiler fmk_onnx_parser opskernel ge_runner |
| 79 | - slice llm_engine jit_exe _caffe_parser func2graph flow_graph aihac_autofusion dflow_runner eager_style_graph_builder_base | 79 | + slice aicpu_const_folding llm_engine jit_exe _caffe_parser func2graph flow_graph aihac_autofusion dflow_runner eager_style_graph_builder_base |
| 80 | eager_style_graph_builder_base_static ge_runner_v2 aihac_symbolizer compress compressweight | 80 | eager_style_graph_builder_base_static ge_runner_v2 aihac_symbolizer compress compressweight |
| 81 | hcom_gradient_split_tune hcom_graph_adaptor acl_op_compiler | 81 | hcom_gradient_split_tune hcom_graph_adaptor acl_op_compiler |
| 82 | LIBRARY DESTINATION ${ARCH_LINUX_PATH}/lib64 COMPONENT ge-compiler | 82 | LIBRARY DESTINATION ${ARCH_LINUX_PATH}/lib64 COMPONENT ge-compiler |
| @@ -12,6 +12,8 @@ set(proto_src_files | |||
| 12 | ${METADEF_PROTO_DIR}/task.proto | 12 | ${METADEF_PROTO_DIR}/task.proto |
| 13 | ) | 13 | ) |
| 14 | 14 | ||
| 15 | +add_subdirectory(constant_folding_stub) | ||
| 16 | + | ||
| 15 | generate_cann_protobuf(aicpu PROTO_SRCS PROTO_HDRS ${proto_src_files}) | 17 | generate_cann_protobuf(aicpu PROTO_SRCS PROTO_HDRS ${proto_src_files}) |
| 16 | 18 | ||
| 17 | set(local_aicpu_src_files | 19 | set(local_aicpu_src_files |
| @@ -37,6 +39,11 @@ set(local_hostcpu_builder_src_files | |||
| 37 | ${PROTO_HDRS} | 39 | ${PROTO_HDRS} |
| 38 | ) | 40 | ) |
| 39 | 41 | ||
| 42 | +set(local_aicpu_const_folding_src_files | ||
| 43 | + ${CMAKE_CURRENT_SOURCE_DIR}/aicpu_const_folding/folding.cc | ||
| 44 | + ${CMAKE_CURRENT_SOURCE_DIR}/aicpu_const_folding/host_cpu_kernel_wrapper.cpp | ||
| 45 | +) | ||
| 46 | + | ||
| 40 | set(local_lib_inc_path | 47 | set(local_lib_inc_path |
| 41 | ${CMAKE_CURRENT_SOURCE_DIR} | 48 | ${CMAKE_CURRENT_SOURCE_DIR} |
| 42 | ${AIR_CODE_DIR}/compiler/engines/cpu_engine | 49 | ${AIR_CODE_DIR}/compiler/engines/cpu_engine |
| @@ -57,6 +64,10 @@ add_library(host_cpu_opskernel_builder SHARED | |||
| 57 | ${local_hostcpu_builder_src_files} | 64 | ${local_hostcpu_builder_src_files} |
| 58 | ) | 65 | ) |
| 59 | 66 | ||
| 67 | +add_library(aicpu_const_folding SHARED | ||
| 68 | + ${local_aicpu_const_folding_src_files} | ||
| 69 | +) | ||
| 70 | + | ||
| 60 | target_include_directories(aicpu_ascend_engine PRIVATE | 71 | target_include_directories(aicpu_ascend_engine PRIVATE |
| 61 | ${local_lib_inc_path} | 72 | ${local_lib_inc_path} |
| 62 | ) | 73 | ) |
| @@ -69,6 +80,28 @@ target_include_directories(host_cpu_opskernel_builder PRIVATE | |||
| 69 | ${local_lib_inc_path} | 80 | ${local_lib_inc_path} |
| 70 | ) | 81 | ) |
| 71 | 82 | ||
| 83 | +if (BUILD_OPEN_PROJECT OR ENABLE_OPEN_SRC) | ||
| 84 | + target_include_directories(aicpu_const_folding PRIVATE | ||
| 85 | + ${CMAKE_CURRENT_SOURCE_DIR} | ||
| 86 | + ${AIR_CODE_DIR}/compiler/engines/cpu_engine | ||
| 87 | + ${AIR_CODE_DIR}/compiler/engines/cpu_engine/common | ||
| 88 | + ${AIR_CODE_DIR}/compiler/engines/cpu_engine/aicpu_const_folding | ||
| 89 | + ${CMAKE_BINARY_DIR}/proto/aicpu | ||
| 90 | + ${CMAKE_BINARY_DIR}/proto/aicpu/proto | ||
| 91 | + ) | ||
| 92 | +else () | ||
| 93 | + target_include_directories(aicpu_const_folding PRIVATE | ||
| 94 | + ${CMAKE_CURRENT_SOURCE_DIR} | ||
| 95 | + ${AIR_CODE_DIR}/compiler/engines/cpu_engine | ||
| 96 | + ${AIR_CODE_DIR}/compiler/engines/cpu_engine/common | ||
| 97 | + ${AIR_CODE_DIR}/compiler/engines/cpu_engine/aicpu_const_folding | ||
| 98 | + ${CMAKE_BINARY_DIR}/proto/aicpu | ||
| 99 | + ${CMAKE_BINARY_DIR}/proto/aicpu/proto | ||
| 100 | + ${TOP_DIR}/inc/aicpu/cpu_kernels | ||
| 101 | + ${TOP_DIR}/inc/external/aicpu | ||
| 102 | + ) | ||
| 103 | +endif () | ||
| 104 | + | ||
| 72 | target_compile_options(aicpu_ascend_engine PRIVATE | 105 | target_compile_options(aicpu_ascend_engine PRIVATE |
| 73 | -Wno-deprecated-declarations | 106 | -Wno-deprecated-declarations |
| 74 | -fno-common | 107 | -fno-common |
| @@ -90,6 +123,14 @@ target_compile_options(host_cpu_opskernel_builder PRIVATE | |||
| 90 | -Werror | 123 | -Werror |
| 91 | ) | 124 | ) |
| 92 | 125 | ||
| 126 | +target_compile_options(aicpu_const_folding PRIVATE | ||
| 127 | + -ftrapv | ||
| 128 | + -fstack-protector-all | ||
| 129 | + -fvisibility-inlines-hidden | ||
| 130 | + -fvisibility=hidden | ||
| 131 | + -Wno-deprecated-declarations | ||
| 132 | +) | ||
| 133 | + | ||
| 93 | target_compile_definitions(aicpu_ascend_engine PRIVATE | 134 | target_compile_definitions(aicpu_ascend_engine PRIVATE |
| 94 | AICPU_PLUGIN | 135 | AICPU_PLUGIN |
| 95 | google=ascend_private | 136 | google=ascend_private |
| @@ -105,6 +146,18 @@ target_compile_definitions(host_cpu_opskernel_builder PRIVATE | |||
| 105 | google=ascend_private | 146 | google=ascend_private |
| 106 | ) | 147 | ) |
| 107 | 148 | ||
| 149 | +target_compile_definitions(aicpu_const_folding PRIVATE | ||
| 150 | + google=ascend_private | ||
| 151 | + LOG_CPP | ||
| 152 | + HOST_VISIBILITY | ||
| 153 | +) | ||
| 154 | + | ||
| 155 | +target_link_options(aicpu_const_folding PRIVATE | ||
| 156 | + -Wl,-z,relro,-z,now | ||
| 157 | + -Wl,-Bsymbolic -Wl,--exclude-libs,ALL | ||
| 158 | + $<$<NOT:$<STREQUAL:${RESERVED_SYMBOL},true>>:-s> | ||
| 159 | +) | ||
| 160 | + | ||
| 108 | target_link_libraries(aicpu_ascend_engine PRIVATE | 161 | target_link_libraries(aicpu_ascend_engine PRIVATE |
| 109 | ge_intf_pub | 162 | ge_intf_pub |
| 110 | msprof_headers | 163 | msprof_headers |
| @@ -175,6 +228,44 @@ target_link_libraries(host_cpu_opskernel_builder PRIVATE | |||
| 175 | -ldl | 228 | -ldl |
| 176 | ) | 229 | ) |
| 177 | 230 | ||
| 231 | +if (BUILD_OPEN_PROJECT OR ENABLE_OPEN_SRC) | ||
| 232 | + target_link_libraries(aicpu_const_folding PRIVATE | ||
| 233 | + ge_intf_pub | ||
| 234 | + $<$<TARGET_EXISTS:aicpu_headers>:aicpu_headers> | ||
| 235 | + air_headers | ||
| 236 | + mmpa_headers | ||
| 237 | + metadef_headers | ||
| 238 | + runtime_headers | ||
| 239 | + c_sec_headers | ||
| 240 | + -Wl,--no-as-needed | ||
| 241 | + constant_folding_ops_stub | ||
| 242 | + slog_headers | ||
| 243 | + error_manager | ||
| 244 | + ascend_protobuf | ||
| 245 | + aicpu_engine_common | ||
| 246 | + mmpa | ||
| 247 | + json | ||
| 248 | + acl_rt | ||
| 249 | + -Wl,--as-needed | ||
| 250 | + ) | ||
| 251 | +else () | ||
| 252 | + target_link_libraries(aicpu_const_folding PRIVATE | ||
| 253 | + ge_intf_pub | ||
| 254 | + air_headers | ||
| 255 | + mmpa_headers | ||
| 256 | + -Wl,--no-as-needed | ||
| 257 | + constant_folding_ops_stub | ||
| 258 | + slog_headers | ||
| 259 | + error_manager | ||
| 260 | + ascend_protobuf | ||
| 261 | + aicpu_engine_common | ||
| 262 | + mmpa | ||
| 263 | + json | ||
| 264 | + acl_rt | ||
| 265 | + -Wl,--as-needed | ||
| 266 | + ) | ||
| 267 | +endif () | ||
| 268 | + | ||
| 178 | #####改名称用的,因为一个cmake不能2个相同的名字的链接so 可执行程序 等 | 269 | #####改名称用的,因为一个cmake不能2个相同的名字的链接so 可执行程序 等 |
| 179 | 270 | ||
| 180 | install(TARGETS aicpu_ascend_engine ${INSTALL_OPTIONAL} | 271 | install(TARGETS aicpu_ascend_engine ${INSTALL_OPTIONAL} |
| @@ -191,3 +282,8 @@ install(TARGETS host_cpu_opskernel_builder ${INSTALL_OPTIONAL} | |||
| 191 | EXPORT host_cpu_opskernel_builder-targets | 282 | EXPORT host_cpu_opskernel_builder-targets |
| 192 | LIBRARY DESTINATION ${INSTALL_LIBRARY_DIR} | 283 | LIBRARY DESTINATION ${INSTALL_LIBRARY_DIR} |
| 193 | ) | 284 | ) |
| 285 | + | ||
| 286 | +install(TARGETS aicpu_const_folding ${INSTALL_OPTIONAL} | ||
| 287 | + EXPORT aicpu_const_folding-targets | ||
| 288 | + LIBRARY DESTINATION ${INSTALL_LIBRARY_DIR} | ||
| 289 | +) | ||
| @@ -0,0 +1,684 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) Huawei Technologies Co., Ltd. 2024-2024. All rights reserved. | ||
| 3 | + * | ||
| 4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 5 | + * you may not use this file except in compliance with the License. | ||
| 6 | + * You may obtain a copy of the License at | ||
| 7 | + * | ||
| 8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 9 | + * | ||
| 10 | + * Unless required by applicable law or agreed to in writing, software | ||
| 11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 13 | + * See the License for the specific language governing permissions and | ||
| 14 | + * limitations under the License. | ||
| 15 | + */ | ||
| 16 | +#include "folding.h" | ||
| 17 | + | ||
| 18 | +#include <vector> | ||
| 19 | +#include <set> | ||
| 20 | +#include <string> | ||
| 21 | +#include <unordered_map> | ||
| 22 | +#include <dirent.h> | ||
| 23 | +#include <dlfcn.h> | ||
| 24 | +#include <cstring> | ||
| 25 | +#include "cpu_kernel_register.h" | ||
| 26 | +#include "cpu_kernel.h" | ||
| 27 | +#include "cpu_context.h" | ||
| 28 | +#include "proto/aicpu/cpu_attr.pb.h" | ||
| 29 | +#include "proto/aicpu/cpu_node_def.pb.h" | ||
| 30 | +#include "proto/aicpu/cpu_tensor.pb.h" | ||
| 31 | +#include "proto/aicpu/cpu_tensor_shape.pb.h" | ||
| 32 | +#include "util/aicpu_log.h" | ||
| 33 | +#include "graph/types.h" | ||
| 34 | +#include "mmpa/mmpa_api.h" | ||
| 35 | + | ||
| 36 | +namespace { | ||
| 37 | +const char *const kVtString = "VT_STRING"; | ||
| 38 | +const char *const kVtListString = "VT_LIST_STRING"; | ||
| 39 | +const char *const kVtFloat = "VT_FLOAT"; | ||
| 40 | +const char *const kVtListFloat = "VT_LIST_FLOAT"; | ||
| 41 | +const char *const kVtInt = "VT_INT"; | ||
| 42 | +const char *const kVtListInt = "VT_LIST_INT"; | ||
| 43 | +const char *const kVtListListInt = "VT_LIST_LIST_INT"; | ||
| 44 | +const char *const kVtBool = "VT_BOOL"; | ||
| 45 | +const char *const kVtListBool = "VT_LIST_BOOL"; | ||
| 46 | +const char *const kVtDataType = "VT_DATA_TYPE"; | ||
| 47 | +const char *const kVtListDataType = "VT_LIST_DATA_TYPE"; | ||
| 48 | +const char *const kVtTensor = "VT_TENSOR"; | ||
| 49 | +const char *const kVtListTensor = "VT_LIST_TENSOR"; | ||
| 50 | +const char kPathSeparator = '/'; | ||
| 51 | +const char *const kConstantFoldingSoPrefix = "libopconstant_folding_"; | ||
| 52 | +const char *const kConstantFoldingSoSuffix = ".so"; | ||
| 53 | +const char *const kExcludedConstantFoldingSo = "libconstant_folding_ops.so"; | ||
| 54 | +const char *const kSymGetAllRegisteredOpTypesV2 = "GetAllRegisteredOpTypesV2"; | ||
| 55 | +const char *const kSymIsRegisteredV2 = "IsRegisteredV2"; | ||
| 56 | +const char *const kSymRunCpuKernelV2 = "RunCpuKernelV2"; | ||
| 57 | + | ||
| 58 | +using AttrValueMap = google::protobuf::Map<string, aicpuops::AttrValue>; | ||
| 59 | + | ||
| 60 | +using GetAllRegisteredOpTypesV2Fn = std::vector<std::string> (*)(); | ||
| 61 | +using IsRegisteredV2Fn = bool (*)(const std::string &); | ||
| 62 | +using RunCpuKernelV2Fn = uint32_t (*)(aicpu::CpuKernelContext &); | ||
| 63 | + | ||
| 64 | +struct V2ModuleBinding { | ||
| 65 | + void *handle = nullptr; | ||
| 66 | + GetAllRegisteredOpTypesV2Fn get_all_op_types = nullptr; | ||
| 67 | + IsRegisteredV2Fn is_registered = nullptr; | ||
| 68 | + RunCpuKernelV2Fn run_cpu_kernel = nullptr; | ||
| 69 | + std::string so_name; | ||
| 70 | +}; | ||
| 71 | + | ||
| 72 | +std::vector<V2ModuleBinding> g_v2_bindings; | ||
| 73 | +// op_type->binding反向索引, Init阶段一次性构建, 运行期只读。 | ||
| 74 | +std::unordered_map<std::string, const V2ModuleBinding *> g_v2_op_index; | ||
| 75 | + | ||
| 76 | +void ConvertGeToAicpuTensor(const ge::GeTensorDesc &tensor_desc, const std::string &tensor_name, | ||
| 77 | + const ge::Tensor &ge_tensor, aicpuops::Tensor *aicpu_tensor) { | ||
| 78 | + aicpu_tensor->set_name(tensor_name); | ||
| 79 | + aicpu_tensor->set_tensor_type(tensor_desc.GetDataType()); | ||
| 80 | + aicpu_tensor->set_data_ptr(static_cast<uint64_t>(reinterpret_cast<intptr_t>(ge_tensor.GetData()))); | ||
| 81 | + aicpu_tensor->set_data_size(static_cast<uint64_t>(ge_tensor.GetSize())); | ||
| 82 | + auto shape = aicpu_tensor->mutable_tensor_shape(); | ||
| 83 | + if (shape != nullptr) { | ||
| 84 | + shape->clear_dim(); | ||
| 85 | + std::vector<int64_t> dims = tensor_desc.GetShape().GetDims(); | ||
| 86 | + for (size_t i = 0; i < dims.size(); i++) { | ||
| 87 | + aicpuops::TensorShape_Dim *aicpu_dims = shape->add_dim(); | ||
| 88 | + if (aicpu_dims != nullptr) { | ||
| 89 | + aicpu_dims->set_size(dims[i]); | ||
| 90 | + } | ||
| 91 | + } | ||
| 92 | + shape->set_data_format(static_cast<ge::Format>(tensor_desc.GetFormat())); | ||
| 93 | + } | ||
| 94 | + AICPUE_LOGI("Op set tensor[%s], tensor info[type:%d, data:%p, size:%llu].", tensor_name.c_str(), | ||
| 95 | + static_cast<int>(tensor_desc.GetDataType()), ge_tensor.GetData(), ge_tensor.GetSize()); | ||
| 96 | +} | ||
| 97 | + | ||
| 98 | +int32_t AddStringAttrToNodeDef(const ge::Operator &op, const char *name, [[maybe_unused]] aicpuops::NodeDef node_def, | ||
| 99 | + aicpuops::AttrValue &attr_value) { | ||
| 100 | + std::string s; | ||
| @@ -0,0 +1,34 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) Huawei Technologies Co., Ltd. 2024. All rights reserved. | ||
| 3 | + * | ||
| 4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 5 | + * | ||
| 6 | + * you may not use this file except in compliance with the License. | ||
| 7 | + * You may obtain a copy of the License at | ||
| 8 | + * | ||
| 9 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 10 | + * | ||
| 11 | + * Unless required by applicable law or agreed to in writing, software | ||
| 12 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 13 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 14 | + * See the License for the specific language governing permissions and | ||
| 15 | + * limitations under the License. | ||
| 16 | + */ | ||
| 17 | +#ifndef GE_GE_LOCAL_ENGINE_ENGINE_AICPU_FOLDING_FOLDING_H_ | ||
| 18 | +#define GE_GE_LOCAL_ENGINE_ENGINE_AICPU_FOLDING_FOLDING_H_ | ||
| 19 | + | ||
| 20 | +#include <cstdint> | ||
| 21 | +#include <map> | ||
| 22 | +#include <string> | ||
| 23 | + | ||
| 24 | +#include "graph/utils/op_desc_utils.h" | ||
| 25 | +#include "graph_metadef/register/graph_register.h" | ||
| 26 | + | ||
| 27 | +extern "C" { | ||
| 28 | +__attribute__((visibility("default"))) int32_t InitCpuConstantFoldingNew(ge::HostCpuOp *(*create_fn)()); | ||
| 29 | + | ||
| 30 | +__attribute__((visibility("default"))) int32_t | ||
| 31 | +CpuConstantFoldingComputeNew(const ge::Operator &op, const std::map<std::string, const ge::Tensor> &inputs, | ||
| 32 | + std::map<std::string, ge::Tensor> outputs); | ||
| 33 | +} | ||
| 34 | +#endif // GE_GE_LOCAL_ENGINE_ENGINE_AICPU_FOLDING_FOLDING_H_ | ||
| @@ -0,0 +1,59 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) Huawei Technologies Co., Ltd. 2026-2026. All rights reserved. | ||
| 3 | + * | ||
| 4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 5 | + * you may not use this file except in compliance with the License. | ||
| 6 | + * You may obtain a copy of the License at | ||
| 7 | + * | ||
| 8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 9 | + * | ||
| 10 | + * Unless required by applicable law or agreed to in writing, software | ||
| 11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 13 | + * See the License for the specific language governing permissions and | ||
| 14 | + * limitations under the License. | ||
| 15 | + */ | ||
| 16 | + | ||
| 17 | +#include "host_cpu_kernel_wrapper.h" | ||
| 18 | +#include <unistd.h> | ||
| 19 | +#include <string> | ||
| 20 | +#include "folding.h" | ||
| 21 | +#include "register/host_cpu_context.h" | ||
| 22 | +#include "graph/utils/op_desc_utils.h" | ||
| 23 | +#include "util/aicpu_log.h" | ||
| 24 | + | ||
| 25 | +extern "C" { | ||
| 26 | +FMK_FUNC_HOST_VISIBILITY ge::graphStatus Initialize(const ge::HostCpuContext &ctx) { | ||
| 27 | + (void)ctx; | ||
| 28 | + AICPUE_LOGI("Enter host CPU kernel wrapper initialize"); | ||
| 29 | + int32_t ret = | ||
| 30 | + InitCpuConstantFoldingNew([]() -> ge::HostCpuOp * { return new (std::nothrow) ge::HostCpuKernelWrapperOpV2(); }); | ||
| 31 | + if (ret != 0) { | ||
| 32 | + AICPUE_LOGW("InitCpuConstantFoldingNew run failed, ret: %d", ret); | ||
| 33 | + return ge::GRAPH_FAILED; | ||
| 34 | + } | ||
| 35 | + | ||
| 36 | + AICPUE_LOGI("Host CPU kernel wrapper initialize successfully"); | ||
| 37 | + return ge::GRAPH_SUCCESS; | ||
| 38 | +} | ||
| 39 | +} | ||
| 40 | + | ||
| 41 | +namespace ge { | ||
| 42 | +HostCpuKernelWrapperOpV2::HostCpuKernelWrapperOpV2() = default; | ||
| 43 | + | ||
| 44 | +graphStatus HostCpuKernelWrapperOpV2::Compute(ge::Operator &op, const std::map<std::string, const ge::Tensor> &inputs, | ||
| 45 | + std::map<std::string, ge::Tensor> &outputs) { | ||
| 46 | + AICPUE_LOGI("Enter host CPU kernel wrapper compute"); | ||
| 47 | + | ||
| 48 | + int32_t ret = CpuConstantFoldingComputeNew(op, inputs, outputs); | ||
| 49 | + if (ret != 0) { | ||
| 50 | + AICPUE_LOGW("CpuConstantFoldingComputeNew run failed, ret: %d", ret); | ||
| 51 | + return ge::GRAPH_FAILED; | ||
| 52 | + } | ||
| 53 | + | ||
| 54 | + AICPUE_LOGI("Host CPU kernel wrapper compute successfully"); | ||
| 55 | + return ge::GRAPH_SUCCESS; | ||
| 56 | +} | ||
| 57 | + | ||
| 58 | +REGISTER_HOST_CPU_OP_BUILDER("HostCpuKernelWrapperOpV2", ge::HostCpuKernelWrapperOpV2); | ||
| 59 | +} // namespace ge | ||
| @@ -0,0 +1,30 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) Huawei Technologies Co., Ltd. 2026. All rights reserved. | ||
| 3 | + * | ||
| 4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 5 | + * you may not use this file except in compliance with the License. | ||
| 6 | + * You may obtain a copy of the License at | ||
| 7 | + * | ||
| 8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 9 | + * | ||
| 10 | + * Unless required by applicable law or agreed to in writing, software | ||
| 11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 13 | + * See the License for the specific language governing permissions and | ||
| 14 | + * limitations under the License. | ||
| 15 | + */ | ||
| 16 | +#ifndef GE_GE_LOCAL_ENGINE_ENGINE_HOST_CPU_KERNEL_WRAPPER_H_ | ||
| 17 | +#define GE_GE_LOCAL_ENGINE_ENGINE_HOST_CPU_KERNEL_WRAPPER_H_ | ||
| 18 | + | ||
| 19 | +#include "register/graph_register.h" | ||
| 20 | + | ||
| 21 | +namespace ge { | ||
| 22 | +class HostCpuKernelWrapperOpV2 : public HostCpuOp { | ||
| 23 | + public: | ||
| 24 | + HostCpuKernelWrapperOpV2(); | ||
| 25 | + ~HostCpuKernelWrapperOpV2() override = default; | ||
| 26 | + graphStatus Compute(Operator &op, const std::map<std::string, const ge::Tensor> &inputs, | ||
| 27 | + std::map<std::string, ge::Tensor> &outputs) override; | ||
| 28 | +}; | ||
| 29 | +} // namespace ge | ||
| 30 | +#endif // GE_GE_LOCAL_ENGINE_ENGINE_HOST_CPU_KERNEL_WRAPPER_H_ | ||
| @@ -0,0 +1,25 @@ | |||
| 1 | +# ----------------------------------------------------------------------------------------------------------- | ||
| 2 | +# Copyright (c) 2025 Huawei Technologies Co., Ltd. | ||
| 3 | +# This program is free software, you can redistribute it and/or modify it under the terms and conditions of | ||
| 4 | +# CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 5 | +# Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 6 | +# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, | ||
| 7 | +# INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | +# See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | +# ----------------------------------------------------------------------------------------------------------- | ||
| 10 | + | ||
| 11 | +cmake_minimum_required(VERSION 3.16) | ||
| 12 | + | ||
| 13 | +add_library(constant_folding_ops_stub SHARED | ||
| 14 | + constant_folding_ops_stub.cpp | ||
| 15 | +) | ||
| 16 | + | ||
| 17 | +target_include_directories(constant_folding_ops_stub PRIVATE | ||
| 18 | + ${CMAKE_CURRENT_SOURCE_DIR} | ||
| 19 | +) | ||
| 20 | + | ||
| 21 | +set_target_properties(constant_folding_ops_stub PROPERTIES | ||
| 22 | + OUTPUT_NAME "constant_folding_ops" | ||
| 23 | +) | ||
| 24 | + | ||
| 25 | +target_link_libraries(constant_folding_ops_stub PRIVATE $<BUILD_INTERFACE:ge_intf_pub>) | ||
| @@ -0,0 +1,35 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) Huawei Technologies Co., Ltd. 2024-2024. All rights reserved. | ||
| 3 | + * | ||
| 4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 5 | + * you may not use this file except in compliance with the License. | ||
| 6 | + * You may obtain a copy of the License at | ||
| 7 | + * | ||
| 8 | + * @file constant_folding_ops_stub.cpp | ||
| 9 | + * @brief Stub library for constant_folding_ops (used only at build time). | ||
| 10 | + * | ||
| 11 | + * This file intentionally provides **no real implementations**. | ||
| 12 | + * It only exists so that the AIR repository can be built independently | ||
| 13 | + * without depending on the real constant_folding_ops.so produced by OPP. | ||
| 14 | + * | ||
| 15 | + * At runtime: | ||
| 16 | + * ✅ The real libconstant_folding_ops.so (from OPP) will be loaded first. | ||
| 17 | + * ✅ This stub library will NOT be used. | ||
| 18 | + * | ||
| 19 | + * If this stub is accidentally loaded (extremely unlikely): | ||
| 20 | + * ✅ It still won't crash, because it exports zero symbols. | ||
| 21 | + * | ||
| 22 | + * This file is safe, minimal, and production-friendly. | ||
| 23 | + */ | ||
| 24 | + | ||
| 25 | +namespace aicpu_stub { | ||
| 26 | +// -------------------------------------------------------------- | ||
| 27 | +// Optional: provide a weak dummy symbol as a safety fallback | ||
| 28 | +// -------------------------------------------------------------- | ||
| 29 | +// If your linker prefers at least one exported symbol to build a shared lib, | ||
| 30 | +// this dummy weak function will satisfy it. | ||
| 31 | +// If not needed, it will never be used. | ||
| 32 | +// -------------------------------------------------------------- | ||
| 33 | +__attribute__((weak)) void constant_folding_ops_stub_marker() {} | ||
| 34 | + | ||
| 35 | +} // namespace aicpu_stub | ||
| @@ -41,6 +41,7 @@ | |||
| 41 | <file value="libeager_style_graph_builder_base_static.a" file_type="static"/> | 41 | <file value="libeager_style_graph_builder_base_static.a" file_type="static"/> |
| 42 | <file value="libllm_engine.so" file_type="shared"/> | 42 | <file value="libllm_engine.so" file_type="shared"/> |
| 43 | <file value="libslice.so" file_type="shared"/> | 43 | <file value="libslice.so" file_type="shared"/> |
| 44 | + <file value="libaicpu_const_folding.so" file_type="shared"/> | ||
| 44 | <file value="libengine.so" file_type="shared" dst_path="lib64/plugin/nnengine" install_path="$(TARGET_ENV)/lib64/plugin/nnengine"/> | 45 | <file value="libengine.so" file_type="shared" dst_path="lib64/plugin/nnengine" install_path="$(TARGET_ENV)/lib64/plugin/nnengine"/> |
| 45 | <file value="libhost_cpu_engine.so" file_type="shared" dst_path="lib64/plugin/opskernel" install_path="$(TARGET_ENV)/lib64/plugin/opskernel"/> | 46 | <file value="libhost_cpu_engine.so" file_type="shared" dst_path="lib64/plugin/opskernel" install_path="$(TARGET_ENV)/lib64/plugin/opskernel"/> |
| 46 | <file value="libaicpu_tf_engine.so" file_type="shared" dst_path="lib64/plugin/opskernel" install_path="$(TARGET_ENV)/lib64/plugin/opskernel"/> | 47 | <file value="libaicpu_tf_engine.so" file_type="shared" dst_path="lib64/plugin/opskernel" install_path="$(TARGET_ENV)/lib64/plugin/opskernel"/> |
| @@ -126,6 +126,7 @@ set(cpu_engine_src_files | |||
| 126 | ${cpueng_src_path}/cpu_engine/aicpu_engine/kernel_builder/aicpu_ascend_ops_kernel_builder.cpp | 126 | ${cpueng_src_path}/cpu_engine/aicpu_engine/kernel_builder/aicpu_ascend_ops_kernel_builder.cpp |
| 127 | ${cpueng_src_path}/cpu_engine/common/kernel_builder/cpu_kernel_builder.cpp | 127 | ${cpueng_src_path}/cpu_engine/common/kernel_builder/cpu_kernel_builder.cpp |
| 128 | ${cpueng_src_path}/cpu_engine/common/optimizer/cpu_optimizer.cpp | 128 | ${cpueng_src_path}/cpu_engine/common/optimizer/cpu_optimizer.cpp |
| 129 | + ${cpueng_src_path}/cpu_engine/aicpu_const_folding/folding.cc | ||
| 129 | ) | 130 | ) |
| 130 | 131 | ||
| 131 | set(engine_common_src_test_files st_main.cpp) | 132 | set(engine_common_src_test_files st_main.cpp) |
| @@ -153,6 +154,7 @@ else () | |||
| 153 | ${CMAKE_BINARY_DIR}/proto/aicpu | 154 | ${CMAKE_BINARY_DIR}/proto/aicpu |
| 154 | ${CMAKE_BINARY_DIR}/proto/aicpu/proto | 155 | ${CMAKE_BINARY_DIR}/proto/aicpu/proto |
| 155 | ${METADEF_DIR}/inc | 156 | ${METADEF_DIR}/inc |
| 157 | + ${TOP_DIR}/inc/aicpu/cpu_kernels | ||
| 156 | ${TOP_DIR}/inc/external/aicpu | 158 | ${TOP_DIR}/inc/external/aicpu |
| 157 | ) | 159 | ) |
| 158 | endif () | 160 | endif () |
| @@ -164,6 +166,7 @@ set(cpu_engine_src_test_files | |||
| 164 | cpu_engine/aicpu_optimizer_st.cpp | 166 | cpu_engine/aicpu_optimizer_st.cpp |
| 165 | cpu_engine/aicpu_kernel_builder_st.cpp | 167 | cpu_engine/aicpu_kernel_builder_st.cpp |
| 166 | cpu_engine/aicpu_pass_st.cpp | 168 | cpu_engine/aicpu_pass_st.cpp |
| 169 | + cpu_engine/folding_st.cpp | ||
| 167 | ) | 170 | ) |
| 168 | 171 | ||
| 169 | set(host_engine_src_files | 172 | set(host_engine_src_files |
| @@ -196,6 +199,7 @@ add_executable(cpu_engine_stest | |||
| 196 | ${cpu_engine_src_files} | 199 | ${cpu_engine_src_files} |
| 197 | ${cpu_engine_src_test_files} | 200 | ${cpu_engine_src_test_files} |
| 198 | ${engine_common_stub_src_files} | 201 | ${engine_common_stub_src_files} |
| 202 | + ${engine_common_stub_src_path}/stub/aicpu/aicpu_stub.cpp | ||
| 199 | ) | 203 | ) |
| 200 | 204 | ||
| 201 | add_executable(host_engine_stest | 205 | add_executable(host_engine_stest |
| @@ -0,0 +1,73 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2025 Huawei Technologies Co., Ltd. | ||
| 3 | + * This program is free software, you can redistribute it and/or modify it under the terms and conditions of | ||
| 4 | + * CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 5 | + * Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 6 | + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, | ||
| 7 | + * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | + * See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | + */ | ||
| 10 | + | ||
| 11 | +#include <gtest/gtest.h> | ||
| 12 | +#include "aicpu_const_folding/folding.h" | ||
| 13 | +#include "stub.h" | ||
| 14 | + | ||
| 15 | +TEST(AicpuConstFoldingST, InitCpuConstantFoldingNew_001) { | ||
| 16 | + int32_t ret = InitCpuConstantFoldingNew([]() -> ge::HostCpuOp * { return new (std::nothrow) ge::HostCpuTestOp(); }); | ||
| 17 | + ASSERT_EQ(ret, 0); | ||
| 18 | +} | ||
| 19 | + | ||
| 20 | +TEST(AicpuConstFoldingST, CpuConstantFoldingComputeNew_001) { | ||
| 21 | + ge::Operator op("testop"); | ||
| 22 | + auto op_desc = ge::OpDescUtils::GetOpDescFromOperator(op); | ||
| 23 | + ge::GeTensorDesc testTensorDesc; | ||
| 24 | + ge::GeShape testgeshape; | ||
| 25 | + testgeshape.SetDimNum(2); | ||
| 26 | + testTensorDesc.SetShape(testgeshape); | ||
| 27 | + op_desc->AddInputDesc("testop", testTensorDesc); | ||
| 28 | + op_desc->AddOutputDesc("testop", testTensorDesc); | ||
| 29 | + ge::AscendString attr1 = "attr1"; | ||
| 30 | + op.SetAttr("testattr1", attr1); | ||
| 31 | + float32_t attr2 = 0; | ||
| 32 | + op.SetAttr("testattr2", attr2); | ||
| 33 | + int32_t attr3 = 0; | ||
| 34 | + op.SetAttr("attr3", attr3); | ||
| 35 | + bool attr4 = true; | ||
| 36 | + op.SetAttr("attr4", attr4); | ||
| 37 | + ge::DataType attr5 = ge::DT_FLOAT; | ||
| 38 | + op.SetAttr("attr5", attr5); | ||
| 39 | + ge::Tensor attr6; | ||
| 40 | + op.SetAttr("attr6", attr6); | ||
| 41 | + | ||
| 42 | + std::vector<ge::AscendString> attrList1; | ||
| 43 | + attrList1.push_back("attrList1"); | ||
| 44 | + op.SetAttr("attrList1", attrList1); | ||
| 45 | + std::vector<float32_t> attrList2; | ||
| 46 | + attrList2.push_back(0); | ||
| 47 | + op.SetAttr("attrList2", attrList2); | ||
| 48 | + std::vector<int32_t> attrList3; | ||
| 49 | + attrList3.push_back(0); | ||
| 50 | + op.SetAttr("attrList3", attrList3); | ||
| 51 | + std::vector<bool> attrList4; | ||
| 52 | + attrList4.push_back(true); | ||
| 53 | + op.SetAttr("attrList4", attrList4); | ||
| 54 | + std::vector<ge::DataType> attrList5; | ||
| 55 | + attrList5.push_back(ge::DT_FLOAT); | ||
| 56 | + op.SetAttr("attrList5", attrList5); | ||
| 57 | + std::vector<ge::Tensor> attrList6; | ||
| 58 | + ge::Tensor testtensor; | ||
| 59 | + attrList6.push_back(testtensor); | ||
| 60 | + op.SetAttr("attrList6", attrList6); | ||
| 61 | + std::vector<std::vector<int64_t>> attrList7; | ||
| 62 | + std::vector<int64_t> testvec; | ||
| 63 | + testvec.push_back(0); | ||
| 64 | + attrList7.push_back(testvec); | ||
| 65 | + op.SetAttr("attrList7", attrList7); | ||
| 66 | + std::map<std::string, const ge::Tensor> inputs; | ||
| 67 | + std::map<std::string, ge::Tensor> outputs; | ||
| 68 | + ge::Tensor testTensor; | ||
| 69 | + inputs.emplace("testop", testTensor); | ||
| 70 | + outputs.emplace("testop", testTensor); | ||
| 71 | + int32_t ret = CpuConstantFoldingComputeNew(op, inputs, outputs); | ||
| 72 | + ASSERT_EQ(ret, 0); | ||
| 73 | +} | ||
| @@ -18,6 +18,7 @@ set(engine_common_stub_files | |||
| 18 | ${CMAKE_CURRENT_SOURCE_DIR}/platform_info_stub.cpp | 18 | ${CMAKE_CURRENT_SOURCE_DIR}/platform_info_stub.cpp |
| 19 | ${CMAKE_CURRENT_SOURCE_DIR}/stub.cpp | 19 | ${CMAKE_CURRENT_SOURCE_DIR}/stub.cpp |
| 20 | ${CMAKE_CURRENT_SOURCE_DIR}/util/util_stub.cpp | 20 | ${CMAKE_CURRENT_SOURCE_DIR}/util/util_stub.cpp |
| 21 | + ${CMAKE_CURRENT_SOURCE_DIR}/aicpu/aicpu_stub.cpp | ||
| 21 | ${PROTO_HDRS} | 22 | ${PROTO_HDRS} |
| 22 | ) | 23 | ) |
| 23 | 24 | ||
| @@ -58,6 +59,7 @@ target_link_libraries(stub_for_aicpu PRIVATE | |||
| 58 | runtime_aicpu_stub | 59 | runtime_aicpu_stub |
| 59 | ascend_protobuf | 60 | ascend_protobuf |
| 60 | json | 61 | json |
| 62 | + aicpu_headers | ||
| 61 | cce_headers | 63 | cce_headers |
| 62 | ) | 64 | ) |
| 63 | 65 | ||
| @@ -0,0 +1,74 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2025 Huawei Technologies Co., Ltd. | ||
| 3 | + * This program is free software, you can redistribute it and/or modify it under the terms and conditions of | ||
| 4 | + * CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 5 | + * Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 6 | + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, | ||
| 7 | + * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | + * See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | + */ | ||
| 10 | + | ||
| 11 | +#include "cpu_context.h" | ||
| 12 | +#include "cpu_kernel_register.h" | ||
| 13 | +#include "cpu_kernel.h" | ||
| 14 | + | ||
| 15 | +namespace aicpu { | ||
| 16 | +CpuKernelContext::CpuKernelContext(DeviceType type) { | ||
| 17 | + (void)type; | ||
| 18 | +} | ||
| 19 | + | ||
| 20 | +uint32_t CpuKernelContext::Init(void *nodeDef) { | ||
| 21 | + (void)nodeDef; | ||
| 22 | + return 0; | ||
| 23 | +} | ||
| 24 | + | ||
| 25 | +CpuKernelRegister &CpuKernelRegister::Instance() { | ||
| 26 | + static CpuKernelRegister instance; | ||
| 27 | + return instance; | ||
| 28 | +} | ||
| 29 | + | ||
| 30 | +class TestCpuKernel : public CpuKernel { | ||
| 31 | + public: | ||
| 32 | + TestCpuKernel() = default; | ||
| 33 | + ~TestCpuKernel() = default; | ||
| 34 | + uint32_t Compute(CpuKernelContext &ctx) override { | ||
| 35 | + return 0; | ||
| 36 | + }; | ||
| 37 | +}; | ||
| 38 | + | ||
| 39 | +std::shared_ptr<CpuKernel> CpuKernelRegister::GetCpuKernel(const std::string &opType) { | ||
| 40 | + std::shared_ptr<CpuKernel> testCpuKernel = MakeShared<TestCpuKernel>(); | ||
| 41 | + return testCpuKernel; | ||
| 42 | +} | ||
| 43 | + | ||
| 44 | +std::shared_ptr<CpuKernel> CpuKernelRegister::GetCpuKernelV2(const std::string &opType) { | ||
| 45 | + std::shared_ptr<CpuKernel> testCpuKernel = MakeShared<TestCpuKernel>(); | ||
| 46 | + return testCpuKernel; | ||
| 47 | +} | ||
| 48 | + | ||
| 49 | +bool CpuKernelRegister::IsRegisteredV2(const std::string &opType) const { | ||
| 50 | + (void)opType; | ||
| 51 | + return true; | ||
| 52 | +} | ||
| 53 | + | ||
| 54 | +uint32_t CpuKernelRegister::RunCpuKernel(CpuKernelContext &ctx) { | ||
| 55 | + return 0; | ||
| 56 | +} | ||
| 57 | + | ||
| 58 | +uint32_t CpuKernelRegister::RunCpuKernelV2(CpuKernelContext &ctx) { | ||
| 59 | + return 0; | ||
| 60 | +} | ||
| 61 | + | ||
| 62 | +std::vector<std::string> CpuKernelRegister::GetAllRegisteredOpTypes() const { | ||
| 63 | + std::vector<std::string> ret; | ||
| 64 | + ret.push_back("testop"); | ||
| 65 | + return ret; | ||
| 66 | +} | ||
| 67 | + | ||
| 68 | +std::vector<std::string> CpuKernelRegister::GetAllRegisteredOpTypesV2() const { | ||
| 69 | + std::vector<std::string> ret; | ||
| 70 | + ret.push_back("testopV2"); | ||
| 71 | + return ret; | ||
| 72 | +} | ||
| 73 | + | ||
| 74 | +} // namespace aicpu | ||
| @@ -129,6 +129,7 @@ set(cpu_engine_src_files | |||
| 129 | ${engine_src_path}/cpu_engine/aicpu_engine/kernel_builder/aicpu_kernel_builder.cpp | 129 | ${engine_src_path}/cpu_engine/aicpu_engine/kernel_builder/aicpu_kernel_builder.cpp |
| 130 | ${engine_src_path}/cpu_engine/common/kernel_builder/cpu_kernel_builder.cpp | 130 | ${engine_src_path}/cpu_engine/common/kernel_builder/cpu_kernel_builder.cpp |
| 131 | ${engine_src_path}/cpu_engine/common/optimizer/cpu_optimizer.cpp | 131 | ${engine_src_path}/cpu_engine/common/optimizer/cpu_optimizer.cpp |
| 132 | + ${engine_src_path}/cpu_engine/aicpu_const_folding/folding.cc | ||
| 132 | ) | 133 | ) |
| 133 | 134 | ||
| 134 | if (BUILD_OPEN_PROJECT OR ENABLE_OPEN_SRC) | 135 | if (BUILD_OPEN_PROJECT OR ENABLE_OPEN_SRC) |
| @@ -154,6 +155,7 @@ else () | |||
| 154 | ${CMAKE_BINARY_DIR}/proto/aicpu | 155 | ${CMAKE_BINARY_DIR}/proto/aicpu |
| 155 | ${CMAKE_BINARY_DIR}/proto/aicpu/proto | 156 | ${CMAKE_BINARY_DIR}/proto/aicpu/proto |
| 156 | ${METADEF_DIR}/inc | 157 | ${METADEF_DIR}/inc |
| 158 | + ${TOP_DIR}/inc/aicpu/cpu_kernels | ||
| 157 | ${TOP_DIR}/inc/external/aicpu | 159 | ${TOP_DIR}/inc/external/aicpu |
| 158 | ) | 160 | ) |
| 159 | endif () | 161 | endif () |
| @@ -165,6 +167,7 @@ set(cpu_engine_src_test_files | |||
| 165 | cpu_engine/aicpu_optimizer_ut.cpp | 167 | cpu_engine/aicpu_optimizer_ut.cpp |
| 166 | cpu_engine/aicpu_kernel_builder_ut.cpp | 168 | cpu_engine/aicpu_kernel_builder_ut.cpp |
| 167 | cpu_engine/aicpu_pass_ut.cpp | 169 | cpu_engine/aicpu_pass_ut.cpp |
| 170 | + cpu_engine/folding_ut.cpp | ||
| 168 | ) | 171 | ) |
| 169 | 172 | ||
| 170 | set(host_engine_src_files | 173 | set(host_engine_src_files |
| @@ -198,6 +201,7 @@ add_executable(cpu_engine_utest | |||
| 198 | ${cpu_engine_src_files} | 201 | ${cpu_engine_src_files} |
| 199 | ${cpu_engine_src_test_files} | 202 | ${cpu_engine_src_test_files} |
| 200 | ${engine_common_stub_src_files} | 203 | ${engine_common_stub_src_files} |
| 204 | + ${engine_common_stub_src_path}/stub/aicpu/aicpu_stub.cpp | ||
| 201 | ) | 205 | ) |
| 202 | 206 | ||
| 203 | add_executable(host_engine_utest | 207 | add_executable(host_engine_utest |
| @@ -0,0 +1,265 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2025 Huawei Technologies Co., Ltd. | ||
| 3 | + * This program is free software, you can redistribute it and/or modify it under the terms and conditions of | ||
| 4 | + * CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 5 | + * Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 6 | + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, | ||
| 7 | + * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | + * See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | + */ | ||
| 10 | + | ||
| 11 | +#include <gtest/gtest.h> | ||
| 12 | +#include <cstdlib> | ||
| 13 | +#include <sys/stat.h> | ||
| 14 | +#include <sys/types.h> | ||
| 15 | +#include <unistd.h> | ||
| 16 | +#include <fstream> | ||
| 17 | +#include <mutex> | ||
| 18 | +#include "aicpu_const_folding/folding.h" | ||
| 19 | +#include "stub.h" | ||
| 20 | + | ||
| 21 | +namespace { | ||
| 22 | +std::mutex &GetEnvMutex() { | ||
| 23 | + static std::mutex env_mutex; | ||
| 24 | + return env_mutex; | ||
| 25 | +} | ||
| 26 | + | ||
| 27 | +bool ReadEnvSafe(const char *name, std::string &value) { | ||
| 28 | + std::lock_guard<std::mutex> guard(GetEnvMutex()); | ||
| 29 | + const char *raw = std::getenv(name); | ||
| 30 | + if (raw == nullptr) { | ||
| 31 | + return false; | ||
| 32 | + } | ||
| 33 | + value.assign(raw); | ||
| 34 | + return true; | ||
| 35 | +} | ||
| 36 | + | ||
| 37 | +void SetEnvSafe(const char *name, const char *value, int overwrite) { | ||
| 38 | + std::lock_guard<std::mutex> guard(GetEnvMutex()); | ||
| 39 | + (void)setenv(name, value, overwrite); | ||
| 40 | +} | ||
| 41 | + | ||
| 42 | +void UnsetEnvSafe(const char *name) { | ||
| 43 | + std::lock_guard<std::mutex> guard(GetEnvMutex()); | ||
| 44 | + (void)unsetenv(name); | ||
| 45 | +} | ||
| 46 | + | ||
| 47 | +void SetAllTestAttrs(ge::Operator &op) { | ||
| 48 | + ge::AscendString attr1 = "attr1"; | ||
| 49 | + op.SetAttr("testattr1", attr1); | ||
| 50 | + float32_t attr2 = 0; | ||
| 51 | + op.SetAttr("testattr2", attr2); | ||
| 52 | + int32_t attr3 = 0; | ||
| 53 | + op.SetAttr("attr3", attr3); | ||
| 54 | + bool attr4 = true; | ||
| 55 | + op.SetAttr("attr4", attr4); | ||
| 56 | + ge::DataType attr5 = ge::DT_FLOAT; | ||
| 57 | + op.SetAttr("attr5", attr5); | ||
| 58 | + ge::Tensor attr6; | ||
| 59 | + op.SetAttr("attr6", attr6); | ||
| 60 | + | ||
| 61 | + std::vector<ge::AscendString> attrList1; | ||
| 62 | + attrList1.push_back("attrList1"); | ||
| 63 | + op.SetAttr("attrList1", attrList1); | ||
| 64 | + std::vector<float32_t> attrList2; | ||
| 65 | + attrList2.push_back(0); | ||
| 66 | + op.SetAttr("attrList2", attrList2); | ||
| 67 | + std::vector<int32_t> attrList3; | ||
| 68 | + attrList3.push_back(0); | ||
| 69 | + op.SetAttr("attrList3", attrList3); | ||
| 70 | + std::vector<bool> attrList4; | ||
| 71 | + attrList4.push_back(true); | ||
| 72 | + op.SetAttr("attrList4", attrList4); | ||
| 73 | + std::vector<ge::DataType> attrList5; | ||
| 74 | + attrList5.push_back(ge::DT_FLOAT); | ||
| 75 | + op.SetAttr("attrList5", attrList5); | ||
| 76 | + std::vector<ge::Tensor> attrList6; | ||
| 77 | + ge::Tensor testtensor; | ||
| 78 | + attrList6.push_back(testtensor); | ||
| 79 | + op.SetAttr("attrList6", attrList6); | ||
| 80 | + std::vector<std::vector<int64_t>> attrList7; | ||
| 81 | + std::vector<int64_t> testvec; | ||
| 82 | + testvec.push_back(0); | ||
| 83 | + attrList7.push_back(testvec); | ||
| 84 | + op.SetAttr("attrList7", attrList7); | ||
| 85 | +} | ||
| 86 | +} // namespace | ||
| 87 | + | ||
| 88 | +class AicpuConstFoldingTest : public ::testing::Test { | ||
| 89 | + protected: | ||
| 90 | + void SetUp() override { | ||
| 91 | + has_saved_home_path_ = ReadEnvSafe("ASCEND_HOME_PATH", saved_home_path_); | ||
| 92 | + } | ||
| 93 | + void TearDown() override { | ||
| 94 | + if (has_saved_home_path_) { | ||
| 95 | + SetEnvSafe("ASCEND_HOME_PATH", saved_home_path_.c_str(), 1); | ||
| 96 | + } else { | ||
| 97 | + UnsetEnvSafe("ASCEND_HOME_PATH"); | ||
| 98 | + } | ||
| 99 | + } | ||
| 100 | + std::string saved_home_path_; | ||
| 101 | + bool has_saved_home_path_ = false; | ||
| 102 | +}; | ||
| 103 | + | ||
| 104 | +TEST_F(AicpuConstFoldingTest, InitCpuConstantFoldingNew_Success) { | ||
| 105 | + setenv("ASCEND_HOME_PATH", "/tmp", 1); | ||
| 106 | + int32_t ret = InitCpuConstantFoldingNew([]() -> ge::HostCpuOp * { return new (std::nothrow) ge::HostCpuTestOp(); }); | ||
| 107 | + ASSERT_EQ(ret, 0); | ||
| 108 | +} | ||
| 109 | + | ||
| 110 | +TEST_F(AicpuConstFoldingTest, InitCpuConstantFoldingNew_NoEnvFail) { | ||
| 111 | + unsetenv("ASCEND_HOME_PATH"); | ||
| 112 | + int32_t ret = InitCpuConstantFoldingNew([]() -> ge::HostCpuOp * { return new (std::nothrow) ge::HostCpuTestOp(); }); | ||
| 113 | + ASSERT_EQ(ret, -1); | ||
| 114 | +} | ||
| 115 | + | ||
| 116 | +TEST_F(AicpuConstFoldingTest, InitCpuConstantFoldingNew_LoadSoTraversal) { | ||
| 117 | + std::string tmp_dir = "/tmp/test_folding_ut_" + std::to_string(getpid()); | ||
| 118 | + std::string host_cpu_dir = tmp_dir + "/opp/built-in/op_impl/host_cpu/"; | ||
| 119 | + std::string cmd_mkdir = "mkdir -p " + host_cpu_dir; | ||
| 120 | + ASSERT_EQ(system(cmd_mkdir.c_str()), 0); | ||
| 121 | + | ||
| 122 | + // Create files matching libopconstant_folding_*.so pattern | ||
| 123 | + std::ofstream(host_cpu_dir + "libopconstant_folding_math.so").close(); | ||
| 124 | + std::ofstream(host_cpu_dir + "libopconstant_folding_nn.so").close(); | ||
| 125 | + std::ofstream(host_cpu_dir + "libopconstant_folding_cv.so").close(); | ||
| 126 | + // Create files that should NOT match the pattern | ||
| 127 | + std::ofstream(host_cpu_dir + "libother.so").close(); | ||
| 128 | + std::ofstream(host_cpu_dir + "libmath_constant_folding_ops.so").close(); | ||
| 129 | + std::ofstream(host_cpu_dir + "notlib_constant_folding_ops.so").close(); | ||
| 130 | + // libconstant_folding_ops.so should be excluded (loaded by host_cpu_engine separately) | ||
| 131 | + std::ofstream(host_cpu_dir + "libconstant_folding_ops.so").close(); | ||
| 132 | + | ||
| 133 | + setenv("ASCEND_HOME_PATH", tmp_dir.c_str(), 1); | ||
| 134 | + int32_t ret = InitCpuConstantFoldingNew([]() -> ge::HostCpuOp * { return new (std::nothrow) ge::HostCpuTestOp(); }); | ||
| 135 | + // Init succeeds even if dlopen fails on empty .so files (just warns) | ||
| 136 | + ASSERT_EQ(ret, 0); | ||
| 137 | + | ||
| 138 | + std::string cmd_rm = "rm -rf " + tmp_dir; | ||
| 139 | + system(cmd_rm.c_str()); | ||
| 140 | +} | ||
| 141 | + | ||
| 142 | +TEST_F(AicpuConstFoldingTest, InitCpuConstantFoldingNew_PathWithTrailingSlash) { | ||
| 143 | + setenv("ASCEND_HOME_PATH", "/tmp/", 1); | ||
| 144 | + int32_t ret = InitCpuConstantFoldingNew([]() -> ge::HostCpuOp * { return new (std::nothrow) ge::HostCpuTestOp(); }); | ||
| 145 | + ASSERT_EQ(ret, 0); | ||
| 146 | +} | ||
| 147 | + | ||
| 148 | +TEST_F(AicpuConstFoldingTest, CpuConstantFoldingComputeNew_Success) { | ||
| 149 | + setenv("ASCEND_HOME_PATH", "/tmp", 1); | ||
| 150 | + InitCpuConstantFoldingNew([]() -> ge::HostCpuOp * { return new (std::nothrow) ge::HostCpuTestOp(); }); | ||
| 151 | + | ||
| 152 | + ge::Operator op("testop"); | ||
| 153 | + auto op_desc = ge::OpDescUtils::GetOpDescFromOperator(op); | ||
| 154 | + ge::GeTensorDesc testTensorDesc; | ||
| 155 | + ge::GeShape testgeshape; | ||
| 156 | + testgeshape.SetDimNum(2); | ||
| 157 | + testTensorDesc.SetShape(testgeshape); | ||
| 158 | + op_desc->AddInputDesc("testop", testTensorDesc); | ||
| 159 | + op_desc->AddOutputDesc("testop", testTensorDesc); | ||
| 160 | + | ||
| 161 | + SetAllTestAttrs(op); | ||
| 162 | + | ||
| 163 | + std::map<std::string, const ge::Tensor> inputs; | ||
| 164 | + std::map<std::string, ge::Tensor> outputs; | ||
| 165 | + ge::Tensor testTensor; | ||
| 166 | + inputs.emplace("testop", testTensor); | ||
| 167 | + outputs.emplace("testop", testTensor); | ||
| 168 | + int32_t ret = CpuConstantFoldingComputeNew(op, inputs, outputs); | ||
| 169 | + ASSERT_EQ(ret, 0); | ||
| 170 | +} | ||
| 171 | + | ||
| 172 | +TEST_F(AicpuConstFoldingTest, CpuConstantFoldingComputeNew_MissingInput) { | ||
| 173 | + setenv("ASCEND_HOME_PATH", "/tmp", 1); | ||
| 174 | + InitCpuConstantFoldingNew([]() -> ge::HostCpuOp * { return new (std::nothrow) ge::HostCpuTestOp(); }); | ||
| 175 | + | ||
| 176 | + ge::Operator op("testop"); | ||
| 177 | + auto op_desc = ge::OpDescUtils::GetOpDescFromOperator(op); | ||
| 178 | + ge::GeTensorDesc testTensorDesc; | ||
| 179 | + op_desc->AddInputDesc("input1", testTensorDesc); | ||
| 180 | + op_desc->AddOutputDesc("output1", testTensorDesc); | ||
| 181 | + // Deliberately not providing required input | ||
| 182 | + std::map<std::string, const ge::Tensor> inputs; | ||
| 183 | + std::map<std::string, ge::Tensor> outputs; | ||
| 184 | + ge::Tensor testTensor; | ||
| 185 | + outputs.emplace("output1", testTensor); | ||
| 186 | + int32_t ret = CpuConstantFoldingComputeNew(op, inputs, outputs); | ||
| 187 | + ASSERT_EQ(ret, -1); | ||
| 188 | +} | ||
| 189 | + | ||
| 190 | +TEST_F(AicpuConstFoldingTest, CpuConstantFoldingComputeNew_MissingOutput) { | ||
| 191 | + setenv("ASCEND_HOME_PATH", "/tmp", 1); | ||
| 192 | + InitCpuConstantFoldingNew([]() -> ge::HostCpuOp * { return new (std::nothrow) ge::HostCpuTestOp(); }); | ||
| 193 | + | ||
| 194 | + ge::Operator op("testop"); | ||
| 195 | + auto op_desc = ge::OpDescUtils::GetOpDescFromOperator(op); | ||
| 196 | + ge::GeTensorDesc testTensorDesc; | ||
| 197 | + op_desc->AddInputDesc("input1", testTensorDesc); | ||
| 198 | + op_desc->AddOutputDesc("output1", testTensorDesc); | ||
| 199 | + std::map<std::string, const ge::Tensor> inputs; | ||
| 200 | + std::map<std::string, ge::Tensor> outputs; | ||
| 201 | + ge::Tensor testTensor; | ||
| 202 | + inputs.emplace("input1", testTensor); | ||
| 203 | + // Deliberately not providing required output | ||
| 204 | + int32_t ret = CpuConstantFoldingComputeNew(op, inputs, outputs); | ||
| 205 | + ASSERT_EQ(ret, -1); | ||
| 206 | +} | ||
| 207 | + | ||
| 208 | +// 验证: 多个 libopconstant_folding_*.so 共存场景下, Init 不会因为 | ||
| 209 | +// 每个 so 都有独立的 CpuKernelRegister 单例而发生 this/成员函数错配的 | ||
| 210 | +// coredump, Compute 回落到 V1 路径仍能正常工作. | ||
| 211 | +TEST_F(AicpuConstFoldingTest, InitCpuConstantFoldingNew_MultiOpsSoNoCrash) { | ||
| 212 | + std::string tmp_dir = "/tmp/test_folding_ut_multi_" + std::to_string(getpid()); | ||
| 213 | + std::string host_cpu_dir = tmp_dir + "/opp/built-in/op_impl/host_cpu/"; | ||
| 214 | + std::string cmd_mkdir = "mkdir -p " + host_cpu_dir; | ||
| 215 | + ASSERT_EQ(system(cmd_mkdir.c_str()), 0); | ||
| 216 | + | ||
| 217 | + std::ofstream(host_cpu_dir + "libopconstant_folding_math.so").close(); | ||
| 218 | + std::ofstream(host_cpu_dir + "libopconstant_folding_nn.so").close(); | ||
| 219 | + std::ofstream(host_cpu_dir + "libopconstant_folding_cv.so").close(); | ||
| 220 | + | ||
| 221 | + setenv("ASCEND_HOME_PATH", tmp_dir.c_str(), 1); | ||
| 222 | + int32_t init_ret = | ||
| 223 | + InitCpuConstantFoldingNew([]() -> ge::HostCpuOp * { return new (std::nothrow) ge::HostCpuTestOp(); }); | ||
| 224 | + ASSERT_EQ(init_ret, 0); | ||
| 225 | + | ||
| 226 | + ge::Operator op("testop"); | ||
| 227 | + auto op_desc = ge::OpDescUtils::GetOpDescFromOperator(op); | ||
| 228 | + ge::GeTensorDesc tensor_desc; | ||
| 229 | + op_desc->AddInputDesc("testop", tensor_desc); | ||
| 230 | + op_desc->AddOutputDesc("testop", tensor_desc); | ||
| 231 | + std::map<std::string, const ge::Tensor> inputs; | ||
| 232 | + std::map<std::string, ge::Tensor> outputs; | ||
| 233 | + ge::Tensor t; | ||
| 234 | + inputs.emplace("testop", t); | ||
| 235 | + outputs.emplace("testop", t); | ||
| 236 | + int32_t rc = CpuConstantFoldingComputeNew(op, inputs, outputs); | ||
| 237 | + ASSERT_EQ(rc, 0); | ||
| 238 | + | ||
| 239 | + std::string cmd_rm = "rm -rf " + tmp_dir; | ||
| 240 | + (void)system(cmd_rm.c_str()); | ||
| 241 | +} | ||
| 242 | + | ||
| 243 | +// 验证: 当 V2 不命中时, Compute 会回退到本地 V1 GetCpuKernel 路径. | ||
| 244 | +// 覆盖 opbase 侧 "GetCpuKernelV2 不再内建回退" 后 ge 侧的外部兜底链路. | ||
| 245 | +TEST_F(AicpuConstFoldingTest, CpuConstantFoldingComputeNew_V2Miss_FallbackV1) { | ||
| 246 | + setenv("ASCEND_HOME_PATH", "/tmp", 1); | ||
| 247 | + int32_t init_ret = | ||
| 248 | + InitCpuConstantFoldingNew([]() -> ge::HostCpuOp * { return new (std::nothrow) ge::HostCpuTestOp(); }); | ||
| 249 | + ASSERT_EQ(init_ret, 0); | ||
| 250 | + | ||
| 251 | + // stub 里 V1 的 GetCpuKernel 总返回非空, V2 反向索引里不会有 "unknown_op", | ||
| 252 | + // Compute 应当走 V1 路径返回 0. | ||
| 253 | + ge::Operator op("unknown_op"); | ||
| 254 | + auto op_desc = ge::OpDescUtils::GetOpDescFromOperator(op); | ||
| 255 | + ge::GeTensorDesc tensor_desc; | ||
| 256 | + op_desc->AddInputDesc("unknown_op", tensor_desc); | ||
| 257 | + op_desc->AddOutputDesc("unknown_op", tensor_desc); | ||
| 258 | + std::map<std::string, const ge::Tensor> inputs; | ||
| 259 | + std::map<std::string, ge::Tensor> outputs; | ||
| 260 | + ge::Tensor t; | ||
| 261 | + inputs.emplace("unknown_op", t); | ||
| 262 | + outputs.emplace("unknown_op", t); | ||
| 263 | + int32_t rc = CpuConstantFoldingComputeNew(op, inputs, outputs); | ||
| 264 | + ASSERT_EQ(rc, 0); | ||
| 265 | +} | ||