已合并
【feat】: HostCPU 融合 Codegen 迁移至标准 CustomOp #4669
ZhuXincheng创建于 6 天前
【feat】: HostCPU 融合 Codegen 迁移至标准 CustomOp #4669
已合并
共 38 个文件变更+1662-4548
| @@ -606,7 +606,9 @@ Status ModelHelper::SaveAutofuseSoBin(const GeRootModelPtr &ge_root_model) { | |||
| 606 | if (bin_file_buffer != nullptr) { | 606 | if (bin_file_buffer != nullptr) { |
| 607 | GELOGD("bin_file_buffer already exists, sync autofuse so to op_so_store_."); | 607 | GELOGD("bin_file_buffer already exists, sync autofuse so to op_so_store_."); |
| 608 | for (const auto &bin_entry : *bin_file_buffer) { | 608 | for (const auto &bin_entry : *bin_file_buffer) { |
| 609 | - op_so_store_.AddKernel(bin_entry.second); | 609 | + if ((bin_entry.second != nullptr) && (bin_entry.second->GetSoBinType() == SoBinType::kAutofuse)) { |
| 610 | + op_so_store_.AddKernel(bin_entry.second); | ||
| 611 | + } | ||
| 610 | } | 612 | } |
| 611 | return SUCCESS; | 613 | return SUCCESS; |
| 612 | } | 614 | } |
| @@ -623,8 +625,21 @@ Status ModelHelper::SaveCustomOpSoBin(const GeRootModelPtr &ge_root_model) { | |||
| 623 | if (!OpSoStoreUtils::IsSoBinType(ge_root_model->GetSoInOmFlag(), SoBinType::kCustomOp)) { | 625 | if (!OpSoStoreUtils::IsSoBinType(ge_root_model->GetSoInOmFlag(), SoBinType::kCustomOp)) { |
| 624 | return SUCCESS; | 626 | return SUCCESS; |
| 625 | } | 627 | } |
| 628 | + auto root_graph = ge_root_model->GetRootGraph(); | ||
| 629 | + GE_ASSERT_NOTNULL(root_graph); | ||
| 630 | + size_t embedded_so_num = 0U; | ||
| 631 | + const auto so_buffer = root_graph->GetExtAttr<std::map<std::string, ge::OpSoBinPtr>>("bin_file_buffer"); | ||
| 632 | + if (so_buffer != nullptr) { | ||
| 633 | + for (const auto &entry : *so_buffer) { | ||
| 634 | + if ((entry.second != nullptr) && (entry.second->GetSoBinType() == SoBinType::kCustomOp)) { | ||
| 635 | + op_so_store_.AddKernel(entry.second); | ||
| 636 | + ++embedded_so_num; | ||
| 637 | + } | ||
| 638 | + } | ||
| 639 | + } | ||
| 626 | GE_ASSERT_SUCCESS(LoadAndStoreOppSo(ge_root_model->GetCustomOpSoSet(), SoBinType::kCustomOp)); | 640 | GE_ASSERT_SUCCESS(LoadAndStoreOppSo(ge_root_model->GetCustomOpSoSet(), SoBinType::kCustomOp)); |
| 627 | - GELOGI("[CustomOp]Save %zu custom op so to OpSoStore success.", ge_root_model->GetCustomOpSoSet().size()); | 641 | + GELOGI("[CustomOp]Save %zu path-based and %zu embedded custom op so to OpSoStore success.", |
| 642 | + ge_root_model->GetCustomOpSoSet().size(), embedded_so_num); | ||
| 628 | return SUCCESS; | 643 | return SUCCESS; |
| 629 | } | 644 | } |
| 630 | 645 | ||
| @@ -32,6 +32,8 @@ | |||
| 32 | 32 | ||
| 33 | 33 | ||
| 34 | 34 | ||
| 35 | + | ||
| 36 | + | ||
| 35 | 37 | ||
| 36 | 38 | ||
| 37 | namespace ge { | 39 | namespace ge { |
| @@ -171,6 +173,37 @@ Status CollectCustomOpTypesFromGraph(const ComputeGraphPtr &graph, const CustomO | |||
| 171 | } | 173 | } |
| 172 | return SUCCESS; | 174 | return SUCCESS; |
| 173 | } | 175 | } |
| 176 | + | ||
| 177 | +bool IsEmbeddedHostCpuFusionSo(const ComputeGraphPtr &root_graph, const std::string &op_type) { | ||
| 178 | + if (root_graph == nullptr) { | ||
| 179 | + return false; | ||
| 180 | + } | ||
| 181 | + const auto so_buffer = root_graph->GetExtAttr<std::map<std::string, OpSoBinPtr>>("bin_file_buffer"); | ||
| 182 | + if (so_buffer == nullptr) { | ||
| 183 | + return false; | ||
| 184 | + } | ||
| 185 | + const std::string so_key = std::string(kFusedHostCpuSoVendor) + "/lib" + op_type + ".so"; | ||
| 186 | + const auto so_it = so_buffer->find(so_key); | ||
| 187 | + return (so_it != so_buffer->cend()) && (so_it->second != nullptr) && | ||
| 188 | + (so_it->second->GetSoBinType() == SoBinType::kCustomOp); | ||
| 189 | +} | ||
| 190 | + | ||
| 191 | +size_t GetEmbeddedCustomOpSoNum(const ComputeGraphPtr &root_graph) { | ||
| 192 | + if (root_graph == nullptr) { | ||
| 193 | + return 0U; | ||
| 194 | + } | ||
| 195 | + const auto so_buffer = root_graph->GetExtAttr<std::map<std::string, OpSoBinPtr>>("bin_file_buffer"); | ||
| 196 | + if (so_buffer == nullptr) { | ||
| 197 | + return 0U; | ||
| 198 | + } | ||
| 199 | + size_t embedded_custom_so_num = 0U; | ||
| 200 | + for (const auto &entry : *so_buffer) { | ||
| 201 | + if ((entry.second != nullptr) && (entry.second->GetSoBinType() == SoBinType::kCustomOp)) { | ||
| 202 | + ++embedded_custom_so_num; | ||
| 203 | + } | ||
| 204 | + } | ||
| 205 | + return embedded_custom_so_num; | ||
| 206 | +} | ||
| 174 | } // namespace | 207 | } // namespace |
| 175 | Status GeRootModel::Initialize(const ComputeGraphPtr &root_graph) { | 208 | Status GeRootModel::Initialize(const ComputeGraphPtr &root_graph) { |
| 176 | GE_ASSERT_NOTNULL(root_graph); | 209 | GE_ASSERT_NOTNULL(root_graph); |
| @@ -379,14 +412,7 @@ Status GeRootModel::ResolvePortableOpSoPath(const std::string &op_type, Portable | |||
| 379 | return SUCCESS; | 412 | return SUCCESS; |
| 380 | } | 413 | } |
| 381 | 414 | ||
| 382 | -Status GeRootModel::CheckAndSetCustomOpSo() { | 415 | +Status GeRootModel::CollectCustomOpTypesForRootModel(std::set<std::string> &used_custom_op_types) const { |
| 383 | - GE_ASSERT_NOTNULL(root_graph_); | ||
| 384 | - GE_ASSERT_NOTNULL(custom_op_registry_); | ||
| 385 | - std::string target_os; | ||
| 386 | - std::string target_cpu; | ||
| 387 | - GE_ASSERT_SUCCESS(GetTargetHostEnv(target_os, target_cpu), "Get target host env failed."); | ||
| 388 | - const bool is_cross_compile = IsCrossCompileTarget(target_os, target_cpu); | ||
| 389 | - std::set<std::string> used_custom_op_types; | ||
| 390 | GE_ASSERT_SUCCESS(CollectCustomOpTypesFromGraph(root_graph_, custom_op_registry_, used_custom_op_types)); | 416 | GE_ASSERT_SUCCESS(CollectCustomOpTypesFromGraph(root_graph_, custom_op_registry_, used_custom_op_types)); |
| 391 | for (const auto &item : subgraph_instance_name_to_model_) { | 417 | for (const auto &item : subgraph_instance_name_to_model_) { |
| 392 | const auto &ge_model = item.second; | 418 | const auto &ge_model = item.second; |
| @@ -395,8 +421,11 @@ Status GeRootModel::CheckAndSetCustomOpSo() { | |||
| 395 | } | 421 | } |
| 396 | GE_ASSERT_SUCCESS(CollectCustomOpTypesFromGraph(ge_model->GetGraph(), custom_op_registry_, used_custom_op_types)); | 422 | GE_ASSERT_SUCCESS(CollectCustomOpTypesFromGraph(ge_model->GetGraph(), custom_op_registry_, used_custom_op_types)); |
| 397 | } | 423 | } |
| 424 | + return SUCCESS; | ||
| 425 | +} | ||
| 398 | 426 | ||
| 399 | - bool has_portable_custom_op = false; | 427 | +Status GeRootModel::CollectPortableCustomOpSo(const std::set<std::string> &used_custom_op_types, |
| 428 | + const bool is_cross_compile, bool &has_portable_custom_op) { | ||
| 400 | for (const auto &op_type : used_custom_op_types) { | 429 | for (const auto &op_type : used_custom_op_types) { |
| 401 | auto *portable_op = CustomOpCast<PortableOp>( | 430 | auto *portable_op = CustomOpCast<PortableOp>( |
| 402 | custom_op_registry_->GetCustomOpCommonCapability(AscendString(op_type.c_str()), CustomOpCapability::kPortable)); | 431 | custom_op_registry_->GetCustomOpCommonCapability(AscendString(op_type.c_str()), CustomOpCapability::kPortable)); |
| @@ -409,6 +438,11 @@ Status GeRootModel::CheckAndSetCustomOpSo() { | |||
| 409 | continue; | 438 | continue; |
| 410 | } | 439 | } |
| 411 | 440 | ||
| 441 | + if (IsEmbeddedHostCpuFusionSo(root_graph_, op_type)) { | ||
| 442 | + GELOGI("[CustomOp] op[%s] uses embedded HostCPU fusion SO, skip path collect.", op_type.c_str()); | ||
| 443 | + continue; | ||
| 444 | + } | ||
| 445 | + | ||
| 412 | std::string so_path; | 446 | std::string so_path; |
| 413 | GE_ASSERT_SUCCESS(ResolvePortableOpSoPath(op_type, portable_op, so_path), | 447 | GE_ASSERT_SUCCESS(ResolvePortableOpSoPath(op_type, portable_op, so_path), |
| 414 | "Resolve custom op so path failed for op[%s].", op_type.c_str()); | 448 | "Resolve custom op so path failed for op[%s].", op_type.c_str()); |
| @@ -416,7 +450,27 @@ Status GeRootModel::CheckAndSetCustomOpSo() { | |||
| 416 | (void)custom_op_so_set_.insert(so_path); | 450 | (void)custom_op_so_set_.insert(so_path); |
| 417 | GELOGI("[CustomOp] Collect custom op so[%s] for op[%s].", so_path.c_str(), op_type.c_str()); | 451 | GELOGI("[CustomOp] Collect custom op so[%s] for op[%s].", so_path.c_str(), op_type.c_str()); |
| 418 | } | 452 | } |
| 453 | + return SUCCESS; | ||
| 454 | +} | ||
| 419 | 455 | ||
| 456 | +Status GeRootModel::CheckAndSetCustomOpSo() { | ||
| 457 | + GE_ASSERT_NOTNULL(root_graph_); | ||
| 458 | + GE_ASSERT_NOTNULL(custom_op_registry_); | ||
| 459 | + std::string target_os; | ||
| 460 | + std::string target_cpu; | ||
| 461 | + GE_ASSERT_SUCCESS(GetTargetHostEnv(target_os, target_cpu), "Get target host env failed."); | ||
| 462 | + const bool is_cross_compile = IsCrossCompileTarget(target_os, target_cpu); | ||
| 463 | + std::set<std::string> used_custom_op_types; | ||
| 464 | + const auto collect_custom_op_status = CollectCustomOpTypesForRootModel(used_custom_op_types); | ||
| 465 | + if (collect_custom_op_status != SUCCESS) { | ||
| 466 | + return collect_custom_op_status; | ||
| 467 | + } | ||
| 468 | + bool has_portable_custom_op = false; | ||
| 469 | + const auto collect_portable_op_status = | ||
| 470 | + CollectPortableCustomOpSo(used_custom_op_types, is_cross_compile, has_portable_custom_op); | ||
| 471 | + if (collect_portable_op_status != SUCCESS) { | ||
| 472 | + return collect_portable_op_status; | ||
| 473 | + } | ||
| 420 | if (is_cross_compile && has_portable_custom_op) { | 474 | if (is_cross_compile && has_portable_custom_op) { |
| 421 | GE_ASSERT_SUCCESS(CollectCustomOpSoFromCustomOppPath(target_os, target_cpu), | 475 | GE_ASSERT_SUCCESS(CollectCustomOpSoFromCustomOppPath(target_os, target_cpu), |
| 422 | "Collect custom op so from ASCEND_CUSTOM_OPP_PATH failed."); | 476 | "Collect custom op so from ASCEND_CUSTOM_OPP_PATH failed."); |
| @@ -425,7 +479,12 @@ Status GeRootModel::CheckAndSetCustomOpSo() { | |||
| 425 | if (!custom_op_so_set_.empty()) { | 479 | if (!custom_op_so_set_.empty()) { |
| 426 | OpSoStoreUtils::SetSoBinType(SoBinType::kCustomOp, so_in_om_); | 480 | OpSoStoreUtils::SetSoBinType(SoBinType::kCustomOp, so_in_om_); |
| 427 | } | 481 | } |
| 428 | - GELOGI("[CustomOp]The num of so is %zu.", custom_op_so_set_.size()); | 482 | + const size_t embedded_custom_so_num = GetEmbeddedCustomOpSoNum(root_graph_); |
| 483 | + if (embedded_custom_so_num > 0U) { | ||
| 484 | + OpSoStoreUtils::SetSoBinType(SoBinType::kCustomOp, so_in_om_); | ||
| 485 | + } | ||
| 486 | + GELOGI("[CustomOp]The num of path-based so is %zu, embedded so is %zu.", custom_op_so_set_.size(), | ||
| 487 | + embedded_custom_so_num); | ||
| 429 | return SUCCESS; | 488 | return SUCCESS; |
| 430 | } | 489 | } |
| 431 | 490 | ||
| @@ -14,6 +14,7 @@ | |||
| 14 | 14 | ||
| 15 | 15 | ||
| 16 | 16 | ||
| 17 | + | ||
| 17 | 18 | ||
| 18 | 19 | ||
| 19 | 20 | ||
| @@ -222,6 +223,9 @@ class GeRootModel : public std::enable_shared_from_this<GeRootModel> { | |||
| 222 | Status CheckAndSetOpMasterDevice(); | 223 | Status CheckAndSetOpMasterDevice(); |
| 223 | Status CheckAndSetAutofuseSo(); | 224 | Status CheckAndSetAutofuseSo(); |
| 224 | Status CheckAndSetCustomOpSo(); | 225 | Status CheckAndSetCustomOpSo(); |
| 226 | + Status CollectCustomOpTypesForRootModel(std::set<std::string> &used_custom_op_types) const; | ||
| 227 | + Status CollectPortableCustomOpSo(const std::set<std::string> &used_custom_op_types, bool is_cross_compile, | ||
| 228 | + bool &has_portable_custom_op); | ||
| 225 | Status GetTargetHostEnv(std::string &host_env_os, std::string &host_env_cpu) const; | 229 | Status GetTargetHostEnv(std::string &host_env_os, std::string &host_env_cpu) const; |
| 226 | bool IsCrossCompileTarget(const std::string &target_os, const std::string &target_cpu) const; | 230 | bool IsCrossCompileTarget(const std::string &target_os, const std::string &target_cpu) const; |
| 227 | Status ResolvePortableOpSoPath(const std::string &op_type, PortableOp *portable_op, std::string &so_path) const; | 231 | Status ResolvePortableOpSoPath(const std::string &op_type, PortableOp *portable_op, std::string &so_path) const; |
| @@ -25,7 +25,7 @@ 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 kAicpuConstFoldingName = "libaicpu_const_folding.so"; | 27 | const std::string kAicpuConstFoldingName = "libaicpu_const_folding.so"; |
| 28 | -const char *const kIsFusedCpuKernelSupported = "IsCpuConstantFoldingFusedOpSupported"; | 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) { |
| 31 | int64_t num_size = out_desc.GetShape().IsScalar() ? 1 : out_desc.GetShape().GetShapeSize(); | 31 | int64_t num_size = out_desc.GetShape().IsScalar() ? 1 : out_desc.GetShape().GetShapeSize(); |
| @@ -141,15 +141,13 @@ void HostCpuEngine::Finalize() const { | |||
| 141 | GELOGI("start HostCpuEngine::Finalize"); | 141 | GELOGI("start HostCpuEngine::Finalize"); |
| 142 | } | 142 | } |
| 143 | 143 | ||
| 144 | -bool HostCpuEngine::IsFusedCpuKernelSupported(const std::string &op_type) const { | 144 | +bool HostCpuEngine::IsHostKernelSupported(const std::string &op_type) const { |
| 145 | - if (is_fused_cpu_kernel_supported_ == nullptr) { | 145 | + if (host_kernel_finder_ == nullptr) { |
| 146 | - GELOGD("HostCPU fused-kernel support query is unavailable for op[%s].", op_type.c_str()); | 146 | + GELOGD("HostCPU Gert HostKernel finder is unavailable for op[%s].", op_type.c_str()); |
| 147 | return false; | 147 | return false; |
| 148 | } | 148 | } |
| 149 | - const bool supported = is_fused_cpu_kernel_supported_(op_type.c_str()) == 1; | 149 | + const bool supported = host_kernel_finder_(op_type) != nullptr; |
| 150 | - if (!supported) { | 150 | + GELOGD("HostCPU Gert HostKernel query: op[%s], supported[%d].", op_type.c_str(), static_cast<int32_t>(supported)); |
| 151 | - GELOGD("HostCPU fused-kernel support query rejected op[%s].", op_type.c_str()); | ||
| 152 | - } | ||
| 153 | return supported; | 151 | return supported; |
| 154 | } | 152 | } |
| 155 | 153 | ||
| @@ -308,14 +306,11 @@ Status HostCpuEngine::LoadLib(const std::string &lib_path, bool invoke_init) { | |||
| 308 | GELOGI("Lib: %s has been opened", lib_path.c_str()); | 306 | GELOGI("Lib: %s has been opened", lib_path.c_str()); |
| 309 | if (lib_path.find(kConstantFoldingName) != lib_path.npos) { | 307 | if (lib_path.find(kConstantFoldingName) != lib_path.npos) { |
| 310 | constant_folding_handle_ = handle; | 308 | constant_folding_handle_ = handle; |
| 311 | - } | 309 | + host_kernel_finder_ = reinterpret_cast<HostKernelFinder>(mmDlsym(handle, kAicpuHostFindFunc)); |
| 312 | - if (lib_path.find(kAicpuConstFoldingName) != lib_path.npos) { | 310 | + if (host_kernel_finder_ == nullptr) { |
| 313 | - is_fused_cpu_kernel_supported_ = | ||
| 314 | - reinterpret_cast<int32_t (*)(const char *)>(mmDlsym(handle, kIsFusedCpuKernelSupported)); | ||
| 315 | - if (is_fused_cpu_kernel_supported_ == nullptr) { | ||
| 316 | const char_t *reason = mmDlerror(); | 311 | const char_t *reason = mmDlerror(); |
| 317 | reason = (reason == nullptr) ? "" : reason; | 312 | reason = (reason == nullptr) ? "" : reason; |
| 318 | - GELOGW("Fused HostCPU support query symbol is unavailable in lib: %s, reason = %s", lib_path.c_str(), reason); | 313 | + GELOGW("Gert HostKernel finder is unavailable in lib: %s, reason = %s", lib_path.c_str(), reason); |
| 319 | } | 314 | } |
| 320 | } | 315 | } |
| 321 | (void)lib_handles_.emplace_back(handle); | 316 | (void)lib_handles_.emplace_back(handle); |
| @@ -19,6 +19,10 @@ | |||
| 19 | 19 | ||
| 20 | 20 | ||
| 21 | 21 | ||
| 22 | +namespace gert { | ||
| 23 | +class KernelContext; | ||
| 24 | +} | ||
| 25 | + | ||
| 22 | namespace ge { | 26 | namespace ge { |
| 23 | class HostCpuEngine { | 27 | class HostCpuEngine { |
| 24 | public: | 28 | public: |
| @@ -37,9 +41,13 @@ class HostCpuEngine { | |||
| 37 | return constant_folding_handle_; | 41 | return constant_folding_handle_; |
| 38 | } | 42 | } |
| 39 | 43 | ||
| 40 | - bool IsFusedCpuKernelSupported(const std::string &op_type) const; | 44 | + // 查询 libconstant_folding_ops.so 的 Gert HostKernel 路由。只要 op_type 能找到函数即可参与融合。 |
| 45 | + bool IsHostKernelSupported(const std::string &op_type) const; | ||
| 41 | 46 | ||
| 42 | private: | 47 | private: |
| 48 | + using HostKernelFunc = graphStatus (*)(gert::KernelContext *); | ||
| 49 | + using HostKernelFinder = HostKernelFunc (*)(std::string); | ||
| 50 | + | ||
| 43 | HostCpuEngine() = default; | 51 | HostCpuEngine() = default; |
| 44 | 52 | ||
| 45 | void *DlopenLib(const std::string &lib_path) const; | 53 | void *DlopenLib(const std::string &lib_path) const; |
| @@ -63,7 +71,7 @@ class HostCpuEngine { | |||
| 63 | std::mutex mu_; | 71 | std::mutex mu_; |
| 64 | std::vector<void *> lib_handles_; | 72 | std::vector<void *> lib_handles_; |
| 65 | void *constant_folding_handle_ = nullptr; | 73 | void *constant_folding_handle_ = nullptr; |
| 66 | - int32_t (*is_fused_cpu_kernel_supported_)(const char *) = nullptr; | 74 | + HostKernelFinder host_kernel_finder_ = nullptr; |
| 67 | bool initialized_ = false; | 75 | bool initialized_ = false; |
| 68 | }; | 76 | }; |
| 69 | } // namespace ge | 77 | } // namespace ge |
| @@ -18,11 +18,7 @@ | |||
| 18 | 18 | ||
| 19 | 19 | ||
| 20 | 20 | ||
| 21 | - | ||
| 22 | - | ||
| 23 | - | ||
| 24 | 21 | ||
| 25 | - | ||
| 26 | 22 | ||
| 27 | 23 | ||
| 28 | 24 | ||
| @@ -58,8 +54,6 @@ const char *const kExcludedConstantFoldingSo = "libconstant_folding_ops.so"; | |||
| 58 | const char *const kSymGetAllRegisteredOpTypesV2 = "GetAllRegisteredOpTypesV2"; | 54 | const char *const kSymGetAllRegisteredOpTypesV2 = "GetAllRegisteredOpTypesV2"; |
| 59 | const char *const kSymIsRegisteredV2 = "IsRegisteredV2"; | 55 | const char *const kSymIsRegisteredV2 = "IsRegisteredV2"; |
| 60 | const char *const kSymRunCpuKernelV2 = "RunCpuKernelV2"; | 56 | const char *const kSymRunCpuKernelV2 = "RunCpuKernelV2"; |
| 61 | -constexpr uint32_t kFusedHostCpuShapeChanged = 1U; | ||
| 62 | -constexpr uint32_t kFusedHostCpuDataChanged = 2U; | ||
| 63 | 57 | ||
| 64 | using AttrValueMap = google::protobuf::Map<string, aicpuops::AttrValue>; | 58 | using AttrValueMap = google::protobuf::Map<string, aicpuops::AttrValue>; |
| 65 | 59 | ||
| @@ -75,62 +69,7 @@ struct V2ModuleBinding { | |||
| 75 | std::string so_name; | 69 | std::string so_name; |
| 76 | }; | 70 | }; |
| 77 | 71 | ||
| 78 | -struct FusedTensorBindingState { | ||
| 79 | - ge::DataType data_type = ge::DT_UNDEFINED; | ||
| 80 | - ge::Format format = ge::FORMAT_RESERVED; | ||
| 81 | - const void *data = nullptr; | ||
| 82 | - size_t data_size = 0U; | ||
| 83 | - std::vector<int64_t> dims; | ||
| 84 | - bool initialized = false; | ||
| 85 | -}; | ||
| 86 | - | ||
| 87 | -struct FusedCpuKernelPlan { | ||
| 88 | - std::unique_ptr<aicpuops::NodeDef> node_def; | ||
| 89 | - std::unique_ptr<aicpu::CpuKernelContext> context; | ||
| 90 | - const V2ModuleBinding *v2_binding = nullptr; | ||
| 91 | - std::shared_ptr<aicpu::CpuKernel> v1_kernel; | ||
| 92 | - std::vector<aicpu::Tensor *> input_tensors; | ||
| 93 | - std::vector<aicpu::Tensor *> output_tensors; | ||
| 94 | - std::vector<FusedTensorBindingState> input_states; | ||
| 95 | - std::vector<FusedTensorBindingState> output_states; | ||
| 96 | -}; | ||
| 97 | - | ||
| 98 | -struct FusedCpuKernelChainNodeDesc { | ||
| 99 | - const ge::Operator *op; | ||
| 100 | - const ge::Tensor *const *inputs; | ||
| 101 | - size_t input_num; | ||
| 102 | - ge::Tensor *const *outputs; | ||
| 103 | - size_t output_num; | ||
| 104 | - const int32_t *input_binding_indices; | ||
| 105 | - const int32_t *output_binding_indices; | ||
| 106 | -}; | ||
| 107 | - | ||
| 108 | -struct FusedHostCpuTensorBinding { | ||
| 109 | - const int64_t *dims; | ||
| 110 | - uint8_t *data; | ||
| 111 | - size_t dim_num; | ||
| 112 | - size_t data_size; | ||
| 113 | - uint32_t flags; | ||
| 114 | -}; | ||
| 115 | - | ||
| 116 | -struct FusedCpuKernelBinding { | ||
| 117 | - const ge::Tensor *source; | ||
| 118 | - aicpu::Tensor *target; | ||
| 119 | - FusedTensorBindingState *state; | ||
| 120 | - size_t binding_index; | ||
| 121 | -}; | ||
| 122 | - | ||
| 123 | -struct FusedCpuKernelChainNode { | ||
| 124 | - FusedCpuKernelPlan plan; | ||
| 125 | -}; | ||
| 126 | - | ||
| 127 | -struct FusedCpuKernelChainPlan { | ||
| 128 | - std::vector<FusedCpuKernelChainNode> nodes; | ||
| 129 | - std::vector<FusedCpuKernelBinding> bindings; | ||
| 130 | -}; | ||
| 131 | - | ||
| 132 | std::vector<V2ModuleBinding> g_v2_bindings; | 72 | std::vector<V2ModuleBinding> g_v2_bindings; |
| 133 | -std::unordered_set<std::string> g_v1_op_types; | ||
| 134 | // op_type->binding反向索引, Init阶段一次性构建, 运行期只读。 | 73 | // op_type->binding反向索引, Init阶段一次性构建, 运行期只读。 |
| 135 | std::unordered_map<std::string, const V2ModuleBinding *> g_v2_op_index; | 74 | std::unordered_map<std::string, const V2ModuleBinding *> g_v2_op_index; |
| 136 | 75 | ||
| @@ -156,27 +95,6 @@ void ConvertGeToAicpuTensor(const ge::GeTensorDesc &tensor_desc, const std::stri | |||
| 156 | static_cast<int>(tensor_desc.GetDataType()), ge_tensor.GetData(), ge_tensor.GetSize()); | 95 | static_cast<int>(tensor_desc.GetDataType()), ge_tensor.GetData(), ge_tensor.GetSize()); |
| 157 | } | 96 | } |
| 158 | 97 | ||
| 159 | -void ConvertFusedGeToAicpuTensor(const std::string &tensor_name, const ge::Tensor &ge_tensor, | ||
| 160 | - aicpuops::Tensor *aicpu_tensor) { | ||
| 161 | - aicpu_tensor->set_name(tensor_name); | ||
| 162 | - aicpu_tensor->set_tensor_type(ge_tensor.GetDataType()); | ||
| 163 | - aicpu_tensor->set_data_ptr(static_cast<uint64_t>(reinterpret_cast<intptr_t>(ge_tensor.GetData()))); | ||
| 164 | - aicpu_tensor->set_data_size(static_cast<uint64_t>(ge_tensor.GetSize())); | ||
| 165 | - auto shape = aicpu_tensor->mutable_tensor_shape(); | ||
| 166 | - if (shape != nullptr) { | ||
| 167 | - shape->clear_dim(); | ||
| 168 | - for (size_t i = 0U; i < ge_tensor.GetShapeDimNum(); ++i) { | ||
| 169 | - aicpuops::TensorShape_Dim *aicpu_dim = shape->add_dim(); | ||
| 170 | - if (aicpu_dim != nullptr) { | ||
| 171 | - aicpu_dim->set_size(ge_tensor.GetShapeDim(i)); | ||
| 172 | - } | ||
| 173 | - } | ||
| 174 | - shape->set_data_format(ge_tensor.GetFormat()); | ||
| 175 | - } | ||
| 176 | - AICPUE_LOGI("Op set fused tensor[%s], tensor info[type:%d, data:%p, size:%llu].", tensor_name.c_str(), | ||
| 177 | - static_cast<int>(ge_tensor.GetDataType()), ge_tensor.GetData(), ge_tensor.GetSize()); | ||
| 178 | -} | ||
| 179 | - | ||
| 180 | int32_t AddStringAttrToNodeDef(const ge::Operator &op, const char *name, [[maybe_unused]] aicpuops::NodeDef node_def, | 98 | int32_t AddStringAttrToNodeDef(const ge::Operator &op, const char *name, [[maybe_unused]] aicpuops::NodeDef node_def, |
| 181 | aicpuops::AttrValue &attr_value) { | 99 | aicpuops::AttrValue &attr_value) { |
| 182 | std::string s; | 100 | std::string s; |
| @@ -608,8 +526,6 @@ __attribute__((visibility("default"))) int32_t InitCpuConstantFoldingNew(ge::Hos | |||
| 608 | 526 | ||
| 609 | std::vector<std::string> ops = aicpu::CpuKernelRegister::Instance().GetAllRegisteredOpTypes(); | 527 | std::vector<std::string> ops = aicpu::CpuKernelRegister::Instance().GetAllRegisteredOpTypes(); |
| 610 | AICPUE_LOGI("Registered V1 ops: %llu", static_cast<uint64_t>(ops.size())); | 528 | AICPUE_LOGI("Registered V1 ops: %llu", static_cast<uint64_t>(ops.size())); |
| 611 | - g_v1_op_types.clear(); | ||
| 612 | - g_v1_op_types.insert(ops.cbegin(), ops.cend()); | ||
| 613 | RegisterHostCpuOp(ops, create_fn); | 529 | RegisterHostCpuOp(ops, create_fn); |
| 614 | 530 | ||
| 615 | // 枚举每个ops so的V2算子, 同时构建op_type->binding反向索引。 | 531 | // 枚举每个ops so的V2算子, 同时构建op_type->binding反向索引。 |
| @@ -656,7 +572,7 @@ int32_t BuildInputTensors(const ge::OpDescPtr &op_desc, const std::map<std::stri | |||
| 656 | return 0; | 572 | return 0; |
| 657 | } | 573 | } |
| 658 | 574 | ||
| 659 | -int32_t BuildOutputTensors(const ge::OpDescPtr &op_desc, const std::map<std::string, ge::Tensor> &outputs, | 575 | +int32_t BuildOutputTensors(const ge::OpDescPtr &op_desc, std::map<std::string, ge::Tensor> &outputs, |
| 660 | const char *op_type, aicpuops::NodeDef &node_def) { | 576 | const char *op_type, aicpuops::NodeDef &node_def) { |
| 661 | uint32_t count = static_cast<uint32_t>(op_desc->GetOutputsSize()); | 577 | uint32_t count = static_cast<uint32_t>(op_desc->GetOutputsSize()); |
| 662 | for (uint32_t i = 0; i < count; ++i) { | 578 | for (uint32_t i = 0; i < count; ++i) { |
| @@ -676,55 +592,6 @@ int32_t BuildOutputTensors(const ge::OpDescPtr &op_desc, const std::map<std::str | |||
| 676 | return 0; | 592 | return 0; |
| 677 | } | 593 | } |
| 678 | 594 | ||
| 679 | -int32_t BuildFusedInputTensorArray(const ge::OpDescPtr &op_desc, const ge::Tensor *const *inputs, | ||
| 680 | - const size_t input_num, aicpuops::NodeDef &node_def) { | ||
| 681 | - const size_t count = op_desc->GetAllInputsSize(); | ||
| 682 | - if ((count != input_num) || ((count != 0U) && (inputs == nullptr))) { | ||
| 683 | - AICPUE_LOGE("Invalid fused input tensor array: op[%s], expected_num[%zu], actual_num[%zu], inputs_null[%d].", | ||
| 684 | - AICPUE_ERROR_CODE, op_desc->GetTypePtr(), count, input_num, static_cast<int32_t>(inputs == nullptr)); | ||
| 685 | - return -1; | ||
| 686 | - } | ||
| 687 | - for (size_t i = 0U; i < count; ++i) { | ||
| 688 | - if (inputs[i] == nullptr) { | ||
| 689 | - AICPUE_LOGE("Fused input tensor is null: op[%s], input_index[%zu].", AICPUE_ERROR_CODE, op_desc->GetTypePtr(), i); | ||
| 690 | - return -1; | ||
| 691 | - } | ||
| 692 | - aicpuops::Tensor *tensor = node_def.add_inputs(); | ||
| 693 | - if (tensor == nullptr) { | ||
| 694 | - AICPUE_LOGE("Failed to add fused input tensor to NodeDef: op[%s], input_index[%zu].", AICPUE_ERROR_CODE, | ||
| 695 | - op_desc->GetTypePtr(), i); | ||
| 696 | - return -1; | ||
| 697 | - } | ||
| 698 | - ConvertFusedGeToAicpuTensor(op_desc->GetInputNameByIndex(static_cast<uint32_t>(i)), *inputs[i], tensor); | ||
| 699 | - } | ||
| 700 | - return 0; | ||
| 701 | -} | ||
| 702 | - | ||
| 703 | -int32_t BuildFusedOutputTensorArray(const ge::OpDescPtr &op_desc, ge::Tensor *const *outputs, const size_t output_num, | ||
| 704 | - aicpuops::NodeDef &node_def) { | ||
| 705 | - const size_t count = op_desc->GetOutputsSize(); | ||
| 706 | - if ((count != output_num) || ((count != 0U) && (outputs == nullptr))) { | ||
| 707 | - AICPUE_LOGE("Invalid fused output tensor array: op[%s], expected_num[%zu], actual_num[%zu], outputs_null[%d].", | ||
| 708 | - AICPUE_ERROR_CODE, op_desc->GetTypePtr(), count, output_num, static_cast<int32_t>(outputs == nullptr)); | ||
| 709 | - return -1; | ||
| 710 | - } | ||
| 711 | - for (size_t i = 0U; i < count; ++i) { | ||
| 712 | - if (outputs[i] == nullptr) { | ||
| 713 | - AICPUE_LOGE("Fused output tensor is null: op[%s], output_index[%zu].", AICPUE_ERROR_CODE, op_desc->GetTypePtr(), | ||
| 714 | - i); | ||
| 715 | - return -1; | ||
| 716 | - } | ||
| 717 | - aicpuops::Tensor *tensor = node_def.add_outputs(); | ||
| 718 | - if (tensor == nullptr) { | ||
| 719 | - AICPUE_LOGE("Failed to add fused output tensor to NodeDef: op[%s], output_index[%zu].", AICPUE_ERROR_CODE, | ||
| 720 | - op_desc->GetTypePtr(), i); | ||
| 721 | - return -1; | ||
| 722 | - } | ||
| 723 | - ConvertFusedGeToAicpuTensor(op_desc->GetOutputNameByIndex(static_cast<uint32_t>(i)), *outputs[i], tensor); | ||
| 724 | - } | ||
| 725 | - return 0; | ||
| 726 | -} | ||
| 727 | - | ||
| 728 | int32_t BuildNodeDefAttrs(const ge::Operator &op, aicpuops::NodeDef &node_def) { | 595 | int32_t BuildNodeDefAttrs(const ge::Operator &op, aicpuops::NodeDef &node_def) { |
| 729 | std::map<ge::AscendString, ge::AscendString> attrs; | 596 | std::map<ge::AscendString, ge::AscendString> attrs; |
| 730 | if (op.GetAllAttrNamesAndTypes(attrs) != ge::GRAPH_SUCCESS) { | 597 | if (op.GetAllAttrNamesAndTypes(attrs) != ge::GRAPH_SUCCESS) { |
| @@ -770,277 +637,6 @@ int32_t BuildNodeDef(const ge::Operator &op, const std::string &op_type_str, | |||
| 770 | return BuildNodeDefAttrs(op, node_def); | 637 | return BuildNodeDefAttrs(op, node_def); |
| 771 | } | 638 | } |
| 772 | 639 | ||
| 773 | -int32_t BuildFusedNodeDefFromTensorArray(const ge::Operator &op, const std::string &op_type_str, | ||
| 774 | - const ge::Tensor *const *inputs, const size_t input_num, | ||
| 775 | - ge::Tensor *const *outputs, const size_t output_num, | ||
| 776 | - aicpuops::NodeDef &node_def) { | ||
| 777 | - const ge::OpDescPtr op_desc = ge::OpDescUtils::GetOpDescFromOperator(op); | ||
| 778 | - if (op_desc == nullptr) { | ||
| 779 | - AICPUE_LOGW("Op[%s] get op desc failed.", op_type_str.c_str()); | ||
| 780 | - return -1; | ||
| 781 | - } | ||
| 782 | - node_def.set_op(op_type_str); | ||
| 783 | - int32_t ret = BuildFusedInputTensorArray(op_desc, inputs, input_num, node_def); | ||
| 784 | - if (ret != 0) { | ||
| 785 | - return ret; | ||
| 786 | - } | ||
| 787 | - ret = BuildFusedOutputTensorArray(op_desc, outputs, output_num, node_def); | ||
| 788 | - if (ret != 0) { | ||
| 789 | - return ret; | ||
| 790 | - } | ||
| 791 | - return BuildNodeDefAttrs(op, node_def); | ||
| 792 | -} | ||
| 793 | - | ||
| 794 | -bool HasSameShape(const ge::Tensor &source, const FusedTensorBindingState &state) { | ||
| 795 | - const size_t dim_num = source.GetShapeDimNum(); | ||
| 796 | - if (state.dims.size() != dim_num) { | ||
| 797 | - return false; | ||
| 798 | - } | ||
| 799 | - for (size_t i = 0U; i < dim_num; ++i) { | ||
| 800 | - if (state.dims[i] != source.GetShapeDim(i)) { | ||
| 801 | - return false; | ||
| 802 | - } | ||
| 803 | - } | ||
| 804 | - return true; | ||
| 805 | -} | ||
| 806 | - | ||
| 807 | -int32_t InitializeFusedTensor(const ge::Tensor &source, aicpu::Tensor *target, FusedTensorBindingState &state) { | ||
| 808 | - const void *data = static_cast<const void *>(source.GetData()); | ||
| 809 | - const size_t data_size = source.GetSize(); | ||
| 810 | - target->SetData(const_cast<void *>(data)); | ||
| 811 | - target->SetDataSize(static_cast<uint64_t>(data_size)); | ||
| 812 | - target->SetDataType(static_cast<aicpu::DataType>(source.GetDataType())); | ||
| 813 | - | ||
| 814 | - const std::shared_ptr<aicpu::TensorShape> tensor_shape = target->GetTensorShape(); | ||
| 815 | - if (tensor_shape == nullptr) { | ||
| 816 | - AICPUE_LOGE("Failed to get target TensorShape while initializing fused Tensor.", AICPUE_ERROR_CODE); | ||
| 817 | - return -1; | ||
| 818 | - } | ||
| 819 | - state.dims.resize(source.GetShapeDimNum()); | ||
| 820 | - for (size_t i = 0U; i < state.dims.size(); ++i) { | ||
| 821 | - state.dims[i] = source.GetShapeDim(i); | ||
| 822 | - } | ||
| 823 | - tensor_shape->SetDimSizes(state.dims); | ||
| 824 | - const ge::Format format = source.GetFormat(); | ||
| 825 | - tensor_shape->SetFormat(static_cast<aicpu::Format>(format)); | ||
| 826 | - | ||
| 827 | - state.data = data; | ||
| 828 | - state.data_size = data_size; | ||
| 829 | - state.data_type = source.GetDataType(); | ||
| 830 | - state.format = format; | ||
| 831 | - state.initialized = true; | ||
| 832 | - return 0; | ||
| 833 | -} | ||
| 834 | - | ||
| 835 | -int32_t RebindFusedTensor(const ge::Tensor &source, aicpu::Tensor *target, FusedTensorBindingState &state) { | ||
| 836 | - if ((target == nullptr) || ((source.GetSize() != 0U) && (source.GetData() == nullptr))) { | ||
| 837 | - AICPUE_LOGE("Failed to rebind fused Tensor: target_null[%d], data_null[%d], data_size[%zu].", AICPUE_ERROR_CODE, | ||
| 838 | - static_cast<int32_t>(target == nullptr), | ||
| 839 | - static_cast<int32_t>((source.GetSize() != 0U) && (source.GetData() == nullptr)), source.GetSize()); | ||
| 840 | - return -1; | ||
| 841 | - } | ||
| 842 | - if (!state.initialized) { | ||
| 843 | - return InitializeFusedTensor(source, target, state); | ||
| 844 | - } | ||
| 845 | - const void *data = static_cast<const void *>(source.GetData()); | ||
| 846 | - const size_t data_size = source.GetSize(); | ||
| 847 | - if (state.data != data) { | ||
| 848 | - target->SetData(const_cast<void *>(data)); | ||
| 849 | - state.data = data; | ||
| 850 | - } | ||
| 851 | - if (state.data_size != data_size) { | ||
| 852 | - target->SetDataSize(static_cast<uint64_t>(data_size)); | ||
| 853 | - state.data_size = data_size; | ||
| 854 | - } | ||
| 855 | - | ||
| 856 | - const ge::DataType data_type = source.GetDataType(); | ||
| 857 | - if (state.data_type != data_type) { | ||
| 858 | - target->SetDataType(static_cast<aicpu::DataType>(data_type)); | ||
| 859 | - state.data_type = data_type; | ||
| 860 | - } | ||
| 861 | - | ||
| 862 | - const ge::Format format = source.GetFormat(); | ||
| 863 | - const bool shape_changed = !HasSameShape(source, state); | ||
| 864 | - if (shape_changed || (state.format != format)) { | ||
| 865 | - const std::shared_ptr<aicpu::TensorShape> tensor_shape = target->GetTensorShape(); | ||
| 866 | - if (tensor_shape == nullptr) { | ||
| 867 | - AICPUE_LOGE("Failed to get target TensorShape while rebinding fused Tensor.", AICPUE_ERROR_CODE); | ||
| 868 | - return -1; | ||
| 869 | - } | ||
| 870 | - if (shape_changed) { | ||
| 871 | - state.dims.resize(source.GetShapeDimNum()); | ||
| 872 | - for (size_t i = 0U; i < state.dims.size(); ++i) { | ||
| 873 | - state.dims[i] = source.GetShapeDim(i); | ||
| 874 | - } | ||
| 875 | - tensor_shape->SetDimSizes(state.dims); | ||
| 876 | - } | ||
| 877 | - tensor_shape->SetFormat(static_cast<aicpu::Format>(format)); | ||
| 878 | - state.format = format; | ||
| 879 | - } | ||
| 880 | - state.initialized = true; | ||
| 881 | - return 0; | ||
| 882 | -} | ||
| 883 | - | ||
| 884 | -int32_t RebindFusedTensorDataByFlags(const ge::Tensor &source, aicpu::Tensor *target, FusedTensorBindingState &state, | ||
| 885 | - const uint32_t binding_flags) { | ||
| 886 | - if ((binding_flags & kFusedHostCpuDataChanged) == 0U) { | ||
| 887 | - return 0; | ||
| 888 | - } | ||
| 889 | - const void *data = static_cast<const void *>(source.GetData()); | ||
| 890 | - const size_t data_size = source.GetSize(); | ||
| 891 | - if ((data_size != 0U) && (data == nullptr)) { | ||
| 892 | - AICPUE_LOGE("Failed to rebind fused Tensor data by flags: data is null, data_size[%zu], binding_flags[%u].", | ||
| 893 | - AICPUE_ERROR_CODE, data_size, binding_flags); | ||
| 894 | - return -1; | ||
| 895 | - } | ||
| 896 | - if (state.data != data) { | ||
| 897 | - target->SetData(const_cast<void *>(data)); | ||
| 898 | - state.data = data; | ||
| 899 | - } | ||
| 900 | - if (state.data_size != data_size) { | ||
| 901 | - target->SetDataSize(static_cast<uint64_t>(data_size)); | ||
| 902 | - state.data_size = data_size; | ||
| 903 | - } | ||
| 904 | - return 0; | ||
| 905 | -} | ||
| 906 | - | ||
| 907 | -int32_t RebindFusedTensorShapeByFlags(const ge::Tensor &source, aicpu::Tensor *target, FusedTensorBindingState &state, | ||
| 908 | - const uint32_t binding_flags) { | ||
| 909 | - if ((binding_flags & kFusedHostCpuShapeChanged) == 0U) { | ||
| 910 | - return 0; | ||
| 911 | - } | ||
| 912 | - const ge::DataType data_type = source.GetDataType(); | ||
| 913 | - if (state.data_type != data_type) { | ||
| 914 | - target->SetDataType(static_cast<aicpu::DataType>(data_type)); | ||
| 915 | - state.data_type = data_type; | ||
| 916 | - } | ||
| 917 | - | ||
| 918 | - const ge::Format format = source.GetFormat(); | ||
| 919 | - const bool shape_changed = !HasSameShape(source, state); | ||
| 920 | - if (shape_changed || (state.format != format)) { | ||
| 921 | - const std::shared_ptr<aicpu::TensorShape> tensor_shape = target->GetTensorShape(); | ||
| 922 | - if (tensor_shape == nullptr) { | ||
| 923 | - AICPUE_LOGE("Failed to get target TensorShape while rebinding fused Tensor by flags: binding_flags[%u].", | ||
| 924 | - AICPUE_ERROR_CODE, binding_flags); | ||
| 925 | - return -1; | ||
| 926 | - } | ||
| 927 | - if (shape_changed) { | ||
| 928 | - state.dims.resize(source.GetShapeDimNum()); | ||
| 929 | - for (size_t i = 0U; i < state.dims.size(); ++i) { | ||
| 930 | - state.dims[i] = source.GetShapeDim(i); | ||
| 931 | - } | ||
| 932 | - tensor_shape->SetDimSizes(state.dims); | ||
| 933 | - } | ||
| 934 | - tensor_shape->SetFormat(static_cast<aicpu::Format>(format)); | ||
| 935 | - state.format = format; | ||
| 936 | - } | ||
| 937 | - return 0; | ||
| 938 | -} | ||
| 939 | - | ||
| 940 | -int32_t RebindFusedTensorByFlags(const ge::Tensor &source, aicpu::Tensor *target, FusedTensorBindingState &state, | ||
| 941 | - uint32_t binding_flags) { | ||
| 942 | - if (target == nullptr) { | ||
| 943 | - AICPUE_LOGE("Failed to rebind fused Tensor by flags: target is null, binding_flags[%u].", AICPUE_ERROR_CODE, | ||
| 944 | - binding_flags); | ||
| 945 | - return -1; | ||
| 946 | - } | ||
| 947 | - if (!state.initialized) { | ||
| 948 | - return RebindFusedTensor(source, target, state); | ||
| 949 | - } | ||
| 950 | - if ((RebindFusedTensorDataByFlags(source, target, state, binding_flags) != 0) || | ||
| 951 | - (RebindFusedTensorShapeByFlags(source, target, state, binding_flags) != 0)) { | ||
| 952 | - return -1; | ||
| 953 | - } | ||
| 954 | - state.initialized = true; | ||
| 955 | - return 0; | ||
| 956 | -} | ||
| 957 | - | ||
| 958 | -int32_t RebindFusedTensorByBinding(const FusedHostCpuTensorBinding &binding, aicpu::Tensor *target, | ||
| 959 | - FusedTensorBindingState &state) { | ||
| 960 | - if ((target == nullptr) || ((binding.dim_num != 0U) && (binding.dims == nullptr)) || | ||
| 961 | - ((binding.data_size != 0U) && (binding.data == nullptr))) { | ||
| 962 | - AICPUE_LOGE( | ||
| 963 | - "Invalid fused Tensor binding: target_null[%d], dim_num[%zu], dims_null[%d], data_size[%zu], " | ||
| 964 | - "data_null[%d], flags[%u].", | ||
| 965 | - AICPUE_ERROR_CODE, static_cast<int32_t>(target == nullptr), binding.dim_num, | ||
| 966 | - static_cast<int32_t>((binding.dim_num != 0U) && (binding.dims == nullptr)), binding.data_size, | ||
| 967 | - static_cast<int32_t>((binding.data_size != 0U) && (binding.data == nullptr)), binding.flags); | ||
| 968 | - return -1; | ||
| 969 | - } | ||
| 970 | - uint32_t binding_flags = binding.flags; | ||
| 971 | - if (!state.initialized) { | ||
| 972 | - binding_flags |= kFusedHostCpuShapeChanged | kFusedHostCpuDataChanged; | ||
| 973 | - } | ||
| 974 | - if ((binding_flags & kFusedHostCpuDataChanged) != 0U) { | ||
| 975 | - target->SetData(binding.data); | ||
| 976 | - target->SetDataSize(static_cast<uint64_t>(binding.data_size)); | ||
| 977 | - state.data = binding.data; | ||
| 978 | - state.data_size = binding.data_size; | ||
| 979 | - } | ||
| 980 | - if ((binding_flags & kFusedHostCpuShapeChanged) != 0U) { | ||
| 981 | - const std::shared_ptr<aicpu::TensorShape> tensor_shape = target->GetTensorShape(); | ||
| 982 | - if (tensor_shape == nullptr) { | ||
| 983 | - AICPUE_LOGE("Failed to get target TensorShape from fused binding: dim_num[%zu], flags[%u].", AICPUE_ERROR_CODE, | ||
| 984 | - binding.dim_num, binding.flags); | ||
| 985 | - return -1; | ||
| 986 | - } | ||
| 987 | - state.dims.resize(binding.dim_num); | ||
| 988 | - for (size_t i = 0U; i < binding.dim_num; ++i) { | ||
| 989 | - state.dims[i] = binding.dims[i]; | ||
| 990 | - } | ||
| 991 | - tensor_shape->SetDimSizes(state.dims); | ||
| 992 | - } | ||
| 993 | - state.initialized = true; | ||
| 994 | - return 0; | ||
| 995 | -} | ||
| 996 | - | ||
| 997 | -int32_t RebindFusedPlan(FusedCpuKernelPlan &plan, const ge::Tensor *const *inputs, const size_t input_num, | ||
| 998 | - ge::Tensor *const *outputs, const size_t output_num) { | ||
| 999 | - if ((plan.context == nullptr) || (input_num != plan.input_tensors.size()) || | ||
| 1000 | - (output_num != plan.output_tensors.size()) || ((input_num != 0U) && (inputs == nullptr)) || | ||
| 1001 | - ((output_num != 0U) && (outputs == nullptr))) { | ||
| 1002 | - AICPUE_LOGE( | ||
| 1003 | - "Invalid fused CPU plan binding: context_null[%d], input_num[%zu], expected_inputs[%zu], " | ||
| 1004 | - "output_num[%zu], expected_outputs[%zu], inputs_null[%d], outputs_null[%d].", | ||
| 1005 | - AICPUE_ERROR_CODE, static_cast<int32_t>(plan.context == nullptr), input_num, plan.input_tensors.size(), | ||
| 1006 | - output_num, plan.output_tensors.size(), static_cast<int32_t>(inputs == nullptr), | ||
| 1007 | - static_cast<int32_t>(outputs == nullptr)); | ||
| 1008 | - return -1; | ||
| 1009 | - } | ||
| 1010 | - for (size_t i = 0U; i < input_num; ++i) { | ||
| 1011 | - if ((inputs[i] == nullptr) || (RebindFusedTensor(*inputs[i], plan.input_tensors[i], plan.input_states[i]) != 0)) { | ||
| 1012 | - AICPUE_LOGE("Failed to rebind fused CPU plan input: input_index[%zu], input_null[%d].", AICPUE_ERROR_CODE, i, | ||
| 1013 | - static_cast<int32_t>(inputs[i] == nullptr)); | ||
| 1014 | - return -1; | ||
| 1015 | - } | ||
| 1016 | - } | ||
| 1017 | - for (size_t i = 0U; i < output_num; ++i) { | ||
| 1018 | - if ((outputs[i] == nullptr) || | ||
| 1019 | - (RebindFusedTensor(*outputs[i], plan.output_tensors[i], plan.output_states[i]) != 0)) { | ||
| 1020 | - AICPUE_LOGE("Failed to rebind fused CPU plan output: output_index[%zu], output_null[%d].", AICPUE_ERROR_CODE, i, | ||
| 1021 | - static_cast<int32_t>(outputs[i] == nullptr)); | ||
| 1022 | - return -1; | ||
| 1023 | - } | ||
| 1024 | - } | ||
| 1025 | - return 0; | ||
| 1026 | -} | ||
| 1027 | - | ||
| 1028 | -int32_t RunFusedCpuKernelPlan(FusedCpuKernelPlan &plan) { | ||
| 1029 | - uint32_t ret = 0U; | ||
| 1030 | - if (plan.v2_binding != nullptr) { | ||
| 1031 | - ret = plan.v2_binding->run_cpu_kernel(*plan.context); | ||
| 1032 | - } else if (plan.v1_kernel != nullptr) { | ||
| 1033 | - ret = plan.v1_kernel->Compute(*plan.context); | ||
| 1034 | - } else { | ||
| 1035 | - AICPUE_LOGE("Fused CPU kernel plan has neither V1 kernel nor V2 binding.", AICPUE_ERROR_CODE); | ||
| 1036 | - return -1; | ||
| 1037 | - } | ||
| 1038 | - if (ret != 0U) { | ||
| 1039 | - AICPUE_LOGE("Fused CPU kernel execution failed: ret[%u].", AICPUE_ERROR_CODE, ret); | ||
| 1040 | - } | ||
| 1041 | - return (ret == 0U) ? 0 : -1; | ||
| 1042 | -} | ||
| 1043 | - | ||
| 1044 | // 查找op_type对应的V2 binding。未命中返回nullptr表示走V1路径。 | 640 | // 查找op_type对应的V2 binding。未命中返回nullptr表示走V1路径。 |
| 1045 | const V2ModuleBinding *LookupV2Binding(const std::string &op_type) { | 641 | const V2ModuleBinding *LookupV2Binding(const std::string &op_type) { |
| 1046 | auto iter = g_v2_op_index.find(op_type); | 642 | auto iter = g_v2_op_index.find(op_type); |
| @@ -1054,14 +650,6 @@ const V2ModuleBinding *LookupV2Binding(const std::string &op_type) { | |||
| 1054 | return binding; | 650 | return binding; |
| 1055 | } | 651 | } |
| 1056 | 652 | ||
| 1057 | -__attribute__((visibility("default"))) int32_t IsCpuConstantFoldingFusedOpSupported(const char *op_type) { | ||
| 1058 | - if ((op_type == nullptr) || (op_type[0] == '\0')) { | ||
| 1059 | - return 0; | ||
| 1060 | - } | ||
| 1061 | - const std::string op_type_str(op_type); | ||
| 1062 | - return ((LookupV2Binding(op_type_str) != nullptr) || (g_v1_op_types.count(op_type_str) > 0U)) ? 1 : 0; | ||
| 1063 | -} | ||
| 1064 | - | ||
| 1065 | __attribute__((visibility("default"))) int32_t | 653 | __attribute__((visibility("default"))) int32_t |
| 1066 | CpuConstantFoldingComputeNew(const ge::Operator &op, const std::map<std::string, const ge::Tensor> &inputs, | 654 | CpuConstantFoldingComputeNew(const ge::Operator &op, const std::map<std::string, const ge::Tensor> &inputs, |
| 1067 | std::map<std::string, ge::Tensor> outputs) { | 655 | std::map<std::string, ge::Tensor> outputs) { |
| @@ -1109,302 +697,4 @@ CpuConstantFoldingComputeNew(const ge::Operator &op, const std::map<std::string, | |||
| 1109 | AICPUE_LOGI("Finish cpu op[%s].", op_type.GetString()); | 697 | AICPUE_LOGI("Finish cpu op[%s].", op_type.GetString()); |
| 1110 | return 0; | 698 | return 0; |
| 1111 | } | 699 | } |
| 1112 | - | ||
| 1113 | -int32_t InitializeFusedCpuKernel(const ge::Operator &op, FusedCpuKernelPlan &plan, std::string &op_type_str, | ||
| 1114 | - ge::AscendString &op_type) { | ||
| 1115 | - if (op.GetOpType(op_type) != ge::GRAPH_SUCCESS) { | ||
| 1116 | - return -1; | ||
| 1117 | - } | ||
| 1118 | - op_type_str = op_type.GetString(); | ||
| 1119 | - plan.v2_binding = LookupV2Binding(op_type_str); | ||
| 1120 | - if (plan.v2_binding == nullptr) { | ||
| 1121 | - plan.v1_kernel = aicpu::CpuKernelRegister::Instance().GetCpuKernel(op_type_str); | ||
| 1122 | - if (plan.v1_kernel == nullptr) { | ||
| 1123 | - AICPUE_LOGW("op type [%s] is not registered in v1 nor v2.", op_type.GetString()); | ||
| 1124 | - return -1; | ||
| 1125 | - } | ||
| 1126 | - } | ||
| 1127 | - return 0; | ||
| 1128 | -} | ||
| 1129 | - | ||
| 1130 | -int32_t AllocateFusedCpuKernelPlan(FusedCpuKernelPlan &plan, const ge::AscendString &op_type) { | ||
| 1131 | - plan.node_def.reset(new (std::nothrow) aicpuops::NodeDef()); | ||
| 1132 | - plan.context.reset(new (std::nothrow) aicpu::CpuKernelContext(aicpu::HOST)); | ||
| 1133 | - if ((plan.node_def == nullptr) || (plan.context == nullptr)) { | ||
| 1134 | - AICPUE_LOGE("Failed to allocate fused CPU kernel plan objects: op[%s], node_def_null[%d], context_null[%d].", | ||
| 1135 | - AICPUE_ERROR_CODE, op_type.GetString(), static_cast<int32_t>(plan.node_def == nullptr), | ||
| 1136 | - static_cast<int32_t>(plan.context == nullptr)); | ||
| 1137 | - return -1; | ||
| 1138 | - } | ||
| 1139 | - return 0; | ||
| 1140 | -} | ||
| 1141 | - | ||
| 1142 | -int32_t InitializeFusedCpuKernelTensors(FusedCpuKernelPlan &plan, const size_t input_num, const size_t output_num, | ||
| 1143 | - const ge::AscendString &op_type) { | ||
| 1144 | - plan.input_tensors.resize(input_num); | ||
| 1145 | - plan.output_tensors.resize(output_num); | ||
| 1146 | - plan.input_states.resize(input_num); | ||
| 1147 | - plan.output_states.resize(output_num); | ||
| 1148 | - for (size_t i = 0U; i < input_num; ++i) { | ||
| 1149 | - plan.input_tensors[i] = plan.context->Input(static_cast<uint32_t>(i)); | ||
| 1150 | - if (plan.input_tensors[i] == nullptr) { | ||
| 1151 | - AICPUE_LOGE("Fused CPU kernel context input is null: op[%s], input_index[%zu], input_num[%zu].", | ||
| 1152 | - AICPUE_ERROR_CODE, op_type.GetString(), i, input_num); | ||
| 1153 | - return -1; | ||
| 1154 | - } | ||
| 1155 | - } | ||
| 1156 | - for (size_t i = 0U; i < output_num; ++i) { | ||
| 1157 | - plan.output_tensors[i] = plan.context->Output(static_cast<uint32_t>(i)); | ||
| 1158 | - if (plan.output_tensors[i] == nullptr) { | ||
| 1159 | - AICPUE_LOGE("Fused CPU kernel context output is null: op[%s], output_index[%zu], output_num[%zu].", | ||
| 1160 | - AICPUE_ERROR_CODE, op_type.GetString(), i, output_num); | ||
| 1161 | - return -1; | ||
| 1162 | - } | ||
| 1163 | - } | ||
| 1164 | - return 0; | ||
| 1165 | -} | ||
| 1166 | - | ||
| 1167 | -int32_t InitializeFusedCpuKernelPlan(const ge::Operator &op, const ge::Tensor *const *inputs, const size_t input_num, | ||
| 1168 | - ge::Tensor *const *outputs, const size_t output_num, FusedCpuKernelPlan &plan) { | ||
| 1169 | - ge::AscendString op_type; | ||
| 1170 | - std::string op_type_str; | ||
| 1171 | - if (InitializeFusedCpuKernel(op, plan, op_type_str, op_type) != 0) { | ||
| 1172 | - return -1; | ||
| 1173 | - } | ||
| 1174 | - if (AllocateFusedCpuKernelPlan(plan, op_type) != 0) { | ||
| 1175 | - return -1; | ||
| 1176 | - } | ||
| 1177 | - if (BuildFusedNodeDefFromTensorArray(op, op_type_str, inputs, input_num, outputs, output_num, *plan.node_def) != 0) { | ||
| 1178 | - AICPUE_LOGE("Failed to build fused CPU NodeDef: op[%s], inputs[%zu], outputs[%zu].", AICPUE_ERROR_CODE, | ||
| 1179 | - op_type.GetString(), input_num, output_num); | ||
| 1180 | - return -1; | ||
| 1181 | - } | ||
| 1182 | - const int32_t context_ret = plan.context->Init(plan.node_def.get()); | ||
| 1183 | - if (context_ret != 0) { | ||
| 1184 | - AICPUE_LOGE("Failed to initialize fused CPU kernel context: op[%s], ret[%d].", AICPUE_ERROR_CODE, | ||
| 1185 | - op_type.GetString(), context_ret); | ||
| 1186 | - return -1; | ||
| 1187 | - } | ||
| 1188 | - if (InitializeFusedCpuKernelTensors(plan, input_num, output_num, op_type) != 0) { | ||
| 1189 | - return -1; | ||
| 1190 | - } | ||
| 1191 | - if (RebindFusedPlan(plan, inputs, input_num, outputs, output_num) != 0) { | ||
| 1192 | - AICPUE_LOGE("Failed to bind fused CPU kernel plan tensors: op[%s], inputs[%zu], outputs[%zu].", AICPUE_ERROR_CODE, | ||
| 1193 | - op_type.GetString(), input_num, output_num); | ||
| 1194 | - return -1; | ||
| 1195 | - } | ||
| 1196 | - AICPUE_LOGD("Created fused cpu execution plan for op[%s], inputs[%zu], outputs[%zu].", op_type.GetString(), input_num, | ||
| 1197 | - output_num); | ||
| 1198 | - return 0; | ||
| 1199 | -} | ||
| 1200 | - | ||
| 1201 | -int32_t CalculateFusedChainBindingCapacity(const FusedCpuKernelChainNodeDesc *descs, const size_t node_num, | ||
| 1202 | - size_t &binding_capacity) { | ||
| 1203 | - binding_capacity = 0U; | ||
| 1204 | - for (size_t i = 0U; i < node_num; ++i) { | ||
| 1205 | - if (descs[i].input_num > (std::numeric_limits<size_t>::max() - descs[i].output_num)) { | ||
| 1206 | - AICPUE_LOGE("Fused CPU chain node binding count overflows size_t: node_index[%zu], inputs[%zu], outputs[%zu].", | ||
| 1207 | - AICPUE_ERROR_CODE, i, descs[i].input_num, descs[i].output_num); | ||
| 1208 | - return -1; | ||
| 1209 | - } | ||
| 1210 | - const size_t node_binding_count = descs[i].input_num + descs[i].output_num; | ||
| 1211 | - if (binding_capacity > (std::numeric_limits<size_t>::max() - node_binding_count)) { | ||
| 1212 | - AICPUE_LOGE( | ||
| 1213 | - "Fused CPU chain binding capacity overflows size_t: node_index[%zu], current_capacity[%zu], " | ||
| 1214 | - "node_binding_count[%zu].", | ||
| 1215 | - AICPUE_ERROR_CODE, i, binding_capacity, node_binding_count); | ||
| 1216 | - return -1; | ||
| 1217 | - } | ||
| 1218 | - binding_capacity += node_binding_count; | ||
| 1219 | - } | ||
| 1220 | - return 0; | ||
| 1221 | -} | ||
| 1222 | - | ||
| 1223 | -int32_t AddFusedChainInputBindings(const FusedCpuKernelChainNodeDesc &desc, const size_t node_index, | ||
| 1224 | - const size_t external_binding_num, FusedCpuKernelChainNode &node, | ||
| 1225 | - FusedCpuKernelChainPlan &chain) { | ||
| 1226 | - for (size_t j = 0U; j < desc.input_num; ++j) { | ||
| 1227 | - const int32_t binding_index = | ||
| 1228 | - (desc.input_binding_indices == nullptr) ? static_cast<int32_t>(j) : desc.input_binding_indices[j]; | ||
| 1229 | - if ((binding_index >= 0) && (static_cast<size_t>(binding_index) < external_binding_num) && | ||
| 1230 | - (desc.inputs[j] != nullptr)) { | ||
| 1231 | - chain.bindings.push_back( | ||
| 1232 | - {desc.inputs[j], node.plan.input_tensors[j], &node.plan.input_states[j], static_cast<size_t>(binding_index)}); | ||
| 1233 | - } else if ((binding_index >= 0) && | ||
| 1234 | - ((desc.inputs[j] == nullptr) || (static_cast<size_t>(binding_index) >= external_binding_num))) { | ||
| 1235 | - AICPUE_LOGE( | ||
| 1236 | - "Invalid fused input binding: node_index[%zu], input_index[%zu], binding_index[%d], " | ||
| 1237 | - "external_binding_num[%zu], input_null[%d].", | ||
| 1238 | - AICPUE_ERROR_CODE, node_index, j, binding_index, external_binding_num, | ||
| 1239 | - static_cast<int32_t>(desc.inputs[j] == nullptr)); | ||
| 1240 | - return -1; | ||
| 1241 | - } | ||
| 1242 | - } | ||
| 1243 | - return 0; | ||
| 1244 | -} | ||
| 1245 | - | ||
| 1246 | -int32_t AddFusedChainOutputBindings(const FusedCpuKernelChainNodeDesc &desc, const size_t node_index, | ||
| 1247 | - const size_t external_binding_num, FusedCpuKernelChainNode &node, | ||
| 1248 | - FusedCpuKernelChainPlan &chain) { | ||
| 1249 | - for (size_t j = 0U; j < desc.output_num; ++j) { | ||
| 1250 | - const int32_t binding_index = | ||
| 1251 | - (desc.output_binding_indices == nullptr) ? static_cast<int32_t>(j) : desc.output_binding_indices[j]; | ||
| 1252 | - if ((binding_index >= 0) && (static_cast<size_t>(binding_index) < external_binding_num) && | ||
| 1253 | - (desc.outputs[j] != nullptr)) { | ||
| 1254 | - chain.bindings.push_back({desc.outputs[j], node.plan.output_tensors[j], &node.plan.output_states[j], | ||
| 1255 | - static_cast<size_t>(binding_index)}); | ||
| 1256 | - } else if ((binding_index >= 0) && | ||
| 1257 | - ((desc.outputs[j] == nullptr) || (static_cast<size_t>(binding_index) >= external_binding_num))) { | ||
| 1258 | - AICPUE_LOGE( | ||
| 1259 | - "Invalid fused output binding: node_index[%zu], output_index[%zu], binding_index[%d], " | ||
| 1260 | - "external_binding_num[%zu], output_null[%d].", | ||
| 1261 | - AICPUE_ERROR_CODE, node_index, j, binding_index, external_binding_num, | ||
| 1262 | - static_cast<int32_t>(desc.outputs[j] == nullptr)); | ||
| 1263 | - return -1; | ||
| 1264 | - } | ||
| 1265 | - } | ||
| 1266 | - return 0; | ||
| 1267 | -} | ||
| 1268 | - | ||
| 1269 | -int32_t InitializeFusedChainNode(const FusedCpuKernelChainNodeDesc &desc, const size_t node_index, | ||
| 1270 | - const size_t external_binding_num, FusedCpuKernelChainPlan &chain) { | ||
| 1271 | - if ((desc.op == nullptr) || ((desc.input_num != 0U) && (desc.inputs == nullptr)) || | ||
| 1272 | - ((desc.output_num != 0U) && (desc.outputs == nullptr))) { | ||
| 1273 | - AICPUE_LOGE( | ||
| 1274 | - "Invalid fused CPU chain node descriptor: node_index[%zu], op_null[%d], input_num[%zu], " | ||
| 1275 | - "inputs_null[%d], output_num[%zu], outputs_null[%d].", | ||
| 1276 | - AICPUE_ERROR_CODE, node_index, static_cast<int32_t>(desc.op == nullptr), desc.input_num, | ||
| 1277 | - static_cast<int32_t>(desc.inputs == nullptr), desc.output_num, static_cast<int32_t>(desc.outputs == nullptr)); | ||
| 1278 | - return -1; | ||
| 1279 | - } | ||
| 1280 | - chain.nodes.emplace_back(); | ||
| 1281 | - FusedCpuKernelChainNode &node = chain.nodes.back(); | ||
| 1282 | - const int32_t init_ret = | ||
| 1283 | - InitializeFusedCpuKernelPlan(*desc.op, desc.inputs, desc.input_num, desc.outputs, desc.output_num, node.plan); | ||
| 1284 | - if (init_ret != 0) { | ||
| 1285 | - AICPUE_LOGE("Initialize fused CPU kernel plan failed: node_index[%zu], input_num[%zu], output_num[%zu], ret[%d].", | ||
| 1286 | - AICPUE_ERROR_CODE, node_index, desc.input_num, desc.output_num, init_ret); | ||
| 1287 | - return -1; | ||
| 1288 | - } | ||
| 1289 | - if ((node.plan.input_tensors.size() != desc.input_num) || (node.plan.input_states.size() != desc.input_num) || | ||
| 1290 | - (node.plan.output_tensors.size() != desc.output_num) || (node.plan.output_states.size() != desc.output_num)) { | ||
| 1291 | - AICPUE_LOGE( | ||
| 1292 | - "Fused CPU kernel plan size mismatch: node_index[%zu], expected inputs[%zu], input_states[%zu], " | ||
| 1293 | - "outputs[%zu], output_states[%zu], actual inputs[%zu], input_states[%zu], outputs[%zu], " | ||
| 1294 | - "output_states[%zu].", | ||
| 1295 | - AICPUE_ERROR_CODE, node_index, desc.input_num, desc.input_num, desc.output_num, desc.output_num, | ||
| 1296 | - node.plan.input_tensors.size(), node.plan.input_states.size(), node.plan.output_tensors.size(), | ||
| 1297 | - node.plan.output_states.size()); | ||
| 1298 | - return -1; | ||
| 1299 | - } | ||
| 1300 | - return (AddFusedChainInputBindings(desc, node_index, external_binding_num, node, chain) == 0) && | ||
| 1301 | - (AddFusedChainOutputBindings(desc, node_index, external_binding_num, node, chain) == 0) | ||
| 1302 | - ? 0 | ||
| 1303 | - : -1; | ||
| 1304 | -} | ||
| 1305 | - | ||
| 1306 | -__attribute__((visibility("default"))) void *CreateCpuConstantFoldingFusedChainPlan(const void *node_descs, | ||
| 1307 | - const size_t node_num, | ||
| 1308 | - const size_t external_input_num, | ||
| 1309 | - const size_t external_output_num) { | ||
| 1310 | - if ((node_descs == nullptr) || (node_num == 0U)) { | ||
| 1311 | - AICPUE_LOGE( | ||
| 1312 | - "Invalid fused CPU chain plan arguments: node_descs_null[%d], node_num[%zu], external_inputs[%zu], " | ||
| 1313 | - "external_outputs[%zu].", | ||
| 1314 | - AICPUE_ERROR_CODE, static_cast<int32_t>(node_descs == nullptr), node_num, external_input_num, | ||
| 1315 | - external_output_num); | ||
| 1316 | - return nullptr; | ||
| 1317 | - } | ||
| 1318 | - const auto *descs = static_cast<const FusedCpuKernelChainNodeDesc *>(node_descs); | ||
| 1319 | - std::unique_ptr<FusedCpuKernelChainPlan> chain = std::make_unique<FusedCpuKernelChainPlan>(); | ||
| 1320 | - | ||
| 1321 | - // 防止计算外部 binding 数量时发生 size_t 整数溢出 | ||
| 1322 | - if (external_input_num > (std::numeric_limits<size_t>::max() - external_output_num)) { | ||
| 1323 | - AICPUE_LOGE("Fused CPU chain external binding count overflows size_t: external_inputs[%zu], external_outputs[%zu].", | ||
| 1324 | - AICPUE_ERROR_CODE, external_input_num, external_output_num); | ||
| 1325 | - return nullptr; | ||
| 1326 | - } | ||
| 1327 | - const size_t external_binding_num = external_input_num + external_output_num; | ||
| 1328 | - chain->nodes.reserve(node_num); | ||
| 1329 | - size_t binding_capacity = 0U; | ||
| 1330 | - if (CalculateFusedChainBindingCapacity(descs, node_num, binding_capacity) != 0) { | ||
| 1331 | - return nullptr; | ||
| 1332 | - } | ||
| 1333 | - chain->bindings.reserve(binding_capacity); | ||
| 1334 | - for (size_t i = 0U; i < node_num; ++i) { | ||
| 1335 | - if (InitializeFusedChainNode(descs[i], i, external_binding_num, *chain) != 0) { | ||
| 1336 | - return nullptr; | ||
| 1337 | - } | ||
| 1338 | - } | ||
| 1339 | - AICPUE_LOGD("Created fused cpu chain execution plan, nodes[%zu], dynamic bindings[%zu].", node_num, | ||
| 1340 | - chain->bindings.size()); | ||
| 1341 | - return chain.release(); | ||
| 1342 | -} | ||
| 1343 | - | ||
| 1344 | -__attribute__((visibility("default"))) int32_t RunCpuConstantFoldingFusedChainPlan(void *plan, | ||
| 1345 | - const uint32_t binding_flags) { | ||
| 1346 | - FusedCpuKernelChainPlan *chain = static_cast<FusedCpuKernelChainPlan *>(plan); | ||
| 1347 | - if (chain == nullptr) { | ||
| 1348 | - AICPUE_LOGE("Run fused CPU chain plan received null plan: binding_flags[%u].", AICPUE_ERROR_CODE, binding_flags); | ||
| 1349 | - return -1; | ||
| 1350 | - } | ||
| 1351 | - if (binding_flags != 0U) { | ||
| 1352 | - for (FusedCpuKernelBinding &binding : chain->bindings) { | ||
| 1353 | - if (RebindFusedTensorByFlags(*binding.source, binding.target, *binding.state, binding_flags) != 0) { | ||
| 1354 | - AICPUE_LOGE("Failed to rebind fused CPU chain binding: binding_index[%zu], flags[%u].", AICPUE_ERROR_CODE, | ||
| 1355 | - binding.binding_index, binding_flags); | ||
| 1356 | - return -1; | ||
| 1357 | - } | ||
| 1358 | - } | ||
| 1359 | - } | ||
| 1360 | - for (size_t node_index = 0U; node_index < chain->nodes.size(); ++node_index) { | ||
| 1361 | - if (RunFusedCpuKernelPlan(chain->nodes[node_index].plan) != 0) { | ||
| 1362 | - AICPUE_LOGE("Failed to run fused CPU chain node: node_index[%zu], node_count[%zu].", AICPUE_ERROR_CODE, | ||
| 1363 | - node_index, chain->nodes.size()); | ||
| 1364 | - return -1; | ||
| 1365 | - } | ||
| 1366 | - } | ||
| 1367 | - return 0; | ||
| 1368 | -} | ||
| 1369 | - | ||
| 1370 | -__attribute__((visibility("default"))) int32_t | ||
| 1371 | -RunCpuConstantFoldingFusedChainPlanBindings(void *plan, const void *binding_data, const uint32_t binding_flags) { | ||
| 1372 | - FusedCpuKernelChainPlan *chain = static_cast<FusedCpuKernelChainPlan *>(plan); | ||
| 1373 | - if (chain == nullptr) { | ||
| 1374 | - AICPUE_LOGE("Run fused CPU chain bindings received null plan: binding_flags[%u].", AICPUE_ERROR_CODE, | ||
| 1375 | - binding_flags); | ||
| 1376 | - return -1; | ||
| 1377 | - } | ||
| 1378 | - if (binding_flags != 0U) { | ||
| 1379 | - if (binding_data == nullptr) { | ||
| 1380 | - AICPUE_LOGE("Run fused CPU chain bindings received null binding data: binding_flags[%u], binding_count[%zu].", | ||
| 1381 | - AICPUE_ERROR_CODE, binding_flags, chain->bindings.size()); | ||
| 1382 | - return -1; | ||
| 1383 | - } | ||
| 1384 | - const auto *bindings = static_cast<const FusedHostCpuTensorBinding *>(binding_data); | ||
| 1385 | - for (FusedCpuKernelBinding &binding : chain->bindings) { | ||
| 1386 | - const FusedHostCpuTensorBinding *runtime_binding = &bindings[binding.binding_index]; | ||
| 1387 | - if ((runtime_binding->flags != 0U) && | ||
| 1388 | - (RebindFusedTensorByBinding(*runtime_binding, binding.target, *binding.state) != 0)) { | ||
| 1389 | - AICPUE_LOGE( | ||
| 1390 | - "Failed to rebind fused CPU runtime binding: binding_index[%zu], runtime_flags[%u], " | ||
| 1391 | - "global_flags[%u].", | ||
| 1392 | - AICPUE_ERROR_CODE, binding.binding_index, runtime_binding->flags, binding_flags); | ||
| 1393 | - return -1; | ||
| 1394 | - } | ||
| 1395 | - } | ||
| 1396 | - } | ||
| 1397 | - for (size_t node_index = 0U; node_index < chain->nodes.size(); ++node_index) { | ||
| 1398 | - if (RunFusedCpuKernelPlan(chain->nodes[node_index].plan) != 0) { | ||
| 1399 | - AICPUE_LOGE("Failed to run fused CPU chain node with runtime bindings: node_index[%zu], node_count[%zu].", | ||
| 1400 | - AICPUE_ERROR_CODE, node_index, chain->nodes.size()); | ||
| 1401 | - return -1; | ||
| 1402 | - } | ||
| 1403 | - } | ||
| 1404 | - return 0; | ||
| 1405 | -} | ||
| 1406 | - | ||
| 1407 | -__attribute__((visibility("default"))) void DestroyCpuConstantFoldingFusedChainPlan(void *plan) { | ||
| 1408 | - delete static_cast<FusedCpuKernelChainPlan *>(plan); | ||
| 1409 | -} | ||
| 1410 | } | 700 | } |
| @@ -17,7 +17,6 @@ | |||
| 17 | 17 | ||
| 18 | 18 | ||
| 19 | 19 | ||
| 20 | - | ||
| 21 | 20 | ||
| 22 | 21 | ||
| 23 | 22 | ||
| @@ -28,23 +27,8 @@ | |||
| 28 | extern "C" { | 27 | extern "C" { |
| 29 | __attribute__((visibility("default"))) int32_t InitCpuConstantFoldingNew(ge::HostCpuOp *(*create_fn)()); | 28 | __attribute__((visibility("default"))) int32_t InitCpuConstantFoldingNew(ge::HostCpuOp *(*create_fn)()); |
| 30 | 29 | ||
| 31 | -__attribute__((visibility("default"))) int32_t IsCpuConstantFoldingFusedOpSupported(const char *op_type); | ||
| 32 | - | ||
| 33 | __attribute__((visibility("default"))) int32_t | 30 | __attribute__((visibility("default"))) int32_t |
| 34 | CpuConstantFoldingComputeNew(const ge::Operator &op, const std::map<std::string, const ge::Tensor> &inputs, | 31 | CpuConstantFoldingComputeNew(const ge::Operator &op, const std::map<std::string, const ge::Tensor> &inputs, |
| 35 | std::map<std::string, ge::Tensor> outputs); | 32 | std::map<std::string, ge::Tensor> outputs); |
| 36 | - | ||
| 37 | -__attribute__((visibility("default"))) void *CreateCpuConstantFoldingFusedChainPlan(const void *node_descs, | ||
| 38 | - size_t node_num, | ||
| 39 | - size_t external_input_num, | ||
| 40 | - size_t external_output_num); | ||
| 41 | - | ||
| 42 | -__attribute__((visibility("default"))) int32_t RunCpuConstantFoldingFusedChainPlan(void *plan, uint32_t binding_flags); | ||
| 43 | - | ||
| 44 | -__attribute__((visibility("default"))) int32_t RunCpuConstantFoldingFusedChainPlanBindings(void *plan, | ||
| 45 | - const void *bindings, | ||
| 46 | - uint32_t binding_flags); | ||
| 47 | - | ||
| 48 | -__attribute__((visibility("default"))) void DestroyCpuConstantFoldingFusedChainPlan(void *plan); | ||
| 49 | } | 33 | } |
| 50 | 34 | ||
| @@ -28,7 +28,6 @@ | |||
| 28 | 28 | ||
| 29 | 29 | ||
| 30 | 30 | ||
| 31 | - | ||
| 32 | 31 | ||
| 33 | using namespace std; | 32 | using namespace std; |
| 34 | using namespace ge; | 33 | using namespace ge; |
| @@ -280,24 +279,12 @@ static ge::Status FillOutputTensorOfAicpuNodeDef(const ge::OpDescPtr &op_desc_pt | |||
| 280 | aicpu_shape->set_data_format(static_cast<ge::Format>(output_desc.GetFormat())); | 279 | aicpu_shape->set_data_format(static_cast<ge::Format>(output_desc.GetFormat())); |
| 281 | aicpu_shape->set_unknown_rank(is_unknow_shape); | 280 | aicpu_shape->set_unknown_rank(is_unknow_shape); |
| 282 | output_tensor->set_tensor_type(static_cast<ge::DataType>(output_desc.GetDataType())); | 281 | output_tensor->set_tensor_type(static_cast<ge::DataType>(output_desc.GetDataType())); |
| 283 | - if (op_desc_ptr->GetType() == ge::kFusedHostCpuOpType) { | ||
| 284 | - output_tensor->set_name(op_desc_ptr->GetOutputNameByIndex(static_cast<uint32_t>(i))); | ||
| 285 | - } | ||
| 286 | } | 282 | } |
| 287 | return ge::SUCCESS; | 283 | return ge::SUCCESS; |
| 288 | } | 284 | } |
| 289 | 285 | ||
| 290 | ge::Status BuildAicpuNodeDef(const ge::OpDescPtr &op_desc_ptr, aicpuops::NodeDef &node_def) { | 286 | ge::Status BuildAicpuNodeDef(const ge::OpDescPtr &op_desc_ptr, aicpuops::NodeDef &node_def) { |
| 291 | std::string op_type = op_desc_ptr->GetType(); | 287 | std::string op_type = op_desc_ptr->GetType(); |
| 292 | - // 将通用节点类型替换成动态 Kernel 注册名 | ||
| 293 | - if (op_type == ge::kFusedHostCpuOpType) { | ||
| 294 | - if (!ge::AttrUtils::GetStr(op_desc_ptr, ge::kFusedHostCpuRegisterName, op_type) || op_type.empty()) { | ||
| 295 | - AICPUE_LOGE("Get fused HostCPU register name failed for op [%s].", op_desc_ptr->GetName().c_str()); | ||
| 296 | - return ge::PARAM_INVALID; | ||
| 297 | - } | ||
| 298 | - AICPUE_LOGD("Resolve fused HostCPU node[%s] to dynamic kernel[%s].", op_desc_ptr->GetName().c_str(), | ||
| 299 | - op_type.c_str()); | ||
| 300 | - } | ||
| 301 | node_def.set_op(op_type); | 288 | node_def.set_op(op_type); |
| 302 | 289 | ||
| 303 | bool is_unknow_shape = false; | 290 | bool is_unknow_shape = false; |
Mcompiler/engines/cpu_engine/cpu_engine/hostcpu_engine/kernel_builder/hostcpu_ops_kernel_builder.cpp+2-17
| @@ -13,11 +13,9 @@ | |||
| 13 | 13 | ||
| 14 | 14 | ||
| 15 | 15 | ||
| 16 | - | ||
| 17 | 16 | ||
| 18 | 17 | ||
| 19 | 18 | ||
| 20 | - | ||
| 21 | 19 | ||
| 22 | 20 | ||
| 23 | 21 | ||
| @@ -63,6 +61,7 @@ ge::Status HostCpuOpsKernelBuilder::CalcOpRunningParam(ge::Node &node) { | |||
| 63 | ge::OpDescUtilsEx::SetType(op_desc_ptr, *op_original_type); | 61 | ge::OpDescUtilsEx::SetType(op_desc_ptr, *op_original_type); |
| 64 | op_type = *op_original_type; | 62 | op_type = *op_original_type; |
| 65 | } | 63 | } |
| 64 | + | ||
| 66 | FACTORY_ENGINE::FactoryType host_engine_ptr = FACTORY_ENGINE::Produce(engine_name_); | 65 | FACTORY_ENGINE::FactoryType host_engine_ptr = FACTORY_ENGINE::Produce(engine_name_); |
| 67 | AICPU_CHECK_NOTNULL_ERRCODE(host_engine_ptr, ErrorCode::INPUT_PARAM_NULL) | 66 | AICPU_CHECK_NOTNULL_ERRCODE(host_engine_ptr, ErrorCode::INPUT_PARAM_NULL) |
| 68 | AicpuOpsKernelInfoStorePtr host_ops_kernel_info_store_ptr = host_engine_ptr->GetAicpuOpsKernelInfoStore(); | 67 | AicpuOpsKernelInfoStorePtr host_ops_kernel_info_store_ptr = host_engine_ptr->GetAicpuOpsKernelInfoStore(); |
| @@ -78,17 +77,7 @@ ge::Status HostCpuOpsKernelBuilder::CalcOpRunningParam(ge::Node &node) { | |||
| 78 | AICPUE_LOGI("Node[%s] set attr optional_input_placeholder is [%s]", node.GetName().c_str(), | 77 | AICPUE_LOGI("Node[%s] set attr optional_input_placeholder is [%s]", node.GetName().c_str(), |
| 79 | optional_input ? "true" : "false"); | 78 | optional_input ? "true" : "false"); |
| 80 | } | 79 | } |
| 81 | - if ((op_type == ge::kFusedHostCpuOpType) && !ge::AttrUtils::HasAttr(op_desc_ptr, kCustomizedOpDef)) { | 80 | + |
| 82 | - // 首次构建时将动态注册名和完整 IO 描述写入 NodeDef,后续沿用通用 HostCPU TaskDef 生成流程。 | ||
| 83 | - AICPUE_LOGD("Build customized NodeDef for fused HostCPU node[%s], inputs[%zu], outputs[%zu].", | ||
| 84 | - node.GetName().c_str(), op_desc_ptr->GetAllInputsSize(), op_desc_ptr->GetOutputsSize()); | ||
| 85 | - aicpuops::NodeDef node_def; | ||
| 86 | - AICPU_CHECK_RES_WITH_LOG(BuildAicpuNodeDef(op_desc_ptr, node_def), "Build NodeDef for fused HostCPU op[%s] failed.", | ||
| 87 | - node.GetName().c_str()); | ||
| 88 | - AICPU_CHECK_RES_WITH_LOG(InsertAicpuNodeDefAttrToOp(op_desc_ptr, node_def, kCustomizedOpDef), | ||
| 89 | - "Serialize NodeDef for fused HostCPU op[%s] failed.", node.GetName().c_str()); | ||
| 90 | - AICPUE_LOGD("Customized NodeDef is ready for fused HostCPU node[%s].", node.GetName().c_str()); | ||
| 91 | - } | ||
| 92 | const KernelBuilderPtr &kernel_builder = kernel_builder_map_["HOSTCPUBuilder"]; | 81 | const KernelBuilderPtr &kernel_builder = kernel_builder_map_["HOSTCPUBuilder"]; |
| 93 | AICPU_CHECK_NOTNULL_ERRCODE(kernel_builder, ErrorCode::NONE_KERNEL_BUILDER); | 82 | AICPU_CHECK_NOTNULL_ERRCODE(kernel_builder, ErrorCode::NONE_KERNEL_BUILDER); |
| 94 | return kernel_builder->CalcOpRunningParam(node); | 83 | return kernel_builder->CalcOpRunningParam(node); |
| @@ -112,10 +101,6 @@ ge::Status HostCpuOpsKernelBuilder::GenerateTask(const ge::Node &ge_node, ge::Ru | |||
| 112 | 101 | ||
| 113 | const KernelBuilderPtr &kernel_builder = kernel_builder_map_["HOSTCPUBuilder"]; | 102 | const KernelBuilderPtr &kernel_builder = kernel_builder_map_["HOSTCPUBuilder"]; |
| 114 | AICPU_CHECK_NOTNULL_ERRCODE(kernel_builder, ErrorCode::NONE_KERNEL_BUILDER); | 103 | AICPU_CHECK_NOTNULL_ERRCODE(kernel_builder, ErrorCode::NONE_KERNEL_BUILDER); |
| 115 | - if (op_type == ge::kFusedHostCpuOpType) { | ||
| 116 | - // TaskDef 仍走通用 HOSTCPUBuilder;其中的 NodeDef 已将公共类型替换为 JIT kernel 注册名。 | ||
| 117 | - AICPUE_LOGD("Generate generic HostCPU task for fused node[%s].", ge_node.GetName().c_str()); | ||
| 118 | - } | ||
| 119 | return kernel_builder->GenerateTask(ge_node, context, tasks); | 104 | return kernel_builder->GenerateTask(ge_node, context, tasks); |
| 120 | } | 105 | } |
| 121 | 106 | ||
| @@ -34,6 +34,7 @@ | |||
| 34 | 34 | ||
| 35 | 35 | ||
| 36 | 36 | ||
| 37 | + | ||
| 37 | 38 | ||
| 38 | namespace ge { | 39 | namespace ge { |
| 39 | namespace { | 40 | namespace { |
| @@ -50,6 +51,7 @@ const char_t *const kAnchorIndex = "anchorIndex"; | |||
| 50 | const char_t *const kTaskL2FusionInfo = "_task_L2FusionInfo"; | 51 | const char_t *const kTaskL2FusionInfo = "_task_L2FusionInfo"; |
| 51 | const char_t *const kDataAnchorIndexForLxfusion = "_data_anchor_index_for_lxfusion"; | 52 | const char_t *const kDataAnchorIndexForLxfusion = "_data_anchor_index_for_lxfusion"; |
| 52 | const char_t *const kEnableCvParallel = "_enable_cv_parallel"; | 53 | const char_t *const kEnableCvParallel = "_enable_cv_parallel"; |
| 54 | +const char_t *const kSoBufferAttr = "bin_file_buffer"; | ||
| 53 | const char_t *const kVectorEngineName = "VectorEngine"; | 55 | const char_t *const kVectorEngineName = "VectorEngine"; |
| 54 | const char_t *const kHostCpuEngineName = "DNN_VM_HOST_CPU"; | 56 | const char_t *const kHostCpuEngineName = "DNN_VM_HOST_CPU"; |
| 55 | const std::string kStableRdfsSort = "3"; | 57 | const std::string kStableRdfsSort = "3"; |
| @@ -480,6 +482,20 @@ Status EnginePartitioner::InheritOriginalAttr(const ComputeGraphPtr &original_co | |||
| 480 | output_merged_compute_graph->SetExtAttr(ge::ATTR_NAME_DEVICE_INDEX_TO_LOGIC_DEVICE_ID, *device_mapping)); | 482 | output_merged_compute_graph->SetExtAttr(ge::ATTR_NAME_DEVICE_INDEX_TO_LOGIC_DEVICE_ID, *device_mapping)); |
| 481 | } | 483 | } |
| 482 | 484 | ||
| 485 | + // HostCPU fusion stores generated custom-op SOs in this ext attr. The merge step | ||
| 486 | + // creates a new graph, so preserve the buffer together with the graph attrs. | ||
| 487 | + const auto so_buffer = original_compute_graph->GetExtAttr<std::map<std::string, ge::OpSoBinPtr>>(kSoBufferAttr); | ||
| 488 | + if (so_buffer != nullptr) { | ||
| 489 | + std::map<std::string, ge::OpSoBinPtr> merged_so_buffer; | ||
| 490 | + const auto existing_so_buffer = | ||
| 491 | + output_merged_compute_graph->GetExtAttr<std::map<std::string, ge::OpSoBinPtr>>(kSoBufferAttr); | ||
| 492 | + if (existing_so_buffer != nullptr) { | ||
| 493 | + merged_so_buffer = *existing_so_buffer; | ||
| 494 | + } | ||
| 495 | + merged_so_buffer.insert(so_buffer->begin(), so_buffer->end()); | ||
| 496 | + GE_ASSERT_TRUE(output_merged_compute_graph->SetExtAttr(kSoBufferAttr, merged_so_buffer)); | ||
| 497 | + } | ||
| 498 | + | ||
| 483 | // AttrStore里面属性组没有被拷贝,并且没有提供CopyAllAttrStore方法,暂时先手动拷贝必须的 | 499 | // AttrStore里面属性组没有被拷贝,并且没有提供CopyAllAttrStore方法,暂时先手动拷贝必须的 |
| 484 | auto origin_shape_env_attr = original_compute_graph->GetAttrsGroup<ShapeEnvAttr>(); | 500 | auto origin_shape_env_attr = original_compute_graph->GetAttrsGroup<ShapeEnvAttr>(); |
| 485 | if (origin_shape_env_attr != nullptr) { | 501 | if (origin_shape_env_attr != nullptr) { |
| @@ -12,11 +12,9 @@ | |||
| 12 | 12 | ||
| 13 | 13 | ||
| 14 | 14 | ||
| 15 | - | ||
| 16 | 15 | ||
| 17 | 16 | ||
| 18 | 17 | ||
| 19 | - | ||
| 20 | 18 | ||
| 21 | 19 | ||
| 22 | 20 | ||
| @@ -36,6 +34,8 @@ | |||
| 36 | 34 | ||
| 37 | 35 | ||
| 38 | 36 | ||
| 37 | + | ||
| 38 | + | ||
| 39 | 39 | ||
| 40 | 40 | ||
| 41 | namespace ge { | 41 | namespace ge { |
| @@ -86,54 +86,6 @@ std::string EscapeCppString(const std::string &value) { | |||
| 86 | return os.str(); | 86 | return os.str(); |
| 87 | } | 87 | } |
| 88 | 88 | ||
| 89 | -std::string RangeExpression(const std::vector<std::pair<int64_t, int64_t>> &ranges) { | ||
| 90 | - std::ostringstream os; | ||
| 91 | - os << "std::vector<std::pair<int64_t, int64_t>>{"; | ||
| 92 | - for (size_t i = 0U; i < ranges.size(); ++i) { | ||
| 93 | - if (i != 0U) { | ||
| 94 | - os << ", "; | ||
| 95 | - } | ||
| 96 | - os << "{" << IntExpression(ranges[i].first) << ", " << IntExpression(ranges[i].second) << "}"; | ||
| 97 | - } | ||
| 98 | - os << "}"; | ||
| 99 | - return os.str(); | ||
| 100 | -} | ||
| 101 | - | ||
| 102 | -std::string TensorDescExpression(const GeTensorDesc &desc) { | ||
| 103 | - std::ostringstream os; | ||
| 104 | - os << "([]() { ge::TensorDesc desc(ge::Shape(std::vector<int64_t>{"; | ||
| 105 | - const auto dims = desc.GetShape().GetDims(); | ||
| 106 | - for (size_t i = 0U; i < dims.size(); ++i) { | ||
| 107 | - if (i != 0U) { | ||
| 108 | - os << ", "; | ||
| 109 | - } | ||
| 110 | - os << dims[i]; | ||
| 111 | - } | ||
| 112 | - os << "}), static_cast<ge::Format>(" << static_cast<int32_t>(desc.GetFormat()) << "), static_cast<ge::DataType>(" | ||
| 113 | - << static_cast<int32_t>(desc.GetDataType()) << ")); "; | ||
| 114 | - if (desc.IsOriginShapeInitialized()) { | ||
| 115 | - os << "desc.SetOriginShape(ge::Shape(std::vector<int64_t>{"; | ||
| 116 | - const auto origin_dims = desc.GetOriginShape().GetDims(); | ||
| 117 | - for (size_t i = 0U; i < origin_dims.size(); ++i) { | ||
| 118 | - if (i != 0U) { | ||
| 119 | - os << ", "; | ||
| 120 | - } | ||
| 121 | - os << origin_dims[i]; | ||
| 122 | - } | ||
| 123 | - os << "})); "; | ||
| 124 | - } | ||
| 125 | - os << "desc.SetOriginFormat(static_cast<ge::Format>(" << static_cast<int32_t>(desc.GetOriginFormat()) | ||
| 126 | - << ")); desc.SetName(std::string(\"" << EscapeCppString(desc.GetName()) << "\", " << desc.GetName().size() | ||
| 127 | - << "U)); desc.SetExpandDimsRule(ge::AscendString(\"" << EscapeCppString(desc.GetExpandDimsRule()) | ||
| 128 | - << "\")); desc.SetPlacement(static_cast<ge::Placement>(" << static_cast<int32_t>(desc.GetPlacement()) << ")); "; | ||
| 129 | - std::vector<std::pair<int64_t, int64_t>> ranges; | ||
| 130 | - if ((desc.GetShapeRange(ranges) == GRAPH_SUCCESS) && !ranges.empty()) { | ||
| 131 | - os << "(void)desc.SetShapeRange(" << RangeExpression(ranges) << "); "; | ||
| 132 | - } | ||
| 133 | - os << "return desc; }())"; | ||
| 134 | - return os.str(); | ||
| 135 | -} | ||
| 136 | - | ||
| 137 | Status GetTensorSize(const GeTensorDesc &desc, size_t &size) { | 89 | Status GetTensorSize(const GeTensorDesc &desc, size_t &size) { |
| 138 | const auto &shape = desc.GetShape(); | 90 | const auto &shape = desc.GetShape(); |
| 139 | if (shape.IsUnknownShape()) { | 91 | if (shape.IsUnknownShape()) { |
| @@ -158,43 +110,6 @@ std::string IntExpression(const int64_t value) { | |||
| 158 | return std::to_string(value) + "LL"; | 110 | return std::to_string(value) + "LL"; |
| 159 | } | 111 | } |
| 160 | 112 | ||
| 161 | -std::string IntVectorExpression(const std::vector<int64_t> &values) { | ||
| 162 | - std::ostringstream os; | ||
| 163 | - os << "{"; | ||
| 164 | - for (size_t i = 0U; i < values.size(); ++i) { | ||
| 165 | - if (i != 0U) { | ||
| 166 | - os << ", "; | ||
| 167 | - } | ||
| 168 | - os << IntExpression(values[i]); | ||
| 169 | - } | ||
| 170 | - os << "}"; | ||
| 171 | - return os.str(); | ||
| 172 | -} | ||
| 173 | - | ||
| 174 | -std::string FloatExpression(const float value) { | ||
| 175 | - std::ostringstream os; | ||
| 176 | - os.imbue(std::locale::classic()); | ||
| 177 | - os << std::setprecision(std::numeric_limits<float>::max_digits10) << value; | ||
| 178 | - std::string expression = os.str(); | ||
| 179 | - if (expression.find_first_of(".eE") == std::string::npos) { | ||
| 180 | - expression += ".0"; | ||
| 181 | - } | ||
| 182 | - return expression + "F"; | ||
| 183 | -} | ||
| 184 | - | ||
| 185 | -std::string FloatVectorExpression(const std::vector<float> &values) { | ||
| 186 | - std::ostringstream os; | ||
| 187 | - os << "{"; | ||
| 188 | - for (size_t i = 0U; i < values.size(); ++i) { | ||
| 189 | - if (i != 0U) { | ||
| 190 | - os << ", "; | ||
| 191 | - } | ||
| 192 | - os << FloatExpression(values[i]); | ||
| 193 | - } | ||
| 194 | - os << "}"; | ||
| 195 | - return os.str(); | ||
| 196 | -} | ||
| 197 | - | ||
| 198 | 113 | ||
| 199 | constexpr size_t kMaxGeneratedSoSize = 10U * 1024U * 1024U; | 114 | constexpr size_t kMaxGeneratedSoSize = 10U * 1024U * 1024U; |
| 200 | 115 | ||
| @@ -338,12 +253,16 @@ bool HasHeader(const std::vector<std::string> &include_paths, const std::string | |||
| 338 | } | 253 | } |
| 339 | 254 | ||
| 340 | bool CheckRequiredHeaders(const std::vector<std::string> &include_paths) { | 255 | bool CheckRequiredHeaders(const std::vector<std::string> &include_paths) { |
| 341 | - static const std::vector<std::string> kRequiredHeaders = {"aicpu/cpu_kernels/cpu_kernel.h", | 256 | + // Keep this list aligned with the headers emitted below. The generated SO only |
| 342 | - "aicpu/cpu_kernels/cpu_kernel_register.h", | 257 | + // uses the public HostCpuExecuteOp/KernelContext ABI; requiring the legacy |
| 343 | - "graph/operator.h", "graph/tensor.h"}; | 258 | + // CpuKernel registration headers made JIT depend on headers it never included. |
| 259 | + static const std::vector<std::string> kRequiredHeaders = { | ||
| 260 | + "exe_graph/runtime/compute_node_info.h", "exe_graph/runtime/gert_tensor_data.h", | ||
| 261 | + "exe_graph/runtime/kernel_context.h", "exe_graph/runtime/kernel_run_context.h", | ||
| 262 | + "exe_graph/runtime/runtime_tensor.h", "graph/custom_op.h"}; | ||
| 344 | for (const auto &header : kRequiredHeaders) { | 263 | for (const auto &header : kRequiredHeaders) { |
| 345 | if (!HasHeader(include_paths, header)) { | 264 | if (!HasHeader(include_paths, header)) { |
| 346 | - GELOGE(UNSUPPORTED, "HostCPU fusion JIT header %s was not found, include_paths=%s.", header.c_str(), | 265 | + GELOGW("HostCPU fusion JIT header %s was not found, include_paths=%s.", header.c_str(), |
| 347 | JoinPaths(include_paths).c_str()); | 266 | JoinPaths(include_paths).c_str()); |
| 348 | return false; | 267 | return false; |
| 349 | } | 268 | } |
| @@ -433,674 +352,483 @@ Status HostCpuFusionCodegen::Generate(const HostCpuFusionRegion ®ion, HostCpu | |||
| 433 | region.chain_id.c_str(), region.nodes.size(), region.external_inputs.size(), region.external_outputs.size()); | 352 | region.chain_id.c_str(), region.nodes.size(), region.external_inputs.size(), region.external_outputs.size()); |
| 434 | return PARAM_INVALID; | 353 | return PARAM_INVALID; |
| 435 | } | 354 | } |
| 436 | - | ||
| 437 | - /** chain_id还必须能作为 C++ 标识符的一部分: | ||
| 438 | - * - 不能以数字开头; | ||
| 439 | - * - 只能包含字母、数字和下划线; | ||
| 440 | - * - 最终注册名不能超过 160 字节。 | ||
| 441 | - */ | ||
| 442 | if (((region.chain_id.front() >= '0') && (region.chain_id.front() <= '9')) || | 355 | if (((region.chain_id.front() >= '0') && (region.chain_id.front() <= '9')) || |
| 443 | !std::all_of(region.chain_id.cbegin(), region.chain_id.cend(), | 356 | !std::all_of(region.chain_id.cbegin(), region.chain_id.cend(), |
| 444 | [](const unsigned char ch) { return IsAsciiAlphaNumeric(ch) || (ch == '_'); })) { | 357 | [](const unsigned char ch) { return IsAsciiAlphaNumeric(ch) || (ch == '_'); })) { |
| 445 | GELOGE(PARAM_INVALID, "Invalid HostCPU fusion chain id[%s].", region.chain_id.c_str()); | 358 | GELOGE(PARAM_INVALID, "Invalid HostCPU fusion chain id[%s].", region.chain_id.c_str()); |
| 446 | return PARAM_INVALID; | 359 | return PARAM_INVALID; |
| 447 | } | 360 | } |
| 361 | + | ||
| 448 | const std::string register_name = std::string(kFusedHostCpuOpType) + "_" + region.chain_id; | 362 | const std::string register_name = std::string(kFusedHostCpuOpType) + "_" + region.chain_id; |
| 449 | if (register_name.size() > kMaxRegisterNameSize) { | 363 | if (register_name.size() > kMaxRegisterNameSize) { |
| 450 | GELOGE(PARAM_INVALID, "HostCPU fusion register name is too long: chain[%s], register_name[%s], size[%zu].", | 364 | GELOGE(PARAM_INVALID, "HostCPU fusion register name is too long: chain[%s], register_name[%s], size[%zu].", |
| 451 | region.chain_id.c_str(), register_name.c_str(), register_name.size()); | 365 | region.chain_id.c_str(), register_name.c_str(), register_name.size()); |
| 452 | return PARAM_INVALID; | 366 | return PARAM_INVALID; |
| 453 | } | 367 | } |
| 454 | - GELOGD("Generate HostCPU fusion orchestration: chain=%s, nodes=%zu, inputs=%zu, outputs=%zu.", | ||
| 455 | - region.chain_id.c_str(), region.nodes.size(), region.external_inputs.size(), region.external_outputs.size()); | ||
| 456 | 368 | ||
| 457 | - // 校验节点和 anchor 唯一性,并将图对象映射为稳定的生成代码下标。 | ||
| 458 | std::unordered_map<const Node *, size_t> node_indexes; | 369 | std::unordered_map<const Node *, size_t> node_indexes; |
| 459 | for (size_t i = 0U; i < region.nodes.size(); ++i) { | 370 | for (size_t i = 0U; i < region.nodes.size(); ++i) { |
| 460 | - if ((region.nodes[i] == nullptr) || (region.nodes[i]->GetOpDesc() == nullptr)) { | 371 | + if ((region.nodes[i] == nullptr) || (region.nodes[i]->GetOpDesc() == nullptr) || |
| 461 | - GELOGE(PARAM_INVALID, "Invalid HostCPU fusion node: chain[%s], node_index[%zu], node_null[%d], op_desc_null[%d].", | 372 | + !node_indexes.emplace(region.nodes[i].get(), i).second) { |
| 462 | - region.chain_id.c_str(), i, static_cast<int32_t>(region.nodes[i] == nullptr), | 373 | + GELOGE(PARAM_INVALID, "Invalid or duplicate HostCPU fusion node: chain[%s], node_index[%zu].", |
| 463 | - static_cast<int32_t>((region.nodes[i] != nullptr) && (region.nodes[i]->GetOpDesc() == nullptr))); | 374 | + region.chain_id.c_str(), i); |
| 464 | - return PARAM_INVALID; | ||
| 465 | - } | ||
| 466 | - if (!node_indexes.emplace(region.nodes[i].get(), i).second) { | ||
| 467 | - GELOGE(PARAM_INVALID, "Duplicate HostCPU fusion node: chain[%s], node_index[%zu], node[%s].", | ||
| 468 | - region.chain_id.c_str(), i, region.nodes[i]->GetNamePtr()); | ||
| 469 | return PARAM_INVALID; | 375 | return PARAM_INVALID; |
| 470 | } | 376 | } |
| 471 | } | 377 | } |
| 378 | + | ||
| 472 | std::unordered_map<const OutDataAnchor *, size_t> input_indexes; | 379 | std::unordered_map<const OutDataAnchor *, size_t> input_indexes; |
| 473 | for (size_t i = 0U; i < region.external_inputs.size(); ++i) { | 380 | for (size_t i = 0U; i < region.external_inputs.size(); ++i) { |
| 474 | - if ((region.external_inputs[i] == nullptr) || | 381 | + const auto &anchor = region.external_inputs[i]; |
| 475 | - (node_indexes.count(region.external_inputs[i]->GetOwnerNode().get()) > 0U)) { | 382 | + if ((anchor == nullptr) || (node_indexes.count(anchor->GetOwnerNode().get()) > 0U) || |
| 476 | - GELOGE(PARAM_INVALID, "Invalid HostCPU fusion external input: chain[%s], input_index[%zu], anchor_null[%d].", | 383 | + !input_indexes.emplace(anchor.get(), i).second) { |
| 477 | - region.chain_id.c_str(), i, static_cast<int32_t>(region.external_inputs[i] == nullptr)); | 384 | + GELOGE(PARAM_INVALID, "Invalid HostCPU fusion external input: chain[%s], input_index[%zu].", |
| 478 | - return PARAM_INVALID; | ||
| 479 | - } | ||
| 480 | - if (!input_indexes.emplace(region.external_inputs[i].get(), i).second) { | ||
| 481 | - GELOGE(PARAM_INVALID, "Duplicate HostCPU fusion external input: chain[%s], input_index[%zu].", | ||
| 482 | region.chain_id.c_str(), i); | 385 | region.chain_id.c_str(), i); |
| 483 | return PARAM_INVALID; | 386 | return PARAM_INVALID; |
| 484 | } | 387 | } |
| 485 | } | 388 | } |
| 389 | + | ||
| 486 | std::unordered_map<const OutDataAnchor *, size_t> output_indexes; | 390 | std::unordered_map<const OutDataAnchor *, size_t> output_indexes; |
| 487 | for (size_t i = 0U; i < region.external_outputs.size(); ++i) { | 391 | for (size_t i = 0U; i < region.external_outputs.size(); ++i) { |
| 488 | - if ((region.external_outputs[i].source == nullptr) || | 392 | + const auto &anchor = region.external_outputs[i].source; |
| 489 | - (node_indexes.count(region.external_outputs[i].source->GetOwnerNode().get()) == 0U)) { | 393 | + if ((anchor == nullptr) || (node_indexes.count(anchor->GetOwnerNode().get()) == 0U) || |
| 490 | - GELOGE(PARAM_INVALID, "Invalid HostCPU fusion external output: chain[%s], output_index[%zu], source_null[%d].", | 394 | + !output_indexes.emplace(anchor.get(), i).second) { |
| 491 | - region.chain_id.c_str(), i, static_cast<int32_t>(region.external_outputs[i].source == nullptr)); | 395 | + GELOGE(PARAM_INVALID, "Invalid HostCPU fusion external output: chain[%s], output_index[%zu].", |
| 492 | - return PARAM_INVALID; | ||
| 493 | - } | ||
| 494 | - if (!output_indexes.emplace(region.external_outputs[i].source.get(), i).second) { | ||
| 495 | - GELOGE(PARAM_INVALID, "Duplicate HostCPU fusion external output: chain[%s], output_index[%zu].", | ||
| 496 | region.chain_id.c_str(), i); | 396 | region.chain_id.c_str(), i); |
| 497 | return PARAM_INVALID; | 397 | return PARAM_INVALID; |
| 498 | } | 398 | } |
| 499 | } | 399 | } |
| 500 | 400 | ||
| 401 | + const auto shape_expression = [](const GeShape &shape) { | ||
| 402 | + std::ostringstream os; | ||
| 403 | + os << "gert::StorageShape({"; | ||
| 404 | + const auto dims = shape.GetDims(); | ||
| 405 | + for (size_t i = 0U; i < dims.size(); ++i) { | ||
| 406 | + if (i != 0U) { | ||
| 407 | + os << ", "; | ||
| 408 | + } | ||
| 409 | + os << IntExpression(dims[i]); | ||
| 410 | + } | ||
| 411 | + os << "}, {"; | ||
| 412 | + for (size_t i = 0U; i < dims.size(); ++i) { | ||
| 413 | + if (i != 0U) { | ||
| 414 | + os << ", "; | ||
| 415 | + } | ||
| 416 | + os << IntExpression(dims[i]); | ||
| 417 | + } | ||
| 418 | + os << "})"; | ||
| 419 | + return os.str(); | ||
| 420 | + }; | ||
| 421 | + const auto format_expression = [](const GeTensorDesc &desc) { | ||
| 422 | + std::ostringstream os; | ||
| 423 | + os << "gert::StorageFormat(static_cast<ge::Format>(" << static_cast<int32_t>(desc.GetOriginFormat()) | ||
| 424 | + << "), static_cast<ge::Format>(" << static_cast<int32_t>(desc.GetFormat()) << "), gert::ExpandDimsType())"; | ||
| 425 | + return os.str(); | ||
| 426 | + }; | ||
| 427 | + const auto emit_bytes = [](const uint8_t *data, const size_t size) { | ||
| 428 | + std::ostringstream os; | ||
| 429 | + os << "{{"; | ||
| 430 | + for (size_t i = 0U; i < size; ++i) { | ||
| 431 | + if (i != 0U) { | ||
| 432 | + os << ", "; | ||
| 433 | + } | ||
| 434 | + os << static_cast<uint32_t>(data[i]) << "U"; | ||
| 435 | + } | ||
| 436 | + os << "}}"; | ||
| 437 | + return os.str(); | ||
| 438 | + }; | ||
| 439 | + | ||
| 440 | + // The generated executor may contain many nodes with the same op type (for example, a | ||
| 441 | + // long Pack chain). Keep one runtime lookup slot per distinct type so the hot path does | ||
| 442 | + // not repeatedly call the HostCPU registry finder. | ||
| 443 | + std::unordered_map<std::string, size_t> kernel_type_indexes; | ||
| 444 | + std::vector<std::string> kernel_types; | ||
| 445 | + kernel_types.reserve(region.nodes.size()); | ||
| 446 | + for (const auto &node : region.nodes) { | ||
| 447 | + const std::string type = node->GetType(); | ||
| 448 | + if (kernel_type_indexes.find(type) == kernel_type_indexes.end()) { | ||
| 449 | + const size_t type_index = kernel_types.size(); | ||
| 450 | + kernel_type_indexes.emplace(type, type_index); | ||
| 451 | + kernel_types.emplace_back(type); | ||
| 452 | + } | ||
| 453 | + } | ||
| 454 | + | ||
| 501 | std::ostringstream code; | 455 | std::ostringstream code; |
| 502 | - code << "#include <array>\n#include <cstddef>\n#include <cstdint>\n#include <cstring>\n#include <limits>\n" | 456 | + code << "#include <algorithm>\n#include <array>\n#include <atomic>\n#include <cstddef>\n#include <cstdint>\n" |
| 503 | - << "#include <memory>\n#include <new>\n#include <string>\n#include <utility>\n#include <vector>\n" | 457 | + << "#include <cstring>\n#include <dlfcn.h>\n#include <memory>\n#include <new>\n" |
| 504 | - << "#include \"aicpu/cpu_kernels/cpu_kernel.h\"\n" | 458 | + << "#include <string>\n#include <vector>\n" |
| 505 | - << "#include \"aicpu/cpu_kernels/cpu_kernel_register.h\"\n" | 459 | + << "#include \"exe_graph/runtime/compute_node_info.h\"\n" |
| 506 | - << "#include \"graph/operator.h\"\n" | 460 | + << "#include \"exe_graph/runtime/gert_tensor_data.h\"\n" |
| 507 | - << "#include \"graph/tensor.h\"\n\n" | 461 | + << "#include \"exe_graph/runtime/kernel_context.h\"\n" |
| 508 | - << "extern \"C\" void *CreateCpuConstantFoldingFusedChainPlan(const void *, size_t, size_t, size_t);\n" | 462 | + << "#include \"exe_graph/runtime/kernel_run_context.h\"\n" |
| 509 | - << "extern \"C\" int32_t RunCpuConstantFoldingFusedChainPlan(void *, uint32_t);\n" | 463 | + << "#include \"exe_graph/runtime/runtime_tensor.h\"\n" |
| 510 | - << "extern \"C\" int32_t RunCpuConstantFoldingFusedChainPlanBindings(void *, const void *, uint32_t);\n" | 464 | + << "#include \"graph/custom_op.h\"\n\n" |
| 511 | - << "extern \"C\" void DestroyCpuConstantFoldingFusedChainPlan(void *);\n\n" | ||
| 512 | << "namespace {\n" | 465 | << "namespace {\n" |
| 513 | - << "struct FusedHostCpuNodePlanDesc {\n" | 466 | + << "using HostKernelFunc = ge::graphStatus (*)(gert::KernelContext *);\n" |
| 514 | - << " const ge::Operator *op;\n" | 467 | + << "using HostKernelFinder = HostKernelFunc (*)(std::string);\n\n" |
| 515 | - << " const ge::Tensor *const *inputs;\n" | 468 | + << "template <size_t InputNum, size_t OutputNum>\n" |
| 516 | - << " size_t input_num;\n" | 469 | + << "class LocalKernelContext final {\n public:\n" |
| 517 | - << " ge::Tensor *const *outputs;\n" | 470 | + << " static constexpr size_t kValueNum = InputNum * 2U + 1U + OutputNum * 2U;\n" |
| 518 | - << " size_t output_num;\n" | 471 | + << " static constexpr size_t kStorageSize = sizeof(KernelRunContext) +\n" |
| 519 | - << " const int32_t *input_binding_indices;\n" | 472 | + << " (kValueNum - 1U) * sizeof(AsyncAnyValue *);\n" |
| 520 | - << " const int32_t *output_binding_indices;\n" | 473 | + << " LocalKernelContext(const gert::ComputeNodeInfo *node_info,\n" |
| 521 | - << "};\n\n" | 474 | + << " const std::array<const gert::Tensor *, InputNum> &inputs,\n" |
| 522 | - << "enum FusedHostCpuBindingFlag : uint32_t {\n" | 475 | + << " const std::array<gert::Tensor *, OutputNum> &outputs, HostKernelFunc func)\n" |
| 523 | - << " kFusedHostCpuShapeChanged = 1U,\n" | 476 | + << " : input_tensor_data_{}, output_tensor_data_{}, values_{}, storage_{} {\n" |
| 524 | - << " kFusedHostCpuDataChanged = 2U\n" | 477 | + << " auto *run = reinterpret_cast<KernelRunContext *>(storage_.data());\n" |
| 525 | - << "};\n\n" | 478 | + << " constexpr size_t input_num = InputNum;\n" |
| 526 | - << "struct FusedHostCpuTensorBinding {\n" | 479 | + << " constexpr size_t output_num = OutputNum;\n" |
| 527 | - << " const int64_t *dims;\n" | 480 | + << " run->input_size = input_num * 2U + 1U;\n" |
| 528 | - << " uint8_t *data;\n" | 481 | + << " run->output_size = output_num * 2U;\n" |
| 529 | - << " size_t dim_num;\n" | 482 | + << " run->compute_node_info = node_info;\n" |
| 530 | - << " size_t data_size;\n" | 483 | + << " run->kernel_extend_info = nullptr;\n" |
| 531 | - << " uint32_t flags;\n" | 484 | + << " for (size_t i = 0U; i < input_num; ++i) {\n" |
| 532 | - << "};\n\n" | 485 | + << " const auto *tensor = inputs[i];\n" |
| 533 | - << "class FusedHostCpuChainPlanGuard {\n public:\n" | 486 | + << " const auto placement = (tensor->GetPlacement() == gert::kFollowing) ? gert::kOnHost :\n" |
| 534 | - << " ~FusedHostCpuChainPlanGuard() { DestroyCpuConstantFoldingFusedChainPlan(plan_); }\n" | 487 | + << " tensor->GetPlacement();\n" |
| 535 | - << " void *Get() const { return plan_; }\n" | 488 | + << " input_tensor_data_[i].MutableTensorData() =\n" |
| 536 | - << " void Reset(void *plan) {\n" | 489 | + << " gert::TensorData(const_cast<void *>(tensor->GetAddr()), nullptr, tensor->GetSize(), placement);\n" |
| 537 | - << " if (plan_ != plan) { DestroyCpuConstantFoldingFusedChainPlan(plan_); plan_ = plan; }\n" | ||
| 538 | - << " }\n" | ||
| 539 | - << " private:\n void *plan_ = nullptr;\n};\n\n" | ||
| 540 | - << "struct FusedHostCpuTensorState {\n" | ||
| 541 | - << " ge::DataType data_type = ge::DT_UNDEFINED;\n" | ||
| 542 | - << " ge::Format format = ge::FORMAT_RESERVED;\n" | ||
| 543 | - << " const void *data = nullptr;\n" | ||
| 544 | - << " size_t data_size = 0U;\n" | ||
| 545 | - << " std::vector<int64_t> dims;\n" | ||
| 546 | - << " bool initialized = false;\n" | ||
| 547 | - << "};\n\n" | ||
| 548 | - << "bool HasSameFusedHostCpuShape(const aicpu::TensorShape &shape,\n" | ||
| 549 | - << " const FusedHostCpuTensorState &state) {\n" | ||
| 550 | - << " const int32_t dim_num = shape.GetDims();\n" | ||
| 551 | - << " if ((dim_num < 0) || (state.dims.size() != static_cast<size_t>(dim_num))) { return false; }\n" | ||
| 552 | - << " for (int32_t i = 0; i < dim_num; ++i) {\n" | ||
| 553 | - << " if (state.dims[static_cast<size_t>(i)] != shape.GetDimSize(i)) { return false; }\n" | ||
| 554 | - << " }\n" | ||
| 555 | - << " return true;\n" | ||
| 556 | - << "}\n\n" | ||
| 557 | - << "bool BuildFusedHostCpuTensor(aicpu::Tensor *source, ge::Tensor &target,\n" | ||
| 558 | - << " FusedHostCpuTensorState &state, bool &changed) {\n" | ||
| 559 | - << " if (source == nullptr) { return false; }\n" | ||
| 560 | - << " const auto shape = source->GetTensorShape();\n" | ||
| 561 | - << " if (shape == nullptr) { return false; }\n" | ||
| 562 | - << " const int32_t dim_num = shape->GetDims();\n" | ||
| 563 | - << " if (dim_num < 0) { return false; }\n" | ||
| 564 | - << " const auto data_type = static_cast<ge::DataType>(source->GetDataType());\n" | ||
| 565 | - << " const auto format = static_cast<ge::Format>(shape->GetFormat());\n" | ||
| 566 | - << " const uint64_t data_size = source->GetDataSize();\n" | ||
| 567 | - << " if ((data_size > static_cast<uint64_t>(std::numeric_limits<size_t>::max())) ||\n" | ||
| 568 | - << " ((data_size != 0U) && (source->GetData() == nullptr))) { return false; }\n" | ||
| 569 | - << " const void *data = source->GetData();\n" | ||
| 570 | - << " const bool rebuild = !state.initialized || (state.data_type != data_type) ||\n" | ||
| 571 | - << " (state.format != format) || !HasSameFusedHostCpuShape(*shape, state) ||\n" | ||
| 572 | - << " ((data_size == 0U) && (state.data_size != 0U));\n" | ||
| 573 | - << " changed = rebuild || (state.data != data) || (state.data_size != data_size);\n" | ||
| 574 | - << " if (rebuild) {\n" | ||
| 575 | - << " state.dims.resize(static_cast<size_t>(dim_num));\n" | ||
| 576 | - << " for (int32_t i = 0; i < dim_num; ++i) {\n" | ||
| 577 | - << " state.dims[static_cast<size_t>(i)] = shape->GetDimSize(i);\n" | ||
| 578 | << " }\n" | 490 | << " }\n" |
| 579 | - << " ge::TensorDesc desc(ge::Shape(state.dims), format, data_type);\n" | 491 | + << " for (size_t i = 0U; i < output_num; ++i) {\n" |
| 580 | - << " desc.SetOriginShape(ge::Shape(state.dims));\n" | 492 | + << " auto *tensor = outputs[i];\n" |
| 581 | - << " desc.SetOriginFormat(format);\n" | 493 | + << " const auto placement = (tensor->GetPlacement() == gert::kFollowing) ? gert::kOnHost :\n" |
| 582 | - << " desc.SetPlacement(ge::kPlacementHost);\n" | 494 | + << " tensor->GetPlacement();\n" |
| 583 | - << " target = ge::Tensor(desc);\n" | 495 | + << " output_tensor_data_[i].MutableTensorData() =\n" |
| 584 | - << " state.data_type = data_type;\n" | 496 | + << " gert::TensorData(tensor->GetAddr(), nullptr, tensor->GetSize(), placement);\n" |
| 585 | - << " state.format = format;\n" | 497 | + << " }\n" |
| 498 | + << " for (size_t i = 0U; i < input_num; ++i) {\n" | ||
| 499 | + << " run->values[i] = &values_[i];\n" | ||
| 500 | + << " values_[i].data.pointer = const_cast<gert::StorageShape *>(&inputs[i]->GetShape());\n" | ||
| 501 | + << " values_[i].deleter = nullptr;\n" | ||
| 502 | + << " run->values[input_num + i] = &values_[input_num + i];\n" | ||
| 503 | + << " values_[input_num + i].data.pointer = &input_tensor_data_[i];\n" | ||
| 504 | + << " values_[input_num + i].deleter = nullptr;\n" | ||
| 505 | + << " }\n" | ||
| 506 | + << " // Keep the same trailing function-pointer slot as AicpuHostExecFunc.\n" | ||
| 507 | + << " run->values[input_num * 2U] = &values_[input_num * 2U];\n" | ||
| 508 | + << " (void)std::memcpy(values_[input_num * 2U].data.inplace, &func, sizeof(func));\n" | ||
| 509 | + << " values_[input_num * 2U].deleter = nullptr;\n" | ||
| 510 | + << " const size_t output_start = input_num * 2U + 1U;\n" | ||
| 511 | + << " for (size_t i = 0U; i < output_num; ++i) {\n" | ||
| 512 | + << " run->values[output_start + i] = &values_[output_start + i];\n" | ||
| 513 | + << " values_[output_start + i].data.pointer = &outputs[i]->GetShape();\n" | ||
| 514 | + << " values_[output_start + i].deleter = nullptr;\n" | ||
| 515 | + << " run->values[output_start + output_num + i] = &values_[output_start + output_num + i];\n" | ||
| 516 | + << " values_[output_start + output_num + i].data.pointer = &output_tensor_data_[i];\n" | ||
| 517 | + << " values_[output_start + output_num + i].deleter = nullptr;\n" | ||
| 518 | + << " }\n" | ||
| 519 | + << " run->output_start = run->values + run->input_size;\n" | ||
| 586 | << " }\n" | 520 | << " }\n" |
| 587 | - << " if ((data_size != 0U) && changed &&\n" | 521 | + << " gert::KernelContext *Get() { return reinterpret_cast<gert::KernelContext *>(storage_.data()); }\n" |
| 588 | - << " (target.SetData(reinterpret_cast<uint8_t *>(source->GetData()),\n" | 522 | + << " private:\n" |
| 589 | - << " static_cast<size_t>(data_size), [](uint8_t *) {}) != ge::GRAPH_SUCCESS)) {\n" | 523 | + << " alignas(gert::GertTensorData) std::array<gert::GertTensorData, InputNum> input_tensor_data_;\n" |
| 590 | - << " return false;\n" | 524 | + << " alignas(gert::GertTensorData) std::array<gert::GertTensorData, OutputNum> output_tensor_data_;\n" |
| 525 | + << " std::array<AsyncAnyValue, kValueNum> values_;\n" | ||
| 526 | + << " alignas(KernelRunContext) std::array<uint8_t, kStorageSize> storage_;\n" | ||
| 527 | + << "};\n\n" | ||
| 528 | + << "class HostKernelCache final {\n public:\n" | ||
| 529 | + << " HostKernelCache() : finder_(nullptr) {}\n" | ||
| 530 | + << " HostKernelFinder GetFinder() {\n" | ||
| 531 | + << " HostKernelFinder finder = finder_.load(std::memory_order_acquire);\n" | ||
| 532 | + << " if (finder != nullptr) { return finder; }\n" | ||
| 533 | + << " const auto candidate = reinterpret_cast<HostKernelFinder>(dlsym(RTLD_DEFAULT, \"AicpuHostFindFunc\"));\n" | ||
| 534 | + << " if (candidate == nullptr) { return nullptr; }\n" | ||
| 535 | + << " HostKernelFinder expected = nullptr;\n" | ||
| 536 | + << " if (!finder_.compare_exchange_strong(expected, candidate, std::memory_order_release,\n" | ||
| 537 | + << " std::memory_order_acquire)) {\n" | ||
| 538 | + << " return expected;\n" | ||
| 539 | + << " }\n" | ||
| 540 | + << " return candidate;\n" | ||
| 591 | << " }\n" | 541 | << " }\n" |
| 592 | - << " state.data = data;\n" | 542 | + << " HostKernelFunc GetKernel(const HostKernelFinder finder,\n" |
| 593 | - << " state.data_size = static_cast<size_t>(data_size);\n" | 543 | + << " std::atomic<HostKernelFunc> &slot, const char *type) {\n" |
| 594 | - << " state.initialized = true;\n" | 544 | + << " HostKernelFunc kernel = slot.load(std::memory_order_acquire);\n" |
| 595 | - << " return true;\n" | 545 | + << " if (kernel != nullptr) { return kernel; }\n" |
| 596 | - << "}\n\n" | 546 | + << " if (finder == nullptr) { return nullptr; }\n" |
| 597 | - << "bool BuildFusedHostCpuRuntimeTensor(const FusedHostCpuTensorBinding &binding,\n" | 547 | + << " const auto candidate = finder(std::string(type));\n" |
| 598 | - << " ge::TensorDesc desc, ge::Tensor &target) {\n" | 548 | + << " if (candidate == nullptr) { return nullptr; }\n" |
| 599 | - << " if (((binding.dim_num != 0U) && (binding.dims == nullptr)) ||\n" | 549 | + << " HostKernelFunc expected = nullptr;\n" |
| 600 | - << " ((binding.data_size != 0U) && (binding.data == nullptr))) { return false; }\n" | 550 | + << " if (!slot.compare_exchange_strong(expected, candidate, std::memory_order_release,\n" |
| 601 | - << " std::vector<int64_t> dims(binding.dim_num);\n" | 551 | + << " std::memory_order_acquire)) {\n" |
| 602 | - << " for (size_t i = 0U; i < binding.dim_num; ++i) { dims[i] = binding.dims[i]; }\n" | 552 | + << " return expected;\n" |
| 603 | - << " desc.SetShape(ge::Shape(dims));\n" | 553 | + << " }\n" |
| 604 | - << " desc.SetOriginShape(ge::Shape(dims));\n" | 554 | + << " return candidate;\n" |
| 605 | - << " desc.SetPlacement(ge::kPlacementHost);\n" | 555 | + << " }\n" |
| 606 | - << " target = ge::Tensor(desc);\n" | 556 | + << " private:\n" |
| 607 | - << " return (binding.data_size == 0U) ||\n" | 557 | + << " std::atomic<HostKernelFinder> finder_;\n" |
| 608 | - << " (target.ResetData(binding.data, binding.data_size, [](uint8_t *) {}) == ge::GRAPH_SUCCESS);\n" | 558 | + << "};\n\n" |
| 559 | + << "HostKernelCache &GetHostKernelCache() {\n" | ||
| 560 | + << " static HostKernelCache cache;\n" | ||
| 561 | + << " return cache;\n" | ||
| 609 | << "}\n" | 562 | << "}\n" |
| 610 | - << "} // namespace\n\n" | 563 | + << "HostKernelFinder GetHostKernelFinder() {\n" |
| 611 | - << "namespace ge {\nclass FusedHostCpuNodeOperator_" << region.chain_id << " : public Operator {\n public:\n" | 564 | + << " return GetHostKernelCache().GetFinder();\n" |
| 612 | - << " FusedHostCpuNodeOperator_" << region.chain_id | 565 | + << "}\n" |
| 613 | - << "(const char *name, const char *type, const std::vector<std::string> &input_names,\n" | 566 | + << "HostKernelFunc GetCachedHostKernel(const HostKernelFinder finder,\n" |
| 614 | - << " const std::vector<std::string> &output_names)\n" | 567 | + << " std::atomic<HostKernelFunc> &slot, const char *type) {\n" |
| 615 | - << " : Operator(name, type) {\n" | 568 | + << " return GetHostKernelCache().GetKernel(finder, slot, type);\n" |
| 616 | - << " for (const auto &input_name : input_names) { InputRegister(input_name.c_str()); }\n" | 569 | + << "}\n"; |
| 617 | - << " for (const auto &output_name : output_names) { OutputRegister(output_name.c_str()); }\n" | 570 | + |
| 618 | - << " }\n};\n\n" | 571 | + for (size_t type_index = 0U; type_index < kernel_types.size(); ++type_index) { |
| 619 | - << "class FusedHostCpuOrchestration_" << region.chain_id << " {\n public:\n" | 572 | + code << "HostKernelFunc GetHostKernel_" << type_index << "(const HostKernelFinder finder) {\n" |
| 620 | - << " graphStatus Initialize() {\n" | 573 | + << " static std::atomic<HostKernelFunc> kernel(nullptr);\n" |
| 621 | - << " if (chain_plan_.Get() != nullptr) { return GRAPH_SUCCESS; }\n" | 574 | + << " return GetCachedHostKernel(finder, kernel, \"" << EscapeString(kernel_types[type_index]) << "\");\n" |
| 622 | - << " // Build immutable CpuKernel contexts after real runtime tensors are available.\n" | 575 | + << "}\n"; |
| 623 | - << " if (!runtime_bound_) {\n" | 576 | + } |
| 624 | - << " static uint8_t placeholder_data = 0U;\n"; | 577 | + |
| 578 | + code << "} // namespace\n\n" | ||
| 579 | + << "namespace ge {\n" | ||
| 580 | + << "class FusedHostCpuCustomOp_" << region.chain_id | ||
| 581 | + << " final : public HostCpuExecuteOp, public PortableOp {\n public:\n" | ||
| 582 | + << " graphStatus Serialize(std::vector<uint8_t> &buffer) override {\n" | ||
| 583 | + << " buffer = {0U};\n" | ||
| 584 | + << " return GRAPH_SUCCESS;\n" | ||
| 585 | + << " }\n" | ||
| 586 | + << " graphStatus Deserialize(const std::vector<uint8_t> &buffer) override {\n" | ||
| 587 | + << " (void)buffer;\n" | ||
| 588 | + << " return GRAPH_SUCCESS;\n" | ||
| 589 | + << " }\n" | ||
| 590 | + << " graphStatus Execute(gert::HostCpuOpExecutionContext *ctx) override {\n" | ||
| 591 | + << " if (ctx == nullptr) { return GRAPH_FAILED; }\n" | ||
| 592 | + << " HostKernelFinder finder = GetHostKernelFinder();\n" | ||
| 593 | + << " if (finder == nullptr) { return GRAPH_FAILED; }\n"; | ||
| 594 | + | ||
| 595 | + for (size_t type_index = 0U; type_index < kernel_types.size(); ++type_index) { | ||
| 596 | + code << " HostKernelFunc cached_kernel_" << type_index << " = nullptr;\n"; | ||
| 597 | + } | ||
| 625 | 598 | ||
| 626 | for (size_t i = 0U; i < region.external_inputs.size(); ++i) { | 599 | for (size_t i = 0U; i < region.external_inputs.size(); ++i) { |
| 627 | - const auto anchor = region.external_inputs[i]; | 600 | + code << " const gert::Tensor *external_input_" << i << " = ctx->GetInputTensor(" << i << "U);\n" |
| 628 | - const auto owner = (anchor == nullptr) ? nullptr : anchor->GetOwnerNode(); | 601 | + << " if (external_input_" << i << " == nullptr) { return GRAPH_FAILED; }\n"; |
| 629 | - const auto op_desc = (owner == nullptr) ? nullptr : owner->GetOpDesc(); | ||
| 630 | - if ((op_desc == nullptr) || (anchor->GetIdx() < 0) || | ||
| 631 | - (static_cast<size_t>(anchor->GetIdx()) >= op_desc->GetOutputsSize())) { | ||
| 632 | - GELOGE(PARAM_INVALID, | ||
| 633 | - "Invalid HostCPU fusion input anchor while generating: chain[%s], input_index[%zu], " | ||
| 634 | - "anchor_null[%d], owner_null[%d].", | ||
| 635 | - region.chain_id.c_str(), i, static_cast<int32_t>(anchor == nullptr), | ||
| 636 | - static_cast<int32_t>(owner == nullptr)); | ||
| 637 | - return PARAM_INVALID; | ||
| 638 | - } | ||
| 639 | - code << " inputs_[" << i << "U] = Tensor(" | ||
| 640 | - << TensorDescExpression(op_desc->GetOutputDesc(static_cast<size_t>(anchor->GetIdx()))) << ");\n" | ||
| 641 | - << " if (inputs_[" << i | ||
| 642 | - << "U].ResetData(&placeholder_data, sizeof(placeholder_data), [](uint8_t *) {}) != GRAPH_SUCCESS) " | ||
| 643 | - << "{ return GRAPH_FAILED; }\n"; | ||
| 644 | } | 602 | } |
| 645 | - for (size_t i = 0U; i < region.external_outputs.size(); ++i) { | ||
| 646 | - const auto anchor = region.external_outputs[i].source; | ||
| 647 | - const auto owner = (anchor == nullptr) ? nullptr : anchor->GetOwnerNode(); | ||
| 648 | - const auto op_desc = (owner == nullptr) ? nullptr : owner->GetOpDesc(); | ||
| 649 | - if ((op_desc == nullptr) || (anchor->GetIdx() < 0) || | ||
| 650 | - (static_cast<size_t>(anchor->GetIdx()) >= op_desc->GetOutputsSize())) { | ||
| 651 | - GELOGE(PARAM_INVALID, | ||
| 652 | - "Invalid HostCPU fusion output anchor while generating: chain[%s], output_index[%zu], " | ||
| 653 | - "anchor_null[%d], owner_null[%d].", | ||
| 654 | - region.chain_id.c_str(), i, static_cast<int32_t>(anchor == nullptr), | ||
| 655 | - static_cast<int32_t>(owner == nullptr)); | ||
| 656 | - return PARAM_INVALID; | ||
| 657 | - } | ||
| 658 | - code << " outputs_[" << i << "U] = Tensor(" | ||
| 659 | - << TensorDescExpression(op_desc->GetOutputDesc(static_cast<size_t>(anchor->GetIdx()))) << ");\n" | ||
| 660 | - << " if (outputs_[" << i | ||
| 661 | - << "U].ResetData(&placeholder_data, sizeof(placeholder_data), [](uint8_t *) {}) != GRAPH_SUCCESS) " | ||
| 662 | - << "{ return GRAPH_FAILED; }\n"; | ||
| 663 | - } | ||
| 664 | - code << " }\n"; | ||
| 665 | 603 | ||
| 666 | - size_t internal_tensor_count = 0U; | 604 | + for (size_t i = 0U; i < region.external_outputs.size(); ++i) { |
| 605 | + const auto &anchor = region.external_outputs[i].source; | ||
| 606 | + const auto &desc = anchor->GetOwnerNode()->GetOpDesc()->GetOutputDesc(static_cast<uint32_t>(anchor->GetIdx())); | ||
| 607 | + if (desc.GetShape().IsUnknownShape()) { | ||
| 608 | + GELOGW("HostCPU fusion external output shape is unknown: chain[%s], output[%zu].", region.chain_id.c_str(), i); | ||
| 609 | + return UNSUPPORTED; | ||
| 610 | + } | ||
| 611 | + code << " gert::Tensor *external_output_" << i << " = ctx->MallocOutputTensor(" << i << "U, " | ||
| 612 | + << shape_expression(desc.GetShape()) << ", " << format_expression(desc) << ", static_cast<ge::DataType>(" | ||
| 613 | + << static_cast<int32_t>(desc.GetDataType()) << "));\n" | ||
| 614 | + << " if (external_output_" << i << " == nullptr) { return GRAPH_FAILED; }\n"; | ||
| 615 | + } | ||
| 616 | + | ||
| 617 | + struct InternalBuffer { | ||
| 618 | + OutDataAnchorPtr anchor; | ||
| 619 | + size_t offset; | ||
| 620 | + }; | ||
| 621 | + std::vector<InternalBuffer> internal_buffers; | ||
| 622 | + std::unordered_map<const OutDataAnchor *, size_t> internal_indexes; | ||
| 623 | + size_t internal_storage_size = 0U; | ||
| 624 | + constexpr size_t kInternalBufferAlignment = alignof(std::max_align_t); | ||
| 667 | for (const auto &node : region.nodes) { | 625 | for (const auto &node : region.nodes) { |
| 668 | for (const auto &anchor : node->GetAllOutDataAnchors()) { | 626 | for (const auto &anchor : node->GetAllOutDataAnchors()) { |
| 669 | - if ((anchor != nullptr) && (output_indexes.count(anchor.get()) == 0U)) { | 627 | + if ((anchor == nullptr) || (output_indexes.count(anchor.get()) > 0U)) { |
| 670 | - ++internal_tensor_count; | 628 | + continue; |
| 671 | } | 629 | } |
| 630 | + size_t tensor_size = 0U; | ||
| 631 | + const auto &desc = node->GetOpDesc()->GetOutputDesc(static_cast<uint32_t>(anchor->GetIdx())); | ||
| 632 | + if (GetTensorSize(desc, tensor_size) != SUCCESS) { | ||
| 633 | + GELOGW("HostCPU fusion internal output size is unknown: chain[%s], node[%s], output[%d].", | ||
| 634 | + region.chain_id.c_str(), node->GetNamePtr(), anchor->GetIdx()); | ||
| 635 | + return UNSUPPORTED; | ||
| 636 | + } | ||
| 637 | + const size_t allocation_size = std::max<size_t>(tensor_size, 1U); | ||
| 638 | + const size_t remainder = internal_storage_size % kInternalBufferAlignment; | ||
| 639 | + const size_t padding = (remainder == 0U) ? 0U : (kInternalBufferAlignment - remainder); | ||
| 640 | + if ((padding > 0U) && (internal_storage_size > (std::numeric_limits<size_t>::max() - padding))) { | ||
| 641 | + GELOGW("HostCPU fusion internal buffer size overflow: chain[%s], node[%s].", region.chain_id.c_str(), | ||
| 642 | + node->GetNamePtr()); | ||
| 643 | + return UNSUPPORTED; | ||
| 644 | + } | ||
| 645 | + internal_storage_size += padding; | ||
| 646 | + if (internal_storage_size > (std::numeric_limits<size_t>::max() - allocation_size)) { | ||
| 647 | + GELOGW("HostCPU fusion internal buffer size overflow: chain[%s], node[%s].", region.chain_id.c_str(), | ||
| 648 | + node->GetNamePtr()); | ||
| 649 | + return UNSUPPORTED; | ||
| 650 | + } | ||
| 651 | + const size_t internal_index = internal_buffers.size(); | ||
| 652 | + internal_indexes.emplace(anchor.get(), internal_index); | ||
| 653 | + internal_buffers.push_back({anchor, internal_storage_size}); | ||
| 654 | + internal_storage_size += allocation_size; | ||
| 672 | } | 655 | } |
| 673 | } | 656 | } |
| 674 | - code << " internal_tensors_.clear();\n" | ||
| 675 | - << " internal_tensors_.reserve(" << internal_tensor_count << "U);\n"; | ||
| 676 | 657 | ||
| 658 | + // All intermediate tensors live for one Execute call. A single max-aligned | ||
| 659 | + // arena preserves their independent addresses while replacing hundreds of | ||
| 660 | + // allocator calls for wide fusion regions with one allocation. Using | ||
| 661 | + // max_align_t as the vector element type also makes the alignment guarantee | ||
| 662 | + // explicit (vector<uint8_t> only guarantees byte alignment). | ||
| 663 | + code << " constexpr size_t kInternalStorageAlignment = alignof(std::max_align_t);\n" | ||
| 664 | + << " const size_t internal_storage_words = (" << std::max<size_t>(internal_storage_size, 1U) | ||
| 665 | + << "U / kInternalStorageAlignment) + ((" << std::max<size_t>(internal_storage_size, 1U) | ||
| 666 | + << "U % kInternalStorageAlignment) == 0U ? 0U : 1U);\n" | ||
| 667 | + << " std::vector<std::max_align_t> internal_storage(internal_storage_words);\n" | ||
| 668 | + << " auto *internal_storage_data = reinterpret_cast<uint8_t *>(internal_storage.data());\n"; | ||
| 669 | + for (size_t internal_index = 0U; internal_index < internal_buffers.size(); ++internal_index) { | ||
| 670 | + const auto &buffer = internal_buffers[internal_index]; | ||
| 671 | + const auto owner = buffer.anchor->GetOwnerNode(); | ||
| 672 | + const auto &desc = owner->GetOpDesc()->GetOutputDesc(static_cast<uint32_t>(buffer.anchor->GetIdx())); | ||
| 673 | + code << " gert::Tensor internal_tensor_" << internal_index << "(" << shape_expression(desc.GetShape()) << ", " | ||
| 674 | + << format_expression(desc) << ", gert::kOnHost, static_cast<ge::DataType>(" | ||
| 675 | + << static_cast<int32_t>(desc.GetDataType()) << "), internal_storage_data + " << buffer.offset << "U);\n"; | ||
| 676 | + } | ||
| 677 | + | ||
| 678 | + std::vector<bool> kernel_type_seen(kernel_types.size(), false); | ||
| 679 | + gert::bg::BufferPool node_info_pool; | ||
| 677 | for (size_t node_index = 0U; node_index < region.nodes.size(); ++node_index) { | 680 | for (size_t node_index = 0U; node_index < region.nodes.size(); ++node_index) { |
| 678 | const auto &node = region.nodes[node_index]; | 681 | const auto &node = region.nodes[node_index]; |
| 679 | const auto op_desc = node->GetOpDesc(); | 682 | const auto op_desc = node->GetOpDesc(); |
| 680 | - GELOGD("Generate fused HostCPU node: chain=%s, index=%zu, node=%s, type=%s, inputs=%zu, outputs=%zu.", | 683 | + size_t node_info_size = 0U; |
| 681 | - region.chain_id.c_str(), node_index, op_desc->GetNamePtr(), op_desc->GetTypePtr(), | 684 | + auto node_info = gert::bg::CreateComputeNodeInfo(node, node_info_pool, node_info_size); |
| 682 | - op_desc->GetAllInputsSize(), op_desc->GetOutputsSize()); | 685 | + if ((node_info == nullptr) || (node_info_size == 0U)) { |
| 683 | - if ((op_desc->GetName().find('\0') != std::string::npos) || (op_desc->GetType().find('\0') != std::string::npos)) { | 686 | + GELOGW("Failed to serialize HostCPU node info: chain[%s], node[%s].", region.chain_id.c_str(), |
| 684 | - GELOGE(UNSUPPORTED, "HostCPU fusion node name or type contains NUL: chain[%s], node_index[%zu], node[%s].", | 687 | + node->GetNamePtr()); |
| 685 | - region.chain_id.c_str(), node_index, op_desc->GetNamePtr()); | ||
| 686 | return UNSUPPORTED; | 688 | return UNSUPPORTED; |
| 687 | } | 689 | } |
| 688 | - const auto in_anchors = node->GetAllInDataAnchors(); | ||
| 689 | - if (in_anchors.size() != op_desc->GetAllInputsSize()) { | ||
| 690 | - GELOGE(PARAM_INVALID, | ||
| 691 | - "HostCPU fusion input anchor count mismatch: chain[%s], node[%s], anchors[%zu], " | ||
| 692 | - "op_desc_inputs[%zu].", | ||
| 693 | - region.chain_id.c_str(), op_desc->GetNamePtr(), in_anchors.size(), op_desc->GetAllInputsSize()); | ||
| 694 | - return PARAM_INVALID; | ||
| 695 | - } | ||
| 696 | - std::vector<int32_t> input_binding_indices(in_anchors.size(), -1); | ||
| 697 | - code << " std::array<const Tensor *, " << in_anchors.size() << "U> node_inputs_" << node_index << "{{"; | ||
| 698 | - for (size_t input_index = 0U; input_index < in_anchors.size(); ++input_index) { | ||
| 699 | - const auto peer = in_anchors.at(input_index)->GetPeerOutAnchor(); | ||
| 700 | - if (peer == nullptr) { | ||
| 701 | - GELOGE(UNSUPPORTED, "HostCPU fusion input has no peer: chain[%s], node[%s], input_index[%zu].", | ||
| 702 | - region.chain_id.c_str(), op_desc->GetNamePtr(), input_index); | ||
| 703 | - return UNSUPPORTED; | ||
| 704 | - } | ||
| 705 | - const std::string input_name = op_desc->GetInputNameByIndex(static_cast<uint32_t>(input_index)); | ||
| 706 | - if (input_name.empty() || (input_name.find('\0') != std::string::npos)) { | ||
| 707 | - GELOGE(UNSUPPORTED, "Invalid HostCPU fusion input name: chain[%s], node[%s], input_index[%zu].", | ||
| 708 | - region.chain_id.c_str(), op_desc->GetNamePtr(), input_index); | ||
| 709 | - return UNSUPPORTED; | ||
| 710 | - } | ||
| 711 | - if (input_index != 0U) { | ||
| 712 | - code << ", "; | ||
| 713 | - } | ||
| 714 | - const auto owner = peer->GetOwnerNode(); | ||
| 715 | - const auto internal_iter = node_indexes.find(owner.get()); | ||
| 716 | - if (internal_iter != node_indexes.end()) { | ||
| 717 | - if (internal_iter->second >= node_index) { | ||
| 718 | - GELOGE(PARAM_INVALID, | ||
| 719 | - "HostCPU fusion nodes are not in topological order: chain[%s], node[%s], " | ||
| 720 | - "input_index[%zu], peer_node_index[%zu], node_index[%zu].", | ||
| 721 | - region.chain_id.c_str(), op_desc->GetNamePtr(), input_index, internal_iter->second, node_index); | ||
| 722 | - return PARAM_INVALID; | ||
| 723 | - } | ||
| 724 | - const auto source_desc = owner->GetOpDesc(); | ||
| 725 | - const std::string source_name = source_desc->GetOutputNameByIndex(static_cast<uint32_t>(peer->GetIdx())); | ||
| 726 | - if (source_name.empty()) { | ||
| 727 | - GELOGE(UNSUPPORTED, | ||
| 728 | - "Invalid HostCPU fusion peer output name: chain[%s], node[%s], input_index[%zu], " | ||
| 729 | - "peer_node[%s].", | ||
| 730 | - region.chain_id.c_str(), op_desc->GetNamePtr(), input_index, owner->GetNamePtr()); | ||
| 731 | - return UNSUPPORTED; | ||
| 732 | - } | ||
| 733 | - const auto output_iter = output_indexes.find(peer.get()); | ||
| 734 | - if (output_iter != output_indexes.end()) { | ||
| 735 | - input_binding_indices[input_index] = | ||
| 736 | - static_cast<int32_t>(region.external_inputs.size() + output_iter->second); | ||
| 737 | - } | ||
| 738 | - code << "node_output_" << internal_iter->second << "_" << peer->GetIdx(); | ||
| 739 | - } else { | ||
| 740 | - const auto external_iter = input_indexes.find(peer.get()); | ||
| 741 | - if (external_iter == input_indexes.end()) { | ||
| 742 | - GELOGE(PARAM_INVALID, | ||
| 743 | - "HostCPU fusion input peer is not an external input: chain[%s], node[%s], " | ||
| 744 | - "input_index[%zu], peer_node[%s].", | ||
| 745 | - region.chain_id.c_str(), op_desc->GetNamePtr(), input_index, owner->GetNamePtr()); | ||
| 746 | - return PARAM_INVALID; | ||
| 747 | - } | ||
| 748 | - input_binding_indices[input_index] = static_cast<int32_t>(external_iter->second); | ||
| 749 | - code << "&inputs_[" << external_iter->second << "U]"; | ||
| 750 | - } | ||
| 751 | - } | ||
| 752 | - code << "}};\n" | ||
| 753 | - << " std::array<int32_t, " << input_binding_indices.size() << "U> node_input_binding_indices_" << node_index | ||
| 754 | - << "{{"; | ||
| 755 | - for (size_t input_index = 0U; input_index < input_binding_indices.size(); ++input_index) { | ||
| 756 | - if (input_index != 0U) { | ||
| 757 | - code << ", "; | ||
| 758 | - } | ||
| 759 | - code << input_binding_indices[input_index]; | ||
| 760 | - } | ||
| 761 | - code << "}};\n"; | ||
| 762 | 690 | ||
| 763 | - // InferShape 在融合前已经完成。这里复用已推导的 TensorDesc:区域外输出复用调用方内存,内部输出按 | 691 | + const auto kernel_type_iter = kernel_type_indexes.find(node->GetType()); |
| 764 | - // 静态字节数申请临时 Tensor。若大小仍未知则拒绝融合,保留原逐节点 InferShape + Kernel 执行路径。 | 692 | + if (kernel_type_iter == kernel_type_indexes.cend()) { |
| 765 | - const auto out_anchors = node->GetAllOutDataAnchors(); | 693 | + GELOGE(PARAM_INVALID, "HostCPU fusion kernel type mapping is missing: chain[%s], node[%s].", |
| 766 | - if (out_anchors.size() != op_desc->GetOutputsSize()) { | 694 | + region.chain_id.c_str(), node->GetNamePtr()); |
| 767 | - GELOGE(PARAM_INVALID, | ||
| 768 | - "HostCPU fusion output anchor count mismatch: chain[%s], node[%s], anchors[%zu], " | ||
| 769 | - "op_desc_outputs[%zu].", | ||
| 770 | - region.chain_id.c_str(), op_desc->GetNamePtr(), out_anchors.size(), op_desc->GetOutputsSize()); | ||
| 771 | return PARAM_INVALID; | 695 | return PARAM_INVALID; |
| 772 | } | 696 | } |
| 773 | - std::vector<int32_t> output_binding_indices(out_anchors.size(), -1); | 697 | + code << " {\n" |
| 774 | - for (size_t output_index = 0U; output_index < out_anchors.size(); ++output_index) { | 698 | + << " static const gert::ComputeNodeInfo *const compute_node_info_" << node_index |
| 775 | - const std::string output_name = op_desc->GetOutputNameByIndex(static_cast<uint32_t>(output_index)); | 699 | + << " = []() -> const gert::ComputeNodeInfo * {\n" |
| 776 | - if (output_name.empty() || (output_name.find('\0') != std::string::npos)) { | 700 | + << " alignas(gert::ComputeNodeInfo) static const std::array<uint8_t, " << node_info_size |
| 777 | - GELOGE(UNSUPPORTED, "Invalid HostCPU fusion output name: chain[%s], node[%s], output_index[%zu].", | 701 | + << "U> node_info = []() {\n" |
| 778 | - region.chain_id.c_str(), op_desc->GetNamePtr(), output_index); | 702 | + << " alignas(gert::ComputeNodeInfo) std::array<uint8_t, " << node_info_size |
| 779 | - return UNSUPPORTED; | 703 | + << "U> info = " << emit_bytes(node_info.get(), node_info_size) << ";\n" |
| 780 | - } | 704 | + << " auto *compute_node_info = reinterpret_cast<gert::ComputeNodeInfo *>(info.data());\n" |
| 781 | - const auto external_iter = output_indexes.find(out_anchors.at(output_index).get()); | 705 | + << " compute_node_info->SetNodeName(\"" << EscapeString(node->GetName()) << "\");\n" |
| 782 | - if (external_iter != output_indexes.end()) { | 706 | + << " compute_node_info->SetNodeType(\"" << EscapeString(node->GetType()) << "\");\n" |
| 783 | - output_binding_indices[output_index] = | 707 | + << " return info;\n" |
| 784 | - static_cast<int32_t>(region.external_inputs.size() + external_iter->second); | 708 | + << " }();\n" |
| 785 | - GELOGD("Reuse fused external output: chain=%s, node=%s, output=%zu, fused_output=%zu.", region.chain_id.c_str(), | 709 | + << " return reinterpret_cast<const gert::ComputeNodeInfo *>(node_info.data());\n" |
| 786 | - op_desc->GetNamePtr(), output_index, external_iter->second); | 710 | + << " }();\n" |
| 787 | - code << " Tensor *node_output_" << node_index << "_" << output_index << " = &outputs_[" | 711 | + << " "; |
| 788 | - << external_iter->second << "U];\n"; | 712 | + if (!kernel_type_seen[kernel_type_iter->second]) { |
| 789 | - } else { | 713 | + code << "cached_kernel_" << kernel_type_iter->second << " = GetHostKernel_" << kernel_type_iter->second |
| 790 | - size_t tensor_size = 0U; | 714 | + << "(finder);\n" |
| 791 | - if (GetTensorSize(op_desc->GetOutputDesc(output_index), tensor_size) != SUCCESS) { | 715 | + << " if (cached_kernel_" << kernel_type_iter->second << " == nullptr) { return GRAPH_FAILED; }\n" |
| 792 | - GELOGD("Skip HostCPU fusion because output size is unknown after InferShape: chain=%s, node=%s, output=%zu.", | 716 | + << " "; |
| 793 | - region.chain_id.c_str(), op_desc->GetNamePtr(), output_index); | 717 | + kernel_type_seen[kernel_type_iter->second] = true; |
| 794 | - return UNSUPPORTED; | ||
| 795 | - } | ||
| 796 | - GELOGD("Allocate fused internal output from inferred TensorDesc: chain=%s, node=%s, output=%zu, bytes=%zu.", | ||
| 797 | - region.chain_id.c_str(), op_desc->GetNamePtr(), output_index, tensor_size); | ||
| 798 | - code << " internal_tensors_.emplace_back(" << TensorDescExpression(op_desc->GetOutputDesc(output_index)) | ||
| 799 | - << ", std::vector<uint8_t>(" << tensor_size << "U));\n" | ||
| 800 | - << " Tensor *node_output_" << node_index << "_" << output_index << " = &internal_tensors_.back();\n"; | ||
| 801 | - } | ||
| 802 | } | 718 | } |
| 803 | - code << " std::array<Tensor *, " << out_anchors.size() << "U> node_outputs_" << node_index << "{{"; | 719 | + code << "HostKernelFunc kernel_" << node_index << " = cached_kernel_" << kernel_type_iter->second << ";\n" |
| 804 | - for (size_t output_index = 0U; output_index < out_anchors.size(); ++output_index) { | 720 | + << " const std::array<const gert::Tensor *, " << node->GetAllInDataAnchors().size() << "U> node_inputs_" |
| 805 | - if (output_index != 0U) { | ||
| 806 | - code << ", "; | ||
| 807 | - } | ||
| 808 | - code << "node_output_" << node_index << "_" << output_index; | ||
| 809 | - } | ||
| 810 | - code << "}};\n" | ||
| 811 | - << " std::array<int32_t, " << output_binding_indices.size() << "U> node_output_binding_indices_" | ||
| 812 | << node_index << "{{"; | 721 | << node_index << "{{"; |
| 813 | - for (size_t output_index = 0U; output_index < output_binding_indices.size(); ++output_index) { | 722 | + |
| 723 | + const auto in_anchors = node->GetAllInDataAnchors(); | ||
| 724 | + for (size_t input_index = 0U; input_index < in_anchors.size(); ++input_index) { | ||
| 725 | + const auto peer = | ||
| 726 | + (in_anchors.at(input_index) == nullptr) ? nullptr : in_anchors.at(input_index)->GetPeerOutAnchor(); | ||
| 727 | + if (peer == nullptr) { | ||
| 728 | + GELOGW("HostCPU fusion input has no peer: chain[%s], node[%s], input[%zu].", region.chain_id.c_str(), | ||
| 729 | + node->GetNamePtr(), input_index); | ||
| 730 | + return UNSUPPORTED; | ||
| 731 | + } | ||
| 732 | + if (input_index != 0U) { | ||
| 733 | + code << ", "; | ||
| 734 | + } | ||
| 735 | + const auto external_iter = input_indexes.find(peer.get()); | ||
| 736 | + if (external_iter != input_indexes.cend()) { | ||
| 737 | + code << "external_input_" << external_iter->second; | ||
| 738 | + continue; | ||
| 739 | + } | ||
| 740 | + const auto output_iter = output_indexes.find(peer.get()); | ||
| 741 | + if (output_iter != output_indexes.cend()) { | ||
| 742 | + code << "external_output_" << output_iter->second; | ||
| 743 | + continue; | ||
| 744 | + } | ||
| 745 | + const auto internal_iter = internal_indexes.find(peer.get()); | ||
| 746 | + if (internal_iter == internal_indexes.cend()) { | ||
| 747 | + GELOGE(PARAM_INVALID, "HostCPU fusion input mapping is missing: chain[%s], node[%s], input[%zu].", | ||
| 748 | + region.chain_id.c_str(), node->GetNamePtr(), input_index); | ||
| 749 | + return PARAM_INVALID; | ||
| 750 | + } | ||
| 751 | + code << "&internal_tensor_" << internal_iter->second; | ||
| 752 | + } | ||
| 753 | + code << "}};\n" | ||
| 754 | + << " const std::array<gert::Tensor *, " << node->GetAllOutDataAnchors().size() << "U> node_outputs_" | ||
| 755 | + << node_index << "{{"; | ||
| 756 | + | ||
| 757 | + const auto out_anchors = node->GetAllOutDataAnchors(); | ||
| 758 | + for (size_t output_index = 0U; output_index < out_anchors.size(); ++output_index) { | ||
| 759 | + const auto &anchor = out_anchors.at(output_index); | ||
| 760 | + if (anchor == nullptr) { | ||
| 761 | + GELOGE(PARAM_INVALID, "HostCPU fusion output anchor is null: chain[%s], node[%s], output[%zu].", | ||
| 762 | + region.chain_id.c_str(), node->GetNamePtr(), output_index); | ||
| 763 | + return PARAM_INVALID; | ||
| 764 | + } | ||
| 814 | if (output_index != 0U) { | 765 | if (output_index != 0U) { |
| 815 | code << ", "; | 766 | code << ", "; |
| 816 | } | 767 | } |
| 817 | - code << output_binding_indices[output_index]; | 768 | + const auto external_iter = output_indexes.find(anchor.get()); |
| 769 | + if (external_iter != output_indexes.cend()) { | ||
| 770 | + code << "external_output_" << external_iter->second; | ||
| 771 | + } else { | ||
| 772 | + const auto internal_iter = internal_indexes.find(anchor.get()); | ||
| 773 | + if (internal_iter == internal_indexes.cend()) { | ||
| 774 | + GELOGE(PARAM_INVALID, "HostCPU fusion output mapping is missing: chain[%s], node[%s], output[%zu].", | ||
| 775 | + region.chain_id.c_str(), node->GetNamePtr(), output_index); | ||
| 776 | + return PARAM_INVALID; | ||
| 777 | + } | ||
| 778 | + code << "&internal_tensor_" << internal_iter->second; | ||
| 779 | + } | ||
| 818 | } | 780 | } |
| 819 | code << "}};\n" | 781 | code << "}};\n" |
| 820 | - << " FusedHostCpuNodeOperator_" << region.chain_id << " op_" << node_index << "(\"" | 782 | + << " LocalKernelContext<" << in_anchors.size() << "U, " << out_anchors.size() << "U> kernel_context_" |
| 821 | - << EscapeString(op_desc->GetName()) << "\", \"" << EscapeString(op_desc->GetType()) | 783 | + << node_index << "(compute_node_info_" << node_index << ", node_inputs_" << node_index << ", node_outputs_" |
| 822 | - << "\", std::vector<std::string>{"; | 784 | + << node_index << ", kernel_" << node_index << ");\n" |
| 823 | - for (size_t i = 0U; i < op_desc->GetAllInputsSize(); ++i) { | 785 | + << " if (kernel_" << node_index << "(kernel_context_" << node_index |
| 824 | - const std::string input_name = op_desc->GetInputNameByIndex(static_cast<uint32_t>(i)); | 786 | + << ".Get()) != GRAPH_SUCCESS) { return GRAPH_FAILED; }\n" |
| 825 | - if (input_name.empty() || (input_name.find('\0') != std::string::npos)) { | 787 | + << " }\n"; |
| 826 | - GELOGE(UNSUPPORTED, "Invalid HostCPU fusion registered input name: chain[%s], node[%s], input_index[%zu].", | ||
| 827 | - region.chain_id.c_str(), op_desc->GetNamePtr(), i); | ||
| 828 | - return UNSUPPORTED; | ||
| 829 | - } | ||
| 830 | - if (i != 0U) { | ||
| 831 | - code << ", "; | ||
| 832 | - } | ||
| 833 | - code << "std::string(\"" << EscapeString(input_name) << "\")"; | ||
| 834 | - } | ||
| 835 | - code << "}, std::vector<std::string>{"; | ||
| 836 | - for (size_t i = 0U; i < op_desc->GetOutputsSize(); ++i) { | ||
| 837 | - const std::string output_name = op_desc->GetOutputNameByIndex(static_cast<uint32_t>(i)); | ||
| 838 | - if (output_name.empty() || (output_name.find('\0') != std::string::npos)) { | ||
| 839 | - GELOGE(UNSUPPORTED, | ||
| 840 | - "Invalid HostCPU fusion registered output name: chain[%s], node[%s], " | ||
| 841 | - "output_index[%zu].", | ||
| 842 | - region.chain_id.c_str(), op_desc->GetNamePtr(), i); | ||
| 843 | - return UNSUPPORTED; | ||
| 844 | - } | ||
| 845 | - if (i != 0U) { | ||
| 846 | - code << ", "; | ||
| 847 | - } | ||
| 848 | - code << "std::string(\"" << EscapeString(output_name) << "\")"; | ||
| 849 | - } | ||
| 850 | - code << "});\n if (op_" << node_index << ".IsEmpty()) { return GRAPH_FAILED; }\n"; | ||
| 851 | - // 仅序列化 IR 声明的计算属性,GE 调度元数据不进入融合 kernel。 | ||
| 852 | - const auto attrs = AttrUtils::GetAllAttrs(op_desc); | ||
| 853 | - for (const auto &attr_name : op_desc->GetIrAttrNames()) { | ||
| 854 | - if (attr_name.empty() || (attr_name.find('\0') != std::string::npos)) { | ||
| 855 | - GELOGE(UNSUPPORTED, "Invalid HostCPU fusion attribute name: chain[%s], node[%s].", region.chain_id.c_str(), | ||
| 856 | - op_desc->GetNamePtr()); | ||
| 857 | - return UNSUPPORTED; | ||
| 858 | - } | ||
| 859 | - const auto attr_iter = attrs.find(attr_name); | ||
| 860 | - if (attr_iter == attrs.end()) { | ||
| 861 | - GELOGE(UNSUPPORTED, "HostCPU fusion IR attribute is missing from OpDesc: chain[%s], node[%s], attr[%s].", | ||
| 862 | - region.chain_id.c_str(), op_desc->GetNamePtr(), attr_name.c_str()); | ||
| 863 | - return UNSUPPORTED; | ||
| 864 | - } | ||
| 865 | - const auto &attr = attr_iter->second; | ||
| 866 | - code << " op_" << node_index << ".SetAttr(\"" << EscapeString(attr_name) << "\", "; | ||
| 867 | - switch (attr.GetValueType()) { | ||
| 868 | - case AnyValue::VT_INT: { | ||
| 869 | - int64_t value = 0; | ||
| 870 | - if (attr.GetValue<int64_t>(value) != GRAPH_SUCCESS) { | ||
| 871 | - GELOGE(UNSUPPORTED, "Failed to read HostCPU fusion int attribute: chain[%s], node[%s], attr[%s].", | ||
| 872 | - region.chain_id.c_str(), op_desc->GetNamePtr(), attr_name.c_str()); | ||
| 873 | - return UNSUPPORTED; | ||
| 874 | - } | ||
| 875 | - code << "static_cast<int64_t>(" << IntExpression(value) << ")"; | ||
| 876 | - break; | ||
| 877 | - } | ||
| 878 | - case AnyValue::VT_FLOAT: { | ||
| 879 | - float value = 0.0F; | ||
| 880 | - if (attr.GetValue<float>(value) != GRAPH_SUCCESS) { | ||
| 881 | - GELOGE(UNSUPPORTED, "Failed to read HostCPU fusion float attribute: chain[%s], node[%s], attr[%s].", | ||
| 882 | - region.chain_id.c_str(), op_desc->GetNamePtr(), attr_name.c_str()); | ||
| 883 | - return UNSUPPORTED; | ||
| 884 | - } | ||
| 885 | - if (!std::isfinite(value)) { | ||
| 886 | - GELOGE(UNSUPPORTED, "Non-finite HostCPU fusion float attribute: chain[%s], node[%s], attr[%s].", | ||
| 887 | - region.chain_id.c_str(), op_desc->GetNamePtr(), attr_name.c_str()); | ||
| 888 | - return UNSUPPORTED; | ||
| 889 | - } | ||
| 890 | - code << FloatExpression(value); | ||
| 891 | - break; | ||
| 892 | - } | ||
| 893 | - case AnyValue::VT_BOOL: { | ||
| 894 | - bool value = false; | ||
| 895 | - if (attr.GetValue<bool>(value) != GRAPH_SUCCESS) { | ||
| 896 | - GELOGE(UNSUPPORTED, "Failed to read HostCPU fusion bool attribute: chain[%s], node[%s], attr[%s].", | ||
| 897 | - region.chain_id.c_str(), op_desc->GetNamePtr(), attr_name.c_str()); | ||
| 898 | - return UNSUPPORTED; | ||
| 899 | - } | ||
| 900 | - code << (value ? "true" : "false"); | ||
| 901 | - break; | ||
| 902 | - } | ||
| 903 | - case AnyValue::VT_STRING: { | ||
| 904 | - std::string value; | ||
| 905 | - if (attr.GetValue<std::string>(value) != GRAPH_SUCCESS) { | ||
| 906 | - GELOGE(UNSUPPORTED, "Failed to read HostCPU fusion string attribute: chain[%s], node[%s], attr[%s].", | ||
| 907 | - region.chain_id.c_str(), op_desc->GetNamePtr(), attr_name.c_str()); | ||
| 908 | - return UNSUPPORTED; | ||
| 909 | - } | ||
| 910 | - code << "std::string(\"" << EscapeString(value) << "\", " << value.size() << "U)"; | ||
| 911 | - break; | ||
| 912 | - } | ||
| 913 | - case AnyValue::VT_LIST_INT: { | ||
| 914 | - std::vector<int64_t> value; | ||
| 915 | - if (attr.GetValue<std::vector<int64_t>>(value) != GRAPH_SUCCESS) { | ||
| 916 | - GELOGE(UNSUPPORTED, "Failed to read HostCPU fusion int-list attribute: chain[%s], node[%s], attr[%s].", | ||
| 917 | - region.chain_id.c_str(), op_desc->GetNamePtr(), attr_name.c_str()); | ||
| 918 | - return UNSUPPORTED; | ||
| 919 | - } | ||
| 920 | - code << "std::vector<int64_t>" << IntVectorExpression(value); | ||
| 921 | - break; | ||
| 922 | - } | ||
| 923 | - case AnyValue::VT_LIST_FLOAT: { | ||
| 924 | - std::vector<float> value; | ||
| 925 | - if (attr.GetValue<std::vector<float>>(value) != GRAPH_SUCCESS) { | ||
| 926 | - GELOGE(UNSUPPORTED, "Failed to read HostCPU fusion float-list attribute: chain[%s], node[%s], attr[%s].", | ||
| 927 | - region.chain_id.c_str(), op_desc->GetNamePtr(), attr_name.c_str()); | ||
| 928 | - return UNSUPPORTED; | ||
| 929 | - } | ||
| 930 | - if (!std::all_of(value.cbegin(), value.cend(), [](const float item) { return std::isfinite(item); })) { | ||
| 931 | - GELOGE(UNSUPPORTED, "Non-finite HostCPU fusion float-list attribute: chain[%s], node[%s], attr[%s].", | ||
| 932 | - region.chain_id.c_str(), op_desc->GetNamePtr(), attr_name.c_str()); | ||
| 933 | - return UNSUPPORTED; | ||
| 934 | - } | ||
| 935 | - code << "std::vector<float>" << FloatVectorExpression(value); | ||
| 936 | - break; | ||
| 937 | - } | ||
| 938 | - default: | ||
| 939 | - GELOGE(UNSUPPORTED, "Unsupported HostCPU fusion attribute type: chain[%s], node[%s], attr[%s], type[%d].", | ||
| 940 | - region.chain_id.c_str(), op_desc->GetNamePtr(), attr_name.c_str(), | ||
| 941 | - static_cast<int32_t>(attr.GetValueType())); | ||
| 942 | - return UNSUPPORTED; | ||
| 943 | - } | ||
| 944 | - code << ");\n"; | ||
| 945 | - } | ||
| 946 | } | 788 | } |
| 947 | - code << " std::array<FusedHostCpuNodePlanDesc, " << region.nodes.size() << "U> node_descs{{\n"; | 789 | + |
| 948 | - for (size_t node_index = 0U; node_index < region.nodes.size(); ++node_index) { | 790 | + code << " return GRAPH_SUCCESS;\n" |
| 949 | - code << " {&op_" << node_index << ", node_inputs_" << node_index << ".data(), node_inputs_" << node_index | ||
| 950 | - << ".size(), node_outputs_" << node_index << ".data(), node_outputs_" << node_index | ||
| 951 | - << ".size(), node_input_binding_indices_" << node_index << ".data(), node_output_binding_indices_" | ||
| 952 | - << node_index << ".data()}" << ((node_index + 1U == region.nodes.size()) ? "\n" : ",\n"); | ||
| 953 | - } | ||
| 954 | - code << " }};\n" | ||
| 955 | - << " void *new_plan = CreateCpuConstantFoldingFusedChainPlan(\n" | ||
| 956 | - << " node_descs.data(), node_descs.size(), " << region.external_inputs.size() << "U, " | ||
| 957 | - << region.external_outputs.size() << "U);\n" | ||
| 958 | - << " if (new_plan == nullptr) { return GRAPH_FAILED; }\n" | ||
| 959 | - << " chain_plan_.Reset(new_plan);\n" | ||
| 960 | - << " return GRAPH_SUCCESS;\n" | ||
| 961 | - << " }\n\n" | ||
| 962 | - << " graphStatus Compute(const Tensor *inputs, const size_t input_num, Tensor *outputs,\n" | ||
| 963 | - << " const size_t output_num, const bool bindings_changed) {\n" | ||
| 964 | - << " if ((input_num != " << region.external_inputs.size() | ||
| 965 | - << "U) || (output_num != " << region.external_outputs.size() << "U) ||\n" | ||
| 966 | - << " ((input_num != 0U) && (inputs == nullptr)) ||\n" | ||
| 967 | - << " ((output_num != 0U) && (outputs == nullptr))) { return GRAPH_FAILED; }\n" | ||
| 968 | - << " const bool rebind_required = !runtime_bound_ || bindings_changed;\n" | ||
| 969 | - << " if (rebind_required) {\n"; | ||
| 970 | - for (size_t i = 0U; i < region.external_inputs.size(); ++i) { | ||
| 971 | - code << " inputs_[" << i << "U] = inputs[" << i << "U];\n"; | ||
| 972 | - } | ||
| 973 | - for (size_t i = 0U; i < region.external_outputs.size(); ++i) { | ||
| 974 | - code << " outputs_[" << i << "U] = outputs[" << i << "U];\n"; | ||
| 975 | - } | ||
| 976 | - code << " runtime_bound_ = true;\n" | ||
| 977 | - << " }\n" | ||
| 978 | - << " const bool initialize_required = chain_plan_.Get() == nullptr;\n" | ||
| 979 | - << " if (initialize_required && (Initialize() != GRAPH_SUCCESS)) { return GRAPH_FAILED; }\n" | ||
| 980 | - << " const uint32_t binding_flags = (!initialize_required && rebind_required) ?\n" | ||
| 981 | - << " (kFusedHostCpuShapeChanged | kFusedHostCpuDataChanged) : 0U;\n" | ||
| 982 | - << " return Run(binding_flags);\n" | ||
| 983 | - << " }\n\n" | ||
| 984 | - << " graphStatus ComputeBindings(const FusedHostCpuTensorBinding *bindings,\n" | ||
| 985 | - << " const uint32_t binding_flags) {\n" | ||
| 986 | - << " const bool initialize_required = chain_plan_.Get() == nullptr;\n" | ||
| 987 | - << " if (initialize_required && (InitializeBindings(bindings) != GRAPH_SUCCESS)) {\n" | ||
| 988 | - << " return GRAPH_FAILED;\n" | ||
| 989 | - << " }\n" | ||
| 990 | - << " return (RunCpuConstantFoldingFusedChainPlanBindings(\n" | ||
| 991 | - << " chain_plan_.Get(), bindings, initialize_required ? 0U : binding_flags) == 0) ?\n" | ||
| 992 | - << " GRAPH_SUCCESS : GRAPH_FAILED;\n" | ||
| 993 | << " }\n" | 791 | << " }\n" |
| 994 | - << " private:\n" | 792 | + << "};\n\n" |
| 995 | - << " graphStatus InitializeBindings(const FusedHostCpuTensorBinding *bindings) {\n" | 793 | + << "REG_OP_BACKEND(FusedHostCpuCustomOp_" << region.chain_id << ", \"" << EscapeString(register_name) |
| 996 | - << " if (bindings == nullptr) { return GRAPH_FAILED; }\n"; | 794 | + << "\", ge::OpBackend::kHostCPU);\n" |
| 997 | - for (size_t i = 0U; i < region.external_inputs.size(); ++i) { | 795 | + << "} // namespace ge\n\n" |
| 998 | - const auto anchor = region.external_inputs[i]; | 796 | + << "namespace {\n" |
| 999 | - const auto owner = (anchor == nullptr) ? nullptr : anchor->GetOwnerNode(); | 797 | + << "ge::BaseCustomOp *CreateFusedHostCpu_" << region.chain_id |
| 1000 | - const auto op_desc = (owner == nullptr) ? nullptr : owner->GetOpDesc(); | 798 | + << "() { return new (std::nothrow) ge::FusedHostCpuCustomOp_" << region.chain_id << "(); }\n" |
| 1001 | - code << " if (!BuildFusedHostCpuRuntimeTensor(bindings[" << i << "U], " | 799 | + << "struct FusedCustomOpCreatorEntry {\n" |
| 1002 | - << TensorDescExpression(op_desc->GetOutputDesc(static_cast<size_t>(anchor->GetIdx()))) << ", inputs_[" << i | 800 | + << " uint32_t struct_size;\n" |
| 1003 | - << "U])) { return GRAPH_FAILED; }\n"; | 801 | + << " const char *op_type;\n" |
| 1004 | - } | 802 | + << " ge::CustomOpCreateFunc creator;\n" |
| 1005 | - for (size_t i = 0U; i < region.external_outputs.size(); ++i) { | 803 | + << " ge::OpBackend backend;\n" |
| 1006 | - const auto anchor = region.external_outputs[i].source; | 804 | + << "};\n" |
| 1007 | - const auto owner = (anchor == nullptr) ? nullptr : anchor->GetOwnerNode(); | 805 | + << "} // namespace\n\n" |
| 1008 | - const auto op_desc = (owner == nullptr) ? nullptr : owner->GetOpDesc(); | 806 | + << "extern \"C\" __attribute__((visibility(\"default\"))) uint32_t " |
| 1009 | - code << " if (!BuildFusedHostCpuRuntimeTensor(bindings[" << (region.external_inputs.size() + i) << "U], " | 807 | + << "GetRegisteredCustomOpCreatorAbiVersion() { return 2U; }\n" |
| 1010 | - << TensorDescExpression(op_desc->GetOutputDesc(static_cast<size_t>(anchor->GetIdx()))) << ", outputs_[" << i | 808 | + << "extern \"C\" __attribute__((visibility(\"default\"))) size_t " |
| 1011 | - << "U])) { return GRAPH_FAILED; }\n"; | 809 | + << "GetRegisteredCustomOpCreatorNum() { return 1U; }\n" |
| 1012 | - } | 810 | + << "extern \"C\" __attribute__((visibility(\"default\"))) int32_t GetRegisteredCustomOpCreators(\n" |
| 1013 | - code << " runtime_bound_ = true;\n" | 811 | + << " FusedCustomOpCreatorEntry *creators, size_t creator_num, size_t creator_struct_size) {\n" |
| 1014 | - << " return Initialize();\n" | 812 | + << " if ((creators == nullptr) || (creator_num < 1U) ||\n" |
| 1015 | - << " }\n" | 813 | + << " (creator_struct_size < sizeof(FusedCustomOpCreatorEntry))) { return -1; }\n" |
| 1016 | - << " graphStatus Run(const uint32_t binding_flags) {\n" | 814 | + << " creators[0] = {sizeof(FusedCustomOpCreatorEntry), \"" << EscapeString(register_name) |
| 1017 | - << " return (RunCpuConstantFoldingFusedChainPlan(chain_plan_.Get(), binding_flags) == 0) ?\n" | 815 | + << "\", CreateFusedHostCpu_" << region.chain_id << ", ge::OpBackend::kHostCPU};\n" |
| 1018 | - << " GRAPH_SUCCESS : GRAPH_FAILED;\n" | 816 | + << " return 0;\n" |
| 1019 | - << " }\n" | ||
| 1020 | - << " FusedHostCpuChainPlanGuard chain_plan_;\n" | ||
| 1021 | - << " std::array<Tensor, " << region.external_inputs.size() << "U> inputs_;\n" | ||
| 1022 | - << " std::array<Tensor, " << region.external_outputs.size() << "U> outputs_;\n" | ||
| 1023 | - << " std::vector<Tensor> internal_tensors_;\n" | ||
| 1024 | - << " bool runtime_bound_ = false;\n" | ||
| 1025 | - << "};\n} // namespace ge\n\n" | ||
| 1026 | - << "namespace aicpu {\n" | ||
| 1027 | - << "constexpr char kFusedHostCpuKernel_" << region.chain_id << "[] = \"" << EscapeString(register_name) | ||
| 1028 | - << "\";\n" | ||
| 1029 | - << "class FusedHostCpuKernel_" << region.chain_id << " final : public CpuKernel {\n public:\n" | ||
| 1030 | - << " uint32_t Compute(CpuKernelContext &ctx) override {\n" | ||
| 1031 | - << " if ((ctx.GetOpType() != kFusedHostCpuKernel_" << region.chain_id << ") ||\n" | ||
| 1032 | - << " (ctx.GetInputsSize() != " << region.external_inputs.size() << "U) ||\n" | ||
| 1033 | - << " (ctx.GetOutputsSize() != " << region.external_outputs.size() << "U)) { return 1U; }\n" | ||
| 1034 | - << " static thread_local std::array<ge::Tensor, " << region.external_inputs.size() << "U> inputs;\n" | ||
| 1035 | - << " static thread_local std::array<FusedHostCpuTensorState, " << region.external_inputs.size() | ||
| 1036 | - << "U> input_states;\n" | ||
| 1037 | - << " bool bindings_changed = false;\n" | ||
| 1038 | - << " bool tensor_changed = false;\n"; | ||
| 1039 | - for (size_t i = 0U; i < region.external_inputs.size(); ++i) { | ||
| 1040 | - code << " if (!BuildFusedHostCpuTensor(ctx.Input(" << i << "U), inputs[" << i << "U], input_states[" << i | ||
| 1041 | - << "U], tensor_changed)) { return 1U; }\n" | ||
| 1042 | - << " bindings_changed = bindings_changed || tensor_changed;\n"; | ||
| 1043 | - } | ||
| 1044 | - code << " static thread_local std::array<ge::Tensor, " << region.external_outputs.size() << "U> outputs;\n" | ||
| 1045 | - << " static thread_local std::array<FusedHostCpuTensorState, " << region.external_outputs.size() | ||
| 1046 | - << "U> output_states;\n"; | ||
| 1047 | - for (size_t i = 0U; i < region.external_outputs.size(); ++i) { | ||
| 1048 | - code << " if (!BuildFusedHostCpuTensor(ctx.Output(" << i << "U), outputs[" << i << "U], output_states[" << i | ||
| 1049 | - << "U], tensor_changed)) { return 1U; }\n" | ||
| 1050 | - << " bindings_changed = bindings_changed || tensor_changed;\n"; | ||
| 1051 | - } | ||
| 1052 | - code << " static thread_local ge::FusedHostCpuOrchestration_" << region.chain_id << " orchestration;\n" | ||
| 1053 | - << " const ge::graphStatus ret = orchestration.Compute(inputs.data(), inputs.size(), outputs.data(),\n" | ||
| 1054 | - << " outputs.size(), bindings_changed);\n" | ||
| 1055 | - << " return (ret == ge::GRAPH_SUCCESS) ? 0U : static_cast<uint32_t>(ret);\n" | ||
| 1056 | - << " }\n};\n" | ||
| 1057 | - << "REGISTER_CPU_KERNEL(kFusedHostCpuKernel_" << region.chain_id << ", FusedHostCpuKernel_" << region.chain_id | ||
| 1058 | - << ");\n" | ||
| 1059 | - << "} // namespace aicpu\n\n" | ||
| 1060 | - << "extern \"C\" __attribute__((visibility(\"default\")))\n" | ||
| 1061 | - << "bool ValidateFusedHostCpuKernelRegistration(const char *register_name) {\n" | ||
| 1062 | - << " if ((register_name == nullptr) ||\n" | ||
| 1063 | - << " (std::strcmp(register_name, aicpu::kFusedHostCpuKernel_" << region.chain_id | ||
| 1064 | - << ") != 0)) { return false; }\n" | ||
| 1065 | - << " const auto kernel = aicpu::CpuKernelRegister::Instance().GetCpuKernel(register_name);\n" | ||
| 1066 | - << " return std::dynamic_pointer_cast<aicpu::FusedHostCpuKernel_" << region.chain_id | ||
| 1067 | - << ">(kernel) != nullptr;\n" | ||
| 1068 | - << "}\n\n" | ||
| 1069 | - << "extern \"C\" __attribute__((visibility(\"default\")))\n" | ||
| 1070 | - << "void *CreateFusedHostCpuKernelState() {\n" | ||
| 1071 | - << " std::unique_ptr<ge::FusedHostCpuOrchestration_" << region.chain_id | ||
| 1072 | - << "> state(new (std::nothrow) ge::FusedHostCpuOrchestration_" << region.chain_id << "());\n" | ||
| 1073 | - << " if (state == nullptr) { return nullptr; }\n" | ||
| 1074 | - << " return state.release();\n" | ||
| 1075 | - << "}\n\n" | ||
| 1076 | - << "extern \"C\" __attribute__((visibility(\"default\")))\n" | ||
| 1077 | - << "void DestroyFusedHostCpuKernelState(void *kernel_state) {\n" | ||
| 1078 | - << " delete static_cast<ge::FusedHostCpuOrchestration_" << region.chain_id << " *>(kernel_state);\n" | ||
| 1079 | - << "}\n\n" | ||
| 1080 | - << "extern \"C\" __attribute__((visibility(\"default\")))\n" | ||
| 1081 | - << "uint32_t RunFusedHostCpuKernel(void *kernel_state, const void *binding_data,\n" | ||
| 1082 | - << " const uint32_t binding_flags) {\n" | ||
| 1083 | - << " if (kernel_state == nullptr) { return 1U; }\n" | ||
| 1084 | - << " const auto *bindings = static_cast<const FusedHostCpuTensorBinding *>(binding_data);\n" | ||
| 1085 | - << " auto *state = static_cast<ge::FusedHostCpuOrchestration_" << region.chain_id << " *>(kernel_state);\n" | ||
| 1086 | - << " const ge::graphStatus ret = state->ComputeBindings(bindings, binding_flags);\n" | ||
| 1087 | - << " return (ret == ge::GRAPH_SUCCESS) ? 0U : static_cast<uint32_t>(ret);\n" | ||
| 1088 | << "}\n"; | 817 | << "}\n"; |
| 1089 | - const std::string source = code.str(); | 818 | + |
| 1090 | - if (source.size() > kMaxGeneratedSourceSize) { | 819 | + result.register_name = register_name; |
| 1091 | - GELOGE(UNSUPPORTED, "HostCPU fusion generated source is too large: chain[%s], source_size[%zu], limit[%zu].", | 820 | + result.source = code.str(); |
| 1092 | - region.chain_id.c_str(), source.size(), kMaxGeneratedSourceSize); | 821 | + if (result.source.size() > kMaxGeneratedSourceSize) { |
| 822 | + GELOGW("HostCPU fusion generated source is too large: chain[%s], source_size[%zu], limit[%zu].", | ||
| 823 | + region.chain_id.c_str(), result.source.size(), kMaxGeneratedSourceSize); | ||
| 824 | + result = {}; | ||
| 1093 | return UNSUPPORTED; | 825 | return UNSUPPORTED; |
| 1094 | } | 826 | } |
| 1095 | - result.register_name = register_name; | 827 | + GELOGD("Generated HostCPU custom-op source: chain=%s, op_type=%s, source_size=%zu.", region.chain_id.c_str(), |
| 1096 | - result.source = source; | 828 | + register_name.c_str(), result.source.size()); |
| 1097 | - GELOGD("Generated HostCPU fusion source: chain=%s, register_name=%s, source_size=%zu.", region.chain_id.c_str(), | ||
| 1098 | - register_name.c_str(), source.size()); | ||
| 1099 | - GELOGD("Generated HostCPU fusion source:\n%s", source.c_str()); | ||
| 1100 | return SUCCESS; | 829 | return SUCCESS; |
| 1101 | } | 830 | } |
| 1102 | 831 | ||
| 1103 | -// NOLINTNEXTLINE(huge_method, huge_cyclomatic_complexity): compiler process setup must remain one failure-atomic path. | ||
| 1104 | Status HostCpuFusionCompiler::Compile(const std::string &source, std::vector<uint8_t> &so_data) const { | 832 | Status HostCpuFusionCompiler::Compile(const std::string &source, std::vector<uint8_t> &so_data) const { |
| 1105 | so_data.clear(); | 833 | so_data.clear(); |
| 1106 | 834 | ||
| @@ -1116,12 +844,11 @@ Status HostCpuFusionCompiler::Compile(const std::string &source, std::vector<uin | |||
| 1116 | 844 | ||
| 1117 | // 校验源码 | 845 | // 校验源码 |
| 1118 | if (source.empty() || (source.size() > kMaxGeneratedSourceSize)) { | 846 | if (source.empty() || (source.size() > kMaxGeneratedSourceSize)) { |
| 1119 | - GELOGE(UNSUPPORTED, "Invalid HostCPU fusion JIT source: source_size[%zu], limit[%zu].", source.size(), | 847 | + GELOGW("Invalid HostCPU fusion JIT source: source_size[%zu], limit[%zu].", source.size(), kMaxGeneratedSourceSize); |
| 1120 | - kMaxGeneratedSourceSize); | ||
| 1121 | return UNSUPPORTED; | 848 | return UNSUPPORTED; |
| 1122 | } | 849 | } |
| 1123 | if (include_paths.empty()) { | 850 | if (include_paths.empty()) { |
| 1124 | - GELOGE(UNSUPPORTED, "HostCPU fusion JIT include path is empty, check ASCEND_OPP_PATH or ASCEND_HOME_PATH."); | 851 | + GELOGW("HostCPU fusion JIT include path is empty, check ASCEND_OPP_PATH or ASCEND_HOME_PATH."); |
| 1125 | return UNSUPPORTED; | 852 | return UNSUPPORTED; |
| 1126 | } | 853 | } |
| 1127 | GELOGD("Compile HostCPU fusion source: compiler=%s, target_cpu=%s, source_size=%zu, include_paths=%s.", | 854 | GELOGD("Compile HostCPU fusion source: compiler=%s, target_cpu=%s, source_size=%zu, include_paths=%s.", |
| @@ -1187,7 +914,8 @@ Status HostCpuFusionCompiler::Compile(const std::string &source, std::vector<uin | |||
| 1187 | compiler_args.emplace_back("-I"); | 914 | compiler_args.emplace_back("-I"); |
| 1188 | compiler_args.emplace_back(include_path); | 915 | compiler_args.emplace_back(include_path); |
| 1189 | } | 916 | } |
| 1190 | - compiler_args.insert(compiler_args.end(), {"-x", "c++", source_path, "-o", so_path}); | 917 | + // Keep libdl after the generated object input so linkers using --as-needed retain it. |
| 918 | + compiler_args.insert(compiler_args.end(), {"-x", "c++", source_path, "-ldl", "-o", so_path}); | ||
| 1191 | // 构造 execvp()参数 | 919 | // 构造 execvp()参数 |
| 1192 | std::vector<const char *> exec_argv; | 920 | std::vector<const char *> exec_argv; |
| 1193 | exec_argv.reserve(compiler_args.size() + 1U); | 921 | exec_argv.reserve(compiler_args.size() + 1U); |
| @@ -1220,8 +948,8 @@ Status HostCpuFusionCompiler::Compile(const std::string &source, std::vector<uin | |||
| 1220 | if (!wait_success || !WIFEXITED(child_status) || (WEXITSTATUS(child_status) != 0)) { | 948 | if (!wait_success || !WIFEXITED(child_status) || (WEXITSTATUS(child_status) != 0)) { |
| 1221 | const int exit_code = (wait_success && WIFEXITED(child_status)) ? WEXITSTATUS(child_status) : -1; | 949 | const int exit_code = (wait_success && WIFEXITED(child_status)) ? WEXITSTATUS(child_status) : -1; |
| 1222 | const std::string diagnostics = ReadCompilerDiagnostics(diagnostics_fd); | 950 | const std::string diagnostics = ReadCompilerDiagnostics(diagnostics_fd); |
| 1223 | - GELOGE(UNSUPPORTED, "HostCPU fusion compiler %s failed, exit_code=%d, diagnostics=%s.", compiler_name.c_str(), | 951 | + GELOGW("HostCPU fusion compiler %s failed, exit_code=%d, diagnostics=%s.", compiler_name.c_str(), exit_code, |
| 1224 | - exit_code, diagnostics.c_str()); | 952 | + diagnostics.c_str()); |
| 1225 | status = UNSUPPORTED; | 953 | status = UNSUPPORTED; |
| 1226 | break; | 954 | break; |
| 1227 | } | 955 | } |
| @@ -1229,7 +957,7 @@ Status HostCpuFusionCompiler::Compile(const std::string &source, std::vector<uin | |||
| 1229 | // 检查.so大小 0 < so_size <= 10 MB 空文件、超过 10 MB 或 lseek失败 | 957 | // 检查.so大小 0 < so_size <= 10 MB 空文件、超过 10 MB 或 lseek失败 |
| 1230 | const off_t so_size = lseek(so_fd, 0, SEEK_END); | 958 | const off_t so_size = lseek(so_fd, 0, SEEK_END); |
| 1231 | if ((so_size <= 0) || (static_cast<uint64_t>(so_size) > kMaxGeneratedSoSize) || (lseek(so_fd, 0, SEEK_SET) < 0)) { | 959 | if ((so_size <= 0) || (static_cast<uint64_t>(so_size) > kMaxGeneratedSoSize) || (lseek(so_fd, 0, SEEK_SET) < 0)) { |
| 1232 | - GELOGE(UNSUPPORTED, "Invalid HostCPU fusion compiler output: so_size[%lld], limit[%zu], errno[%d].", | 960 | + GELOGW("Invalid HostCPU fusion compiler output: so_size[%lld], limit[%zu], errno[%d].", |
| 1233 | static_cast<long long>(so_size), kMaxGeneratedSoSize, errno); | 961 | static_cast<long long>(so_size), kMaxGeneratedSoSize, errno); |
| 1234 | break; | 962 | break; |
| 1235 | } | 963 | } |
| @@ -1251,8 +979,8 @@ Status HostCpuFusionCompiler::Compile(const std::string &source, std::vector<uin | |||
| 1251 | offset += static_cast<size_t>(read_size); | 979 | offset += static_cast<size_t>(read_size); |
| 1252 | } | 980 | } |
| 1253 | if (!IsExpectedElf(so_data, target_cpu)) { | 981 | if (!IsExpectedElf(so_data, target_cpu)) { |
| 1254 | - GELOGE(UNSUPPORTED, "HostCPU fusion compiler output is not an expected ELF: target_cpu[%s], so_size[%zu].", | 982 | + GELOGW("HostCPU fusion compiler output is not an expected ELF: target_cpu[%s], so_size[%zu].", target_cpu.c_str(), |
| 1255 | - target_cpu.c_str(), so_data.size()); | 983 | + so_data.size()); |
| 1256 | so_data.clear(); | 984 | so_data.clear(); |
| 1257 | break; | 985 | break; |
| 1258 | } | 986 | } |
| @@ -34,7 +34,7 @@ struct HostCpuFusionRegion { | |||
| 34 | std::vector<HostCpuFusionOutput> external_outputs; | 34 | std::vector<HostCpuFusionOutput> external_outputs; |
| 35 | }; | 35 | }; |
| 36 | 36 | ||
| 37 | -// source 用于维测和测试,so_data 写入图属性并在运行时加载。 | 37 | +// source 用于维测和测试,so_data 作为标准 custom-op SO 写入模型。 |
| 38 | struct HostCpuFusionCodegenResult { | 38 | struct HostCpuFusionCodegenResult { |
| 39 | std::string register_name; | 39 | std::string register_name; |
| 40 | std::string source; | 40 | std::string source; |
| @@ -50,8 +50,8 @@ class HostCpuFusionCompiler { | |||
| 50 | virtual Status Compile(const std::string &source, std::vector<uint8_t> &so_data) const; | 50 | virtual Status Compile(const std::string &source, std::vector<uint8_t> &so_data) const; |
| 51 | }; | 51 | }; |
| 52 | 52 | ||
| 53 | -// 生成注册到 aicpu::CpuKernelRegister 的融合 CpuKernel;内部编排为每个原始算子缓存 CpuKernel 执行计划, | 53 | +// 生成注册到 CustomOpRegistry(kHostCPU) 的普通 HostCpuExecuteOp。执行时按 op_type 从 |
| 54 | -// 稳态仅更新 Tensor 数据和变化的描述信息并按拓扑序执行。 | 54 | +// libconstant_folding_ops.so 查询 Gert HostKernel,并使用临时 KernelContext 按拓扑序执行。 |
| 55 | class HostCpuFusionCodegen { | 55 | class HostCpuFusionCodegen { |
| 56 | public: | 56 | public: |
| 57 | Status Generate(const HostCpuFusionRegion ®ion, HostCpuFusionCodegenResult &result) const; | 57 | Status Generate(const HostCpuFusionRegion ®ion, HostCpuFusionCodegenResult &result) const; |
| @@ -14,14 +14,23 @@ | |||
| 14 | 14 | ||
| 15 | 15 | ||
| 16 | 16 | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 17 | 20 | ||
| 18 | 21 | ||
| 19 | 22 | ||
| 20 | 23 | ||
| 21 | 24 | ||
| 22 | 25 | ||
| 26 | + | ||
| 27 | + | ||
| 28 | + | ||
| 29 | + | ||
| 23 | 30 | ||
| 31 | + | ||
| 24 | 32 | ||
| 33 | + | ||
| 25 | 34 | ||
| 26 | 35 | ||
| 27 | 36 | ||
| @@ -31,10 +40,9 @@ namespace { | |||
| 31 | constexpr size_t kMaxGeneratedSoSize = 10U * 1024U * 1024U; | 40 | constexpr size_t kMaxGeneratedSoSize = 10U * 1024U * 1024U; |
| 32 | constexpr char kHostCpuEngineName[] = "DNN_VM_HOST_CPU"; | 41 | constexpr char kHostCpuEngineName[] = "DNN_VM_HOST_CPU"; |
| 33 | constexpr char kHostCpuKernelLibName[] = "DNN_VM_HOST_CPU_OP_STORE"; | 42 | constexpr char kHostCpuKernelLibName[] = "DNN_VM_HOST_CPU_OP_STORE"; |
| 34 | -constexpr char kHostCpuTaskKernelLibName[] = "HOSTCPUKernel"; | ||
| 35 | -constexpr char kOpKernelLibAttr[] = "opKernelLib"; | ||
| 36 | constexpr char kSmallShapeHostCpu[] = "SmallShapeHostcpu"; | 43 | constexpr char kSmallShapeHostCpu[] = "SmallShapeHostcpu"; |
| 37 | constexpr char kResourceListAttr[] = "_resource_list"; | 44 | constexpr char kResourceListAttr[] = "_resource_list"; |
| 45 | +constexpr char kSoBufferAttr[] = "bin_file_buffer"; | ||
| 38 | 46 | ||
| 39 | bool IsValidFusedHostCpuSoElf(const std::vector<uint8_t> &data) { | 47 | bool IsValidFusedHostCpuSoElf(const std::vector<uint8_t> &data) { |
| 40 | return (data.size() >= 20U) && (data.size() <= kMaxGeneratedSoSize) && (data[0] == 0x7FU) && (data[1] == 'E') && | 48 | return (data.size() >= 20U) && (data.size() <= kMaxGeneratedSoSize) && (data[0] == 0x7FU) && (data[1] == 'E') && |
| @@ -132,7 +140,8 @@ bool IsCandidate(const NodePtr &node, const HostCpuFusionOpSupportChecker &op_su | |||
| 132 | GELOGD("Skip HostCPU fusion node[%s]: OpDesc is null.", node->GetNamePtr()); | 140 | GELOGD("Skip HostCPU fusion node[%s]: OpDesc is null.", node->GetNamePtr()); |
| 133 | return false; | 141 | return false; |
| 134 | } | 142 | } |
| 135 | - if (node->GetType() == kFusedHostCpuOpType) { | 143 | + bool generated = false; |
| 144 | + if (AttrUtils::GetBool(node->GetOpDesc(), kFusedHostCpuGenerated, generated) && generated) { | ||
| 136 | GELOGD("Skip HostCPU fusion node[%s]: node is already fused.", node->GetNamePtr()); | 145 | GELOGD("Skip HostCPU fusion node[%s]: node is already fused.", node->GetNamePtr()); |
| 137 | return false; | 146 | return false; |
| 138 | } | 147 | } |
| @@ -318,10 +327,15 @@ std::vector<NodePtr> GetComponentSinks(const std::vector<NodePtr> &component, | |||
| 318 | return sinks; | 327 | return sinks; |
| 319 | } | 328 | } |
| 320 | 329 | ||
| 321 | -HostCpuFusionRegion BuildRegionForSink(const std::vector<NodePtr> &topological_nodes, | 330 | +std::unordered_set<const Node *> CollectComponentAncestors(const std::unordered_set<const Node *> &component_set, |
| 322 | - const std::unordered_set<const Node *> &component_set, const NodePtr &sink) { | 331 | + const NodePtr &sink) { |
| 323 | std::unordered_set<const Node *> ancestors; | 332 | std::unordered_set<const Node *> ancestors; |
| 324 | - std::deque<NodePtr> pending{sink}; | 333 | + std::deque<NodePtr> pending; |
| 334 | + for (const auto &in_node : sink->GetInDataNodes()) { | ||
| 335 | + if (component_set.count(in_node.get()) > 0U) { | ||
| 336 | + pending.emplace_back(in_node); | ||
| 337 | + } | ||
| 338 | + } | ||
| 325 | while (!pending.empty()) { | 339 | while (!pending.empty()) { |
| 326 | const auto current = pending.front(); | 340 | const auto current = pending.front(); |
| 327 | pending.pop_front(); | 341 | pending.pop_front(); |
| @@ -334,10 +348,46 @@ HostCpuFusionRegion BuildRegionForSink(const std::vector<NodePtr> &topological_n | |||
| 334 | } | 348 | } |
| 335 | } | 349 | } |
| 336 | } | 350 | } |
| 351 | + return ancestors; | ||
| 352 | +} | ||
| 353 | + | ||
| 354 | +bool HasSameAncestors(const std::unordered_set<const Node *> &lhs, const std::unordered_set<const Node *> &rhs) { | ||
| 355 | + return (lhs.size() == rhs.size()) && | ||
| 356 | + std::all_of(lhs.cbegin(), lhs.cend(), [&rhs](const Node *node) { return rhs.count(node) > 0U; }); | ||
| 357 | +} | ||
| 358 | + | ||
| 359 | +struct SinkAncestorGroup { | ||
| 360 | + std::unordered_set<const Node *> ancestors; | ||
| 361 | + std::vector<NodePtr> sinks; | ||
| 362 | +}; | ||
| 363 | + | ||
| 364 | +std::vector<SinkAncestorGroup> GroupSinksByAncestors(const std::unordered_set<const Node *> &component_set, | ||
| 365 | + const std::vector<NodePtr> &sinks) { | ||
| 366 | + std::vector<SinkAncestorGroup> groups; | ||
| 367 | + for (const auto &sink : sinks) { | ||
| 368 | + auto ancestors = CollectComponentAncestors(component_set, sink); | ||
| 369 | + const auto group = std::find_if(groups.begin(), groups.end(), [&ancestors](const SinkAncestorGroup &candidate) { | ||
| 370 | + return HasSameAncestors(candidate.ancestors, ancestors); | ||
| 371 | + }); | ||
| 372 | + if (group != groups.end()) { | ||
| 373 | + group->sinks.emplace_back(sink); | ||
| 374 | + continue; | ||
| 375 | + } | ||
| 376 | + groups.push_back({std::move(ancestors), {sink}}); | ||
| 377 | + } | ||
| 378 | + return groups; | ||
| 379 | +} | ||
| 380 | + | ||
| 381 | +HostCpuFusionRegion BuildRegionForSinkGroup(const std::vector<NodePtr> &topological_nodes, | ||
| 382 | + const SinkAncestorGroup &group) { | ||
| 383 | + std::unordered_set<const Node *> region_nodes = group.ancestors; | ||
| 384 | + for (const auto &sink : group.sinks) { | ||
| 385 | + region_nodes.emplace(sink.get()); | ||
| 386 | + } | ||
| 337 | 387 | ||
| 338 | HostCpuFusionRegion region; | 388 | HostCpuFusionRegion region; |
| 339 | for (const auto &node : topological_nodes) { | 389 | for (const auto &node : topological_nodes) { |
| 340 | - if (ancestors.count(node.get()) > 0U) { | 390 | + if (region_nodes.count(node.get()) > 0U) { |
| 341 | region.nodes.emplace_back(node); | 391 | region.nodes.emplace_back(node); |
| 342 | } | 392 | } |
| 343 | } | 393 | } |
| @@ -419,14 +469,17 @@ Status BuildComponentRegions(const ComputeGraphPtr &graph, const std::vector<Nod | |||
| 419 | sinks.size()); | 469 | sinks.size()); |
| 420 | return FAILED; | 470 | return FAILED; |
| 421 | } | 471 | } |
| 422 | - GELOGD("HostCPU fusion component[%zu] contains %zu nodes and %zu sinks, clone_and_split=%d, nodes=[%s].", | 472 | + GELOGD("HostCPU fusion component[%zu] contains %zu nodes and %zu sinks, ancestor_grouping=%d, nodes=[%s].", |
| 423 | component_index, component.size(), sinks.size(), static_cast<int32_t>(requires_split), | 473 | component_index, component.size(), sinks.size(), static_cast<int32_t>(requires_split), |
| 424 | GetNodeNames(component).c_str()); | 474 | GetNodeNames(component).c_str()); |
| 425 | - for (const auto &sink : sinks) { | 475 | + const auto sink_groups = GroupSinksByAncestors(component_set, sinks); |
| 426 | - auto region = BuildRegionForSink(topological_nodes, component_set, sink); | 476 | + GELOGD("HostCPU fusion component[%zu] groups %zu sinks into %zu ancestor group(s).", component_index, sinks.size(), |
| 477 | + sink_groups.size()); | ||
| 478 | + for (const auto &group : sink_groups) { | ||
| 479 | + auto region = BuildRegionForSinkGroup(topological_nodes, group); | ||
| 427 | if (region.nodes.size() < 2U) { | 480 | if (region.nodes.size() < 2U) { |
| 428 | - GELOGD("Skip HostCPU fusion component[%zu] sink[%s]: ancestor region has only %zu node(s).", component_index, | 481 | + GELOGD("Skip HostCPU fusion component[%zu] sink group[%s]: ancestor region has only %zu node(s).", |
| 429 | - sink->GetNamePtr(), region.nodes.size()); | 482 | + component_index, GetNodeNames(group.sinks).c_str(), region.nodes.size()); |
| 430 | continue; | 483 | continue; |
| 431 | } | 484 | } |
| 432 | regions.emplace_back(std::move(region)); | 485 | regions.emplace_back(std::move(region)); |
| @@ -480,16 +533,15 @@ bool AddFusedOutputDescs(const HostCpuFusionRegion ®ion, const OpDescPtr &op_ | |||
| 480 | } | 533 | } |
| 481 | 534 | ||
| 482 | bool SetFusedOpAttributes(const PreparedFusionRegion &prepared, const OpDescPtr &op_desc) { | 535 | bool SetFusedOpAttributes(const PreparedFusionRegion &prepared, const OpDescPtr &op_desc) { |
| 483 | - const auto ®ion = prepared.region; | 536 | + op_desc->SetOpEngineName(kEngineNameCustom); |
| 484 | - op_desc->SetOpEngineName(kHostCpuEngineName); | 537 | + op_desc->SetOpKernelLibName(kCustomOpKernelLibName); |
| 485 | - op_desc->SetOpKernelLibName(kHostCpuKernelLibName); | 538 | + return AttrUtils::SetStr(op_desc, ATTR_NAME_ENGINE_NAME_FOR_LX, kEngineNameCustom) && |
| 486 | - return AttrUtils::SetStr(op_desc, ATTR_NAME_ENGINE_NAME_FOR_LX, kHostCpuEngineName) && | 539 | + AttrUtils::SetStr(op_desc, ATTR_NAME_KKERNEL_LIB_NAME_FOR_LX, kCustomOpKernelLibName) && |
| 487 | - AttrUtils::SetStr(op_desc, ATTR_NAME_KKERNEL_LIB_NAME_FOR_LX, kHostCpuKernelLibName) && | 540 | + AttrUtils::SetStr(op_desc, kAttrLowingFunc, kHostCpuCustomOpLowerFunc) && |
| 488 | - AttrUtils::SetStr(op_desc, kOpKernelLibAttr, kHostCpuTaskKernelLibName) && | ||
| 489 | AttrUtils::SetInt(op_desc, ATTR_NAME_UNKNOWN_SHAPE_TYPE, DEPEND_IN_SHAPE) && | 541 | AttrUtils::SetInt(op_desc, ATTR_NAME_UNKNOWN_SHAPE_TYPE, DEPEND_IN_SHAPE) && |
| 490 | AttrUtils::SetBool(op_desc, kSmallShapeHostCpu, true) && | 542 | AttrUtils::SetBool(op_desc, kSmallShapeHostCpu, true) && |
| 491 | - AttrUtils::SetStr(op_desc, kFusedHostCpuRegisterName, prepared.codegen.register_name) && | 543 | + AttrUtils::SetBool(op_desc, kFusedHostCpuGenerated, true) && |
| 492 | - AttrUtils::SetStr(op_desc, kFusedHostCpuSoKey, std::string(kFusedHostCpuSoDataPrefix) + region.chain_id); | 544 | + AttrUtils::SetStr(op_desc, kFusedHostCpuRegisterName, prepared.codegen.register_name); |
| 493 | } | 545 | } |
| 494 | 546 | ||
| 495 | bool SetFusedOpMetadata(const HostCpuFusionRegion ®ion, const OpDescPtr &op_desc) { | 547 | bool SetFusedOpMetadata(const HostCpuFusionRegion ®ion, const OpDescPtr &op_desc) { |
| @@ -512,8 +564,7 @@ bool SetFusedOpMetadata(const HostCpuFusionRegion ®ion, const OpDescPtr &op_d | |||
| 512 | 564 | ||
| 513 | OpDescPtr CreateFusedOpDesc(const PreparedFusionRegion &prepared) { | 565 | OpDescPtr CreateFusedOpDesc(const PreparedFusionRegion &prepared) { |
| 514 | const auto ®ion = prepared.region; | 566 | const auto ®ion = prepared.region; |
| 515 | - auto op_desc = | 567 | + auto op_desc = std::make_shared<OpDesc>(prepared.codegen.register_name, prepared.codegen.register_name); |
| 516 | - std::make_shared<OpDesc>(std::string(kFusedHostCpuOpType) + "_" + region.chain_id, kFusedHostCpuOpType); | ||
| 517 | if (!AddFusedInputDescs(region, op_desc) || !AddFusedOutputDescs(region, op_desc)) { | 568 | if (!AddFusedInputDescs(region, op_desc) || !AddFusedOutputDescs(region, op_desc)) { |
| 518 | return nullptr; | 569 | return nullptr; |
| 519 | } | 570 | } |
| @@ -548,10 +599,8 @@ struct ReplacedFusionOutput { | |||
| 548 | OutDataAnchorPtr new_source; | 599 | OutDataAnchorPtr new_source; |
| 549 | }; | 600 | }; |
| 550 | 601 | ||
| 551 | -Status RollbackFusionCommit(const ComputeGraphPtr &graph, const ComputeGraphPtr &root_graph, | 602 | +Status RollbackFusionCommit(const ComputeGraphPtr &graph, const std::vector<NodePtr> &fused_nodes, |
| 552 | - const std::vector<NodePtr> &fused_nodes, | 603 | + const std::vector<ReplacedFusionOutput> &replaced_outputs) { |
| 553 | - const std::vector<ReplacedFusionOutput> &replaced_outputs, | ||
| 554 | - const std::vector<std::string> &root_graph_so_keys) { | ||
| 555 | GELOGW("Rollback HostCPU fusion graph commit: graph[%s], new_nodes=%zu, replaced_edges=%zu.", | 604 | GELOGW("Rollback HostCPU fusion graph commit: graph[%s], new_nodes=%zu, replaced_edges=%zu.", |
| 556 | graph->GetName().c_str(), fused_nodes.size(), replaced_outputs.size()); | 605 | graph->GetName().c_str(), fused_nodes.size(), replaced_outputs.size()); |
| 557 | for (auto iter = replaced_outputs.rbegin(); iter != replaced_outputs.rend(); ++iter) { | 606 | for (auto iter = replaced_outputs.rbegin(); iter != replaced_outputs.rend(); ++iter) { |
| @@ -560,28 +609,10 @@ Status RollbackFusionCommit(const ComputeGraphPtr &graph, const ComputeGraphPtr | |||
| 560 | graph->GetName().c_str(), static_cast<int32_t>(iter->consumer == nullptr)); | 609 | graph->GetName().c_str(), static_cast<int32_t>(iter->consumer == nullptr)); |
| 561 | } | 610 | } |
| 562 | } | 611 | } |
| 563 | - const Status rollback_status = RollbackNewNodes(graph, fused_nodes); | 612 | + return RollbackNewNodes(graph, fused_nodes); |
| 564 | - for (const auto &so_key : root_graph_so_keys) { | ||
| 565 | - if (root_graph->DelAttr(so_key) != GRAPH_SUCCESS) { | ||
| 566 | - GELOGE(FAILED, "Failed to remove rolled-back fused HostCPU SO data: graph[%s], so_key[%s].", | ||
| 567 | - root_graph->GetName().c_str(), so_key.c_str()); | ||
| 568 | - } | ||
| 569 | - } | ||
| 570 | - return rollback_status; | ||
| 571 | } | 613 | } |
| 572 | 614 | ||
| 573 | -NodePtr CreateAndRegisterFusedNode(const ComputeGraphPtr &graph, const ComputeGraphPtr &root_graph, | 615 | +NodePtr CreateFusedNode(const ComputeGraphPtr &graph, const PreparedFusionRegion &prepared) { |
| 574 | - const PreparedFusionRegion &prepared, std::vector<std::string> &root_graph_so_keys, | ||
| 575 | - std::string &so_key) { | ||
| 576 | - so_key = std::string(kFusedHostCpuSoDataPrefix) + prepared.region.chain_id; | ||
| 577 | - if (AttrUtils::HasAttr(root_graph, so_key) || | ||
| 578 | - !AttrUtils::SetBytes(root_graph, so_key, | ||
| 579 | - Buffer::CopyFrom(prepared.codegen.so_data.data(), prepared.codegen.so_data.size()))) { | ||
| 580 | - GELOGE(FAILED, "Failed to set fused HostCPU graph SO data: graph[%s], so_key[%s], so_size=%zu.", | ||
| 581 | - graph->GetName().c_str(), so_key.c_str(), prepared.codegen.so_data.size()); | ||
| 582 | - return nullptr; | ||
| 583 | - } | ||
| 584 | - root_graph_so_keys.emplace_back(so_key); | ||
| 585 | const auto op_desc = CreateFusedOpDesc(prepared); | 616 | const auto op_desc = CreateFusedOpDesc(prepared); |
| 586 | if (op_desc == nullptr) { | 617 | if (op_desc == nullptr) { |
| 587 | GELOGE(FAILED, "Failed to create fused HostCPU OpDesc: graph[%s], chain[%s].", graph->GetName().c_str(), | 618 | GELOGE(FAILED, "Failed to create fused HostCPU OpDesc: graph[%s], chain[%s].", graph->GetName().c_str(), |
| @@ -599,10 +630,9 @@ NodePtr CreateAndRegisterFusedNode(const ComputeGraphPtr &graph, const ComputeGr | |||
| 599 | op_desc->GetName().c_str()); | 630 | op_desc->GetName().c_str()); |
| 600 | return nullptr; | 631 | return nullptr; |
| 601 | } | 632 | } |
| 602 | - GELOGD("HostCPU fusion adds node[%s]: chain[%s], so_key[%s], so_graph[%s], so_size=%zu, inputs=%zu, outputs=%zu.", | 633 | + GELOGD("HostCPU fusion adds custom-op node[%s]: chain[%s], so_size=%zu, inputs=%zu, outputs=%zu.", |
| 603 | - fused_node->GetNamePtr(), prepared.region.chain_id.c_str(), so_key.c_str(), root_graph->GetName().c_str(), | 634 | + fused_node->GetNamePtr(), prepared.region.chain_id.c_str(), prepared.codegen.so_data.size(), |
| 604 | - prepared.codegen.so_data.size(), prepared.region.external_inputs.size(), | 635 | + prepared.region.external_inputs.size(), prepared.region.external_outputs.size()); |
| 605 | - prepared.region.external_outputs.size()); | ||
| 606 | return fused_node; | 636 | return fused_node; |
| 607 | } | 637 | } |
| 608 | 638 | ||
| @@ -641,12 +671,9 @@ bool ReplaceFusedNodeOutputs(const ComputeGraphPtr &graph, const PreparedFusionR | |||
| 641 | return true; | 671 | return true; |
| 642 | } | 672 | } |
| 643 | 673 | ||
| 644 | -bool AddPreparedFusionNode(const ComputeGraphPtr &graph, const ComputeGraphPtr &root_graph, | 674 | +bool AddPreparedFusionNode(const ComputeGraphPtr &graph, const PreparedFusionRegion &prepared, |
| 645 | - const PreparedFusionRegion &prepared, std::vector<NodePtr> &fused_nodes, | 675 | + std::vector<NodePtr> &fused_nodes, std::vector<ReplacedFusionOutput> &replaced_outputs) { |
| 646 | - std::vector<std::string> &root_graph_so_keys, | 676 | + const auto fused_node = CreateFusedNode(graph, prepared); |
| 647 | - std::vector<ReplacedFusionOutput> &replaced_outputs) { | ||
| 648 | - std::string so_key; | ||
| 649 | - const auto fused_node = CreateAndRegisterFusedNode(graph, root_graph, prepared, root_graph_so_keys, so_key); | ||
| 650 | if (fused_node == nullptr) { | 677 | if (fused_node == nullptr) { |
| 651 | return false; | 678 | return false; |
| 652 | } | 679 | } |
| @@ -685,6 +712,107 @@ bool RemoveOriginalFusionNodes(const ComputeGraphPtr &graph, const std::vector<P | |||
| 685 | return true; | 712 | return true; |
| 686 | } | 713 | } |
| 687 | 714 | ||
| 715 | +struct FusionCustomOpArtifacts { | ||
| 716 | + std::vector<std::string> inserted_so_keys; | ||
| 717 | + std::vector<AscendString> registered_op_types; | ||
| 718 | +}; | ||
| 719 | + | ||
| 720 | +OpSoBinPtr CreateFusionCustomOpSoBin(const PreparedFusionRegion &prepared) { | ||
| 721 | + const auto &so_data = prepared.codegen.so_data; | ||
| 722 | + if (so_data.empty() || (so_data.size() > std::numeric_limits<uint32_t>::max())) { | ||
| 723 | + GELOGE(PARAM_INVALID, "Invalid generated HostCPU custom-op SO size[%zu], op_type[%s].", so_data.size(), | ||
| 724 | + prepared.codegen.register_name.c_str()); | ||
| 725 | + return nullptr; | ||
| 726 | + } | ||
| 727 | + auto data = std::make_unique<char_t[]>(so_data.size()); | ||
| 728 | + std::copy(so_data.cbegin(), so_data.cend(), data.get()); | ||
| 729 | + const std::string so_name = "lib" + prepared.codegen.register_name + ".so"; | ||
| 730 | + return MakeShared<OpSoBin>(so_name, kFusedHostCpuSoVendor, std::move(data), static_cast<uint32_t>(so_data.size()), | ||
| 731 | + SoBinType::kCustomOp); | ||
| 732 | +} | ||
| 733 | + | ||
| 734 | +bool IsSameSoBin(const OpSoBinPtr &lhs, const OpSoBinPtr &rhs) { | ||
| 735 | + return (lhs != nullptr) && (rhs != nullptr) && (lhs->GetSoBinType() == rhs->GetSoBinType()) && | ||
| 736 | + (lhs->GetBinDataSize() == rhs->GetBinDataSize()) && | ||
| 737 | + std::equal(lhs->GetBinData(), lhs->GetBinData() + lhs->GetBinDataSize(), rhs->GetBinData()); | ||
| 738 | +} | ||
| 739 | + | ||
| 740 | +void RollbackFusionCustomOpArtifacts(const ComputeGraphPtr &root_graph, const FusionCustomOpArtifacts &artifacts) { | ||
| 741 | + if (!artifacts.registered_op_types.empty()) { | ||
| 742 | + CustomOpFactory::RemoveCustomOps(artifacts.registered_op_types); | ||
| 743 | + } | ||
| 744 | + if (artifacts.inserted_so_keys.empty()) { | ||
| 745 | + return; | ||
| 746 | + } | ||
| 747 | + auto so_buffer = root_graph->GetExtAttr<std::map<std::string, OpSoBinPtr>>(kSoBufferAttr); | ||
| 748 | + if (so_buffer == nullptr) { | ||
| 749 | + return; | ||
| 750 | + } | ||
| 751 | + auto updated_buffer = *so_buffer; | ||
| 752 | + for (const auto &key : artifacts.inserted_so_keys) { | ||
| 753 | + (void)updated_buffer.erase(key); | ||
| 754 | + } | ||
| 755 | + if (updated_buffer.empty()) { | ||
| 756 | + (void)root_graph->DelExtAttr(kSoBufferAttr); | ||
| 757 | + } else if (!root_graph->SetExtAttr(kSoBufferAttr, updated_buffer)) { | ||
| 758 | + GELOGW("Failed to restore custom-op SO buffer while rolling back HostCPU fusion for graph[%s].", | ||
| 759 | + root_graph->GetName().c_str()); | ||
| 760 | + } | ||
| 761 | +} | ||
| 762 | + | ||
| 763 | +Status PrepareFusionCustomOpArtifacts(const ComputeGraphPtr &root_graph, | ||
| 764 | + const std::vector<PreparedFusionRegion> &prepared_regions, | ||
| 765 | + FusionCustomOpArtifacts &artifacts) { | ||
| 766 | + artifacts = {}; | ||
| 767 | + std::map<std::string, OpSoBinPtr> updated_buffer; | ||
| 768 | + const auto current_buffer = root_graph->GetExtAttr<std::map<std::string, OpSoBinPtr>>(kSoBufferAttr); | ||
| 769 | + if (current_buffer != nullptr) { | ||
| 770 | + updated_buffer = *current_buffer; | ||
| 771 | + } | ||
| 772 | + | ||
| 773 | + std::vector<OpSoBinPtr> bins_to_load; | ||
| 774 | + const auto registry = CustomOpFactory::GetGlobalRegistryPtr(); | ||
| 775 | + GE_CHECK_NOTNULL(registry); | ||
| 776 | + for (const auto &prepared : prepared_regions) { | ||
| 777 | + const auto so_bin = CreateFusionCustomOpSoBin(prepared); | ||
| 778 | + GE_CHECK_NOTNULL(so_bin); | ||
| 779 | + const std::string so_key = so_bin->GetVendorName() + "/" + so_bin->GetSoName(); | ||
| 780 | + const auto existing = updated_buffer.find(so_key); | ||
| 781 | + if ((existing != updated_buffer.end()) && !IsSameSoBin(existing->second, so_bin)) { | ||
| 782 | + GELOGE(PARAM_INVALID, "HostCPU fusion custom-op SO key[%s] maps to different contents.", so_key.c_str()); | ||
| 783 | + return PARAM_INVALID; | ||
| 784 | + } | ||
| 785 | + if (existing == updated_buffer.end()) { | ||
| 786 | + updated_buffer.emplace(so_key, so_bin); | ||
| 787 | + artifacts.inserted_so_keys.emplace_back(so_key); | ||
| 788 | + } | ||
| 789 | + const AscendString op_type(prepared.codegen.register_name.c_str()); | ||
| 790 | + if (!registry->HasCreator(op_type, OpBackend::kHostCPU)) { | ||
| 791 | + bins_to_load.emplace_back(so_bin); | ||
| 792 | + artifacts.registered_op_types.emplace_back(op_type); | ||
| 793 | + } | ||
| 794 | + } | ||
| 795 | + | ||
| 796 | + if (!bins_to_load.empty()) { | ||
| 797 | + std::vector<CustomOpSoHandlePtr> handles; | ||
| 798 | + GE_CHK_STATUS_RET(CustomOpSoLoader::GetInstance().LoadCustomOpSoBins(bins_to_load, handles), | ||
| 799 | + "Failed to load generated HostCPU custom-op SOs."); | ||
| 800 | + const auto status = CustomOpRegistryBuilder::AddCreatorsFromSoHandles(handles, registry); | ||
| 801 | + if (status != SUCCESS) { | ||
| 802 | + GELOGE(status, "Failed to register generated HostCPU custom-op creators."); | ||
| 803 | + artifacts.registered_op_types.clear(); | ||
| 804 | + return status; | ||
| 805 | + } | ||
| 806 | + } | ||
| 807 | + if (!root_graph->SetExtAttr(kSoBufferAttr, updated_buffer)) { | ||
| 808 | + CustomOpFactory::RemoveCustomOps(artifacts.registered_op_types); | ||
| 809 | + artifacts.registered_op_types.clear(); | ||
| 810 | + GELOGE(FAILED, "Failed to save generated HostCPU custom-op SOs on root graph[%s].", root_graph->GetName().c_str()); | ||
| 811 | + return FAILED; | ||
| 812 | + } | ||
| 813 | + return SUCCESS; | ||
| 814 | +} | ||
| 815 | + | ||
| 688 | Status CommitFusionRegions(const ComputeGraphPtr &graph, const std::vector<PreparedFusionRegion> &prepared_regions, | 816 | Status CommitFusionRegions(const ComputeGraphPtr &graph, const std::vector<PreparedFusionRegion> &prepared_regions, |
| 689 | NodeEngineMap &node_atomic_engine_map, NodeEngineMap &node_composite_engine_map) { | 817 | NodeEngineMap &node_atomic_engine_map, NodeEngineMap &node_composite_engine_map) { |
| 690 | const auto root_graph = GraphUtils::FindRootGraph(graph); | 818 | const auto root_graph = GraphUtils::FindRootGraph(graph); |
| @@ -692,19 +820,23 @@ Status CommitFusionRegions(const ComputeGraphPtr &graph, const std::vector<Prepa | |||
| 692 | GELOGE(FAILED, "Failed to find root graph when committing HostCPU fusion for graph %s.", graph->GetName().c_str()); | 820 | GELOGE(FAILED, "Failed to find root graph when committing HostCPU fusion for graph %s.", graph->GetName().c_str()); |
| 693 | return FAILED; | 821 | return FAILED; |
| 694 | } | 822 | } |
| 823 | + FusionCustomOpArtifacts artifacts; | ||
| 824 | + GE_CHK_STATUS_RET(PrepareFusionCustomOpArtifacts(root_graph, prepared_regions, artifacts), | ||
| 825 | + "Failed to prepare HostCPU fusion custom-op artifacts for graph[%s].", graph->GetName().c_str()); | ||
| 695 | std::vector<NodePtr> fused_nodes; | 826 | std::vector<NodePtr> fused_nodes; |
| 696 | - std::vector<std::string> root_graph_so_keys; | ||
| 697 | std::vector<ReplacedFusionOutput> replaced_outputs; | 827 | std::vector<ReplacedFusionOutput> replaced_outputs; |
| 698 | GELOGD("HostCPU fusion starts graph commit: graph[%s], regions=%zu.", graph->GetName().c_str(), | 828 | GELOGD("HostCPU fusion starts graph commit: graph[%s], regions=%zu.", graph->GetName().c_str(), |
| 699 | prepared_regions.size()); | 829 | prepared_regions.size()); |
| 700 | for (const auto &prepared : prepared_regions) { | 830 | for (const auto &prepared : prepared_regions) { |
| 701 | - if (!AddPreparedFusionNode(graph, root_graph, prepared, fused_nodes, root_graph_so_keys, replaced_outputs)) { | 831 | + if (!AddPreparedFusionNode(graph, prepared, fused_nodes, replaced_outputs)) { |
| 702 | - (void)RollbackFusionCommit(graph, root_graph, fused_nodes, replaced_outputs, root_graph_so_keys); | 832 | + (void)RollbackFusionCommit(graph, fused_nodes, replaced_outputs); |
| 833 | + RollbackFusionCustomOpArtifacts(root_graph, artifacts); | ||
| 703 | return FAILED; | 834 | return FAILED; |
| 704 | } | 835 | } |
| 705 | } | 836 | } |
| 706 | if (!ValidateFusionGraph(graph, "transition")) { | 837 | if (!ValidateFusionGraph(graph, "transition")) { |
| 707 | - (void)RollbackFusionCommit(graph, root_graph, fused_nodes, replaced_outputs, root_graph_so_keys); | 838 | + (void)RollbackFusionCommit(graph, fused_nodes, replaced_outputs); |
| 839 | + RollbackFusionCustomOpArtifacts(root_graph, artifacts); | ||
| 708 | return FAILED; | 840 | return FAILED; |
| 709 | } | 841 | } |
| 710 | GELOGD("HostCPU fusion transition graph validation passed: graph[%s], fused_nodes=%zu.", graph->GetName().c_str(), | 842 | GELOGD("HostCPU fusion transition graph validation passed: graph[%s], fused_nodes=%zu.", graph->GetName().c_str(), |
| @@ -714,8 +846,8 @@ Status CommitFusionRegions(const ComputeGraphPtr &graph, const std::vector<Prepa | |||
| 714 | return FAILED; | 846 | return FAILED; |
| 715 | } | 847 | } |
| 716 | for (const auto &node : fused_nodes) { | 848 | for (const auto &node : fused_nodes) { |
| 717 | - node_atomic_engine_map[node] = kHostCpuEngineName; | 849 | + node_atomic_engine_map[node] = kEngineNameCustom; |
| 718 | - node_composite_engine_map[node] = kHostCpuEngineName; | 850 | + node_composite_engine_map[node] = kEngineNameCustom; |
| 719 | } | 851 | } |
| 720 | if (!ValidateFusionGraph(graph, "final")) { | 852 | if (!ValidateFusionGraph(graph, "final")) { |
| 721 | return FAILED; | 853 | return FAILED; |
| @@ -734,7 +866,7 @@ HostCpuFusionPass::HostCpuFusionPass(std::shared_ptr<HostCpuFusionCompiler> comp | |||
| 734 | } | 866 | } |
| 735 | if (op_support_checker_ == nullptr) { | 867 | if (op_support_checker_ == nullptr) { |
| 736 | op_support_checker_ = [](const std::string &op_type) { | 868 | op_support_checker_ = [](const std::string &op_type) { |
| 737 | - return HostCpuEngine::GetInstance().IsFusedCpuKernelSupported(op_type); | 869 | + return HostCpuEngine::GetInstance().IsHostKernelSupported(op_type); |
| 738 | }; | 870 | }; |
| 739 | } | 871 | } |
| 740 | } | 872 | } |
| @@ -35,7 +35,7 @@ ge::OpDescPtr GetOpDescPtr(const HostCpuOpExecutionContext &ctx) { | |||
| 35 | const auto node_type = ctx.GetNodeType(); | 35 | const auto node_type = ctx.GetNodeType(); |
| 36 | auto const node_op = ge::OperatorFactory::CreateOperator("_", node_type); | 36 | auto const node_op = ge::OperatorFactory::CreateOperator("_", node_type); |
| 37 | if (node_op.IsEmpty()) { | 37 | if (node_op.IsEmpty()) { |
| 38 | - GELOGE(ge::FAILED, "get op from OperatorFactory fail. opType: %s", node_type); | 38 | + GELOGW("get op from OperatorFactory fail. opType: %s", node_type); |
| 39 | return nullptr; | 39 | return nullptr; |
| 40 | } | 40 | } |
| 41 | GELOGD("get op from OperatorFactory success. opType is %s", node_type); | 41 | GELOGD("get op from OperatorFactory success. opType is %s", node_type); |
| @@ -12,11 +12,11 @@ | |||
| 12 | 12 | ||
| 13 | 13 | ||
| 14 | namespace ge { | 14 | namespace ge { |
| 15 | -// Compiler、HostCPU Builder 和 RT2 通过这些属性传递 FusedHostCpu 内部序列化信息。 | 15 | +// Compiler 和 RT2 通过这些属性识别由 HostCPU 融合生成的普通 HostCPU 自定义算子。 |
| 16 | constexpr char kFusedHostCpuOpType[] = "FusedHostCpu"; | 16 | constexpr char kFusedHostCpuOpType[] = "FusedHostCpu"; |
| 17 | constexpr char kFusedHostCpuRegisterName[] = "_host_cpu_fusion_register_name"; | 17 | constexpr char kFusedHostCpuRegisterName[] = "_host_cpu_fusion_register_name"; |
| 18 | -constexpr char kFusedHostCpuSoKey[] = "_host_cpu_fusion_so_key"; | 18 | +constexpr char kFusedHostCpuGenerated[] = "_host_cpu_fusion_generated"; |
| 19 | -constexpr char kFusedHostCpuSoDataPrefix[] = "_hostcpu_codegen_so_data_"; | 19 | +constexpr char kFusedHostCpuSoVendor[] = "host_cpu_fusion"; |
| 20 | constexpr char kFusedHostCpuOriginalNodes[] = "_host_cpu_fusion_original_nodes"; | 20 | constexpr char kFusedHostCpuOriginalNodes[] = "_host_cpu_fusion_original_nodes"; |
| 21 | constexpr char kFusedHostCpuOriginalTypes[] = "_host_cpu_fusion_original_types"; | 21 | constexpr char kFusedHostCpuOriginalTypes[] = "_host_cpu_fusion_original_types"; |
| 22 | constexpr char kFusedHostCpuOutputRefs[] = "_host_cpu_fusion_output_refs"; | 22 | constexpr char kFusedHostCpuOutputRefs[] = "_host_cpu_fusion_output_refs"; |
| @@ -97,6 +97,12 @@ ge::Status CreateSoPathHolder(const ge::NodePtr &node, bg::ValueHolderPtr &so_pa | |||
| 97 | } | 97 | } |
| 98 | auto buffer = bin_file_buffer->find(so_path); | 98 | auto buffer = bin_file_buffer->find(so_path); |
| 99 | if (buffer == bin_file_buffer->end()) { | 99 | if (buffer == bin_file_buffer->end()) { |
| 100 | + // bin_file_buffer 可能还包含 HostCPU fusion 的 kCustomOp SO | ||
| 101 | + if (mmAccess(so_path.c_str()) == EN_OK) { | ||
| 102 | + GELOGD("Autofuse SO is not embedded, use file path: %s.", so_path.c_str()); | ||
| 103 | + return ge::SUCCESS; | ||
| 104 | + } | ||
| 105 | + | ||
| 100 | GELOGE(ge::FAILED, "Not exist autofuse so in bin_file_buffer, key:%s.", so_path.c_str()); | 106 | GELOGE(ge::FAILED, "Not exist autofuse so in bin_file_buffer, key:%s.", so_path.c_str()); |
| 101 | return ge::FAILED; | 107 | return ge::FAILED; |
| 102 | } | 108 | } |
| @@ -29,11 +29,7 @@ | |||
| 29 | 29 | ||
| 30 | 30 | ||
| 31 | 31 | ||
| 32 | - | ||
| 33 | 32 | ||
| 34 | - | ||
| 35 | - | ||
| 36 | - | ||
| 37 | 33 | ||
| 38 | namespace gert { | 34 | namespace gert { |
| 39 | namespace { | 35 | namespace { |
| @@ -246,133 +242,11 @@ LowerResult LoweringAiCpuCCNode(const ge::NodePtr &node, const LowerInput &lower | |||
| 246 | return {HyperStatus::Success(), {cc_launch_holder, launch_holder}, node_output.shapes, out_addrs}; | 242 | return {HyperStatus::Success(), {cc_launch_holder, launch_holder}, node_output.shapes, out_addrs}; |
| 247 | } | 243 | } |
| 248 | 244 | ||
| 249 | -bool GetFusedHostCpuSoData(const ge::NodePtr &node, std::string &fused_register_name, ge::Buffer &so_data, | ||
| 250 | - const char *&error_message, std::string &so_key, ge::ComputeGraphPtr &root_graph) { | ||
| 251 | - error_message = "Load fused HostCPU kernel failed"; | ||
| 252 | - if (!ge::AttrUtils::GetStr(node->GetOpDescBarePtr(), ge::kFusedHostCpuRegisterName, fused_register_name)) { | ||
| 253 | - error_message = "Load fused HostCPU kernel failed"; | ||
| 254 | - GELOGE(ge::INTERNAL_ERROR, "Load fused HostCPU kernel failed for node %s: register name is missing.", | ||
| 255 | - node->GetNamePtr()); | ||
| 256 | - return false; | ||
| 257 | - } | ||
| 258 | - if (!ge::AttrUtils::GetStr(node->GetOpDescBarePtr(), ge::kFusedHostCpuSoKey, so_key)) { | ||
| 259 | - error_message = "Load fused HostCPU kernel failed"; | ||
| 260 | - GELOGE(ge::INTERNAL_ERROR, "Load fused HostCPU kernel failed for node %s: so key is missing.", node->GetNamePtr()); | ||
| 261 | - return false; | ||
| 262 | - } | ||
| 263 | - const auto owner_graph = node->GetOwnerComputeGraph(); | ||
| 264 | - root_graph = ge::GraphUtils::FindRootGraph(owner_graph); | ||
| 265 | - if (root_graph == nullptr) { | ||
| 266 | - error_message = "Load fused HostCPU kernel failed"; | ||
| 267 | - GELOGE(ge::INTERNAL_ERROR, "Load fused HostCPU kernel failed for node %s: root graph was not found.", | ||
| 268 | - node->GetNamePtr()); | ||
| 269 | - return false; | ||
| 270 | - } | ||
| 271 | - if (!ge::AttrUtils::GetBytes(root_graph, so_key, so_data)) { | ||
| 272 | - error_message = "Load fused HostCPU kernel failed"; | ||
| 273 | - GELOGE(ge::INTERNAL_ERROR, | ||
| 274 | - "Load fused HostCPU kernel failed for node %s: so key[%s] was not found in root graph[%s], " | ||
| 275 | - "owner graph[%s].", | ||
| 276 | - node->GetNamePtr(), so_key.c_str(), root_graph->GetName().c_str(), | ||
| 277 | - owner_graph == nullptr ? "null" : owner_graph->GetName().c_str()); | ||
| 278 | - return false; | ||
| 279 | - } | ||
| 280 | - return true; | ||
| 281 | -} | ||
| 282 | - | ||
| 283 | -bool LoadFusedHostCpuKernel(const ge::NodePtr &node, std::string &fused_register_name, | ||
| 284 | - FusedHostCpuKernelFunctions &kernel_funcs, void *&fused_kernel_state, | ||
| 285 | - const char *&error_message) { | ||
| 286 | - std::string so_key; | ||
| 287 | - ge::Buffer so_data; | ||
| 288 | - ge::ComputeGraphPtr root_graph; | ||
| 289 | - if (!GetFusedHostCpuSoData(node, fused_register_name, so_data, error_message, so_key, root_graph)) { | ||
| 290 | - return false; | ||
| 291 | - } | ||
| 292 | - GELOGD("Load fused HostCPU kernel for node[%s]: register_name[%s], so_key[%s], so_graph[%s], so_size=%zu.", | ||
| 293 | - node->GetNamePtr(), fused_register_name.c_str(), so_key.c_str(), root_graph->GetName().c_str(), | ||
| 294 | - so_data.GetSize()); | ||
| 295 | - auto &resource_manager = AicpuResourceManager::GetInstance(); | ||
| 296 | - if (resource_manager.LoadFusedHostCpuSo(fused_register_name, so_data.GetData(), so_data.GetSize()) != | ||
| 297 | - ge::GRAPH_SUCCESS) { | ||
| 298 | - GELOGE(ge::INTERNAL_ERROR, "Load fused HostCPU kernel failed for node %s.", node->GetNamePtr()); | ||
| 299 | - return false; | ||
| 300 | - } | ||
| 301 | - kernel_funcs = resource_manager.GetFusedHostCpuKernelFunctions(fused_register_name); | ||
| 302 | - if ((kernel_funcs.create_func == nullptr) || (kernel_funcs.destroy_func == nullptr) || | ||
| 303 | - (kernel_funcs.run_func == nullptr)) { | ||
| 304 | - error_message = "Resolve fused HostCPU entry failed"; | ||
| 305 | - GELOGE(ge::INTERNAL_ERROR, "Resolve fused HostCPU private entry failed for node %s.", node->GetNamePtr()); | ||
| 306 | - return false; | ||
| 307 | - } | ||
| 308 | - fused_kernel_state = kernel_funcs.create_func(); | ||
| 309 | - if (fused_kernel_state == nullptr) { | ||
| 310 | - error_message = "Prepare fused HostCPU state failed"; | ||
| 311 | - (void)resource_manager.ReleaseFusedHostCpuSo(fused_register_name); | ||
| 312 | - GELOGE(ge::INTERNAL_ERROR, "Prepare fused HostCPU execution state failed for node %s.", node->GetNamePtr()); | ||
| 313 | - return false; | ||
| 314 | - } | ||
| 315 | - return true; | ||
| 316 | -} | ||
| 317 | - | ||
| 318 | -void *CreateFusedHostCpuComputeState(const ge::NodePtr &node, const size_t in_num, const size_t io_num, | ||
| 319 | - const std::string &fused_register_name, | ||
| 320 | - const FusedHostCpuKernelFunctions &kernel_funcs, void *fused_kernel_state) { | ||
| 321 | - std::vector<FusedHostCpuTensorMeta> tensor_metas; | ||
| 322 | - tensor_metas.reserve(io_num); | ||
| 323 | - for (size_t i = 0U; i < in_num; ++i) { | ||
| 324 | - const ge::GeTensorDesc desc = node->GetOpDescBarePtr()->GetInputDesc(i); | ||
| 325 | - tensor_metas.emplace_back(FusedHostCpuTensorMeta{desc.GetShape().GetDimNum()}); | ||
| 326 | - } | ||
| 327 | - for (size_t i = 0U; i < node->GetAllOutDataAnchorsSize(); ++i) { | ||
| 328 | - const ge::GeTensorDesc desc = node->GetOpDescBarePtr()->GetOutputDesc(i); | ||
| 329 | - tensor_metas.emplace_back(FusedHostCpuTensorMeta{desc.GetShape().GetDimNum()}); | ||
| 330 | - } | ||
| 331 | - void *fused_compute_state = | ||
| 332 | - kernel::CreateFusedHostCpuComputeState(fused_register_name.c_str(), fused_kernel_state, kernel_funcs.destroy_func, | ||
| 333 | - kernel_funcs.run_func, tensor_metas.data(), tensor_metas.size()); | ||
| 334 | - if (fused_compute_state == nullptr) { | ||
| 335 | - kernel_funcs.destroy_func(fused_kernel_state); | ||
| 336 | - (void)AicpuResourceManager::GetInstance().ReleaseFusedHostCpuSo(fused_register_name); | ||
| 337 | - GELOGE(ge::INTERNAL_ERROR, "Prepare fused HostCPU compute state failed for node %s.", node->GetNamePtr()); | ||
| 338 | - return nullptr; | ||
| 339 | - } | ||
| 340 | - const FusedHostCpuDestroyMeta destroy_meta = {fused_compute_state}; | ||
| 341 | - bg::FrameSelector::OnDeInitRoot([destroy_meta]() -> std::vector<bg::ValueHolderPtr> { | ||
| 342 | - auto meta_holder = bg::ValueHolder::CreateConst(&destroy_meta, sizeof(destroy_meta)); | ||
| 343 | - return {bg::ValueHolder::CreateVoidGuarder("ReleaseFusedHostCpuKernelState", meta_holder, {})}; | ||
| 344 | - }); | ||
| 345 | - bg::FrameSelector::OnDeInitRoot([fused_register_name]() -> std::vector<bg::ValueHolderPtr> { | ||
| 346 | - auto name_holder = bg::ValueHolder::CreateConst(fused_register_name.c_str(), fused_register_name.size() + 1U, true); | ||
| 347 | - return {bg::ValueHolder::CreateVoidGuarder("ReleaseFusedHostCpuSo", name_holder, {})}; | ||
| 348 | - }); | ||
| 349 | - GELOGD("Fused HostCPU kernel[%s] is ready for node[%s].", fused_register_name.c_str(), node->GetNamePtr()); | ||
| 350 | - return fused_compute_state; | ||
| 351 | -} | ||
| 352 | - | ||
| 353 | -void *PrepareFusedHostCpuComputeState(const ge::NodePtr &node, const size_t in_num, const size_t io_num, | ||
| 354 | - std::string &fused_register_name, const char *&error_message) { | ||
| 355 | - FusedHostCpuKernelFunctions kernel_funcs; | ||
| 356 | - void *fused_kernel_state = nullptr; | ||
| 357 | - if (!LoadFusedHostCpuKernel(node, fused_register_name, kernel_funcs, fused_kernel_state, error_message)) { | ||
| 358 | - return nullptr; | ||
| 359 | - } | ||
| 360 | - void *fused_compute_state = | ||
| 361 | - CreateFusedHostCpuComputeState(node, in_num, io_num, fused_register_name, kernel_funcs, fused_kernel_state); | ||
| 362 | - if (fused_compute_state == nullptr) { | ||
| 363 | - error_message = "Prepare fused HostCPU compute state failed"; | ||
| 364 | - } | ||
| 365 | - return fused_compute_state; | ||
| 366 | -} | ||
| 367 | - | ||
| 368 | struct HostAiCpuLoweringData { | 245 | struct HostAiCpuLoweringData { |
| 369 | const domi::KernelDef *kernel_def = nullptr; | 246 | const domi::KernelDef *kernel_def = nullptr; |
| 370 | bg::ValueHolderPtr session_id; | 247 | bg::ValueHolderPtr session_id; |
| 371 | bg::AicpuArgs aicpu_args; | 248 | bg::AicpuArgs aicpu_args; |
| 372 | size_t in_num = 0U; | 249 | size_t in_num = 0U; |
| 373 | - bool is_fused_host_cpu = false; | ||
| 374 | - std::string fused_register_name; | ||
| 375 | - void *fused_compute_state = nullptr; | ||
| 376 | }; | 250 | }; |
| 377 | 251 | ||
| 378 | const char *PrepareHostAiCpuLowering(const ge::NodePtr &node, const LowerInput &lower_input, | 252 | const char *PrepareHostAiCpuLowering(const ge::NodePtr &node, const LowerInput &lower_input, |
| @@ -384,18 +258,6 @@ const char *PrepareHostAiCpuLowering(const ge::NodePtr &node, const LowerInput & | |||
| 384 | } | 258 | } |
| 385 | lowering_data.kernel_def = &task_def->kernel(); | 259 | lowering_data.kernel_def = &task_def->kernel(); |
| 386 | lowering_data.session_id = bg::GetSessionId(*lower_input.global_data); | 260 | lowering_data.session_id = bg::GetSessionId(*lower_input.global_data); |
| 387 | - lowering_data.is_fused_host_cpu = node->GetType() == ge::kFusedHostCpuOpType; | ||
| 388 | - if (lowering_data.is_fused_host_cpu) { | ||
| 389 | - GELOGD("Lower fused HostCPU node[%s]: inputs=%zu, outputs=%zu.", node->GetNamePtr(), | ||
| 390 | - node->GetAllInDataAnchorsSize(), node->GetAllOutDataAnchorsSize()); | ||
| 391 | - } | ||
| 392 | - | ||
| 393 | - // 融合 so 只注册编排 kernel,原始 HostCPU kernel 仍由基础库提供,必须先加载基础库。 | ||
| 394 | - if (lowering_data.is_fused_host_cpu && | ||
| 395 | - (AicpuResourceManager::GetInstance().LoadConstantFoldingLib() != ge::GRAPH_SUCCESS)) { | ||
| 396 | - GELOGE(ge::INTERNAL_ERROR, "Load HostCPU base library failed for fused node %s.", node->GetNamePtr()); | ||
| 397 | - return "Load HostCPU base library failed"; | ||
| 398 | - } | ||
| 399 | 261 | ||
| 400 | // alloc args | 262 | // alloc args |
| 401 | lowering_data.in_num = node->GetInDataNodesAndAnchors().size(); | 263 | lowering_data.in_num = node->GetInDataNodesAndAnchors().size(); |
| @@ -408,15 +270,6 @@ const char *PrepareHostAiCpuLowering(const ge::NodePtr &node, const LowerInput & | |||
| 408 | } | 270 | } |
| 409 | const auto io_num = lowering_data.in_num + node->GetAllOutDataAnchorsSize(); | 271 | const auto io_num = lowering_data.in_num + node->GetAllOutDataAnchorsSize(); |
| 410 | lowering_data.aicpu_args = bg::BuildHostCCAicpuArg(node, *lowering_data.kernel_def, io_num, lowering_data.session_id); | 272 | lowering_data.aicpu_args = bg::BuildHostCCAicpuArg(node, *lowering_data.kernel_def, io_num, lowering_data.session_id); |
| 411 | - | ||
| 412 | - if (lowering_data.is_fused_host_cpu) { | ||
| 413 | - const char *fused_state_error = nullptr; | ||
| 414 | - lowering_data.fused_compute_state = PrepareFusedHostCpuComputeState( | ||
| 415 | - node, lowering_data.in_num, io_num, lowering_data.fused_register_name, fused_state_error); | ||
| 416 | - if (lowering_data.fused_compute_state == nullptr) { | ||
| 417 | - return fused_state_error; | ||
| 418 | - } | ||
| 419 | - } | ||
| 420 | return nullptr; | 273 | return nullptr; |
| 421 | } | 274 | } |
| 422 | 275 | ||
| @@ -428,12 +281,6 @@ LowerResult BuildHostAiCpuLoweringResult(const ge::NodePtr &node, const LowerInp | |||
| 428 | 281 | ||
| 429 | std::vector<bg::DevMemValueHolderPtr> output_addrs; | 282 | std::vector<bg::DevMemValueHolderPtr> output_addrs; |
| 430 | const bg::IoInfo io_info{lower_input.input_addrs, lower_input.input_shapes, output_sizes, output_shapes}; | 283 | const bg::IoInfo io_info{lower_input.input_addrs, lower_input.input_shapes, output_sizes, output_shapes}; |
| 431 | - if (lowering_data.is_fused_host_cpu) { | ||
| 432 | - auto compute_holder = bg::BuildFusedHostCpuComputeNode(node, lowering_data.fused_compute_state, io_info, | ||
| 433 | - *lower_input.global_data, output_addrs); | ||
| 434 | - SetReleaseAfter(lower_input.input_addrs, compute_holder); | ||
| 435 | - return {HyperStatus::Success(), {}, output_shapes, output_addrs}; | ||
| 436 | - } | ||
| 437 | auto compute_holder = | 284 | auto compute_holder = |
| 438 | bg::AicpuHostCompute(node, lowering_data.aicpu_args, io_info, *lower_input.global_data, output_addrs); | 285 | bg::AicpuHostCompute(node, lowering_data.aicpu_args, io_info, *lower_input.global_data, output_addrs); |
| 439 | 286 | ||
| @@ -10,7 +10,6 @@ | |||
| 10 | 10 | ||
| 11 | 11 | ||
| 12 | 12 | ||
| 13 | - | ||
| 14 | 13 | ||
| 15 | 14 | ||
| 16 | 15 | ||
| @@ -23,7 +22,6 @@ | |||
| 23 | 22 | ||
| 24 | 23 | ||
| 25 | 24 | ||
| 26 | - | ||
| 27 | 25 | ||
| 28 | namespace gert { | 26 | namespace gert { |
| 29 | namespace bg { | 27 | namespace bg { |
| @@ -47,7 +45,6 @@ DevMemValueHolderPtr AllocHostCpuOutputMemory(const ge::NodePtr &node, const IoI | |||
| 47 | inputs.insert(inputs.cend(), io_info.input_addrs.cbegin(), io_info.input_addrs.cend()); | 45 | inputs.insert(inputs.cend(), io_info.input_addrs.cbegin(), io_info.input_addrs.cend()); |
| 48 | auto output = DevMemValueHolder::CreateSingleDataOutput("AllocHostCpuOutputMemory", inputs, | 46 | auto output = DevMemValueHolder::CreateSingleDataOutput("AllocHostCpuOutputMemory", inputs, |
| 49 | node->GetOpDescBarePtr()->GetStreamId()); | 47 | node->GetOpDescBarePtr()->GetStreamId()); |
| 50 | - GE_ASSERT_NOTNULL(output); | ||
| 51 | output->SetPlacement(kOnHost); | 48 | output->SetPlacement(kOnHost); |
| 52 | return output; | 49 | return output; |
| 53 | } | 50 | } |
| @@ -272,46 +269,5 @@ ValueHolderPtr AicpuHostCompute(const ge::NodePtr &node, const AicpuArgs &args, | |||
| 272 | } | 269 | } |
| 273 | return compute_holder; | 270 | return compute_holder; |
| 274 | } | 271 | } |
| 275 | - | ||
| 276 | -ValueHolderPtr BuildFusedHostCpuComputeNode(const ge::NodePtr &node, void *compute_state, const IoInfo &io_info, | ||
| 277 | - LoweringGlobalData &global_data, | ||
| 278 | - std::vector<DevMemValueHolderPtr> &output_addrs) { | ||
| 279 | - GE_ASSERT_NOTNULL(node); | ||
| 280 | - GE_ASSERT_NOTNULL(compute_state); | ||
| 281 | - const auto op_desc = node->GetOpDescBarePtr(); | ||
| 282 | - GE_ASSERT_NOTNULL(op_desc); | ||
| 283 | - GE_ASSERT_TRUE(io_info.input_shapes.size() == io_info.input_addrs.size()); | ||
| 284 | - GE_ASSERT_TRUE(io_info.output_shapes.size() == io_info.output_sizes.size()); | ||
| 285 | - | ||
| 286 | - output_addrs = AllocHostCpuOutputsMemory(node, io_info, global_data); | ||
| 287 | - GE_ASSERT_TRUE(io_info.output_shapes.size() == output_addrs.size()); | ||
| 288 | - | ||
| 289 | - const size_t input_num = io_info.input_shapes.size(); | ||
| 290 | - const size_t output_num = io_info.output_shapes.size(); | ||
| 291 | - GE_ASSERT_TRUE(input_num == op_desc->GetAllInputsSize()); | ||
| 292 | - GE_ASSERT_TRUE(output_num == op_desc->GetOutputsSize()); | ||
| 293 | - GE_ASSERT_TRUE(output_num != 0U); | ||
| 294 | - | ||
| 295 | - const FusedHostCpuComputeMeta compute_meta = {compute_state, input_num, output_num}; | ||
| 296 | - | ||
| 297 | - std::vector<ValueHolderPtr> inputs; | ||
| 298 | - inputs.emplace_back(ValueHolder::CreateConst(&compute_meta, sizeof(compute_meta))); | ||
| 299 | - inputs.insert(inputs.cend(), io_info.input_shapes.cbegin(), io_info.input_shapes.cend()); | ||
| 300 | - inputs.insert(inputs.cend(), io_info.input_addrs.cbegin(), io_info.input_addrs.cend()); | ||
| 301 | - inputs.insert(inputs.cend(), io_info.output_shapes.cbegin(), io_info.output_shapes.cend()); | ||
| 302 | - inputs.insert(inputs.cend(), output_addrs.cbegin(), output_addrs.cend()); | ||
| 303 | - | ||
| 304 | - const auto allocated_output_addrs = output_addrs; | ||
| 305 | - output_addrs = DevMemValueHolder::CreateDataOutput("FusedHostCpuCompute", inputs, output_num, op_desc->GetStreamId()); | ||
| 306 | - GE_ASSERT_EQ(output_addrs.size(), allocated_output_addrs.size()); | ||
| 307 | - for (size_t i = 0U; i < output_addrs.size(); ++i) { | ||
| 308 | - GE_ASSERT_NOTNULL(output_addrs[i]); | ||
| 309 | - GE_ASSERT_NOTNULL(allocated_output_addrs[i]); | ||
| 310 | - output_addrs[i]->SetPlacement(allocated_output_addrs[i]->GetPlacement()); | ||
| 311 | - } | ||
| 312 | - GELOGD("Build fused HostCPU private-entry compute: node[%s], inputs=%zu, outputs=%zu.", node->GetNamePtr(), input_num, | ||
| 313 | - output_num); | ||
| 314 | - return output_addrs[0U]; | ||
| 315 | -} | ||
| 316 | } // namespace bg | 272 | } // namespace bg |
| 317 | } // namespace gert | 273 | } // namespace gert |
| @@ -52,10 +52,6 @@ ValueHolderPtr AicpuHostExecFuncProcess(const AicpuHostProcFunc &func, const IoI | |||
| 52 | const std::vector<DevMemValueHolderPtr> &output_addrs); | 52 | const std::vector<DevMemValueHolderPtr> &output_addrs); |
| 53 | ValueHolderPtr AicpuHostCompute(const ge::NodePtr &node, const AicpuArgs &args, const IoInfo &io_info, | 53 | ValueHolderPtr AicpuHostCompute(const ge::NodePtr &node, const AicpuArgs &args, const IoInfo &io_info, |
| 54 | LoweringGlobalData &global_data, std::vector<DevMemValueHolderPtr> &output_addrs); | 54 | LoweringGlobalData &global_data, std::vector<DevMemValueHolderPtr> &output_addrs); |
| 55 | -// Build the ExecuteGraph node; the registered runtime kernel is FusedHostCpuCompute. | ||
| 56 | -ValueHolderPtr BuildFusedHostCpuComputeNode(const ge::NodePtr &node, void *compute_state, const IoInfo &io_info, | ||
| 57 | - LoweringGlobalData &global_data, | ||
| 58 | - std::vector<DevMemValueHolderPtr> &output_addrs); | ||
| 59 | ValueHolderPtr GetContainerIdHolder(const LowerInput &lower_input); | 55 | ValueHolderPtr GetContainerIdHolder(const LowerInput &lower_input); |
| 60 | } // namespace bg | 56 | } // namespace bg |
| 61 | } // namespace gert | 57 | } // namespace gert |
| @@ -12,8 +12,6 @@ | |||
| 12 | 12 | ||
| 13 | 13 | ||
| 14 | 14 | ||
| 15 | - | ||
| 16 | - | ||
| 17 | 15 | ||
| 18 | 16 | ||
| 19 | 17 | ||
| @@ -31,7 +29,6 @@ | |||
| 31 | 29 | ||
| 32 | 30 | ||
| 33 | 31 | ||
| 34 | - | ||
| 35 | 32 | ||
| 36 | 33 | ||
| 37 | 34 | ||
| @@ -42,7 +39,6 @@ | |||
| 42 | 39 | ||
| 43 | 40 | ||
| 44 | 41 | ||
| 45 | - | ||
| 46 | 42 | ||
| 47 | using namespace ge; | 43 | using namespace ge; |
| 48 | 44 | ||
| @@ -416,183 +412,6 @@ ge::graphStatus AicpuHostCompute(KernelContext *context) { | |||
| 416 | } | 412 | } |
| 417 | REGISTER_KERNEL(AicpuHostCompute).RunFunc(AicpuHostCompute); | 413 | REGISTER_KERNEL(AicpuHostCompute).RunFunc(AicpuHostCompute); |
| 418 | 414 | ||
| 419 | -namespace { | ||
| 420 | -struct FusedHostCpuTensorState { | ||
| 421 | - const void *data = nullptr; | ||
| 422 | - size_t data_size = 0U; | ||
| 423 | - std::vector<int64_t> dims; | ||
| 424 | - bool initialized = false; | ||
| 425 | -}; | ||
| 426 | - | ||
| 427 | -struct FusedHostCpuCallState { | ||
| 428 | - std::string register_name; | ||
| 429 | - void *kernel_state = nullptr; | ||
| 430 | - FusedHostCpuDestroyFunc destroy_func = nullptr; | ||
| 431 | - FusedHostCpuRunFunc run_func = nullptr; | ||
| 432 | - std::vector<FusedHostCpuTensorBinding> bindings; | ||
| 433 | - std::vector<FusedHostCpuTensorState> tensor_states; | ||
| 434 | -}; | ||
| 435 | - | ||
| 436 | -bool HasSameShape(const gert::Shape &shape, const FusedHostCpuTensorState &state) { | ||
| 437 | - if (state.dims.size() != shape.GetDimNum()) { | ||
| 438 | - return false; | ||
| 439 | - } | ||
| 440 | - for (size_t i = 0U; i < shape.GetDimNum(); ++i) { | ||
| 441 | - if (state.dims[i] != shape.GetDim(i)) { | ||
| 442 | - return false; | ||
| 443 | - } | ||
| 444 | - } | ||
| 445 | - return true; | ||
| 446 | -} | ||
| 447 | - | ||
| 448 | -ge::graphStatus BuildFusedHostCpuBinding(const StorageShape *storage_shape, GertTensorData *tensor_data, | ||
| 449 | - FusedHostCpuTensorState &state, FusedHostCpuTensorBinding &binding) { | ||
| 450 | - GE_ASSERT_NOTNULL(storage_shape); | ||
| 451 | - GE_ASSERT_NOTNULL(tensor_data); | ||
| 452 | - GE_ASSERT_TRUE((tensor_data->GetSize() == 0U) || (tensor_data->GetAddr() != nullptr)); | ||
| 453 | - const auto &origin_shape = storage_shape->GetOriginShape(); | ||
| 454 | - const bool shape_changed = !state.initialized || !HasSameShape(origin_shape, state); | ||
| 455 | - if (shape_changed) { | ||
| 456 | - if (state.dims.size() != origin_shape.GetDimNum()) { | ||
| 457 | - state.dims.resize(origin_shape.GetDimNum()); | ||
| 458 | - } | ||
| 459 | - for (size_t i = 0U; i < state.dims.size(); ++i) { | ||
| 460 | - state.dims[i] = origin_shape.GetDim(i); | ||
| 461 | - } | ||
| 462 | - binding.dims = state.dims.data(); | ||
| 463 | - binding.dim_num = state.dims.size(); | ||
| 464 | - } | ||
| 465 | - const void *data = tensor_data->GetAddr(); | ||
| 466 | - const size_t data_size = tensor_data->GetSize(); | ||
| 467 | - const bool data_changed = !state.initialized || (state.data != data) || (state.data_size != data_size); | ||
| 468 | - if (data_changed) { | ||
| 469 | - binding.data = reinterpret_cast<uint8_t *>(tensor_data->GetAddr()); | ||
| 470 | - binding.data_size = data_size; | ||
| 471 | - state.data = data; | ||
| 472 | - state.data_size = data_size; | ||
| 473 | - } | ||
| 474 | - binding.flags = (shape_changed ? kFusedHostCpuShapeChanged : 0U) | (data_changed ? kFusedHostCpuDataChanged : 0U); | ||
| 475 | - state.initialized = true; | ||
| 476 | - return ge::GRAPH_SUCCESS; | ||
| 477 | -} | ||
| 478 | -} // namespace | ||
| 479 | - | ||
| 480 | -void *CreateFusedHostCpuComputeState(const char *register_name, void *kernel_state, | ||
| 481 | - const FusedHostCpuDestroyFunc destroy_func, const FusedHostCpuRunFunc run_func, | ||
| 482 | - const FusedHostCpuTensorMeta *tensor_metas, const size_t io_num) { | ||
| 483 | - if ((register_name == nullptr) || (kernel_state == nullptr) || (destroy_func == nullptr) || (run_func == nullptr) || | ||
| 484 | - (tensor_metas == nullptr) || (io_num == 0U)) { | ||
| 485 | - GELOGE(ge::PARAM_INVALID, | ||
| 486 | - "Invalid fused HostCPU compute state arguments: register_null[%d], kernel_state_null[%d], " | ||
| 487 | - "destroy_null[%d], run_null[%d], tensor_metas_null[%d], io_num[%zu].", | ||
| 488 | - static_cast<int32_t>(register_name == nullptr), static_cast<int32_t>(kernel_state == nullptr), | ||
| 489 | - static_cast<int32_t>(destroy_func == nullptr), static_cast<int32_t>(run_func == nullptr), | ||
| 490 | - static_cast<int32_t>(tensor_metas == nullptr), io_num); | ||
| 491 | - return nullptr; | ||
| 492 | - } | ||
| 493 | - std::unique_ptr<FusedHostCpuCallState> state = std::make_unique<FusedHostCpuCallState>(); | ||
| 494 | - state->register_name = register_name; | ||
| 495 | - state->kernel_state = kernel_state; | ||
| 496 | - state->destroy_func = destroy_func; | ||
| 497 | - state->run_func = run_func; | ||
| 498 | - state->bindings.reserve(io_num); | ||
| 499 | - state->tensor_states.reserve(io_num); | ||
| 500 | - for (size_t i = 0U; i < io_num; ++i) { | ||
| 501 | - std::vector<int64_t> dims(tensor_metas[i].dim_num, ge::UNKNOWN_DIM); | ||
| 502 | - FusedHostCpuTensorState tensor_state; | ||
| 503 | - tensor_state.dims = std::move(dims); | ||
| 504 | - state->tensor_states.emplace_back(std::move(tensor_state)); | ||
| 505 | - state->bindings.emplace_back( | ||
| 506 | - FusedHostCpuTensorBinding{state->tensor_states.back().dims.data(), nullptr, tensor_metas[i].dim_num, 0U, 0U}); | ||
| 507 | - } | ||
| 508 | - return state.release(); | ||
| 509 | -} | ||
| 510 | - | ||
| 511 | -void DestroyFusedHostCpuComputeState(void *compute_state) { | ||
| 512 | - FusedHostCpuCallState *state = static_cast<FusedHostCpuCallState *>(compute_state); | ||
| 513 | - if (state == nullptr) { | ||
| 514 | - return; | ||
| 515 | - } | ||
| 516 | - state->destroy_func(state->kernel_state); | ||
| 517 | - delete state; | ||
| 518 | -} | ||
| 519 | - | ||
| 520 | -// Runtime callback for the ExecuteGraph kernel registered as FusedHostCpuCompute. | ||
| 521 | -ge::graphStatus RunFusedHostCpuCompute(KernelContext *context) { | ||
| 522 | - GE_ASSERT_NOTNULL(context); | ||
| 523 | - const auto compute_meta = context->GetInputPointer<FusedHostCpuComputeMeta>(0U); | ||
| 524 | - GE_ASSERT_NOTNULL(compute_meta); | ||
| 525 | - FusedHostCpuCallState *call_state = static_cast<FusedHostCpuCallState *>(compute_meta->compute_state); | ||
| 526 | - GE_ASSERT_NOTNULL(call_state); | ||
| 527 | - GE_ASSERT_NOTNULL(call_state->kernel_state); | ||
| 528 | - GE_ASSERT_NOTNULL(call_state->run_func); | ||
| 529 | - const auto input_num = compute_meta->input_num; | ||
| 530 | - const auto output_num = compute_meta->output_num; | ||
| 531 | - const auto io_num = input_num + output_num; | ||
| 532 | - GE_ASSERT_TRUE(call_state->bindings.size() == io_num); | ||
| 533 | - GE_ASSERT_TRUE(call_state->tensor_states.size() == io_num); | ||
| 534 | - | ||
| 535 | - const size_t input_shape_start = 1U; | ||
| 536 | - const size_t input_addr_start = input_shape_start + input_num; | ||
| 537 | - const size_t output_shape_start = input_addr_start + input_num; | ||
| 538 | - const size_t output_addr_start = output_shape_start + output_num; | ||
| 539 | - GE_ASSERT_TRUE(context->GetInputNum() == (output_addr_start + output_num)); | ||
| 540 | - | ||
| 541 | - uint32_t binding_flags = 0U; | ||
| 542 | - for (size_t i = 0U; i < input_num; ++i) { | ||
| 543 | - const auto storage_shape = context->GetInputPointer<StorageShape>(input_shape_start + i); | ||
| 544 | - auto tensor_data = context->MutableInputPointer<GertTensorData>(input_addr_start + i); | ||
| 545 | - GE_ASSERT_SUCCESS( | ||
| 546 | - BuildFusedHostCpuBinding(storage_shape, tensor_data, call_state->tensor_states[i], call_state->bindings[i])); | ||
| 547 | - binding_flags |= call_state->bindings[i].flags; | ||
| 548 | - } | ||
| 549 | - | ||
| 550 | - for (size_t i = 0U; i < output_num; ++i) { | ||
| 551 | - const auto storage_shape = context->GetInputPointer<StorageShape>(output_shape_start + i); | ||
| 552 | - auto tensor_data = context->MutableInputPointer<GertTensorData>(output_addr_start + i); | ||
| 553 | - const size_t tensor_index = input_num + i; | ||
| 554 | - GE_ASSERT_SUCCESS(BuildFusedHostCpuBinding(storage_shape, tensor_data, call_state->tensor_states[tensor_index], | ||
| 555 | - call_state->bindings[tensor_index])); | ||
| 556 | - binding_flags |= call_state->bindings[tensor_index].flags; | ||
| 557 | - } | ||
| 558 | - | ||
| 559 | - const uint32_t ret = call_state->run_func(call_state->kernel_state, | ||
| 560 | - static_cast<const void *>(call_state->bindings.data()), binding_flags); | ||
| 561 | - GE_ASSERT_TRUE(ret == 0U, "Fused HostCPU private entry failed: register_name[%s], ret=%u.", | ||
| 562 | - call_state->register_name.c_str(), ret); | ||
| 563 | - return ge::GRAPH_SUCCESS; | ||
| 564 | -} | ||
| 565 | - | ||
| 566 | -ge::graphStatus CreateFusedHostCpuComputeOutputs(const ge::FastNode *node, KernelContext *context) { | ||
| 567 | - (void)node; | ||
| 568 | - GE_ASSERT_NOTNULL(context); | ||
| 569 | - GE_ASSERT_TRUE(context->GetInputNum() >= context->GetOutputNum()); | ||
| 570 | - const size_t output_addr_start = context->GetInputNum() - context->GetOutputNum(); | ||
| 571 | - for (size_t i = 0U; i < context->GetOutputNum(); ++i) { | ||
| 572 | - auto chain = context->GetOutput(i); | ||
| 573 | - auto tensor_data = context->MutableInputPointer<GertTensorData>(output_addr_start + i); | ||
| 574 | - GE_ASSERT_NOTNULL(chain); | ||
| 575 | - GE_ASSERT_NOTNULL(tensor_data); | ||
| 576 | - chain->Set(tensor_data, nullptr); | ||
| 577 | - } | ||
| 578 | - return ge::GRAPH_SUCCESS; | ||
| 579 | -} | ||
| 580 | - | ||
| 581 | -REGISTER_KERNEL(FusedHostCpuCompute) | ||
| 582 | - .RunFunc(RunFusedHostCpuCompute) | ||
| 583 | - .OutputsCreator(CreateFusedHostCpuComputeOutputs) | ||
| 584 | - .ConcurrentCriticalSectionKey(kKernelUseMemory); | ||
| 585 | - | ||
| 586 | -ge::graphStatus ReleaseFusedHostCpuKernelState(KernelContext *context) { | ||
| 587 | - GE_ASSERT_NOTNULL(context); | ||
| 588 | - const auto destroy_meta = context->GetInputPointer<FusedHostCpuDestroyMeta>(0U); | ||
| 589 | - GE_ASSERT_NOTNULL(destroy_meta); | ||
| 590 | - GE_ASSERT_NOTNULL(destroy_meta->compute_state); | ||
| 591 | - DestroyFusedHostCpuComputeState(destroy_meta->compute_state); | ||
| 592 | - return ge::GRAPH_SUCCESS; | ||
| 593 | -} | ||
| 594 | -REGISTER_KERNEL(ReleaseFusedHostCpuKernelState).RunFunc(ReleaseFusedHostCpuKernelState); | ||
| 595 | - | ||
| 596 | ge::graphStatus AicpuHostExecFunc(KernelContext *context) { | 415 | ge::graphStatus AicpuHostExecFunc(KernelContext *context) { |
| 597 | const auto input_size = context->GetInputNum(); | 416 | const auto input_size = context->GetInputNum(); |
| 598 | // func取输入的最后一个,因为前面输入个数不固定。 | 417 | // func取输入的最后一个,因为前面输入个数不固定。 |
| @@ -9,8 +9,6 @@ | |||
| 9 | */ | 9 | */ |
| 10 | 10 | ||
| 11 | 11 | ||
| 12 | - | ||
| 13 | - | ||
| 14 | 12 | ||
| 15 | 13 | ||
| 16 | 14 | ||
| @@ -25,14 +23,6 @@ | |||
| 25 | 23 | ||
| 26 | 24 | ||
| 27 | 25 | ||
| 28 | - | ||
| 29 | - | ||
| 30 | - | ||
| 31 | - | ||
| 32 | - | ||
| 33 | - | ||
| 34 | - | ||
| 35 | - | ||
| 36 | 26 | ||
| 37 | namespace gert { | 27 | namespace gert { |
| 38 | namespace { | 28 | namespace { |
| @@ -44,78 +34,6 @@ void FreeHbmMem(void *p) { | |||
| 44 | 34 | ||
| 45 | const std::string kHostCpuLibRelativePathOld = "/op_impl/built-in/host_cpu/libconstant_folding_ops.so"; | 35 | const std::string kHostCpuLibRelativePathOld = "/op_impl/built-in/host_cpu/libconstant_folding_ops.so"; |
| 46 | const std::string kHostCpuLibRelativePath = "/built-in/op_impl/host_cpu/libconstant_folding_ops.so"; | 36 | const std::string kHostCpuLibRelativePath = "/built-in/op_impl/host_cpu/libconstant_folding_ops.so"; |
| 47 | -constexpr size_t kMaxFusedHostCpuSoSize = 10U * 1024U * 1024U; | ||
| 48 | -constexpr size_t kMaxFusedRegisterNameSize = 160U; | ||
| 49 | -constexpr char kValidateFusedHostCpuKernelRegistration[] = "ValidateFusedHostCpuKernelRegistration"; | ||
| 50 | -constexpr char kCreateFusedHostCpuKernelState[] = "CreateFusedHostCpuKernelState"; | ||
| 51 | -constexpr char kDestroyFusedHostCpuKernelState[] = "DestroyFusedHostCpuKernelState"; | ||
| 52 | -constexpr char kRunFusedHostCpuKernel[] = "RunFusedHostCpuKernel"; | ||
| 53 | - | ||
| 54 | -bool IsAsciiAlphaNumeric(const unsigned char ch) { | ||
| 55 | - return ((ch >= '0') && (ch <= '9')) || ((ch >= 'A') && (ch <= 'Z')) || ((ch >= 'a') && (ch <= 'z')); | ||
| 56 | -} | ||
| 57 | - | ||
| 58 | -bool IsValidFusedRegisterName(const std::string ®ister_name) { | ||
| 59 | - const std::string prefix = std::string(ge::kFusedHostCpuOpType) + "_"; | ||
| 60 | - if ((register_name.size() <= prefix.size()) || (register_name.size() > kMaxFusedRegisterNameSize) || | ||
| 61 | - (register_name.compare(0U, prefix.size(), prefix) != 0)) { | ||
| 62 | - return false; | ||
| 63 | - } | ||
| 64 | - return std::all_of(register_name.cbegin() + static_cast<std::ptrdiff_t>(prefix.size()), register_name.cend(), | ||
| 65 | - [](const unsigned char ch) { return IsAsciiAlphaNumeric(ch) || (ch == '_'); }); | ||
| 66 | -} | ||
| 67 | - | ||
| 68 | -uint64_t HashFusedSo(const uint8_t *data, const size_t size) { | ||
| 69 | - uint64_t hash = 1469598103934665603ULL; | ||
| 70 | - for (size_t i = 0U; i < size; ++i) { | ||
| 71 | - hash ^= data[i]; | ||
| 72 | - hash *= 1099511628211ULL; | ||
| 73 | - } | ||
| 74 | - return hash; | ||
| 75 | -} | ||
| 76 | - | ||
| 77 | -bool IsExpectedFusedElf(const uint8_t *data, const size_t size) { | ||
| 78 | - if ((size < 20U) || (data[0] != 0x7FU) || (data[1] != 'E') || (data[2] != 'L') || (data[3] != 'F') || | ||
| 79 | - (data[4] != 2U) || (data[5] != 1U) || (data[6] != 1U) || (data[16] != 3U) || (data[17] != 0U)) { | ||
| 80 | - return false; | ||
| 81 | - } | ||
| 82 | - const uint16_t machine = static_cast<uint16_t>(data[18]) | (static_cast<uint16_t>(data[19]) << 8U); | ||
| 83 | - | ||
| 84 | - return machine == 183U; | ||
| 85 | - | ||
| 86 | - return machine == 62U; | ||
| 87 | - | ||
| 88 | - (void)machine; | ||
| 89 | - return true; | ||
| 90 | - | ||
| 91 | -} | ||
| 92 | - | ||
| 93 | -bool ValidateFusedHostCpuRegistration(void *handle, const std::string ®ister_name) { | ||
| 94 | - using ValidateRegistration = bool (*)(const char *); | ||
| 95 | - const auto validate = | ||
| 96 | - reinterpret_cast<ValidateRegistration>(mmDlsym(handle, kValidateFusedHostCpuKernelRegistration)); | ||
| 97 | - return (validate != nullptr) && validate(register_name.c_str()); | ||
| 98 | -} | ||
| 99 | - | ||
| 100 | - | ||
| 101 | -bool WriteAll(const int fd, const uint8_t *data, const size_t size) { | ||
| 102 | - size_t offset = 0U; | ||
| 103 | - while (offset < size) { | ||
| 104 | - const ssize_t written = write(fd, data + offset, size - offset); | ||
| 105 | - if (written < 0) { | ||
| 106 | - if (errno == EINTR) { | ||
| 107 | - continue; | ||
| 108 | - } | ||
| 109 | - return false; | ||
| 110 | - } | ||
| 111 | - if (written == 0) { | ||
| 112 | - return false; | ||
| 113 | - } | ||
| 114 | - offset += static_cast<size_t>(written); | ||
| 115 | - } | ||
| 116 | - return true; | ||
| 117 | -} | ||
| 118 | - | ||
| 119 | 37 | ||
| 120 | ge::graphStatus GetRealPath(std::string &path) { | 38 | ge::graphStatus GetRealPath(std::string &path) { |
| 121 | const std::string real_path = ge::RealPath(path.c_str()); | 39 | const std::string real_path = ge::RealPath(path.c_str()); |
| @@ -154,20 +72,10 @@ AicpuResourceManager &AicpuResourceManager::GetInstance() { | |||
| 154 | } | 72 | } |
| 155 | 73 | ||
| 156 | AicpuResourceManager::~AicpuResourceManager() { | 74 | AicpuResourceManager::~AicpuResourceManager() { |
| 157 | - // CpuKernelRegister 没有注销接口,其 std::function creator 指向 JIT so。这里必须先让基础 HostCPU | ||
| 158 | - // 库在 dlclose 时销毁 registry,再由进程回收仍映射的 JIT so,不能提前 dlclose 形成悬空 creator。 | ||
| 159 | if (so_handle_ != nullptr) { | 75 | if (so_handle_ != nullptr) { |
| 160 | (void)mmDlclose(so_handle_); | 76 | (void)mmDlclose(so_handle_); |
| 161 | so_handle_ = nullptr; | 77 | so_handle_ = nullptr; |
| 162 | } | 78 | } |
| 163 | - | ||
| 164 | - for (const std::pair<const uint64_t, int> &fd_entry : fused_so_fds_) { | ||
| 165 | - (void)close(fd_entry.second); | ||
| 166 | - } | ||
| 167 | - for (const int fd : fused_quarantined_so_fds_) { | ||
| 168 | - (void)close(fd); | ||
| 169 | - } | ||
| 170 | - | ||
| 171 | } | 79 | } |
| 172 | 80 | ||
| 173 | ge::graphStatus AicpuResourceManager::LoadConstantFoldingLib() { | 81 | ge::graphStatus AicpuResourceManager::LoadConstantFoldingLib() { |
| @@ -210,174 +118,6 @@ ge::graphStatus AicpuResourceManager::LoadConstantFoldingLib() { | |||
| 210 | return ge::GRAPH_SUCCESS; | 118 | return ge::GRAPH_SUCCESS; |
| 211 | } | 119 | } |
| 212 | 120 | ||
| 213 | -ge::graphStatus AicpuResourceManager::TryReuseFusedHostCpuSo(const std::string ®ister_name, const uint8_t *so_data, | ||
| 214 | - const size_t so_size, const uint64_t so_hash, | ||
| 215 | - bool &handled) { | ||
| 216 | - handled = false; | ||
| 217 | - const auto register_iter = fused_register_hashes_.find(register_name); | ||
| 218 | - if (register_iter != fused_register_hashes_.end()) { | ||
| 219 | - handled = true; | ||
| 220 | - const auto content_iter = fused_so_contents_.find(so_hash); | ||
| 221 | - if ((register_iter->second != so_hash) || (content_iter == fused_so_contents_.end()) || | ||
| 222 | - (content_iter->second.size() != so_size) || | ||
| 223 | - !std::equal(content_iter->second.cbegin(), content_iter->second.cend(), so_data)) { | ||
| 224 | - GELOGE(ge::PARAM_INVALID, "Fused HostCPU register name %s maps to different shared objects.", | ||
| 225 | - register_name.c_str()); | ||
| 226 | - return ge::PARAM_INVALID; | ||
| 227 | - } | ||
| 228 | - ++fused_register_ref_counts_[register_name]; | ||
| 229 | - ++fused_so_ref_counts_[so_hash]; | ||
| 230 | - GELOGD("Reuse fused HostCPU shared object by register name[%s].", register_name.c_str()); | ||
| 231 | - return ge::GRAPH_SUCCESS; | ||
| 232 | - } | ||
| 233 | - const auto handle_iter = fused_so_handles_.find(so_hash); | ||
| 234 | - if (handle_iter == fused_so_handles_.end()) { | ||
| 235 | - return ge::GRAPH_SUCCESS; | ||
| 236 | - } | ||
| 237 | - handled = true; | ||
| 238 | - const auto content_iter = fused_so_contents_.find(so_hash); | ||
| 239 | - if ((content_iter == fused_so_contents_.end()) || (content_iter->second.size() != so_size) || | ||
| 240 | - !std::equal(content_iter->second.cbegin(), content_iter->second.cend(), so_data)) { | ||
| 241 | - GELOGE(ge::PARAM_INVALID, "Hash collision detected while loading fused HostCPU shared object %s.", | ||
| 242 | - register_name.c_str()); | ||
| 243 | - return ge::PARAM_INVALID; | ||
| 244 | - } | ||
| 245 | - GELOGE(ge::PARAM_INVALID, "Fused HostCPU shared object content is already cached by another register name %s.", | ||
| 246 | - register_name.c_str()); | ||
| 247 | - return ge::PARAM_INVALID; | ||
| 248 | -} | ||
| 249 | - | ||
| 250 | -ge::graphStatus AicpuResourceManager::LoadFusedHostCpuSo(const std::string ®ister_name, const uint8_t *so_data, | ||
| 251 | - const size_t so_size) { | ||
| 252 | - if (!IsValidFusedRegisterName(register_name) || (so_data == nullptr) || (so_size > kMaxFusedHostCpuSoSize) || | ||
| 253 | - !IsExpectedFusedElf(so_data, so_size)) { | ||
| 254 | - GELOGE(ge::PARAM_INVALID, "Invalid fused HostCPU shared object for register name %s.", register_name.c_str()); | ||
| 255 | - return ge::PARAM_INVALID; | ||
| 256 | - } | ||
| 257 | - const uint64_t so_hash = HashFusedSo(so_data, so_size); | ||
| 258 | - GELOGD("Load fused HostCPU shared object: register_name[%s], so_size=%zu, hash=%llu.", register_name.c_str(), so_size, | ||
| 259 | - static_cast<unsigned long long>(so_hash)); | ||
| 260 | - // 同一注册名可被多个模型复用;每次成功加载都对应模型卸载阶段的一次 Release。 | ||
| 261 | - const std::lock_guard<std::mutex> lock(fused_so_mutex_); | ||
| 262 | - bool handled = false; | ||
| 263 | - const auto reuse_status = TryReuseFusedHostCpuSo(register_name, so_data, so_size, so_hash, handled); | ||
| 264 | - if (handled) { | ||
| 265 | - return reuse_status; | ||
| 266 | - } | ||
| 267 | - | ||
| 268 | - GELOGW("Fused HostCPU shared object loading is unsupported on the current platform: register_name[%s].", | ||
| 269 | - register_name.c_str()); | ||
| 270 | - return ge::UNSUPPORTED; | ||
| 271 | - | ||
| 272 | - return LoadNewFusedHostCpuSo(register_name, so_data, so_size, so_hash); | ||
| 273 | - | ||
| 274 | -} | ||
| 275 | - | ||
| 276 | - | ||
| 277 | -ge::graphStatus AicpuResourceManager::LoadNewFusedHostCpuSo(const std::string ®ister_name, const uint8_t *so_data, | ||
| 278 | - const size_t so_size, const uint64_t so_hash) { | ||
| 279 | - void *handle = nullptr; | ||
| 280 | - int fd = -1; | ||
| 281 | - FusedHostCpuKernelFunctions kernel_funcs; | ||
| 282 | - if (OpenFusedHostCpuSo(register_name, so_data, so_size, handle, fd, kernel_funcs) != ge::GRAPH_SUCCESS) { | ||
| 283 | - return ge::INTERNAL_ERROR; | ||
| 284 | - } | ||
| 285 | - fused_so_handles_[so_hash] = handle; | ||
| 286 | - // glibc 会按 dlopen 路径复用已加载对象。保持 fd 存活,确保后续融合 SO 不会再次取得相同的 | ||
| 287 | - // /proc/self/fd/<fd> 路径而错误复用当前 handle。 | ||
| 288 | - fused_so_fds_[so_hash] = fd; | ||
| 289 | - fused_so_ref_counts_[so_hash] = 1U; | ||
| 290 | - fused_so_contents_[so_hash] = std::vector<uint8_t>(so_data, so_data + so_size); | ||
| 291 | - fused_register_hashes_[register_name] = so_hash; | ||
| 292 | - fused_register_ref_counts_[register_name] = 1U; | ||
| 293 | - fused_kernel_funcs_[register_name] = kernel_funcs; | ||
| 294 | - GELOGD("Fused HostCPU kernel[%s] registered successfully, cached_so_count=%zu.", register_name.c_str(), | ||
| 295 | - fused_so_handles_.size()); | ||
| 296 | - return ge::GRAPH_SUCCESS; | ||
| 297 | -} | ||
| 298 | - | ||
| 299 | -ge::graphStatus AicpuResourceManager::OpenFusedHostCpuSo(const std::string ®ister_name, const uint8_t *so_data, | ||
| 300 | - const size_t so_size, void *&handle, int &fd, | ||
| 301 | - FusedHostCpuKernelFunctions &kernel_funcs) { | ||
| 302 | - fd = static_cast<int>(syscall(__NR_memfd_create, "fused_host_cpu", 0U)); | ||
| 303 | - if (fd < 0) { | ||
| 304 | - GELOGE(ge::INTERNAL_ERROR, "Create memfd for fused HostCPU shared object failed, errno=%d.", errno); | ||
| 305 | - return ge::INTERNAL_ERROR; | ||
| 306 | - } | ||
| 307 | - if (!WriteAll(fd, so_data, so_size)) { | ||
| 308 | - GELOGE(ge::INTERNAL_ERROR, "Write fused HostCPU shared object failed, errno=%d.", errno); | ||
| 309 | - (void)close(fd); | ||
| 310 | - return ge::INTERNAL_ERROR; | ||
| 311 | - } | ||
| 312 | - const std::string path = "/proc/self/fd/" + std::to_string(fd); | ||
| 313 | - const auto open_flag = static_cast<uint32_t>(MMPA_RTLD_NOW) | static_cast<uint32_t>(RTLD_LOCAL); | ||
| 314 | - GELOGD("Open fused HostCPU shared object from anonymous fd[%d] for register name[%s].", fd, register_name.c_str()); | ||
| 315 | - handle = mmDlopen(path.c_str(), static_cast<int32_t>(open_flag)); | ||
| 316 | - if (handle == nullptr) { | ||
| 317 | - const ge::char_t *error = mmDlerror(); | ||
| 318 | - GELOGE(ge::INTERNAL_ERROR, "Load fused HostCPU shared object failed for %s, error=%s.", register_name.c_str(), | ||
| 319 | - (error == nullptr) ? "" : error); | ||
| 320 | - (void)close(fd); | ||
| 321 | - return ge::INTERNAL_ERROR; | ||
| 322 | - } | ||
| 323 | - if (!ValidateFusedHostCpuRegistration(handle, register_name)) { | ||
| 324 | - GELOGE(ge::INTERNAL_ERROR, "Shared object did not register fused HostCPU CpuKernel %s.", register_name.c_str()); | ||
| 325 | - fused_quarantined_so_handles_.emplace_back(handle); | ||
| 326 | - fused_quarantined_so_fds_.emplace_back(fd); | ||
| 327 | - return ge::INTERNAL_ERROR; | ||
| 328 | - } | ||
| 329 | - kernel_funcs.create_func = reinterpret_cast<FusedHostCpuCreateFunc>(mmDlsym(handle, kCreateFusedHostCpuKernelState)); | ||
| 330 | - kernel_funcs.destroy_func = | ||
| 331 | - reinterpret_cast<FusedHostCpuDestroyFunc>(mmDlsym(handle, kDestroyFusedHostCpuKernelState)); | ||
| 332 | - kernel_funcs.run_func = reinterpret_cast<FusedHostCpuRunFunc>(mmDlsym(handle, kRunFusedHostCpuKernel)); | ||
| 333 | - if ((kernel_funcs.create_func == nullptr) || (kernel_funcs.destroy_func == nullptr) || | ||
| 334 | - (kernel_funcs.run_func == nullptr)) { | ||
| 335 | - GELOGE(ge::INTERNAL_ERROR, "Shared object does not export complete private fused HostCPU entries for %s.", | ||
| 336 | - register_name.c_str()); | ||
| 337 | - fused_quarantined_so_handles_.emplace_back(handle); | ||
| 338 | - fused_quarantined_so_fds_.emplace_back(fd); | ||
| 339 | - return ge::INTERNAL_ERROR; | ||
| 340 | - } | ||
| 341 | - return ge::GRAPH_SUCCESS; | ||
| 342 | -} | ||
| 343 | - | ||
| 344 | - | ||
| 345 | -FusedHostCpuKernelFunctions AicpuResourceManager::GetFusedHostCpuKernelFunctions(const std::string ®ister_name) { | ||
| 346 | - const std::lock_guard<std::mutex> lock(fused_so_mutex_); | ||
| 347 | - const auto iter = fused_kernel_funcs_.find(register_name); | ||
| 348 | - return (iter == fused_kernel_funcs_.end()) ? FusedHostCpuKernelFunctions() : iter->second; | ||
| 349 | -} | ||
| 350 | - | ||
| 351 | -ge::graphStatus AicpuResourceManager::ReleaseFusedHostCpuSo(const std::string ®ister_name) { | ||
| 352 | - const std::lock_guard<std::mutex> lock(fused_so_mutex_); | ||
| 353 | - const auto ref_iter = fused_register_ref_counts_.find(register_name); | ||
| 354 | - const auto hash_iter = fused_register_hashes_.find(register_name); | ||
| 355 | - if ((ref_iter == fused_register_ref_counts_.end()) || (hash_iter == fused_register_hashes_.end()) || | ||
| 356 | - (ref_iter->second == 0U)) { | ||
| 357 | - GELOGE(ge::PARAM_INVALID, "Fused HostCPU kernel %s is not owned by any loaded model.", register_name.c_str()); | ||
| 358 | - return ge::PARAM_INVALID; | ||
| 359 | - } | ||
| 360 | - const uint64_t so_hash = hash_iter->second; | ||
| 361 | - const auto so_ref_iter = fused_so_ref_counts_.find(so_hash); | ||
| 362 | - const auto handle_iter = fused_so_handles_.find(so_hash); | ||
| 363 | - if ((so_ref_iter == fused_so_ref_counts_.end()) || (so_ref_iter->second == 0U) || | ||
| 364 | - (handle_iter == fused_so_handles_.end())) { | ||
| 365 | - GELOGE(ge::INTERNAL_ERROR, "Fused HostCPU kernel %s has incomplete shared object ownership.", | ||
| 366 | - register_name.c_str()); | ||
| 367 | - return ge::INTERNAL_ERROR; | ||
| 368 | - } | ||
| 369 | - --so_ref_iter->second; | ||
| 370 | - if (--ref_iter->second > 0U) { | ||
| 371 | - GELOGD("Keep fused HostCPU kernel[%s], remaining model references=%zu.", register_name.c_str(), ref_iter->second); | ||
| 372 | - return ge::GRAPH_SUCCESS; | ||
| 373 | - } | ||
| 374 | - | ||
| 375 | - // CpuKernelRegister 不提供注销接口。creator 是定义在 JIT so 中的 std::function,引用归零后仍必须保留 | ||
| 376 | - // so 映射和内容缓存,后续模型可直接复用;进程退出时由操作系统统一回收映射。 | ||
| 377 | - GELOGD("Released model reference for fused HostCPU kernel[%s]; keep JIT so in process cache.", register_name.c_str()); | ||
| 378 | - return ge::GRAPH_SUCCESS; | ||
| 379 | -} | ||
| 380 | - | ||
| 381 | std::function<uint32_t(void *)> AicpuResourceManager::GetRunCpuKernel() const { | 121 | std::function<uint32_t(void *)> AicpuResourceManager::GetRunCpuKernel() const { |
| 382 | return run_cpu_kernel_; | 122 | return run_cpu_kernel_; |
| 383 | } | 123 | } |
| @@ -456,14 +196,6 @@ ge::graphStatus EnsureCreateTfSession(KernelContext *context) { | |||
| 456 | } | 196 | } |
| 457 | REGISTER_KERNEL(EnsureCreateTfSession).RunFunc(EnsureCreateTfSession); | 197 | REGISTER_KERNEL(EnsureCreateTfSession).RunFunc(EnsureCreateTfSession); |
| 458 | 198 | ||
| 459 | -ge::graphStatus ReleaseFusedHostCpuSo(KernelContext *context) { | ||
| 460 | - GE_ASSERT_NOTNULL(context); | ||
| 461 | - GE_ASSERT_NOTNULL(context->GetInputValue<const char *>(0U)); | ||
| 462 | - const std::string register_name(context->GetInputValue<const char *>(0U)); | ||
| 463 | - return AicpuResourceManager::GetInstance().ReleaseFusedHostCpuSo(register_name); | ||
| 464 | -} | ||
| 465 | -REGISTER_KERNEL(ReleaseFusedHostCpuSo).RunFunc(ReleaseFusedHostCpuSo); | ||
| 466 | - | ||
| 467 | ge::graphStatus CreateStepId(KernelContext *context) { | 199 | ge::graphStatus CreateStepId(KernelContext *context) { |
| 468 | auto step_id = context->GetOutputPointer<void *>(0U); | 200 | auto step_id = context->GetOutputPointer<void *>(0U); |
| 469 | auto iteration = context->GetOutputPointer<int64_t>(1U); | 201 | auto iteration = context->GetOutputPointer<int64_t>(1U); |
| @@ -11,12 +11,8 @@ | |||
| 11 | 11 | ||
| 12 | 12 | ||
| 13 | 13 | ||
| 14 | - | ||
| 15 | - | ||
| 16 | 14 | ||
| 17 | 15 | ||
| 18 | - | ||
| 19 | - | ||
| 20 | 16 | ||
| 21 | 17 | ||
| 22 | 18 | ||
| @@ -30,15 +26,6 @@ | |||
| 30 | namespace gert { | 26 | namespace gert { |
| 31 | 27 | ||
| 32 | using AicpuHostProcFunc = ge::graphStatus (*)(KernelContext *); | 28 | using AicpuHostProcFunc = ge::graphStatus (*)(KernelContext *); |
| 33 | -using FusedHostCpuCreateFunc = void *(*)(); | ||
| 34 | -using FusedHostCpuDestroyFunc = void (*)(void *); | ||
| 35 | -using FusedHostCpuRunFunc = uint32_t (*)(void *, const void *, uint32_t); | ||
| 36 | - | ||
| 37 | -struct FusedHostCpuKernelFunctions { | ||
| 38 | - FusedHostCpuCreateFunc create_func = nullptr; | ||
| 39 | - FusedHostCpuDestroyFunc destroy_func = nullptr; | ||
| 40 | - FusedHostCpuRunFunc run_func = nullptr; | ||
| 41 | -}; | ||
| 42 | 29 | ||
| 43 | class AicpuResourceManager { | 30 | class AicpuResourceManager { |
| 44 | public: | 31 | public: |
| @@ -46,9 +33,6 @@ class AicpuResourceManager { | |||
| 46 | ~AicpuResourceManager(); | 33 | ~AicpuResourceManager(); |
| 47 | 34 | ||
| 48 | ge::graphStatus LoadConstantFoldingLib(); | 35 | ge::graphStatus LoadConstantFoldingLib(); |
| 49 | - ge::graphStatus LoadFusedHostCpuSo(const std::string ®ister_name, const uint8_t *so_data, size_t so_size); | ||
| 50 | - ge::graphStatus ReleaseFusedHostCpuSo(const std::string ®ister_name); | ||
| 51 | - FusedHostCpuKernelFunctions GetFusedHostCpuKernelFunctions(const std::string ®ister_name); | ||
| 52 | std::function<uint32_t(void *)> GetRunCpuKernel() const; | 36 | std::function<uint32_t(void *)> GetRunCpuKernel() const; |
| 53 | std::function<AicpuHostProcFunc(std::string)> GetAicpuHostFindFunc() const; | 37 | std::function<AicpuHostProcFunc(std::string)> GetAicpuHostFindFunc() const; |
| 54 | 38 | ||
| @@ -68,12 +52,6 @@ class AicpuResourceManager { | |||
| 68 | ge::graphStatus HasLoadedCustAicpuSo(const std::string &so_name, bool &loaded); | 52 | ge::graphStatus HasLoadedCustAicpuSo(const std::string &so_name, bool &loaded); |
| 69 | 53 | ||
| 70 | private: | 54 | private: |
| 71 | - ge::graphStatus TryReuseFusedHostCpuSo(const std::string ®ister_name, const uint8_t *so_data, size_t so_size, | ||
| 72 | - uint64_t so_hash, bool &handled); | ||
| 73 | - ge::graphStatus LoadNewFusedHostCpuSo(const std::string ®ister_name, const uint8_t *so_data, size_t so_size, | ||
| 74 | - uint64_t so_hash); | ||
| 75 | - ge::graphStatus OpenFusedHostCpuSo(const std::string ®ister_name, const uint8_t *so_data, size_t so_size, | ||
| 76 | - void *&handle, int &fd, FusedHostCpuKernelFunctions &kernel_funcs); | ||
| 77 | ge::graphStatus CheckOrCreateHandle(const std::string &op_name, const rtStream_t stream, | 55 | ge::graphStatus CheckOrCreateHandle(const std::string &op_name, const rtStream_t stream, |
| 78 | const GertTensorData *handle_data); | 56 | const GertTensorData *handle_data); |
| 79 | AicpuResourceManager() = default; | 57 | AicpuResourceManager() = default; |
| @@ -83,18 +61,6 @@ class AicpuResourceManager { | |||
| 83 | std::function<uint32_t(void *)> run_cpu_kernel_ = nullptr; | 61 | std::function<uint32_t(void *)> run_cpu_kernel_ = nullptr; |
| 84 | std::function<AicpuHostProcFunc(std::string)> aicpu_host_find_func_ = nullptr; | 62 | std::function<AicpuHostProcFunc(std::string)> aicpu_host_find_func_ = nullptr; |
| 85 | void *so_handle_ = nullptr; | 63 | void *so_handle_ = nullptr; |
| 86 | - // CpuKernelRegister 没有注销接口。引用计数仅表示活跃模型数;引用归零后仍保留 so 映射,避免其中的 | ||
| 87 | - // std::function creator 因 dlclose 变成悬空指针,并支持后续模型复用同一产物。 | ||
| 88 | - std::mutex fused_so_mutex_; | ||
| 89 | - std::map<std::string, uint64_t> fused_register_hashes_; | ||
| 90 | - std::map<std::string, size_t> fused_register_ref_counts_; | ||
| 91 | - std::map<std::string, FusedHostCpuKernelFunctions> fused_kernel_funcs_; | ||
| 92 | - std::map<uint64_t, void *> fused_so_handles_; | ||
| 93 | - std::map<uint64_t, int> fused_so_fds_; | ||
| 94 | - std::map<uint64_t, size_t> fused_so_ref_counts_; | ||
| 95 | - std::map<uint64_t, std::vector<uint8_t>> fused_so_contents_; | ||
| 96 | - std::vector<void *> fused_quarantined_so_handles_; | ||
| 97 | - std::vector<int> fused_quarantined_so_fds_; | ||
| 98 | 64 | ||
| 99 | std::map<uint64_t, std::deque<GertTensorData>> tensors_; | 65 | std::map<uint64_t, std::deque<GertTensorData>> tensors_; |
| 100 | std::map<std::string, uint64_t> handles_; | 66 | std::map<std::string, uint64_t> handles_; |