diff --git a/ge/common/dump/dump_properties.cc b/ge/common/dump/dump_properties.cc index ef755540..84bdb7bf 100644 --- a/ge/common/dump/dump_properties.cc +++ b/ge/common/dump/dump_properties.cc @@ -18,6 +18,7 @@ #include #include +#include #include "common/ge/ge_util.h" #include "framework/common/util.h" @@ -37,6 +38,159 @@ const uint32_t kAtomicOverflow = (0x1 << 1); const uint32_t kAllOverflow = (kAicoreOverflow | kAtomicOverflow); } // namespace namespace ge { +FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY void DumpProperties::Split(const std::string &s, + std::vector &result, + const char *delchar) { + if (s.empty()) { + return; + } + result.clear(); + + char *buffer = new (std::nothrow)char[s.size() + 1]; + if (buffer == nullptr) { + GELOGE(FAILED, "[Split][string] failed while malloc memory, string value is:%s", s.c_str()); + REPORT_CALL_ERROR("E19999", "Memory malloc may fail when split string, get fatal exception, " + "string value is:%s", s.c_str()); + return; + } + buffer[s.size()] = '\0'; + errno_t e = strcpy_s(buffer, s.size() + 1, s.c_str()); + if (e != EOK) { + delete[] buffer; + return; + } + char *context = nullptr; + char *p = strtok_s(buffer, delchar, &context); + while (p != nullptr) { + result.emplace_back(p); + p = strtok_s(nullptr, delchar, &context); + } + delete[] buffer; +} + +FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY Status DumpProperties::CheckDumpStep(const std::string &dump_step) { + std::string modified_dum_step = dump_step + "|"; + std::smatch result; + std::vector match_vecs; + std::regex pattern(R"((\d{1,}-\d{1,}\||\d{1,}\|)+)"); + if (regex_match(modified_dum_step, result, pattern)) { + Split(result.str(), match_vecs, "|"); + if (match_vecs.empty()) { + REPORT_CALL_ERROR("E19999", "Split may get fatal exception, dump_step:%s.", dump_step.c_str()); + GELOGE(FAILED, "[Check][Param] failed. Split may get fatal exception, ge.exec.dumpStep:%s.", dump_step.c_str()); + return FAILED; + } + // 100 is the max sets of dump steps. + if (match_vecs.size() > 100) { + REPORT_INPUT_ERROR("E10001", std::vector({"parameter", "value", "reason"}), + std::vector({ + "ge.exec.dumpStep", + dump_step.c_str(), + " is not supported, only support dump <= 100 sets of data"})); + GELOGE(PARAM_INVALID, "[Check][Param] get dump_step value:%s, " + "dump_step only support dump <= 100 sets of data.", dump_step.c_str()); + return PARAM_INVALID; + } + for (const auto &match_vec : match_vecs) { + std::vector vec_after_split; + Split(match_vec, vec_after_split, "-"); + if (match_vecs.empty()) { + REPORT_CALL_ERROR("E19999", "Split may get fatal exception."); + GELOGE(FAILED, "[Check][Param] failed, split may get fatal exception."); + return FAILED; + } + if (vec_after_split.size() > 1) { + if (std::atoi(vec_after_split[0].c_str()) >= std::atoi(vec_after_split[1].c_str())) { + REPORT_INPUT_ERROR("E10001", std::vector({"parameter", "value", "reason"}), + std::vector({ + "ge.exec.dumpStep", + dump_step.c_str(), + " is not supported." + "in range steps, the first step is >= second step, correct example:'0|5|10-20"})); + GELOGE(PARAM_INVALID, "[Check][Param] get dump_step value:%s, " + "in range steps, the first step is >= second step, correct example:'0|5|10-20'", dump_step.c_str()); + return PARAM_INVALID; + } + } + } + } else { + REPORT_INPUT_ERROR("E10001", std::vector({"parameter", "value", "reason"}), + std::vector({ + "ge.exec.dumpStep", + dump_step.c_str(), + " is not supported, correct example:'0|5|10|50-100."})); + GELOGE(PARAM_INVALID, "[Check][Param] get dump_step value:%s, " + "dump_step string style is error, correct example:'0|5|10|50-100.'", dump_step.c_str()); + return PARAM_INVALID; + } + return SUCCESS; +} + +FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY Status DumpProperties::CheckDumpMode(const std::string &dump_mode) { + const std::set dump_mode_list = {"input", "output", "all"}; + std::set::iterator iter; + + if ((iter = dump_mode_list.find(dump_mode)) == dump_mode_list.end()) { + REPORT_INPUT_ERROR("E10001", std::vector({"parameter", "value", "reason"}), + std::vector({ + "ge.exec.dumpMode", + dump_mode.c_str(), + " is not supported, should be one of the following:[input, output, all]"})); + GELOGE(PARAM_INVALID, "[Check][Param] the dump_debug_mode:%s, is is not supported," + "should be one of the following:[input, output, all].", dump_mode.c_str()); + return PARAM_INVALID; + } + return SUCCESS; +} + +FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY Status DumpProperties::CheckDumpPath(const std::string &input) { + if (mmIsDir(input.c_str()) != EN_OK) { + REPORT_INPUT_ERROR("E10001", std::vector({"parameter", "value", "reason"}), + std::vector({ + "ge.exec.dumpPath", + input.c_str(), + " is not a directory."})); + GELOGE(PARAM_INVALID, "[Check][Param] the path:%s, is not directory.", input.c_str()); + return PARAM_INVALID; + } + char trusted_path[MMPA_MAX_PATH] = { "\0" }; + if (mmRealPath(input.c_str(), trusted_path, MMPA_MAX_PATH) != EN_OK) { + REPORT_INPUT_ERROR("E10001", std::vector({"parameter", "value", "reason"}), + std::vector({ + "ge.exec.dumpPath", + input.c_str(), + " dumpPath invalid."})); + GELOGE(PARAM_INVALID, "[Check][Param] the dumpPath:%s, is invalid.", input.c_str()); + return PARAM_INVALID; + } + if (mmAccess2(trusted_path, M_R_OK | M_W_OK) != EN_OK) { + REPORT_INPUT_ERROR("E10001", std::vector({"parameter", "value", "reason"}), + std::vector({ + "ge.exec.dumpPath", + input.c_str(), + " does't have read, write permissions."})); + GELOGE(PARAM_INVALID, "[Check][Param] the path:%s, does't have read, write permissions.", input.c_str()); + return PARAM_INVALID; + } + return SUCCESS; +} + +FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY Status DumpProperties::CheckEnableDump(const std::string &input) { + std::set enable_dump_option_list = {"1", "0"}; + auto it = enable_dump_option_list.find(input); + if (it == enable_dump_option_list.end()) { + REPORT_INPUT_ERROR("E10001", std::vector({"parameter", "value", "reason"}), + std::vector({ + "ge.exec.enableDump", + input.c_str(), + " only support 1 or 0."})); + GELOGE(PARAM_INVALID, "[Check][Param] Not support ge.exec.enableDump or ge.exec.enableDumpDebug format:%s, " + "only support 1 or 0.", input.c_str()); + return PARAM_INVALID; + } + return SUCCESS; +} + FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY DumpProperties::DumpProperties(const DumpProperties &other) { CopyFrom(other); } @@ -47,7 +201,26 @@ FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY DumpProperties &DumpProperties: return *this; } -FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY void DumpProperties::InitByOptions() { +FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY Status DumpProperties::SetDumpOptions() { + if (enable_dump_ == kEnableFlag) { + std::string dump_step; + if (GetContext().GetOption(OPTION_EXEC_DUMP_STEP, dump_step) == GRAPH_SUCCESS) { + GE_CHK_STATUS_RET(CheckDumpStep(dump_step), "[Check][dump_step] failed."); + GELOGI("Get dump step %s successfully", dump_step.c_str()); + SetDumpStep(dump_step); + } + string dump_mode = "output"; + if (GetContext().GetOption(OPTION_EXEC_DUMP_MODE, dump_mode) == GRAPH_SUCCESS) { + GELOGI("Get dump mode %s successfully", dump_mode.c_str()); + GE_CHK_STATUS_RET(CheckDumpMode(dump_mode), "[Check][dump_mode] failed."); + SetDumpMode(dump_mode); + } + AddPropertyValue(DUMP_ALL_MODEL, {}); + } + return SUCCESS; +} + +FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY Status DumpProperties::InitByOptions() { enable_dump_.clear(); enable_dump_debug_.clear(); dump_path_.clear(); @@ -57,17 +230,32 @@ FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY void DumpProperties::InitByOpti is_infer_op_debug_ = false; op_debug_mode_ = 0; - std::string enable_dump; + std::string enable_dump = std::to_string(false); (void)GetContext().GetOption(OPTION_EXEC_ENABLE_DUMP, enable_dump); enable_dump_ = enable_dump; + if (!enable_dump_.empty()) { + GE_CHK_STATUS_RET(CheckEnableDump(enable_dump_), "[Check][enable_dump] failed."); + } - std::string enable_dump_debug; + std::string enable_dump_debug = std::to_string(false); (void)GetContext().GetOption(OPTION_EXEC_ENABLE_DUMP_DEBUG, enable_dump_debug); enable_dump_debug_ = enable_dump_debug; - + if (!enable_dump_debug_.empty()) { + GE_CHK_STATUS_RET(CheckEnableDump(enable_dump_debug_), "[Check][enable_dump_debug] failed."); + } + if ((enable_dump_ == kEnableFlag) && (enable_dump_debug_ == kEnableFlag)) { + REPORT_INPUT_ERROR("E10001", std::vector({"parameter", "value", "reason"}), + std::vector({ + "ge.exec.enableDump and ge.exec.enableDumpDebug", + enable_dump_ + ", " + enable_dump_debug, + "ge.exec.enableDump and ge.exec.enableDumpDebug cannot be set to 1 at the same time."})); + GELOGE(FAILED, "ge.exec.enableDump and ge.exec.enableDumpDebug cannot be both set to 1 at the same time."); + return FAILED; + } if ((enable_dump_ == kEnableFlag) || (enable_dump_debug_ == kEnableFlag)) { std::string dump_path; if (GetContext().GetOption(OPTION_EXEC_DUMP_PATH, dump_path) == GRAPH_SUCCESS) { + GE_CHK_STATUS_RET(CheckDumpPath(dump_path), "Check dump path failed."); if (!dump_path.empty() && dump_path[dump_path.size() - 1] != '/') { dump_path = dump_path + "/"; } @@ -75,25 +263,21 @@ FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY void DumpProperties::InitByOpti GELOGI("Get dump path %s successfully", dump_path.c_str()); SetDumpPath(dump_path); } else { - GELOGW("Dump path is not set"); + REPORT_INPUT_ERROR("E10001", std::vector({"parameter", "value", "reason"}), + std::vector({ + "ge.exec.dumpPath", + dump_path, + "ge.exec.dumpPath is not set."})); + GELOGE(FAILED, "[Check][dump_path] failed. Dump path is not set."); + return FAILED; } } - if (enable_dump_ == kEnableFlag) { - std::string dump_step; - if (GetContext().GetOption(OPTION_EXEC_DUMP_STEP, dump_step) == GRAPH_SUCCESS) { - GELOGI("Get dump step %s successfully", dump_step.c_str()); - SetDumpStep(dump_step); - } - string dump_mode; - if (GetContext().GetOption(OPTION_EXEC_DUMP_MODE, dump_mode) == GRAPH_SUCCESS) { - GELOGI("Get dump mode %s successfully", dump_mode.c_str()); - SetDumpMode(dump_mode); - } - AddPropertyValue(DUMP_ALL_MODEL, {}); - } + GE_CHK_STATUS_RET(SetDumpOptions(), "SetDumpOptions failed."); + + GE_CHK_STATUS_RET(SetDumpDebugOptions(), "SetDumpDebugOptions failed."); - SetDumpDebugOptions(); + return SUCCESS; } // The following is the new dump scenario of the fusion operator @@ -253,14 +437,20 @@ void DumpProperties::CopyFrom(const DumpProperties &other) { } } -void DumpProperties::SetDumpDebugOptions() { +Status DumpProperties::SetDumpDebugOptions() { if (enable_dump_debug_ == kEnableFlag) { std::string dump_debug_mode; if (GetContext().GetOption(OPTION_EXEC_DUMP_DEBUG_MODE, dump_debug_mode) == GRAPH_SUCCESS) { GELOGD("Get dump debug mode %s successfully", dump_debug_mode.c_str()); } else { - GELOGW("Dump debug mode is not set."); - return; + REPORT_INPUT_ERROR("E10001", std::vector({"parameter", "value", "reason"}), + std::vector({ + "ge.exec.dumpDebugMode", + dump_debug_mode, + "ge.exec.dumpDebugMode is not set."})); + GELOGE(PARAM_INVALID, "[Check][dump_debug_mode] failed. Dump debug mode is not set."); + + return PARAM_INVALID; } if (dump_debug_mode == OP_DEBUG_AICORE) { @@ -276,10 +466,17 @@ void DumpProperties::SetDumpDebugOptions() { is_train_op_debug_ = true; op_debug_mode_ = kAllOverflow; } else { - GELOGW("ge.exec.dumpDebugMode is invalid."); + REPORT_INPUT_ERROR("E10001", std::vector({"parameter", "value", "reason"}), + std::vector({ + "ge.exec.dumpDebugMode", + dump_debug_mode, + "ge.exec.dumpDebugMode is invalid."})); + GELOGE(PARAM_INVALID, "[Set][DumpDebugOptions] failed, ge.exec.dumpDebugMode is invalid."); + return PARAM_INVALID; } } else { GELOGI("ge.exec.enableDumpDebug is false or is not set."); } + return SUCCESS; } } // namespace ge diff --git a/ge/common/dump/dump_properties.h b/ge/common/dump/dump_properties.h index 98487491..cbfc362d 100644 --- a/ge/common/dump/dump_properties.h +++ b/ge/common/dump/dump_properties.h @@ -23,6 +23,7 @@ #include namespace ge { +using Status = uint32_t; class DumpProperties { public: DumpProperties() = default; @@ -33,7 +34,7 @@ class DumpProperties { DumpProperties &operator=(const DumpProperties &dump); - void InitByOptions(); + Status InitByOptions(); void AddPropertyValue(const std::string &model, const std::set &layers); @@ -95,7 +96,20 @@ class DumpProperties { private: void CopyFrom(const DumpProperties &other); - void SetDumpDebugOptions(); + Status SetDumpDebugOptions(); + + Status SetDumpOptions(); + + void Split(const std::string &s, std::vector &result, const char *delchar); + + Status CheckDumpStep(const std::string &dump_step); + + Status CheckDumpMode(const std::string &dump_mode); + + Status CheckDumpPath(const std::string &input); + + Status CheckEnableDump(const std::string &input); + std::string enable_dump_; std::string enable_dump_debug_; diff --git a/ge/session/inner_session.cc b/ge/session/inner_session.cc index 54e62d32..58b78f41 100755 --- a/ge/session/inner_session.cc +++ b/ge/session/inner_session.cc @@ -121,7 +121,7 @@ Status InnerSession::Initialize() { GE_CHK_RT_RET(rtSetDevice(GetContext().DeviceId())); DumpProperties dump_properties; - dump_properties.InitByOptions(); + GE_CHK_STATUS_RET(dump_properties.InitByOptions(), "Init dump properties failed."); GE_CHK_STATUS_RET(AddDumpProperties(dump_properties), "[Add][DumpProperties] failed."); ret = graph_manager_.Initialize(options_); diff --git a/tests/ut/ge/CMakeLists.txt b/tests/ut/ge/CMakeLists.txt index f808bce7..5b8958b4 100755 --- a/tests/ut/ge/CMakeLists.txt +++ b/tests/ut/ge/CMakeLists.txt @@ -780,6 +780,7 @@ set(MULTI_PARTS_TEST_FILES "common/util_unittest.cc" "common/dump_manager_unittest.cc" "common/dump_op_unittest.cc" + "common/dump_properties_unittest.cc" "common/dump_exception_unittest.cc" "common/opdebug_register_unittest.cc" "common/format_transfer_unittest.cc" diff --git a/tests/ut/ge/common/dump_properties_unittest.cc b/tests/ut/ge/common/dump_properties_unittest.cc new file mode 100644 index 00000000..57809013 --- /dev/null +++ b/tests/ut/ge/common/dump_properties_unittest.cc @@ -0,0 +1,126 @@ +/** + * Copyright 2019-2020 Huawei Technologies Co., Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#define protected public +#define private public + +#include "common/dump/dump_properties.h" +#include "ge_local_context.h" +#include "ge/ge_api_types.h" +#include "common/debug/log.h" +#include "common/ge_inner_error_codes.h" + +namespace ge { +class UTEST_dump_properties : public testing::Test { + protected: + void SetUp() {} + void TearDown() {} +}; + +TEST_F(UTEST_dump_properties, check_dump_step) { + DumpProperties dp; + std::string dump_step{"0|3-5|10"}; + std::string unsupport_input1{"0|5-3|10"}; + std::string unsupport_input2{"one"}; + std::string unsupport_input3; + for (int i = 0; i < 200; ++i) { + unsupport_input3 += std::to_string(i) + "|"; + } + unsupport_input3.pop_back(); + Status st = dp.CheckDumpStep(dump_step); + EXPECT_EQ(st, SUCCESS); + st = dp.CheckDumpStep(unsupport_input1); + EXPECT_NE(st, SUCCESS); + st = dp.CheckDumpStep(unsupport_input2); + EXPECT_NE(st, SUCCESS); + st = dp.CheckDumpStep(unsupport_input3); + EXPECT_NE(st, SUCCESS); +} + +TEST_F(UTEST_dump_properties, check_dump_mode) { + DumpProperties dp; + std::string dump_mode_1{"input"}; + std::string dump_mode_2{"output"}; + std::string dump_mode_3{"all"}; + std::string unsupport_input1{"mode1"}; + Status st = dp.CheckDumpMode(dump_mode_1); + EXPECT_EQ(st, SUCCESS); + st = dp.CheckDumpMode(dump_mode_2); + EXPECT_EQ(st, SUCCESS); + st = dp.CheckDumpMode(dump_mode_3); + EXPECT_EQ(st, SUCCESS); + st = dp.CheckDumpMode(unsupport_input1); + EXPECT_NE(st, SUCCESS); +} + +TEST_F(UTEST_dump_properties, check_dump_path) { + DumpProperties dp; + std::string dump_path{"/tmp/"}; + std::string unsupport_input1{" \\unsupported"}; + Status st = dp.CheckDumpPath(dump_path); + EXPECT_EQ(st, SUCCESS); + st = dp.CheckDumpPath(unsupport_input1); + EXPECT_NE(st, SUCCESS); +} + +TEST_F(UTEST_dump_properties, check_enable_dump) { + DumpProperties dp; + std::string enable_dump_t{"1"}; + std::string enable_dump_f{"0"}; + std::string unsupport_input1{"true"}; + std::string unsupport_input2{"false"}; + Status st = dp.CheckEnableDump(enable_dump_t); + EXPECT_EQ(st, SUCCESS); + st = dp.CheckEnableDump(enable_dump_f); + EXPECT_EQ(st, SUCCESS); + st = dp.CheckEnableDump(unsupport_input1); + EXPECT_NE(st, SUCCESS); + st = dp.CheckEnableDump(unsupport_input2); + EXPECT_NE(st, SUCCESS); +} + +TEST_F(UTEST_dump_properties, init_by_options_success_1) { + DumpProperties dp; + std::map options {{OPTION_EXEC_ENABLE_DUMP, "1"}, + {OPTION_EXEC_DUMP_PATH, "/tmp/"}, + {OPTION_EXEC_DUMP_STEP, "0|1-3|10"}, + {OPTION_EXEC_DUMP_MODE, "all"}}; + GetThreadLocalContext().SetGlobalOption(options); + Status st = dp.InitByOptions(); + EXPECT_EQ(st, SUCCESS); +} + +TEST_F(UTEST_dump_properties, init_by_options_success_2) { + DumpProperties dp; + std::map options {{OPTION_EXEC_ENABLE_DUMP_DEBUG, "1"}, + {OPTION_EXEC_DUMP_PATH, "/tmp/"}, + {OPTION_EXEC_DUMP_DEBUG_MODE, "aicore_overflow"}}; + GetThreadLocalContext().SetGlobalOption(options); + Status st = dp.InitByOptions(); + EXPECT_EQ(st, SUCCESS); +} + +TEST_F(UTEST_dump_properties, init_by_options_failed) { + DumpProperties dp; + std::map options {{OPTION_EXEC_ENABLE_DUMP_DEBUG, "1"}, + {OPTION_EXEC_DUMP_PATH, "/tmp/"}}; + GetThreadLocalContext().SetGlobalOption(options); + Status st = dp.InitByOptions(); + EXPECT_NE(st, SUCCESS); +} +} // namespace ge \ No newline at end of file