已合并
【Fix】:OM2 dump配置下发BUG修复(mode_name和layer错误配置导致dump功能异常) #4759
【Fix】:OM2 dump配置下发BUG修复(mode_name和layer错误配置导致dump功能异常) #4759
已合并
wangbin创建于 24 天前
共 4 个文件变更+97-21
@@ -126,8 +126,9 @@ class DumpConfig {
126 // 配置是否需要 Dump126 // 配置是否需要 Dump
127 bool NeedDump() const;127 bool NeedDump() const;
128 128 
129- // 判断某个算子是否需要 dump129+ // 判断该算子是否需要 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 都需要 dump207+ 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 
149Status ModelDumpManager::AddOm2TaskInfo(const GertModelTaskDesc &task_info) {152Status 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 测试类
248class DumpCallbackManagerTest : public Test {310class DumpCallbackManagerTest : public Test {
249 protected:311 protected: