已合并
ge support fx converter. #78
gaoyong10创建于 19 天前
ge support fx converter. #78
已合并
共 18 个文件变更+1192-405
| @@ -299,6 +299,7 @@ Status SerializeModelMeta(const gert::Om2ModelData &model_data, const std::share | |||
| 299 | (void)model_meta_info.Set("dynamic_type", model_data.model_meta.dynamic_type); | 299 | (void)model_meta_info.Set("dynamic_type", model_data.model_meta.dynamic_type); |
| 300 | (void)model_meta_info.Set("work_size", model_data.model_meta.work_size); | 300 | (void)model_meta_info.Set("work_size", model_data.model_meta.work_size); |
| 301 | (void)model_meta_info.Set("zero_copy_size", model_data.model_meta.zero_copy_size); | 301 | (void)model_meta_info.Set("zero_copy_size", model_data.model_meta.zero_copy_size); |
| 302 | + (void)model_meta_info.Set("reusable_notify_num", model_data.model_meta.reusable_notify_num); | ||
| 302 | (void)model_meta_info.Set("name", model_data.model_meta.model_name); | 303 | (void)model_meta_info.Set("name", model_data.model_meta.model_name); |
| 303 | (void)model_meta_info.Set("root_graph_name", model_data.model_meta.root_graph_name); | 304 | (void)model_meta_info.Set("root_graph_name", model_data.model_meta.root_graph_name); |
| 304 | 305 | ||
| @@ -9,6 +9,8 @@ | |||
| 9 | */ | 9 | */ |
| 10 | 10 | ||
| 11 | 11 | ||
| 12 | + | ||
| 13 | + | ||
| 12 | 14 | ||
| 13 | 15 | ||
| 14 | 16 | ||
| @@ -49,6 +51,22 @@ constexpr size_t kAippDimShapeIdx = 5U; | |||
| 49 | constexpr int32_t kAippDecimalRadix = 10; | 51 | constexpr int32_t kAippDecimalRadix = 10; |
| 50 | constexpr char_t const *kLegacySoSuffix = "_legacy.so"; | 52 | constexpr char_t const *kLegacySoSuffix = "_legacy.so"; |
| 51 | 53 | ||
| 54 | +void DumpDynamicCodegenArtifacts(const Om2CodegenArtifacts &artifacts) { | ||
| 55 | + const char *const dump_dir = std::getenv("OM2_DYNAMIC_DEBUG_DUMP_SOURCE_DIR"); | ||
| 56 | + if ((dump_dir == nullptr) || (*dump_dir == '\0')) { | ||
| 57 | + return; | ||
| 58 | + } | ||
| 59 | + for (const auto &artifact : artifacts) { | ||
| 60 | + std::ofstream output(std::string(dump_dir) + "/" + artifact.file_name, | ||
| 61 | + std::ios::out | std::ios::binary | std::ios::trunc); | ||
| 62 | + if (!output.is_open()) { | ||
| 63 | + GELOGW("[OM2] Failed to dump dynamic codegen artifact %s", artifact.file_name.c_str()); | ||
| 64 | + continue; | ||
| 65 | + } | ||
| 66 | + (void)output.write(artifact.data.data(), static_cast<std::streamsize>(artifact.data.size())); | ||
| 67 | + } | ||
| 68 | +} | ||
| 69 | + | ||
| 52 | bool IsLegacySoName(const std::string &name) { | 70 | bool IsLegacySoName(const std::string &name) { |
| 53 | constexpr size_t suffix_size = sizeof("_legacy.so") - 1U; | 71 | constexpr size_t suffix_size = sizeof("_legacy.so") - 1U; |
| 54 | return name.size() >= suffix_size && name.compare(name.size() - suffix_size, suffix_size, kLegacySoSuffix) == 0; | 72 | return name.size() >= suffix_size && name.compare(name.size() - suffix_size, suffix_size, kLegacySoSuffix) == 0; |
| @@ -1065,11 +1083,16 @@ Status Om2PackageHelper::BuildKernelBinaries(const GeRootModelPtr &ge_root_model | |||
| 1065 | Status Om2PackageHelper::BuildSoBinaries(const std::vector<OpSoBinPtr> &so_bins, | 1083 | Status Om2PackageHelper::BuildSoBinaries(const std::vector<OpSoBinPtr> &so_bins, |
| 1066 | std::vector<gert::Om2SoBinary> &so_binaries) { | 1084 | std::vector<gert::Om2SoBinary> &so_binaries) { |
| 1067 | std::map<std::string, std::vector<uint8_t>> binaries_by_name; | 1085 | std::map<std::string, std::vector<uint8_t>> binaries_by_name; |
| 1086 | + GELOGI("[OM2][SO_TRACE] count=%zu data=%p", so_bins.size(), so_bins.data()); | ||
| 1087 | + size_t so_index = 0U; | ||
| 1068 | for (const auto &so_bin : so_bins) { | 1088 | for (const auto &so_bin : so_bins) { |
| 1089 | + GELOGI("[OM2][SO_TRACE] index=%zu object=%p use_count=%ld", so_index, so_bin.get(), so_bin.use_count()); | ||
| 1069 | GE_ASSERT_NOTNULL(so_bin, "[OM2] OpSoBin is nullptr"); | 1090 | GE_ASSERT_NOTNULL(so_bin, "[OM2] OpSoBin is nullptr"); |
| 1070 | GE_ASSERT_TRUE(!so_bin->GetSoName().empty(), "[OM2] SO name is empty"); | 1091 | GE_ASSERT_TRUE(!so_bin->GetSoName().empty(), "[OM2] SO name is empty"); |
| 1071 | const auto *const data = so_bin->GetBinData(); | 1092 | const auto *const data = so_bin->GetBinData(); |
| 1072 | const size_t data_size = so_bin->GetBinDataSize(); | 1093 | const size_t data_size = so_bin->GetBinDataSize(); |
| 1094 | + GELOGI("[OM2][SO_TRACE] index=%zu name=%s type=%u ptr=%p size=%zu", so_index, | ||
| 1095 | + so_bin->GetSoName().c_str(), static_cast<unsigned>(so_bin->GetSoBinType()), data, data_size); | ||
| 1073 | GE_ASSERT_TRUE((data != nullptr) && (data_size > 0U), "[OM2] SO binary is empty: %s", | 1096 | GE_ASSERT_TRUE((data != nullptr) && (data_size > 0U), "[OM2] SO binary is empty: %s", |
| 1074 | so_bin->GetSoName().c_str()); | 1097 | so_bin->GetSoName().c_str()); |
| 1075 | std::vector<uint8_t> binary(data, data + data_size); | 1098 | std::vector<uint8_t> binary(data, data + data_size); |
| @@ -1080,6 +1103,7 @@ Status Om2PackageHelper::BuildSoBinaries(const std::vector<OpSoBinPtr> &so_bins, | |||
| 1080 | GE_ASSERT_TRUE(iter->second == binary, "[OM2] SO binary has conflicting content: %s", | 1103 | GE_ASSERT_TRUE(iter->second == binary, "[OM2] SO binary has conflicting content: %s", |
| 1081 | so_bin->GetSoName().c_str()); | 1104 | so_bin->GetSoName().c_str()); |
| 1082 | } | 1105 | } |
| 1106 | + ++so_index; | ||
| 1083 | } | 1107 | } |
| 1084 | 1108 | ||
| 1085 | so_binaries.clear(); | 1109 | so_binaries.clear(); |
| @@ -1235,6 +1259,10 @@ Status Om2PackageHelper::BuildModelMeta(const GeModelPtr &ge_model, gert::Om2Mod | |||
| 1235 | int64_t zero_copy_size = 0; | 1259 | int64_t zero_copy_size = 0; |
| 1236 | (void)AttrUtils::GetInt(ge_model, ATTR_MODEL_ZERO_COPY_MEMORY_SIZE, zero_copy_size); | 1260 | (void)AttrUtils::GetInt(ge_model, ATTR_MODEL_ZERO_COPY_MEMORY_SIZE, zero_copy_size); |
| 1237 | model_meta.zero_copy_size = zero_copy_size; | 1261 | model_meta.zero_copy_size = zero_copy_size; |
| 1262 | + int64_t reusable_notify_num = 0; | ||
| 1263 | + (void)AttrUtils::GetInt(ge_model, ATTR_MODEL_NOTIFY_NUM, reusable_notify_num); | ||
| 1264 | + GE_ASSERT_TRUE(reusable_notify_num >= 0, "[OM2] Invalid reusable notify count: %ld", reusable_notify_num); | ||
| 1265 | + model_meta.reusable_notify_num = static_cast<size_t>(reusable_notify_num); | ||
| 1238 | model_meta.dynamic_batch_info = extra_info.dynamic_batch_info; | 1266 | model_meta.dynamic_batch_info = extra_info.dynamic_batch_info; |
| 1239 | model_meta.dynamic_type = extra_info.dynamic_type; | 1267 | model_meta.dynamic_type = extra_info.dynamic_type; |
| 1240 | model_meta.dynamic_output_shape = extra_info.dynamic_output_shape; | 1268 | model_meta.dynamic_output_shape = extra_info.dynamic_output_shape; |
| @@ -1359,6 +1387,7 @@ Status Om2PackageHelper::BuildDynamicOm2ModelData(const GeRootModelPtr &ge_root_ | |||
| 1359 | 1387 | ||
| 1360 | const std::string model_name = root_model_iter->second->GetName(); | 1388 | const std::string model_name = root_model_iter->second->GetName(); |
| 1361 | model_data.program_body.source_artifacts = result.program_body_artifacts; | 1389 | model_data.program_body.source_artifacts = result.program_body_artifacts; |
| 1390 | + DumpDynamicCodegenArtifacts(model_data.program_body.source_artifacts); | ||
| 1362 | GE_ASSERT_SUCCESS(Om2Utils::CompileGeneratedCppToSo(model_data.program_body.source_artifacts, | 1391 | GE_ASSERT_SUCCESS(Om2Utils::CompileGeneratedCppToSo(model_data.program_body.source_artifacts, |
| 1363 | model_name, model_data.program_body.so_artifact, false)); | 1392 | model_name, model_data.program_body.so_artifact, false)); |
| 1364 | model_data.program_body.so_artifact.file_name = "lib" + model_name + "_program_body.so"; | 1393 | model_data.program_body.so_artifact.file_name = "lib" + model_name + "_program_body.so"; |
| @@ -10,6 +10,8 @@ | |||
| 10 | 10 | ||
| 11 | 11 | ||
| 12 | 12 | ||
| 13 | + | ||
| 14 | + | ||
| 13 | 15 | ||
| 14 | 16 | ||
| 15 | 17 | ||
| @@ -142,24 +144,23 @@ ge::graphStatus ChainNormalizer::Normalize(ge::ExecuteGraph &execute_graph, std: | |||
| 142 | GE_ASSERT_GRAPH_SUCCESS(AllocateChainIndices(execute_graph, chains)); | 144 | GE_ASSERT_GRAPH_SUCCESS(AllocateChainIndices(execute_graph, chains)); |
| 143 | GE_ASSERT_GRAPH_SUCCESS(RecordChainSources(execute_graph.GetAllNodes(), chains)); | 145 | GE_ASSERT_GRAPH_SUCCESS(RecordChainSources(execute_graph.GetAllNodes(), chains)); |
| 144 | for (const auto *const node : execute_graph.GetAllNodes()) { | 146 | for (const auto *const node : execute_graph.GetAllNodes()) { |
| 145 | - if (!IsConstType(node->GetTypePtr())) { | 147 | + if ((node == nullptr) || !IsConstType(node->GetTypePtr())) { |
| 146 | continue; | 148 | continue; |
| 147 | } | 149 | } |
| 148 | - std::vector<uint32_t> output_chain_indices; | 150 | + for (size_t i = 0U; i < node->GetDataOutNum(); ++i) { |
| 149 | - GE_ASSERT_GRAPH_SUCCESS(GetOutputChainIndices(*node, output_chain_indices)); | 151 | + uint32_t chain_index = 0U; |
| 150 | - if (output_chain_indices.size() != 1U) { | 152 | + GE_ASSERT_GRAPH_SUCCESS(GetChainIndex(*node, static_cast<uint32_t>(i), EndpointDirection::kOutput, |
| 151 | - continue; | 153 | + chain_index)); |
| 154 | + const auto iter = const_producers_.find(chain_index); | ||
| 155 | + GE_ASSERT_TRUE(iter == const_producers_.cend() || iter->second == node, | ||
| 156 | + "OM2 chain %u has multiple Const producers", chain_index); | ||
| 157 | + const_producers_[chain_index] = node; | ||
| 152 | } | 158 | } |
| 153 | - const auto chain_index = output_chain_indices[0U]; | ||
| 154 | - const auto iter = const_producers_.find(chain_index); | ||
| 155 | - GE_ASSERT_TRUE((iter == const_producers_.cend()) || (iter->second == node), | ||
| 156 | - "OM2 chain %u has multiple Const producers", chain_index); | ||
| 157 | - const_producers_[chain_index] = node; | ||
| 158 | } | 159 | } |
| 159 | return ge::GRAPH_SUCCESS; | 160 | return ge::GRAPH_SUCCESS; |
| 160 | } | 161 | } |
| 161 | 162 | ||
| 162 | -const ge::FastNode *ChainNormalizer::GetConstProducer(const uint32_t chain_index) const { | 163 | +const ge::FastNode *ChainNormalizer::FindConstProducer(const uint32_t chain_index) const { |
| 163 | const auto iter = const_producers_.find(chain_index); | 164 | const auto iter = const_producers_.find(chain_index); |
| 164 | return iter == const_producers_.cend() ? nullptr : iter->second; | 165 | return iter == const_producers_.cend() ? nullptr : iter->second; |
| 165 | } | 166 | } |
| @@ -205,6 +206,13 @@ ge::graphStatus ChainNormalizer::AllocateGraphChains(const std::vector<ge::FastN | |||
| 205 | 206 | ||
| 206 | ge::graphStatus ChainNormalizer::RecordChainSources(const std::vector<ge::FastNode *> &nodes, | 207 | ge::graphStatus ChainNormalizer::RecordChainSources(const std::vector<ge::FastNode *> &nodes, |
| 207 | std::vector<ChainInfo> &chains) const { | 208 | std::vector<ChainInfo> &chains) const { |
| 209 | + // Legacy GE graphs use OutputData itself as the model-output marker. FXRT | ||
| 210 | + // graphs add an explicit Output/NetOutput node and use OutputData as tensor | ||
| 211 | + // shells. Select the convention per graph to preserve both routes. | ||
| 212 | + const bool has_explicit_model_output = std::any_of( | ||
| 213 | + nodes.cbegin(), nodes.cend(), [](const ge::FastNode *node) { | ||
| 214 | + return (node != nullptr) && (IsOutputType(node->GetTypePtr()) || IsTypeNetOutput(node->GetTypePtr())); | ||
| 215 | + }); | ||
| 208 | for (const auto *const node : nodes) { | 216 | for (const auto *const node : nodes) { |
| 209 | GE_ASSERT_NOTNULL(node); | 217 | GE_ASSERT_NOTNULL(node); |
| 210 | const auto *const op_desc = node->GetOpDescBarePtr(); | 218 | const auto *const op_desc = node->GetOpDescBarePtr(); |
| @@ -232,16 +240,30 @@ ge::graphStatus ChainNormalizer::RecordChainSources(const std::vector<ge::FastNo | |||
| 232 | binding_phase = GetConstDataBindingPhase(source_index); | 240 | binding_phase = GetConstDataBindingPhase(source_index); |
| 233 | binding_kind = GetConstDataBindingKind(source_index); | 241 | binding_kind = GetConstDataBindingKind(source_index); |
| 234 | } else if (IsTypeOutputData(node->GetTypePtr())) { | 242 | } else if (IsTypeOutputData(node->GetTypePtr())) { |
| 235 | - source_kind = ChainSourceKind::kModelOutput; | 243 | + // OutputData is also used as a shell for intermediate tensors by FXRT. |
| 244 | + // The model-output ownership and port index are recorded from NetOutput | ||
| 245 | + // below, so every OutputData output starts as an ordinary kernel output. | ||
| 246 | + source_kind = has_explicit_model_output ? ChainSourceKind::kKernelOutput : ChainSourceKind::kModelOutput; | ||
| 247 | + } else if (IsOutputType(node->GetTypePtr()) || IsTypeNetOutput(node->GetTypePtr())) { | ||
| 248 | + // A NetOutput input position is the authoritative model-output port. | ||
| 249 | + // Do not infer it from OutputData's local output index: intermediate | ||
| 250 | + // OutputData shells commonly have one output and would all become index 0. | ||
| 251 | + for (size_t i = 0U; i < node->GetDataInNum(); ++i) { | ||
| 252 | + uint32_t chain_index = 0U; | ||
| 253 | + GE_ASSERT_GRAPH_SUCCESS( | ||
| 254 | + GetChainIndex(*node, static_cast<uint32_t>(i), EndpointDirection::kInput, chain_index)); | ||
| 255 | + GE_ASSERT_GRAPH_SUCCESS(UpdateChainSource(chains[chain_index], ChainSourceKind::kModelOutput, | ||
| 256 | + static_cast<int64_t>(i), ChainBindingPhase::kRun, | ||
| 257 | + ChainBindingKind::kNone)); | ||
| 258 | + } | ||
| 259 | + continue; | ||
| 236 | } | 260 | } |
| 237 | for (size_t i = 0U; i < node->GetDataOutNum(); ++i) { | 261 | for (size_t i = 0U; i < node->GetDataOutNum(); ++i) { |
| 238 | uint32_t chain_index = 0U; | 262 | uint32_t chain_index = 0U; |
| 239 | GE_ASSERT_GRAPH_SUCCESS(GetChainIndex(*node, static_cast<uint32_t>(i), EndpointDirection::kOutput, | 263 | GE_ASSERT_GRAPH_SUCCESS(GetChainIndex(*node, static_cast<uint32_t>(i), EndpointDirection::kOutput, |
| 240 | chain_index)); | 264 | chain_index)); |
| 241 | auto &chain = chains[chain_index]; | 265 | auto &chain = chains[chain_index]; |
| 242 | - const auto output_source_index = IsTypeOutputData(node->GetTypePtr()) ? static_cast<int64_t>(i) : source_index; | 266 | + GE_ASSERT_GRAPH_SUCCESS(UpdateChainSource(chain, source_kind, source_index, binding_phase, binding_kind)); |
| 243 | - GE_ASSERT_GRAPH_SUCCESS( | ||
| 244 | - UpdateChainSource(chain, source_kind, output_source_index, binding_phase, binding_kind)); | ||
| 245 | } | 267 | } |
| 246 | } | 268 | } |
| 247 | return ge::GRAPH_SUCCESS; | 269 | return ge::GRAPH_SUCCESS; |
| @@ -25,7 +25,10 @@ class ChainNormalizer { | |||
| 25 | ge::graphStatus Normalize(ge::ExecuteGraph &execute_graph, std::vector<ChainInfo> &chains); | 25 | ge::graphStatus Normalize(ge::ExecuteGraph &execute_graph, std::vector<ChainInfo> &chains); |
| 26 | ge::graphStatus GetInputChainIndices(const ge::FastNode &node, std::vector<uint32_t> &indices) const; | 26 | ge::graphStatus GetInputChainIndices(const ge::FastNode &node, std::vector<uint32_t> &indices) const; |
| 27 | ge::graphStatus GetOutputChainIndices(const ge::FastNode &node, std::vector<uint32_t> &indices) const; | 27 | ge::graphStatus GetOutputChainIndices(const ge::FastNode &node, std::vector<uint32_t> &indices) const; |
| 28 | - const ge::FastNode *GetConstProducer(uint32_t chain_index) const; | 28 | + // CEM may replace a Const edge with an InnerData edge when a lifecycle constant is |
| 29 | + // exported from Init into Main. Preserve the original Const producer so collectors | ||
| 30 | + // can materialize the process-local value without depending on graph plumbing. | ||
| 31 | + const ge::FastNode *FindConstProducer(uint32_t chain_index) const; | ||
| 29 | 32 | ||
| 30 | private: | 33 | private: |
| 31 | enum class EndpointDirection : uint64_t { kInput = 0U, kOutput = 1U }; | 34 | enum class EndpointDirection : uint64_t { kInput = 0U, kOutput = 1U }; |
| @@ -197,39 +197,21 @@ struct ExecutionPlanCollector::CanonicalIfAnalysis { | |||
| 197 | }; | 197 | }; |
| 198 | 198 | ||
| 199 | ge::graphStatus ExecutionPlanCollector::Collect(ge::ExecuteGraph &execute_graph, | 199 | ge::graphStatus ExecutionPlanCollector::Collect(ge::ExecuteGraph &execute_graph, |
| 200 | - const ChainNormalizer &chain_normalizer, | 200 | + const ChainNormalizer &chain_normalizer, |
| 201 | - const ProgramPlanType plan_type, ProgramBlock &program_block) const { | 201 | + const ProgramPlanType plan_type, ProgramBlock &program_block) const { |
| 202 | program_block = {}; | 202 | program_block = {}; |
| 203 | program_block.plan_type = plan_type; | 203 | program_block.plan_type = plan_type; |
| 204 | program_block.root_region_index = 0U; | 204 | program_block.root_region_index = 0U; |
| 205 | program_block.regions.push_back({0U, execute_graph.GetName(), {}}); | 205 | program_block.regions.push_back({0U, execute_graph.GetName(), {}}); |
| 206 | - ge::graphStatus ret = ge::GRAPH_SUCCESS; | ||
| 207 | switch (plan_type) { | 206 | switch (plan_type) { |
| 208 | case ProgramPlanType::kSequential: | 207 | case ProgramPlanType::kSequential: |
| 209 | - ret = CollectSequential(execute_graph, chain_normalizer, program_block); | 208 | + return CollectSequential(execute_graph, chain_normalizer, program_block); |
| 210 | - break; | ||
| 211 | case ProgramPlanType::kStructuredTopological: | 209 | case ProgramPlanType::kStructuredTopological: |
| 212 | case ProgramPlanType::kStructuredTopologicalPriority: | 210 | case ProgramPlanType::kStructuredTopologicalPriority: |
| 213 | - ret = CollectRegion(execute_graph, chain_normalizer, 0U, program_block); | 211 | + return CollectRegion(execute_graph, chain_normalizer, 0U, program_block); |
| 214 | - break; | ||
| 215 | - default: | ||
| 216 | - GELOGE(ge::GRAPH_FAILED, "Unknown OM2 plan type for graph %s", execute_graph.GetName().c_str()); | ||
| 217 | - return ge::GRAPH_FAILED; | ||
| 218 | } | 212 | } |
| 219 | - if (ret != ge::GRAPH_SUCCESS) { | 213 | + GELOGE(ge::GRAPH_FAILED, "Unknown OM2 plan type for graph %s", execute_graph.GetName().c_str()); |
| 220 | - return ret; | 214 | + return ge::GRAPH_FAILED; |
| 221 | - } | ||
| 222 | - std::map<std::string, size_t> kernel_counts; | ||
| 223 | - for (const auto &kernel : program_block.kernels) { | ||
| 224 | - ++kernel_counts[kernel.kernel_type]; | ||
| 225 | - } | ||
| 226 | - GELOGI("OM2 kernel collection finished: graph=%s, total=%zu", execute_graph.GetName().c_str(), | ||
| 227 | - program_block.kernels.size()); | ||
| 228 | - for (const auto &kernel_count : kernel_counts) { | ||
| 229 | - GELOGI("OM2 kernel collection summary: graph=%s, type=%s, count=%zu", execute_graph.GetName().c_str(), | ||
| 230 | - kernel_count.first.c_str(), kernel_count.second); | ||
| 231 | - } | ||
| 232 | - return ge::GRAPH_SUCCESS; | ||
| 233 | } | 215 | } |
| 234 | 216 | ||
| 235 | ge::graphStatus ExecutionPlanCollector::CollectSequential(ge::ExecuteGraph &execute_graph, | 217 | ge::graphStatus ExecutionPlanCollector::CollectSequential(ge::ExecuteGraph &execute_graph, |
| @@ -275,47 +257,29 @@ ge::graphStatus ExecutionPlanCollector::CollectKernel(const ge::FastNode &node, | |||
| 275 | chain.Set(nullptr, nullptr); | 257 | chain.Set(nullptr, nullptr); |
| 276 | } | 258 | } |
| 277 | }); | 259 | }); |
| 278 | - const auto get_const_producer = [&node, &chain_normalizer, | 260 | + const auto materialize_input = [&node, &input_chains, &chain_normalizer, &input_chain_indices]( |
| 279 | - &input_chain_indices](const uint32_t input_index) -> const ge::FastNode * { | 261 | + const uint32_t input_index) -> ge::graphStatus { |
| 262 | + GE_ASSERT_TRUE(input_index < node.GetDataInNum()); | ||
| 280 | const ge::FastEdge *producer_edge = nullptr; | 263 | const ge::FastEdge *producer_edge = nullptr; |
| 281 | for (const auto *const edge : node.GetAllInDataEdgesRef()) { | 264 | for (const auto *const edge : node.GetAllInDataEdgesRef()) { |
| 282 | if ((edge != nullptr) && (edge->dst_input == static_cast<int32_t>(input_index))) { | 265 | if ((edge != nullptr) && (edge->dst_input == static_cast<int32_t>(input_index))) { |
| 283 | - if (producer_edge != nullptr) { | 266 | + GE_ASSERT_TRUE(producer_edge == nullptr, "OM2 kernel %s input %u has multiple producers", |
| 284 | - GELOGE(ge::GRAPH_PARAM_INVALID, "OM2 kernel %s input %u has multiple producers", node.GetNamePtr(), | 267 | + node.GetNamePtr(), input_index); |
| 285 | - input_index); | ||
| 286 | - return nullptr; | ||
| 287 | - } | ||
| 288 | producer_edge = edge; | 268 | producer_edge = edge; |
| 289 | } | 269 | } |
| 290 | } | 270 | } |
| 291 | - if (producer_edge == nullptr) { | 271 | + GE_ASSERT_NOTNULL(producer_edge, "OM2 kernel %s input %u has no producer", node.GetNamePtr(), input_index); |
| 292 | - GELOGE(ge::GRAPH_PARAM_INVALID, "OM2 kernel %s input %u has no producer", node.GetNamePtr(), input_index); | 272 | + const ge::FastNode *producer = producer_edge->src; |
| 293 | - return nullptr; | 273 | + int32_t producer_output = producer_edge->src_output; |
| 274 | + if (!IsConstType(producer->GetTypePtr())) { | ||
| 275 | + producer = chain_normalizer.FindConstProducer(input_chain_indices[input_index]); | ||
| 276 | + producer_output = 0; | ||
| 294 | } | 277 | } |
| 295 | - const auto *const direct_producer = producer_edge->src; | 278 | + GE_ASSERT_NOTNULL(producer, "OM2 kernel %s input %u has no Const producer", node.GetNamePtr(), input_index); |
| 296 | - if (IsConstType(direct_producer->GetTypePtr())) { | 279 | + GE_ASSERT_TRUE(IsConstType(producer->GetTypePtr()), |
| 297 | - return direct_producer; | 280 | + "OM2 kernel %s input %u must be driven by Const", node.GetNamePtr(), input_index); |
| 298 | - } | 281 | + GE_ASSERT_TRUE((producer_output == 0) && (producer->GetDataOutNum() == 1U), |
| 299 | - const auto *const const_producer = chain_normalizer.GetConstProducer(input_chain_indices[input_index]); | 282 | + "OM2 Const producer %s has invalid output index %d", producer->GetNamePtr(), producer_output); |
| 300 | - if (const_producer != nullptr) { | ||
| 301 | - GELOGI("OM2 kernel %s input %u resolves Const producer %s through producer=%s type=%s", node.GetNamePtr(), | ||
| 302 | - input_index, const_producer->GetNamePtr(), direct_producer->GetNamePtr(), direct_producer->GetTypePtr()); | ||
| 303 | - return const_producer; | ||
| 304 | - } | ||
| 305 | - GELOGE(ge::GRAPH_PARAM_INVALID, | ||
| 306 | - "OM2 kernel %s input %u must be driven by Const, producer=%s type=%s", node.GetNamePtr(), input_index, | ||
| 307 | - direct_producer->GetNamePtr(), direct_producer->GetTypePtr()); | ||
| 308 | - return nullptr; | ||
| 309 | - }; | ||
| 310 | - const auto materialize_input = [&node, &input_chains, &get_const_producer](const uint32_t input_index) | ||
| 311 | - -> ge::graphStatus { | ||
| 312 | - GE_ASSERT_TRUE(input_index < node.GetDataInNum()); | ||
| 313 | - const auto *const producer = get_const_producer(input_index); | ||
| 314 | - GE_ASSERT_NOTNULL(producer); | ||
| 315 | - const auto *const producer_edge = node.GetInDataEdgeByIndex(static_cast<int32_t>(input_index)); | ||
| 316 | - GE_ASSERT_NOTNULL(producer_edge); | ||
| 317 | - GE_ASSERT_TRUE((producer_edge->src_output == 0) && (producer->GetDataOutNum() == 1U), | ||
| 318 | - "OM2 Const producer %s has invalid output index %d", producer->GetNamePtr(), producer_edge->src_output); | ||
| 319 | return MaterializeConstOutput(*producer, input_chains[input_index]); | 283 | return MaterializeConstOutput(*producer, input_chains[input_index]); |
| 320 | }; | 284 | }; |
| 321 | const auto ordinary_restore_input_indices = builder->GetRestoreConstInputIndices(); | 285 | const auto ordinary_restore_input_indices = builder->GetRestoreConstInputIndices(); |
| @@ -378,9 +342,9 @@ ge::graphStatus ExecutionPlanCollector::CollectKernel(const ge::FastNode &node, | |||
| 378 | } | 342 | } |
| 379 | } | 343 | } |
| 380 | GE_ASSERT_NOTNULL(producer_edge); | 344 | GE_ASSERT_NOTNULL(producer_edge); |
| 381 | - const auto *const const_producer = get_const_producer(resolved_index); | 345 | + const auto *const const_producer = chain_normalizer.FindConstProducer(input_chain_indices[resolved_index]); |
| 382 | - GE_ASSERT_NOTNULL(const_producer); | 346 | + descriptor.producer_name = const_producer == nullptr ? producer_edge->src->GetNamePtr() |
| 383 | - descriptor.producer_name = const_producer->GetNamePtr(); | 347 | + : const_producer->GetNamePtr(); |
| 384 | GE_ASSERT_TRUE(!descriptor.initializer.empty(), "OM2 kernel %s custom const input %u has no initializer", | 348 | GE_ASSERT_TRUE(!descriptor.initializer.empty(), "OM2 kernel %s custom const input %u has no initializer", |
| 385 | node.GetNamePtr(), resolved_index); | 349 | node.GetNamePtr(), resolved_index); |
| 386 | GE_ASSERT_TRUE(!descriptor.payload.empty(), "OM2 kernel %s custom const input %u has no payload", | 350 | GE_ASSERT_TRUE(!descriptor.payload.empty(), "OM2 kernel %s custom const input %u has no payload", |
| @@ -407,8 +371,6 @@ ge::graphStatus ExecutionPlanCollector::CollectKernel(const ge::FastNode &node, | |||
| 407 | } | 371 | } |
| 408 | kernel_index = static_cast<uint32_t>(program_block.kernels.size()); | 372 | kernel_index = static_cast<uint32_t>(program_block.kernels.size()); |
| 409 | program_block.kernels.emplace_back(std::move(kernel_info)); | 373 | program_block.kernels.emplace_back(std::move(kernel_info)); |
| 410 | - GELOGI("OM2 collected kernel[%u]: name=%s, type=%s, total=%zu", kernel_index, node.GetNamePtr(), | ||
| 411 | - node.GetTypePtr(), program_block.kernels.size()); | ||
| 412 | return ge::GRAPH_SUCCESS; | 374 | return ge::GRAPH_SUCCESS; |
| 413 | } | 375 | } |
| 414 | 376 | ||
| @@ -25,6 +25,10 @@ class BuildTensorKernelCodeBuilder : public KernelCodeBuilder { | |||
| 25 | {"tensor_attr", Om2ValueType::kGertBuildTensorAttrPtr}}, info)); | 25 | {"tensor_attr", Om2ValueType::kGertBuildTensorAttrPtr}}, info)); |
| 26 | return SetOutputPortNames(context, {"tensor"}, info); | 26 | return SetOutputPortNames(context, {"tensor"}, info); |
| 27 | } | 27 | } |
| 28 | + | ||
| 29 | + std::vector<uint32_t> GetRestoreConstInputIndices() const override { | ||
| 30 | + return {2U}; | ||
| 31 | + } | ||
| 28 | }; | 32 | }; |
| 29 | REGISTER_KERNEL_CODE_BUILDER("BuildTensor", BuildTensorKernelCodeBuilder); | 33 | REGISTER_KERNEL_CODE_BUILDER("BuildTensor", BuildTensorKernelCodeBuilder); |
| 30 | 34 | ||
| @@ -48,10 +48,10 @@ bool IsSupportedBinding(const ChainBindingKind binding_kind) { | |||
| 48 | case ChainBindingKind::kSpaceRegistry: | 48 | case ChainBindingKind::kSpaceRegistry: |
| 49 | case ChainBindingKind::kBinary: | 49 | case ChainBindingKind::kBinary: |
| 50 | case ChainBindingKind::kOuterWeightMem: | 50 | case ChainBindingKind::kOuterWeightMem: |
| 51 | + case ChainBindingKind::kNotifies: | ||
| 51 | return true; | 52 | return true; |
| 52 | case ChainBindingKind::kNone: | 53 | case ChainBindingKind::kNone: |
| 53 | case ChainBindingKind::kRuntimeEvents: | 54 | case ChainBindingKind::kRuntimeEvents: |
| 54 | - case ChainBindingKind::kNotifies: | ||
| 55 | case ChainBindingKind::kRtSession: | 55 | case ChainBindingKind::kRtSession: |
| 56 | return false; | 56 | return false; |
| 57 | } | 57 | } |
| @@ -19,13 +19,10 @@ | |||
| 19 | 19 | ||
| 20 | namespace gert { | 20 | namespace gert { |
| 21 | namespace om2 { | 21 | namespace om2 { |
| 22 | -Om2ModelPtr Om2Generator::Lower(const ge::GeRootModelPtr &root_model) const { | 22 | +namespace { |
| 23 | - return Om2CompileLowering().Lower(root_model); | 23 | +Om2GenerationResult GenerateFromModel(const Om2ModelPtr &model, const std::string &model_name) { |
| 24 | -} | 24 | + if (model == nullptr || model->GetExecuteGraph() == nullptr) { |
| 25 | - | 25 | + GELOGE(ge::GRAPH_PARAM_INVALID, "Failed to generate OM2 from an empty model"); |
| 26 | -Om2GenerationResult Om2Generator::Generate(const ge::GeRootModelPtr &root_model) const { | ||
| 27 | - auto model = Lower(root_model); | ||
| 28 | - if (model == nullptr) { | ||
| 29 | return {}; | 26 | return {}; |
| 30 | } | 27 | } |
| 31 | ProgramInfo program_info; | 28 | ProgramInfo program_info; |
| @@ -34,13 +31,7 @@ Om2GenerationResult Om2Generator::Generate(const ge::GeRootModelPtr &root_model) | |||
| 34 | } | 31 | } |
| 35 | ProgramBodyCodegenResult program_body_result; | 32 | ProgramBodyCodegenResult program_body_result; |
| 36 | ProgramBodyCodegenOption program_body_option; | 33 | ProgramBodyCodegenOption program_body_option; |
| 37 | - program_body_option.model_name = root_model->GetModelName(); | 34 | + program_body_option.model_name = model_name.empty() ? "om2_dynamic" : model_name; |
| 38 | - if (program_body_option.model_name.empty() && (root_model->GetRootGraph() != nullptr)) { | ||
| 39 | - program_body_option.model_name = root_model->GetRootGraph()->GetName(); | ||
| 40 | - } | ||
| 41 | - if (program_body_option.model_name.empty()) { | ||
| 42 | - program_body_option.model_name = "om2_dynamic"; | ||
| 43 | - } | ||
| 44 | program_body_option.interface_file_name = program_body_option.model_name + "_interface.h"; | 35 | program_body_option.interface_file_name = program_body_option.model_name + "_interface.h"; |
| 45 | program_body_option.source_file_name = program_body_option.model_name + "_program_body.cpp"; | 36 | program_body_option.source_file_name = program_body_option.model_name + "_program_body.cpp"; |
| 46 | program_body_option.makefile_file_name = "Makefile"; | 37 | program_body_option.makefile_file_name = "Makefile"; |
| @@ -51,5 +42,31 @@ Om2GenerationResult Om2Generator::Generate(const ge::GeRootModelPtr &root_model) | |||
| 51 | ge::DumpGraph(model->GetExecuteGraph().get(), "ExecuteGraphAfterProgramInfoCollect"); | 42 | ge::DumpGraph(model->GetExecuteGraph().get(), "ExecuteGraphAfterProgramInfoCollect"); |
| 52 | return {std::move(program_body_result.artifacts)}; | 43 | return {std::move(program_body_result.artifacts)}; |
| 53 | } | 44 | } |
| 45 | +} // namespace | ||
| 46 | + | ||
| 47 | +Om2ModelPtr Om2Generator::Lower(const ge::GeRootModelPtr &root_model) const { | ||
| 48 | + return Om2CompileLowering().Lower(root_model); | ||
| 49 | +} | ||
| 50 | + | ||
| 51 | +Om2GenerationResult Om2Generator::Generate(const ge::GeRootModelPtr &root_model) const { | ||
| 52 | + auto model = Lower(root_model); | ||
| 53 | + std::string model_name; | ||
| 54 | + if (root_model != nullptr) { | ||
| 55 | + model_name = root_model->GetModelName(); | ||
| 56 | + if (model_name.empty() && (root_model->GetRootGraph() != nullptr)) { | ||
| 57 | + model_name = root_model->GetRootGraph()->GetName(); | ||
| 58 | + } | ||
| 59 | + } | ||
| 60 | + return GenerateFromModel(model, model_name); | ||
| 61 | +} | ||
| 62 | + | ||
| 63 | +Om2GenerationResult Om2Generator::GenerateFromExecuteGraph(const ge::ExecuteGraphPtr &execute_graph, | ||
| 64 | + const std::string &model_name) const { | ||
| 65 | + if (execute_graph == nullptr) { | ||
| 66 | + GELOGE(ge::GRAPH_PARAM_INVALID, "Failed to generate OM2 from a null ExecuteGraph"); | ||
| 67 | + return {}; | ||
| 68 | + } | ||
| 69 | + return GenerateFromModel(std::make_shared<Om2Model>(execute_graph), model_name); | ||
| 70 | +} | ||
| 54 | } // namespace om2 | 71 | } // namespace om2 |
| 55 | } // namespace gert | 72 | } // namespace gert |
| @@ -14,6 +14,7 @@ | |||
| 14 | 14 | ||
| 15 | 15 | ||
| 16 | 16 | ||
| 17 | + | ||
| 17 | 18 | ||
| 18 | namespace gert { | 19 | namespace gert { |
| 19 | namespace om2 { | 20 | namespace om2 { |
| @@ -25,6 +26,8 @@ class Om2Generator { | |||
| 25 | public: | 26 | public: |
| 26 | Om2ModelPtr Lower(const ge::GeRootModelPtr &root_model) const; | 27 | Om2ModelPtr Lower(const ge::GeRootModelPtr &root_model) const; |
| 27 | Om2GenerationResult Generate(const ge::GeRootModelPtr &root_model) const; | 28 | Om2GenerationResult Generate(const ge::GeRootModelPtr &root_model) const; |
| 29 | + Om2GenerationResult GenerateFromExecuteGraph(const ge::ExecuteGraphPtr &execute_graph, | ||
| 30 | + const std::string &model_name) const; | ||
| 28 | }; | 31 | }; |
| 29 | } // namespace om2 | 32 | } // namespace om2 |
| 30 | } // namespace gert | 33 | } // namespace gert |
| @@ -58,6 +58,7 @@ struct Om2ModelMeta { | |||
| 58 | std::string root_graph_name; | 58 | std::string root_graph_name; |
| 59 | size_t work_size = 0U; | 59 | size_t work_size = 0U; |
| 60 | int64_t zero_copy_size = 0; | 60 | int64_t zero_copy_size = 0; |
| 61 | + size_t reusable_notify_num = 0U; | ||
| 61 | std::vector<ge::Om2TensorDesc> input_desc; | 62 | std::vector<ge::Om2TensorDesc> input_desc; |
| 62 | std::vector<ge::Om2TensorDesc> output_desc; | 63 | std::vector<ge::Om2TensorDesc> output_desc; |
| 63 | std::vector<ge::Om2TensorDesc> input_desc_v2; | 64 | std::vector<ge::Om2TensorDesc> input_desc_v2; |
| @@ -40,6 +40,7 @@ enum class AttrDataType { | |||
| 40 | BOOL, | 40 | BOOL, |
| 41 | STRING, | 41 | STRING, |
| 42 | INT32, | 42 | INT32, |
| 43 | + INT64, | ||
| 43 | UINT32, | 44 | UINT32, |
| 44 | FLOAT32, | 45 | FLOAT32, |
| 45 | FLOAT16, | 46 | FLOAT16, |
| @@ -58,6 +59,7 @@ static const std::map<std::string, AttrDataType> kAttrDataTypeMap{{"bool", AttrD | |||
| 58 | {"string", AttrDataType::STRING}, | 59 | {"string", AttrDataType::STRING}, |
| 59 | {"int", AttrDataType::INT32}, | 60 | {"int", AttrDataType::INT32}, |
| 60 | {"int32", AttrDataType::INT32}, | 61 | {"int32", AttrDataType::INT32}, |
| 62 | + {"int64", AttrDataType::INT64}, | ||
| 61 | {"uint", AttrDataType::UINT32}, | 63 | {"uint", AttrDataType::UINT32}, |
| 62 | {"uint32", AttrDataType::UINT32}, | 64 | {"uint32", AttrDataType::UINT32}, |
| 63 | {"float", AttrDataType::FLOAT32}, | 65 | {"float", AttrDataType::FLOAT32}, |
| @@ -77,7 +79,7 @@ static const std::vector<AttrDataType> kValidSrcDTypeList{AttrDataType::BOOL, | |||
| 77 | AttrDataType::LIST_INT32, AttrDataType::LIST_FLOAT32}; | 79 | AttrDataType::LIST_INT32, AttrDataType::LIST_FLOAT32}; |
| 78 | 80 | ||
| 79 | static const std::vector<AttrDataType> kValidDstDTypeList{ | 81 | static const std::vector<AttrDataType> kValidDstDTypeList{ |
| 80 | - AttrDataType::UINT32, AttrDataType::INT32, AttrDataType::FLOAT32, | 82 | + AttrDataType::UINT32, AttrDataType::INT32, AttrDataType::INT64, AttrDataType::FLOAT32, |
| 81 | AttrDataType::FLOAT16, AttrDataType::BFLOAT16, AttrDataType::LIST_INT32, | 83 | AttrDataType::FLOAT16, AttrDataType::BFLOAT16, AttrDataType::LIST_INT32, |
| 82 | AttrDataType::LIST_UINT32, AttrDataType::LIST_FLOAT16, AttrDataType::LIST_FLOAT32}; | 84 | AttrDataType::LIST_UINT32, AttrDataType::LIST_FLOAT16, AttrDataType::LIST_FLOAT32}; |
| 83 | 85 | ||
| @@ -266,6 +268,24 @@ class AttrDataManager { | |||
| 266 | return attr_data_ptr; | 268 | return attr_data_ptr; |
| 267 | } | 269 | } |
| 268 | 270 | ||
| 271 | + AttrDataPtr GetFloatAttrValueAndToInt64(const ge::Operator &op, const char *attr_name) const { | ||
| 272 | + float attr_value = 0.0F; | ||
| 273 | + if (op.GetAttr(attr_name, attr_value) != ge::GRAPH_SUCCESS) { | ||
| 274 | + GELOGW("Failed to retrieve attribute [%s] from op.", attr_name); | ||
| 275 | + return nullptr; | ||
| 276 | + } | ||
| 277 | + | ||
| 278 | + // Dynamic TBE metadata uses int64 as the transport type for scalar attrs | ||
| 279 | + // on int64 kernels. The attr itself remains a schema-level float; the | ||
| 280 | + // tiling ABI consumes the numeric converted value. | ||
| 281 | + std::vector<int64_t> attr_vec; | ||
| 282 | + attr_vec.push_back(static_cast<int64_t>(attr_value)); | ||
| 283 | + | ||
| 284 | + AttrDataPtr attr_data_ptr = nullptr; | ||
| 285 | + OP_TILING_MAKE_SHARED(attr_data_ptr = std::make_shared<AttrDataImpl<int64_t>>(attr_vec), return nullptr); | ||
| 286 | + return attr_data_ptr; | ||
| 287 | + } | ||
| 288 | + | ||
| 269 | AttrDataPtr GetListFloatAttrValueAndToListFp16(const ge::Operator &op, const char *attr_name) const { | 289 | AttrDataPtr GetListFloatAttrValueAndToListFp16(const ge::Operator &op, const char *attr_name) const { |
| 270 | std::vector<float> attr_value; | 290 | std::vector<float> attr_value; |
| 271 | if (op.GetAttr(attr_name, attr_value) != ge::GRAPH_SUCCESS) { | 291 | if (op.GetAttr(attr_name, attr_value) != ge::GRAPH_SUCCESS) { |
| @@ -328,6 +348,7 @@ const std::map<uint32_t, GetOpAttrValueFunc> AttrDataManager::attr_func_ = { | |||
| 328 | {GenerateAttrFuncKey(AttrDataType::LIST_FLOAT32, AttrDataType::LIST_FLOAT16), | 348 | {GenerateAttrFuncKey(AttrDataType::LIST_FLOAT32, AttrDataType::LIST_FLOAT16), |
| 329 | &AttrDataManager::GetListFloatAttrValueAndToListFp16}, | 349 | &AttrDataManager::GetListFloatAttrValueAndToListFp16}, |
| 330 | {GenerateAttrFuncKey(AttrDataType::FLOAT32, AttrDataType::INT32), &AttrDataManager::GetFloatAttrValueAndToInt}, | 350 | {GenerateAttrFuncKey(AttrDataType::FLOAT32, AttrDataType::INT32), &AttrDataManager::GetFloatAttrValueAndToInt}, |
| 351 | + {GenerateAttrFuncKey(AttrDataType::FLOAT32, AttrDataType::INT64), &AttrDataManager::GetFloatAttrValueAndToInt64}, | ||
| 331 | {GenerateAttrFuncKey(AttrDataType::LIST_FLOAT32, AttrDataType::LIST_INT32), | 352 | {GenerateAttrFuncKey(AttrDataType::LIST_FLOAT32, AttrDataType::LIST_INT32), |
| 332 | &AttrDataManager::GetListFloatAttrValueAndToListInt}}; | 353 | &AttrDataManager::GetListFloatAttrValueAndToListInt}}; |
| 333 | 354 | ||
| @@ -89,7 +89,8 @@ typedef enum { | |||
| 89 | OM2_RUN_ATTR_INPUTS = 1, | 89 | OM2_RUN_ATTR_INPUTS = 1, |
| 90 | OM2_RUN_ATTR_INPUT_COUNT = 2, | 90 | OM2_RUN_ATTR_INPUT_COUNT = 2, |
| 91 | OM2_RUN_ATTR_OUTPUTS = 3, | 91 | OM2_RUN_ATTR_OUTPUTS = 3, |
| 92 | - OM2_RUN_ATTR_OUTPUT_COUNT = 4 | 92 | + OM2_RUN_ATTR_OUTPUT_COUNT = 4, |
| 93 | + OM2_RUN_ATTR_NOTIFIES = 5 | ||
| 93 | } Om2ProgramBodyRunAttrId; | 94 | } Om2ProgramBodyRunAttrId; |
| 94 | 95 | ||
| 95 | typedef union { | 96 | typedef union { |
| @@ -98,6 +99,7 @@ typedef union { | |||
| 98 | size_t input_count; | 99 | size_t input_count; |
| 99 | void *const *outputs; | 100 | void *const *outputs; |
| 100 | size_t output_count; | 101 | size_t output_count; |
| 102 | + void *notifies; | ||
| 101 | uint64_t reserved; | 103 | uint64_t reserved; |
| 102 | } Om2ProgramBodyRunAttrValue; | 104 | } Om2ProgramBodyRunAttrValue; |
| 103 | 105 | ||
| @@ -125,4 +125,8 @@ target_link_libraries(gert PRIVATE | |||
| 125 | target_compile_options(gert PRIVATE ${AIR_COMMON_COMPILE_OPTION} | 125 | target_compile_options(gert PRIVATE ${AIR_COMMON_COMPILE_OPTION} |
| 126 | $<$<STREQUAL:${CMAKE_CXX_COMPILER_ID},Clang>:-fblocks> | 126 | $<$<STREQUAL:${CMAKE_CXX_COMPILER_ID},Clang>:-fblocks> |
| 127 | -fno-strict-aliasing | 127 | -fno-strict-aliasing |
| 128 | + # FXRT's converter reuses the GE runtime-v2 pass objects through its | ||
| 129 | + # offline optimizer. Export their ABI symbols from the shared | ||
| 130 | + # runtime so the converter can resolve them after installation. | ||
| 131 | + -fvisibility=default | ||
| 128 | ) | 132 | ) |
| @@ -11,6 +11,7 @@ | |||
| 11 | 11 | ||
| 12 | 12 | ||
| 13 | 13 | ||
| 14 | + | ||
| 14 | 15 | ||
| 15 | 16 | ||
| 16 | 17 | ||
| @@ -29,7 +30,7 @@ ge::graphStatus Tiling(KernelContext *context); | |||
| 29 | ge::graphStatus FallibleTiling(KernelContext *context); | 30 | ge::graphStatus FallibleTiling(KernelContext *context); |
| 30 | ge::graphStatus TilingAppendWorkspace(KernelContext *context); | 31 | ge::graphStatus TilingAppendWorkspace(KernelContext *context); |
| 31 | ge::graphStatus TilingAppendMemCheck(KernelContext *context); | 32 | ge::graphStatus TilingAppendMemCheck(KernelContext *context); |
| 32 | -ge::graphStatus FillTilingInfo(const KernelContext *context, ExceptionDumpInfoWrapper &wrapper); | 33 | +VISIBILITY_EXPORT ge::graphStatus FillTilingInfo(const KernelContext *context, ExceptionDumpInfoWrapper &wrapper); |
| 33 | std::vector<std::string> PrintTilingData(const KernelContext *context); | 34 | std::vector<std::string> PrintTilingData(const KernelContext *context); |
| 34 | ge::graphStatus RefreshOutputAddr(KernelContext *context, RtKernelLaunchArgsEx *launch_arg); | 35 | ge::graphStatus RefreshOutputAddr(KernelContext *context, RtKernelLaunchArgsEx *launch_arg); |
| 35 | ge::graphStatus AlignWorkspaceSizes(KernelContext *context); | 36 | ge::graphStatus AlignWorkspaceSizes(KernelContext *context); |