已合并
【Fix】:OM2 dump配置下发BUG修复(mode_name和layer错误配置导致dump功能异常) #4759
wangbin创建于 24 天前
【Fix】:OM2 dump配置下发BUG修复(mode_name和layer错误配置导致dump功能异常) #4759
已合并
共 4 个文件变更+97-21
| @@ -126,8 +126,9 @@ class DumpConfig { | |||
| 126 | // 配置是否需要 Dump | 126 | // 配置是否需要 Dump |
| 127 | bool NeedDump() const; | 127 | bool NeedDump() const; |
| 128 | 128 | ||
| 129 | - // 判断某个算子是否需要 dump | 129 | + // 判断该算子是否需要 dump |
| 130 | - bool IsOpNeedDump(const std::string &op_name) const; | 130 | + bool IsOpNeedDump(const std::string &model_name, const std::string &root_graph_name, |
| 131 | + const std::string &op_name) const; | ||
| 131 | 132 | ||
| 132 | private: | 133 | private: |
| 133 | DumpConfig() = default; | 134 | DumpConfig() = default; |
| @@ -188,36 +188,43 @@ bool DumpConfig::NeedDump() const { | |||
| 188 | return false; | 188 | return false; |
| 189 | } | 189 | } |
| 190 | 190 | ||
| 191 | -bool DumpConfig::IsOpNeedDump(const std::string &op_name) const { | 191 | +// 规则1:没有配置 dump_list 时,按全局 data dump 开关生效,默认该 op 需要 dump |
| 192 | +// 规则2:model_name 为空时,对齐 OM1 的 DUMP_LAYER_OP_MODEL,表示全局 layer 配置,不绑定具体模型 | ||
| 193 | +// 规则3:非全局 layer 配置时,只有 model_name 或 root_graph_name 命中当前模型,layer 才生效 | ||
| 194 | +// 规则4:模型不匹配时,即使 layer 命中当前 op,也不允许 dump | ||
| 195 | +// 规则5:模型匹配且 layer/watcher_nodes 为空时,表示 dump 该模型所有 op | ||
| 196 | +// 规则6:模型匹配且 layer 非空时,只 dump layer 中显式配置的 op | ||
| 197 | +// 规则7:watcher_nodes 模型匹配后按 watcher node 名精确匹配 | ||
| 198 | +// 规则8:所有 dump_list 项均未匹配当前模型/op 时,不 dump | ||
| 199 | +bool DumpConfig::IsOpNeedDump(const std::string &model_name, const std::string &root_graph_name, | ||
| 200 | + const std::string &op_name) const { | ||
| 192 | std::lock_guard<std::mutex> lock(mutex_); | 201 | std::lock_guard<std::mutex> lock(mutex_); |
| 193 | - // 如果没有配置 dump list,默认返回 true(由全局开关控制是否真的 dump) | ||
| 194 | if (model_dump_config_list_.empty()) { | 202 | if (model_dump_config_list_.empty()) { |
| 195 | return true; | 203 | return true; |
| 196 | } | 204 | } |
| 197 | 205 | ||
| 198 | - // 如果配置了 dump list,按照以下逻辑判断 | ||
| 199 | for (const auto &model_config : model_dump_config_list_) { | 206 | for (const auto &model_config : model_dump_config_list_) { |
| 200 | - // layers 为空,表示该模型所有 op 都需要 dump | 207 | + const bool is_global_layer_config = model_config.model_name.empty(); |
| 208 | + const bool is_model_matched = is_global_layer_config || (model_config.model_name == model_name) || | ||
| 209 | + (model_config.model_name == root_graph_name); | ||
| 210 | + if (!is_model_matched) { | ||
| 211 | + continue; | ||
| 212 | + } | ||
| 213 | + | ||
| 201 | if (model_config.layers.empty() && model_config.watcher_nodes.empty()) { | 214 | if (model_config.layers.empty() && model_config.watcher_nodes.empty()) { |
| 202 | return true; | 215 | return true; |
| 203 | } | 216 | } |
| 204 | 217 | ||
| 205 | - // 遍历 layers 匹配(前缀匹配) | 218 | + if (std::find(model_config.layers.begin(), model_config.layers.end(), op_name) != model_config.layers.end()) { |
| 206 | - for (const auto &layer : model_config.layers) { | 219 | + return true; |
| 207 | - if (op_name == layer) { | ||
| 208 | - return true; | ||
| 209 | - } | ||
| 210 | } | 220 | } |
| 211 | 221 | ||
| 212 | - // watcher nodes 匹配(精确匹配) | 222 | + if (std::find(model_config.watcher_nodes.begin(), model_config.watcher_nodes.end(), op_name) != |
| 213 | - for (const auto &node : model_config.watcher_nodes) { | 223 | + model_config.watcher_nodes.end()) { |
| 214 | - if (op_name == node) { | 224 | + return true; |
| 215 | - return true; | ||
| 216 | - } | ||
| 217 | } | 225 | } |
| 218 | } | 226 | } |
| 219 | 227 | ||
| 220 | - // 有 dump list,但当前 op 不在列表中 | ||
| 221 | return false; | 228 | return false; |
| 222 | } | 229 | } |
| 223 | 230 | ||
| @@ -117,13 +117,16 @@ Status ModelDumpManager::IsDataDumpEnabled(const char *op_name, uint8_t *is_data | |||
| 117 | } | 117 | } |
| 118 | 118 | ||
| 119 | const char *safe_op_name = (op_name != nullptr) ? op_name : ""; | 119 | const char *safe_op_name = (op_name != nullptr) ? op_name : ""; |
| 120 | + const char *model_name = (model_info_.model_name != nullptr) ? model_info_.model_name : ""; | ||
| 121 | + const char *root_graph_name = (model_info_.root_graph_name != nullptr) ? model_info_.root_graph_name : ""; | ||
| 120 | 122 | ||
| 121 | // 对齐 v1 KernelTaskInfo.is_data_dump_ 的判断逻辑: | 123 | // 对齐 v1 KernelTaskInfo.is_data_dump_ 的判断逻辑: |
| 122 | // is_data_dump_ 是纯 data dump 相关的,只判断: | 124 | // is_data_dump_ 是纯 data dump 相关的,只判断: |
| 123 | // 1. data dump 开关已启用 | 125 | // 1. data dump 开关已启用 |
| 124 | // 2. 算子在 dump layer/list 配置中 | 126 | // 2. 算子在 dump layer/list 配置中 |
| 125 | - const bool need_data_dump = | 127 | + // data dump 是否生效需要同时满足全局开关和当前模型/op 命中 dump_list,避免 model_name 不匹配时误 dump。 |
| 126 | - DumpConfig::Instance().IsDataDumpEnabled() && DumpConfig::Instance().IsOpNeedDump(safe_op_name); | 128 | + const bool need_data_dump = DumpConfig::Instance().IsDataDumpEnabled() && |
| 129 | + DumpConfig::Instance().IsOpNeedDump(model_name, root_graph_name, safe_op_name); | ||
| 127 | 130 | ||
| 128 | GELOGD("IsDataDumpEnabled: op_name=%s, need_data_dump=%u", safe_op_name, static_cast<uint32_t>(need_data_dump)); | 131 | GELOGD("IsDataDumpEnabled: op_name=%s, need_data_dump=%u", safe_op_name, static_cast<uint32_t>(need_data_dump)); |
| 129 | *is_data_dump = need_data_dump ? 1U : 0U; | 132 | *is_data_dump = need_data_dump ? 1U : 0U; |
| @@ -148,13 +151,16 @@ Status ModelDumpManager::PreprocessOm2TaskInfo(const GertModelTaskDesc &task_inf | |||
| 148 | 151 | ||
| 149 | Status ModelDumpManager::AddOm2TaskInfo(const GertModelTaskDesc &task_info) { | 152 | Status ModelDumpManager::AddOm2TaskInfo(const GertModelTaskDesc &task_info) { |
| 150 | const char *op_name = (task_info.op_name != nullptr) ? task_info.op_name : ""; | 153 | const char *op_name = (task_info.op_name != nullptr) ? task_info.op_name : ""; |
| 154 | + const char *model_name = (model_info_.model_name != nullptr) ? model_info_.model_name : ""; | ||
| 155 | + const char *root_graph_name = (model_info_.root_graph_name != nullptr) ? model_info_.root_graph_name : ""; | ||
| 151 | GELOGD("AddOm2TaskInfo: op_name=%s, task_id=%u, stream_id=%u", op_name, task_info.task_id, task_info.stream_id); | 156 | GELOGD("AddOm2TaskInfo: op_name=%s, task_id=%u, stream_id=%u", op_name, task_info.task_id, task_info.stream_id); |
| 152 | 157 | ||
| 153 | // 判断该算子是否需要保存到 data dump: | 158 | // 判断该算子是否需要保存到 data dump: |
| 154 | // 1. 配置了 data dump 且算子在列表中 | 159 | // 1. 配置了 data dump 且算子在列表中 |
| 155 | // 2. 开启了 overflow dump(所有算子都需要保存用于定位) | 160 | // 2. 开启了 overflow dump(所有算子都需要保存用于定位) |
| 156 | - const bool need_data_dump = | 161 | + // data dump 是否生效需要同时满足全局开关和当前模型/op 命中 dump_list,避免 model_name 不匹配时误保存任务。 |
| 157 | - DumpConfig::Instance().IsDataDumpEnabled() && DumpConfig::Instance().IsOpNeedDump(op_name); | 162 | + const bool need_data_dump = DumpConfig::Instance().IsDataDumpEnabled() && |
| 163 | + DumpConfig::Instance().IsOpNeedDump(model_name, root_graph_name, op_name); | ||
| 158 | const bool need_overflow_dump = DumpConfig::Instance().IsOverflowDumpEnabled(); | 164 | const bool need_overflow_dump = DumpConfig::Instance().IsOverflowDumpEnabled(); |
| 159 | const bool need_save_to_data_dump = need_data_dump || need_overflow_dump; | 165 | const bool need_save_to_data_dump = need_data_dump || need_overflow_dump; |
| 160 | 166 | ||
| @@ -244,6 +244,68 @@ TEST_F(DumpConfigTest, DefaultValuesTest) { | |||
| 244 | EXPECT_EQ(DumpConfig::Instance().GetDumpDebug(), GE_DUMP_DEBUG_DEFAULT); | 244 | EXPECT_EQ(DumpConfig::Instance().GetDumpDebug(), GE_DUMP_DEBUG_DEFAULT); |
| 245 | } | 245 | } |
| 246 | 246 | ||
| 247 | +TEST_F(DumpConfigTest, IsOpNeedDumpByModelNameAndLayerTest) { | ||
| 248 | + const char *kModelLayerDumpConfig = R"({ | ||
| 249 | + "dump": { | ||
| 250 | + "dump_path": "/tmp/dump_test", | ||
| 251 | + "dump_mode": "all", | ||
| 252 | + "dump_list": [ | ||
| 253 | + { | ||
| 254 | + "model_name": "test_model", | ||
| 255 | + "layer": ["layer1", "layer2"] | ||
| 256 | + } | ||
| 257 | + ] | ||
| 258 | + } | ||
| 259 | + })"; | ||
| 260 | + ASSERT_EQ(DumpConfig::Instance().ParseAndValidate(kModelLayerDumpConfig, | ||
| 261 | + static_cast<int32_t>(strlen(kModelLayerDumpConfig))), | ||
| 262 | + SUCCESS); | ||
| 263 | + | ||
| 264 | + EXPECT_TRUE(DumpConfig::Instance().IsOpNeedDump("test_model", "root_graph", "layer1")); | ||
| 265 | + EXPECT_FALSE(DumpConfig::Instance().IsOpNeedDump("test_model", "root_graph", "layer3")); | ||
| 266 | + EXPECT_FALSE(DumpConfig::Instance().IsOpNeedDump("invalid_model", "root_graph", "layer1")); | ||
| 267 | + EXPECT_TRUE(DumpConfig::Instance().IsOpNeedDump("invalid_model", "test_model", "layer2")); | ||
| 268 | +} | ||
| 269 | + | ||
| 270 | +TEST_F(DumpConfigTest, IsOpNeedDumpByMatchedModelWithoutLayerTest) { | ||
| 271 | + const char *kModelAllOpDumpConfig = R"({ | ||
| 272 | + "dump": { | ||
| 273 | + "dump_path": "/tmp/dump_test", | ||
| 274 | + "dump_list": [ | ||
| 275 | + { | ||
| 276 | + "model_name": "test_model" | ||
| 277 | + } | ||
| 278 | + ] | ||
| 279 | + } | ||
| 280 | + })"; | ||
| 281 | + ASSERT_EQ(DumpConfig::Instance().ParseAndValidate(kModelAllOpDumpConfig, | ||
| 282 | + static_cast<int32_t>(strlen(kModelAllOpDumpConfig))), | ||
| 283 | + SUCCESS); | ||
| 284 | + | ||
| 285 | + EXPECT_TRUE(DumpConfig::Instance().IsOpNeedDump("test_model", "root_graph", "any_op")); | ||
| 286 | + EXPECT_FALSE(DumpConfig::Instance().IsOpNeedDump("invalid_model", "root_graph", "any_op")); | ||
| 287 | +} | ||
| 288 | + | ||
| 289 | +TEST_F(DumpConfigTest, IsOpNeedDumpByGlobalLayerTest) { | ||
| 290 | + const char *kGlobalLayerDumpConfig = R"({ | ||
| 291 | + "dump": { | ||
| 292 | + "dump_path": "/tmp/dump_test", | ||
| 293 | + "dump_list": [ | ||
| 294 | + { | ||
| 295 | + "layer": ["layer1"] | ||
| 296 | + } | ||
| 297 | + ] | ||
| 298 | + } | ||
| 299 | + })"; | ||
| 300 | + ASSERT_EQ(DumpConfig::Instance().ParseAndValidate(kGlobalLayerDumpConfig, | ||
| 301 | + static_cast<int32_t>(strlen(kGlobalLayerDumpConfig))), | ||
| 302 | + SUCCESS); | ||
| 303 | + | ||
| 304 | + EXPECT_TRUE(DumpConfig::Instance().IsOpNeedDump("model1", "root_graph1", "layer1")); | ||
| 305 | + EXPECT_TRUE(DumpConfig::Instance().IsOpNeedDump("model2", "root_graph2", "layer1")); | ||
| 306 | + EXPECT_FALSE(DumpConfig::Instance().IsOpNeedDump("model1", "root_graph1", "layer2")); | ||
| 307 | +} | ||
| 308 | + | ||
| 247 | // DumpCallbackManager 测试类 | 309 | // DumpCallbackManager 测试类 |
| 248 | class DumpCallbackManagerTest : public Test { | 310 | class DumpCallbackManagerTest : public Test { |
| 249 | protected: | 311 | protected: |