From: @zhangbuxue Reviewed-by: @guoqi1024,@zhaizhiqiang Signed-off-by: @zhaizhiqiangpull/15928/MERGE
| @@ -37,7 +37,7 @@ class ReduceCPUKernel : public CPUKernel { | |||
| enum ReduceType { kReduceAll, kReduceAny, kReduceMax, kReduceMin, kReduceSum, kReduceMean }; | |||
| std::vector<size_t> input_shape_; | |||
| std::vector<int64_t> axis_; | |||
| ReduceType reduce_type_; | |||
| ReduceType reduce_type_{kReduceAll}; | |||
| std::function<void(const T *, size_t, T *)> reduce_func_; | |||
| }; | |||
| @@ -12,6 +12,7 @@ set(_DEBUG_SRC_LIST | |||
| "${CMAKE_CURRENT_SOURCE_DIR}/data_dump/dump_json_parser.cc" | |||
| "${CMAKE_CURRENT_SOURCE_DIR}/data_dump/cpu_e2e_dump.cc" | |||
| "${CMAKE_CURRENT_SOURCE_DIR}/data_dump/dump_utils.cc" | |||
| "${CMAKE_CURRENT_SOURCE_DIR}/data_dump/npy_header.cc" | |||
| ) | |||
| set(_OFFLINE_SRC_LIST | |||
| @@ -19,7 +19,7 @@ | |||
| #include "backend/session/anf_runtime_algorithm.h" | |||
| namespace mindspore { | |||
| void CPUE2eDump::DumpCNodeData(const CNodePtr &node) { | |||
| void CPUE2eDump::DumpCNodeData(const CNodePtr &node, uint32_t graph_id) { | |||
| MS_EXCEPTION_IF_NULL(node); | |||
| auto &dump_json_parser = DumpJsonParser::GetInstance(); | |||
| std::string kernel_name = node->fullname_with_scope(); | |||
| @@ -29,7 +29,7 @@ void CPUE2eDump::DumpCNodeData(const CNodePtr &node) { | |||
| MS_LOG(DEBUG) << "E2e dump CNode data start: " << kernel_name << ", current iteration is " | |||
| << dump_json_parser.cur_dump_iter(); | |||
| std::string dump_path = GenerateDumpPath(); | |||
| std::string dump_path = GenerateDumpPath(graph_id); | |||
| if (dump_json_parser.InputNeedDump()) { | |||
| DumpCNodeInputs(node, dump_path); | |||
| } | |||
| @@ -129,12 +129,12 @@ void CPUE2eDump::DumpSingleAnfNode(const AnfNodePtr &anf_node, const size_t outp | |||
| DumpMemToFile(file_path, NOT_NULL(addr), int_shapes, type); | |||
| } | |||
| void CPUE2eDump::DumpParametersAndConst(const session::KernelGraph *graph) { | |||
| void CPUE2eDump::DumpParametersAndConst(const session::KernelGraph *graph, uint32_t graph_id) { | |||
| MS_EXCEPTION_IF_NULL(graph); | |||
| MS_LOG(INFO) << "Start e2e dump parameters and Const values"; | |||
| std::map<std::string, size_t> const_map; | |||
| GetConstantId(graph, &const_map); | |||
| const std::string &dump_path = GenerateDumpPath(); | |||
| const std::string &dump_path = GenerateDumpPath(graph_id); | |||
| // dump parameters | |||
| const auto ¶meters = graph->inputs(); | |||
| @@ -29,9 +29,9 @@ class CPUE2eDump { | |||
| CPUE2eDump() = default; | |||
| ~CPUE2eDump() = default; | |||
| // Dump data when task error. | |||
| static void DumpParametersAndConst(const session::KernelGraph *graph); | |||
| static void DumpParametersAndConst(const session::KernelGraph *graph, uint32_t graph_id); | |||
| static void DumpCNodeData(const CNodePtr &node); | |||
| static void DumpCNodeData(const CNodePtr &node, uint32_t graph_id); | |||
| private: | |||
| static void DumpCNodeInputs(const CNodePtr &node, const std::string &dump_path); | |||
| @@ -20,12 +20,14 @@ | |||
| #include "utils/ms_context.h" | |||
| #include "utils/convert_utils_base.h" | |||
| #include "backend/session/anf_runtime_algorithm.h" | |||
| #include "debug/data_dump/npy_header.h" | |||
| namespace { | |||
| constexpr auto kCommonDumpSettings = "common_dump_settings"; | |||
| constexpr auto kAsyncDumpSettings = "async_dump_settings"; | |||
| constexpr auto kE2eDumpSettings = "e2e_dump_settings"; | |||
| constexpr auto kDumpMode = "dump_mode"; | |||
| constexpr auto kDumpFormat = "dump_format"; | |||
| constexpr auto kPath = "path"; | |||
| constexpr auto kNetName = "net_name"; | |||
| constexpr auto kIteration = "iteration"; | |||
| @@ -42,6 +44,8 @@ constexpr auto kMindsporeDumpConfig = "MINDSPORE_DUMP_CONFIG"; | |||
| } // namespace | |||
| namespace mindspore { | |||
| uint32_t DumpJsonParser::dump_format_ = 0; | |||
| auto DumpJsonParser::CheckJsonKeyExist(const nlohmann::json &content, const std::string &key) { | |||
| auto iter = content.find(key); | |||
| if (iter == content.end()) { | |||
| @@ -137,13 +141,15 @@ bool DumpJsonParser::GetIterDumpFlag() { | |||
| return e2e_dump_enabled_ && (iteration_ == 0 || cur_dump_iter_ == iteration_); | |||
| } | |||
| bool DumpJsonParser::DumpToFile(const std::string &filename, const void *data, size_t len) { | |||
| bool DumpJsonParser::DumpToFile(const std::string &filename, const void *data, size_t len, const ShapeVector &shape, | |||
| TypeId type) { | |||
| if (filename.empty() || data == nullptr || len == 0) { | |||
| MS_LOG(ERROR) << "Incorrect parameter."; | |||
| return false; | |||
| } | |||
| auto realpath = Common::GetRealPath(filename); | |||
| std::string file_format = dump_format_ == 1 ? ".npy" : ".bin"; | |||
| auto realpath = Common::GetRealPath(filename + file_format); | |||
| if (!realpath.has_value()) { | |||
| MS_LOG(ERROR) << "Get real path failed."; | |||
| return false; | |||
| @@ -154,6 +160,10 @@ bool DumpJsonParser::DumpToFile(const std::string &filename, const void *data, s | |||
| MS_LOG(ERROR) << "Open file " << realpath.value() << " fail."; | |||
| return false; | |||
| } | |||
| if (dump_format_ == 1) { | |||
| std::string npy_header = GenerateNpyHeader(shape, type); | |||
| fd << npy_header; | |||
| } | |||
| (void)fd.write(reinterpret_cast<const char *>(data), SizeToLong(len)); | |||
| fd.close(); | |||
| return true; | |||
| @@ -176,6 +186,7 @@ void DumpJsonParser::ParseCommonDumpSetting(const nlohmann::json &content) { | |||
| ParseInputOutput(*input_output); | |||
| ParseKernels(*kernels); | |||
| ParseSupportDevice(*support_device); | |||
| ParseDumpFormat(*common_dump_settings); | |||
| } | |||
| void DumpJsonParser::ParseAsyncDumpSetting(const nlohmann::json &content) { | |||
| @@ -209,19 +220,19 @@ void DumpJsonParser::ParseE2eDumpSetting(const nlohmann::json &content) { | |||
| void CheckJsonUnsignedType(const nlohmann::json &content, const std::string &key) { | |||
| if (!content.is_number_unsigned()) { | |||
| MS_LOG(EXCEPTION) << "Dump Json Parse Failed." << key << " should be unsigned int type"; | |||
| MS_LOG(EXCEPTION) << "Dump config parse failed, " << key << " should be unsigned int type"; | |||
| } | |||
| } | |||
| void CheckJsonStringType(const nlohmann::json &content, const std::string &key) { | |||
| if (!content.is_string()) { | |||
| MS_LOG(EXCEPTION) << "Dump Json Parse Failed." << key << " should be string type"; | |||
| MS_LOG(EXCEPTION) << "Dump config parse failed, " << key << " should be string type"; | |||
| } | |||
| } | |||
| void CheckJsonArrayType(const nlohmann::json &content, const std::string &key) { | |||
| if (!content.is_array()) { | |||
| MS_LOG(EXCEPTION) << "Dump Json Parse Failed." << key << " should be array type"; | |||
| MS_LOG(EXCEPTION) << "Dump config parse failed, " << key << " should be array type"; | |||
| } | |||
| } | |||
| @@ -229,7 +240,18 @@ void DumpJsonParser::ParseDumpMode(const nlohmann::json &content) { | |||
| CheckJsonUnsignedType(content, kDumpMode); | |||
| dump_mode_ = content; | |||
| if (dump_mode_ != 0 && dump_mode_ != 1) { | |||
| MS_LOG(EXCEPTION) << "Dump Json Parse Failed. dump_mode should be 0 or 1"; | |||
| MS_LOG(EXCEPTION) << "Dump config parse failed, dump_mode should be 0 or 1, but got " << dump_format_; | |||
| } | |||
| } | |||
| void DumpJsonParser::ParseDumpFormat(const nlohmann::json &content) { | |||
| auto iter = content.find(kDumpFormat); | |||
| if (iter == content.end()) { | |||
| return; | |||
| } | |||
| dump_format_ = *iter; | |||
| if (dump_format_ != 0 && dump_format_ != 1) { | |||
| MS_LOG(EXCEPTION) << "Dump config parse failed, dump_format should be 0(.bin) or 1(.npy), but got " << dump_format_; | |||
| } | |||
| } | |||
| @@ -33,7 +33,8 @@ class DumpJsonParser { | |||
| } | |||
| void Parse(); | |||
| static bool DumpToFile(const std::string &filename, const void *data, size_t len); | |||
| static bool DumpToFile(const std::string &filename, const void *data, size_t len, const ShapeVector &shape, | |||
| TypeId type); | |||
| void CopyJsonToDir(); | |||
| bool NeedDump(const std::string &op_full_name) const; | |||
| void MatchKernel(const std::string &kernel_name); | |||
| @@ -62,6 +63,7 @@ class DumpJsonParser { | |||
| DISABLE_COPY_AND_ASSIGN(DumpJsonParser) | |||
| std::mutex lock_; | |||
| static uint32_t dump_format_; | |||
| bool async_dump_enabled_{false}; | |||
| bool e2e_dump_enabled_{false}; | |||
| uint32_t dump_mode_{0}; | |||
| @@ -84,6 +86,7 @@ class DumpJsonParser { | |||
| auto CheckJsonKeyExist(const nlohmann::json &content, const std::string &key); | |||
| void ParseDumpMode(const nlohmann::json &content); | |||
| void ParseDumpFormat(const nlohmann::json &content); | |||
| void ParseDumpPath(const nlohmann::json &content); | |||
| void ParseNetName(const nlohmann::json &content); | |||
| void ParseIteration(const nlohmann::json &content); | |||
| @@ -34,7 +34,7 @@ uint32_t ConvertPhysicalDeviceId(uint32_t device_id) { | |||
| return kernel_runtime->device_id(); | |||
| } | |||
| std::string GenerateDumpPath(const uint32_t *device_id) { | |||
| std::string GenerateDumpPath(uint32_t graph_id, const uint32_t *device_id) { | |||
| auto &dump_json_parser = DumpJsonParser::GetInstance(); | |||
| std::string net_name = dump_json_parser.net_name(); | |||
| std::string iterator = std::to_string(dump_json_parser.cur_dump_iter()); | |||
| @@ -42,12 +42,9 @@ std::string GenerateDumpPath(const uint32_t *device_id) { | |||
| if (dump_path.back() != '/') { | |||
| dump_path += "/"; | |||
| } | |||
| if (device_id == nullptr) { | |||
| dump_path += (net_name + "/iteration_" + iterator); | |||
| } else { | |||
| auto physical_device = ConvertPhysicalDeviceId(*device_id); | |||
| dump_path += (net_name + "/device_" + std::to_string(physical_device) + "/iteration_" + iterator); | |||
| } | |||
| uint32_t physical_device = device_id == nullptr ? 0 : ConvertPhysicalDeviceId(*device_id); | |||
| dump_path += ("rank_" + std::to_string(physical_device) + "/" + net_name + "/graph_" + std::to_string(graph_id) + | |||
| "/iteration_" + iterator); | |||
| return dump_path; | |||
| } | |||
| @@ -27,7 +27,7 @@ namespace mindspore { | |||
| static const size_t PARAMETER_OUTPUT_INDEX = 0; | |||
| static const size_t VALUE_NODE_OUTPUT_INDEX = 0; | |||
| std::string GenerateDumpPath(const uint32_t *device_id = nullptr); | |||
| std::string GenerateDumpPath(uint32_t graph_id, const uint32_t *device_id = nullptr); | |||
| void GetFileKernelName(NotNull<std::string *> kernel_name); | |||
| @@ -223,18 +223,19 @@ void E2eDump::DumpParametersAndConst(const session::KernelGraph *graph, const st | |||
| bool E2eDump::DumpData(const session::KernelGraph *graph, uint32_t device_id, const Debugger *debugger) { | |||
| MS_EXCEPTION_IF_NULL(graph); | |||
| auto &dump_json_parser = DumpJsonParser::GetInstance(); | |||
| uint32_t graph_id = graph->graph_id(); | |||
| if (starting_graph_id == INT32_MAX) { | |||
| starting_graph_id = graph->graph_id(); | |||
| starting_graph_id = graph_id; | |||
| } | |||
| if (starting_graph_id == graph->graph_id()) { | |||
| if (starting_graph_id == graph_id) { | |||
| dump_json_parser.UpdateDumpIter(); | |||
| } | |||
| if (!dump_json_parser.GetIterDumpFlag()) { | |||
| return true; | |||
| } | |||
| MS_LOG(INFO) << "Start e2e dump. Current iteration is " << dump_json_parser.cur_dump_iter(); | |||
| MS_LOG(INFO) << "Current graph id is " << graph->graph_id(); | |||
| std::string dump_path = GenerateDumpPath(&device_id); | |||
| MS_LOG(INFO) << "Current graph id is " << graph_id; | |||
| std::string dump_path = GenerateDumpPath(graph_id, &device_id); | |||
| DumpInput(graph, dump_path, debugger); | |||
| DumpOutput(graph, dump_path, debugger); | |||
| @@ -0,0 +1,145 @@ | |||
| /** | |||
| * Copyright 2021 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 "debug/data_dump/npy_header.h" | |||
| #include <unordered_map> | |||
| #include <utility> | |||
| #include <sstream> | |||
| #include <cmath> | |||
| #include "mindspore/core/utils/log_adapter.h" | |||
| #include "mindspore/core/ir/dtype.h" | |||
| namespace mindspore { | |||
| namespace { | |||
| // npy file header start information | |||
| const char kMagicPrefix[] = "\x93NUMPY"; | |||
| // magical length include kMagicPrefix length and version length | |||
| const size_t kMagicLen = 8; | |||
| const size_t kArrayAlign = 64; | |||
| // first: header_length_type, second: encoding_type | |||
| // header_length_type: 1 represents 2 bytes; 2 and 3 represents 4 bytes | |||
| // encoding_type: 1 and 2 represents 'latin1'; 3 represents 'utf8' | |||
| using version_type = std::pair<int, int>; | |||
| // data type description | |||
| // byteorder char: '<' is little endian; '>' is big endian; '|' is ignore(no change to byte order) | |||
| // type char: 'b' represents bool; 'u' represents uint; 'i' represents int; 'f' represents float | |||
| struct DtypeDescr { | |||
| char byteorder; | |||
| char type; | |||
| size_t length; | |||
| std::string str() const; | |||
| }; | |||
| // npy file header description, includes data type description, fortran_order and array shape | |||
| // fortran_order: true represents the array data Fortran-contiguous; false represents the array data C-contiguity | |||
| struct NpyHeader { | |||
| public: | |||
| DtypeDescr dtype_descr; | |||
| bool fortran_order; | |||
| ShapeVector shape; | |||
| std::string str() const; | |||
| private: | |||
| std::string fortran_order_to_str() const; | |||
| std::string shape_to_str() const; | |||
| }; | |||
| std::string DtypeDescr::str() const { | |||
| std::ostringstream buffer; | |||
| buffer << "\'" << byteorder << type << length << "\'"; | |||
| return buffer.str(); | |||
| } | |||
| std::string NpyHeader::str() const { | |||
| const std::string first_field = "'descr': "; | |||
| const std::string second_field = "'fortran_order': "; | |||
| const std::string third_field = "'shape': "; | |||
| std::ostringstream buffer; | |||
| buffer << "{" << first_field << dtype_descr.str() << ", " << second_field << fortran_order_to_str() << ", " | |||
| << third_field << shape_to_str() << ", }"; | |||
| return buffer.str(); | |||
| } | |||
| std::string NpyHeader::fortran_order_to_str() const { return fortran_order ? "True" : "False"; } | |||
| std::string NpyHeader::shape_to_str() const { | |||
| std::ostringstream buffer; | |||
| buffer << "("; | |||
| for (const auto i : shape) { | |||
| buffer << std::to_string(i) << ","; | |||
| } | |||
| buffer << ")"; | |||
| return buffer.str(); | |||
| } | |||
| } // namespace | |||
| void int_to_byte(size_t number, char *byte, size_t length) { | |||
| for (size_t i = 0; i < length; i++) { | |||
| byte[i] = (number >> (i * 8)) & 0xff; | |||
| } | |||
| } | |||
| std::string GenerateNpyHeader(const ShapeVector &shape, TypeId type_id, bool fortran_order) { | |||
| static std::unordered_map<TypeId, DtypeDescr> type_desc_map = { | |||
| {kNumberTypeBool, DtypeDescr{'|', 'b', 1}}, {kNumberTypeInt8, DtypeDescr{'|', 'i', 1}}, | |||
| {kNumberTypeInt16, DtypeDescr{'<', 'i', 2}}, {kNumberTypeInt32, DtypeDescr{'<', 'i', 4}}, | |||
| {kNumberTypeInt64, DtypeDescr{'<', 'i', 8}}, {kNumberTypeUInt8, DtypeDescr{'|', 'u', 1}}, | |||
| {kNumberTypeUInt16, DtypeDescr{'<', 'u', 2}}, {kNumberTypeUInt32, DtypeDescr{'<', 'u', 4}}, | |||
| {kNumberTypeUInt64, DtypeDescr{'<', 'u', 8}}, {kNumberTypeFloat16, DtypeDescr{'<', 'f', 2}}, | |||
| {kNumberTypeFloat32, DtypeDescr{'<', 'f', 4}}, {kNumberTypeFloat64, DtypeDescr{'<', 'f', 8}}, | |||
| }; | |||
| auto type_desc = type_desc_map.find(type_id); | |||
| if (type_desc == type_desc_map.end()) { | |||
| MS_LOG(EXCEPTION) << "Not support dump the " << TypeIdToType(type_id)->ToString() << " data to npy file."; | |||
| } | |||
| NpyHeader npy_header{type_desc->second, fortran_order, shape}; | |||
| std::string header_str = npy_header.str(); | |||
| size_t header_len = header_str.length(); | |||
| version_type version{1, 0}; | |||
| size_t total_len = kMagicLen + 2 + header_len + 1; | |||
| if (total_len > std::pow(2, 16)) { | |||
| version = {2, 0}; | |||
| total_len = kMagicLen + 4 + header_len + 1; | |||
| } | |||
| std::ostringstream out; | |||
| out << kMagicPrefix; | |||
| out.put(version.first); | |||
| out.put(version.second); | |||
| size_t pad_len = kArrayAlign - total_len % kArrayAlign; | |||
| size_t padding_header_len = header_len + pad_len + 1; | |||
| if (version == version_type{1, 0}) { | |||
| char length_byte[2]; | |||
| int_to_byte(padding_header_len, length_byte, 2); | |||
| out.write(length_byte, 2); | |||
| } else { | |||
| char length_byte[4]; | |||
| int_to_byte(padding_header_len, length_byte, 4); | |||
| out.write(length_byte, 4); | |||
| } | |||
| std::string padding(pad_len, ' '); | |||
| out << header_str << padding << "\n"; | |||
| return out.str(); | |||
| } | |||
| } // namespace mindspore | |||
| @@ -0,0 +1,28 @@ | |||
| /** | |||
| * Copyright 2021 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. | |||
| */ | |||
| #ifndef MINDSPORE_MINDSPORE_CCSRC_DEBUG_DATA_DUMP_NPY_HEADER_H_ | |||
| #define MINDSPORE_MINDSPORE_CCSRC_DEBUG_DATA_DUMP_NPY_HEADER_H_ | |||
| #include <string> | |||
| #include "mindspore/core/utils/shape_utils.h" | |||
| #include "mindspore/core/ir/dtype/type_id.h" | |||
| namespace mindspore { | |||
| std::string GenerateNpyHeader(const ShapeVector &shape, TypeId type_id, bool fortran_order = false); | |||
| } // namespace mindspore | |||
| #endif // MINDSPORE_MINDSPORE_CCSRC_DEBUG_DATA_DUMP_NPY_HEADER_H_ | |||
| @@ -172,12 +172,11 @@ class TensorLoader { | |||
| } else { | |||
| shape = shape + "_0"; | |||
| } | |||
| std::string file_extension = ".bin"; | |||
| std::string path = ""; | |||
| if (trans_flag) { | |||
| path = filepath + '_' + shape + '_' + TypeIdToType(host_type)->ToString() + '_' + host_fmt + file_extension; | |||
| path = filepath + '_' + shape + '_' + TypeIdToType(host_type)->ToString() + '_' + host_fmt; | |||
| } else { | |||
| path = filepath + '_' + shape + '_' + TypeIdToType(device_type)->ToString() + '_' + addr_format + file_extension; | |||
| path = filepath + '_' + shape + '_' + TypeIdToType(device_type)->ToString() + '_' + addr_format; | |||
| } | |||
| MS_LOG(INFO) << "Dump path is " << path; | |||
| @@ -188,7 +187,7 @@ class TensorLoader { | |||
| std::shared_ptr<TensorData> node = iter->second; | |||
| size_t host_size = node->GetByteSize(); | |||
| return DumpJsonParser::DumpToFile(path, node->GetDataPtr(), host_size); | |||
| return DumpJsonParser::DumpToFile(path, node->GetDataPtr(), host_size, host_shape, host_type); | |||
| } | |||
| MS_LOG(INFO) << "Tensor name:" << tensor_name << " not found in tensor_list_map"; | |||
| return true; | |||
| @@ -664,10 +664,8 @@ bool AscendDeviceAddress::DumpMemToFile(const std::string &filepath, const std:: | |||
| } else { | |||
| shape = shape + "_0"; | |||
| } | |||
| std::string file_extension = ".bin"; | |||
| if (trans_flag) { | |||
| std::string path = | |||
| filepath + '_' + shape + '_' + TypeIdToType(host_type)->ToString() + '_' + host_fmt + file_extension; | |||
| std::string path = filepath + '_' + shape + '_' + TypeIdToType(host_type)->ToString() + '_' + host_fmt; | |||
| MS_LOG(INFO) << "E2E Dump path is " << path; | |||
| mindspore::tensor::TensorPtr out_tensor = std::make_shared<tensor::Tensor>(host_type, host_shape); | |||
| size_t host_size = out_tensor->data().nbytes(); | |||
| @@ -676,17 +674,16 @@ bool AscendDeviceAddress::DumpMemToFile(const std::string &filepath, const std:: | |||
| MS_LOG(ERROR) << "Copy device mem to host failed"; | |||
| return ret; | |||
| } | |||
| ret = DumpJsonParser::DumpToFile(path, out_tensor->data_c(), host_size); | |||
| ret = DumpJsonParser::DumpToFile(path, out_tensor->data_c(), host_size, host_shape, host_type); | |||
| } else { | |||
| auto host_tmp = std::vector<uint8_t>(size_); | |||
| auto ret_rt_memcpy = rtMemcpy(host_tmp.data(), size_, ptr_, size_, RT_MEMCPY_DEVICE_TO_HOST); | |||
| if (ret_rt_memcpy != RT_ERROR_NONE) { | |||
| MS_LOG(ERROR) << "SyncDeviceToHost: rtMemcpy mem size[" << size_ << "] fail, ret[" << ret_rt_memcpy << "]"; | |||
| } | |||
| std::string path = | |||
| filepath + '_' + shape + '_' + TypeIdToType(type_id_)->ToString() + '_' + format_ + file_extension; | |||
| std::string path = filepath + '_' + shape + '_' + TypeIdToType(type_id_)->ToString() + '_' + format_; | |||
| MS_LOG(INFO) << "E2E Dump path is " << path; | |||
| ret = DumpJsonParser::DumpToFile(path, host_tmp.data(), size_); | |||
| ret = DumpJsonParser::DumpToFile(path, host_tmp.data(), size_, host_shape_, type_id_); | |||
| } | |||
| return ret; | |||
| @@ -37,10 +37,9 @@ bool CPUDeviceAddress::DumpMemToFile(const std::string &filepath, const std::str | |||
| shape += '_' + std::to_string(value); | |||
| } | |||
| } | |||
| std::string file_extension = ".bin"; | |||
| std::string path = filepath + '_' + shape + '_' + TypeIdToType(type_id_)->ToString() + '_' + format_ + file_extension; | |||
| std::string path = filepath + '_' + shape + '_' + TypeIdToType(type_id_)->ToString() + '_' + format_; | |||
| MS_LOG(DEBUG) << "E2E Dump path is " << path; | |||
| ret = DumpJsonParser::DumpToFile(path, ptr_, size_); | |||
| ret = DumpJsonParser::DumpToFile(path, ptr_, size_, host_shape, host_type); | |||
| return ret; | |||
| } | |||
| @@ -380,6 +380,7 @@ bool CPUKernelRuntime::Run(session::KernelGraph *kernel_graph, bool is_task_sink | |||
| auto &dump_json_parser = DumpJsonParser::GetInstance(); | |||
| dump_json_parser.UpdateDumpIter(); | |||
| bool iter_dump_flag = dump_json_parser.GetIterDumpFlag(); | |||
| uint32_t graph_id = kernel_graph->graph_id(); | |||
| for (const auto &kernel : kernels) { | |||
| #ifdef ENABLE_PROFILE | |||
| @@ -421,7 +422,7 @@ bool CPUKernelRuntime::Run(session::KernelGraph *kernel_graph, bool is_task_sink | |||
| MS_LOG(EXCEPTION) << e.what() << "\nTrace:" << trace::DumpSourceLines(kernel); | |||
| } | |||
| if (iter_dump_flag) { | |||
| CPUE2eDump::DumpCNodeData(kernel); | |||
| CPUE2eDump::DumpCNodeData(kernel, graph_id); | |||
| } | |||
| if (profiler_inst->GetEnableFlag()) { | |||
| profiler_inst->OpDataProducerEnd(); | |||
| @@ -439,7 +440,7 @@ bool CPUKernelRuntime::Run(session::KernelGraph *kernel_graph, bool is_task_sink | |||
| #endif | |||
| } | |||
| if (iter_dump_flag) { | |||
| CPUE2eDump::DumpParametersAndConst(kernel_graph); | |||
| CPUE2eDump::DumpParametersAndConst(kernel_graph, graph_id); | |||
| } | |||
| return true; | |||
| } | |||
| @@ -0,0 +1,16 @@ | |||
| { | |||
| "common_dump_settings": { | |||
| "dump_mode": 0, | |||
| "path": "/test", | |||
| "net_name": "Net", | |||
| "iteration": 0, | |||
| "input_output": 0, | |||
| "kernels": ["Default/Conv-op12"], | |||
| "support_device": [0,1,2,3,4,5,6,7], | |||
| "dump_format": 1 | |||
| }, | |||
| "e2e_dump_settings": { | |||
| "enable": true, | |||
| "trans_flag": false | |||
| } | |||
| } | |||
| @@ -14,8 +14,10 @@ | |||
| # ============================================================================ | |||
| import os | |||
| import json | |||
| import sys | |||
| import time | |||
| import shutil | |||
| import numpy as np | |||
| import pytest | |||
| import mindspore.context as context | |||
| @@ -29,7 +31,6 @@ from mindspore.nn import Momentum | |||
| from mindspore.nn import TrainOneStepCell | |||
| from mindspore.nn import WithLossCell | |||
| context.set_context(mode=context.GRAPH_MODE, device_target="Ascend") | |||
| class Net(nn.Cell): | |||
| def __init__(self): | |||
| @@ -39,8 +40,10 @@ class Net(nn.Cell): | |||
| def construct(self, x_, y_): | |||
| return self.add(x_, y_) | |||
| x = np.random.randn(1, 3, 3, 4).astype(np.float32) | |||
| y = np.random.randn(1, 3, 3, 4).astype(np.float32) | |||
| x = np.array([[1, 2, 3], [4, 5, 6]]).astype(np.float32) | |||
| y = np.array([[7, 8, 9], [10, 11, 12]]).astype(np.float32) | |||
| def change_current_dump_json(file_name, dump_path): | |||
| with open(file_name, 'r+') as f: | |||
| @@ -50,6 +53,7 @@ def change_current_dump_json(file_name, dump_path): | |||
| with open(file_name, 'w') as f: | |||
| json.dump(data, f) | |||
| @pytest.mark.level0 | |||
| @pytest.mark.platform_arm_ascend_training | |||
| @pytest.mark.platform_x86_ascend_training | |||
| @@ -61,7 +65,7 @@ def test_async_dump(): | |||
| change_current_dump_json('async_dump.json', dump_path) | |||
| os.environ['MINDSPORE_DUMP_CONFIG'] = pwd + "/async_dump.json" | |||
| device_id = context.get_context("device_id") | |||
| dump_file_path = pwd + '/async_dump/device_{}/Net_graph_0/0/0/'.format(device_id) | |||
| dump_file_path = dump_path + '/device_{}/Net_graph_0/0/0/'.format(device_id) | |||
| if os.path.isdir(dump_path): | |||
| shutil.rmtree(dump_path) | |||
| add = Net() | |||
| @@ -69,24 +73,90 @@ def test_async_dump(): | |||
| time.sleep(5) | |||
| assert len(os.listdir(dump_file_path)) == 1 | |||
| @pytest.mark.level0 | |||
| @pytest.mark.platform_arm_ascend_training | |||
| @pytest.mark.platform_x86_ascend_training | |||
| @pytest.mark.env_onecard | |||
| def test_e2e_dump(): | |||
| context.set_context(mode=context.GRAPH_MODE, device_target="Ascend") | |||
| def run_e2e_dump_bin(): | |||
| if sys.platform != 'linux': | |||
| return | |||
| pwd = os.getcwd() | |||
| dump_path = pwd + "/e2e_dump" | |||
| change_current_dump_json('e2e_dump.json', dump_path) | |||
| os.environ['MINDSPORE_DUMP_CONFIG'] = pwd + "/e2e_dump.json" | |||
| dump_path = pwd + '/e2e_dump' | |||
| change_current_dump_json('e2e_dump_bin.json', dump_path) | |||
| os.environ['MINDSPORE_DUMP_CONFIG'] = pwd + '/e2e_dump_bin.json' | |||
| device_id = context.get_context("device_id") | |||
| dump_file_path = pwd + '/e2e_dump/Net/device_{}/iteration_1/'.format(device_id) | |||
| dump_file_path = dump_path + '/rank_{}/Net/graph_0/iteration_1/'.format(device_id) | |||
| if os.path.isdir(dump_path): | |||
| shutil.rmtree(dump_path) | |||
| add = Net() | |||
| add(Tensor(x), Tensor(y)) | |||
| time.sleep(5) | |||
| assert len(os.listdir(dump_file_path)) == 5 | |||
| if context.get_context("device_target") == "Ascend": | |||
| output_name = "Default--Add-op1_output_0_shape_2_3_Float32_DefaultFormat.bin" | |||
| else: | |||
| output_name = "Default--Add-op3_output_0_shape_2_3_Float32_DefaultFormat.bin" | |||
| output_path = dump_file_path + output_name | |||
| real_path = os.path.realpath(output_path) | |||
| output = np.fromfile(real_path, dtype=np.float32) | |||
| expect = np.array([8, 10, 12, 14, 16, 18], np.float32) | |||
| assert output.dtype == expect.dtype | |||
| assert np.array_equal(output, expect) | |||
| def run_e2e_dump_npy(): | |||
| if sys.platform != 'linux': | |||
| return | |||
| pwd = os.getcwd() | |||
| dump_path = pwd + '/e2e_dump' | |||
| change_current_dump_json('e2e_dump_npy.json', dump_path) | |||
| os.environ['MINDSPORE_DUMP_CONFIG'] = pwd + '/e2e_dump_npy.json' | |||
| device_id = context.get_context("device_id") | |||
| dump_file_path = dump_path + '/rank_{}/Net/graph_0/iteration_1/'.format(device_id) | |||
| if os.path.isdir(dump_path): | |||
| shutil.rmtree(dump_path) | |||
| add = Net() | |||
| add(Tensor(x), Tensor(y)) | |||
| if context.get_context("device_target") == "Ascend": | |||
| output_name = "Default--Add-op1_output_0_shape_2_3_Float32_DefaultFormat.npy" | |||
| else: | |||
| output_name = "Default--Add-op3_output_0_shape_2_3_Float32_DefaultFormat.npy" | |||
| output_path = dump_file_path + output_name | |||
| real_path = os.path.realpath(output_path) | |||
| output = np.load(real_path) | |||
| expect = np.array([[8, 10, 12], [14, 16, 18]], np.float32) | |||
| assert output.dtype == expect.dtype | |||
| assert np.array_equal(output, expect) | |||
| @pytest.mark.level0 | |||
| @pytest.mark.platform_arm_ascend_training | |||
| @pytest.mark.platform_x86_ascend_training | |||
| @pytest.mark.env_onecard | |||
| def test_e2e_dump_bin(): | |||
| context.set_context(mode=context.GRAPH_MODE, device_target="Ascend") | |||
| run_e2e_dump_bin() | |||
| @pytest.mark.level0 | |||
| @pytest.mark.platform_arm_ascend_training | |||
| @pytest.mark.platform_x86_ascend_training | |||
| @pytest.mark.env_onecard | |||
| def test_e2e_dump_npy(): | |||
| context.set_context(mode=context.GRAPH_MODE, device_target="Ascend") | |||
| run_e2e_dump_npy() | |||
| @pytest.mark.level0 | |||
| @pytest.mark.platform_x86_cpu | |||
| @pytest.mark.env_onecard | |||
| def test_cpu_e2e_dump_bin(): | |||
| context.set_context(mode=context.GRAPH_MODE, device_target="CPU") | |||
| run_e2e_dump_bin() | |||
| @pytest.mark.level0 | |||
| @pytest.mark.platform_x86_cpu | |||
| @pytest.mark.env_onecard | |||
| def test_cpu_e2e_dump_npy(): | |||
| context.set_context(mode=context.GRAPH_MODE, save_graphs=True, device_target="CPU") | |||
| run_e2e_dump_npy() | |||
| class ReluReduceMeanDenseRelu(Cell): | |||
| def __init__(self, kernel, bias, in_channel, num_class): | |||
| @@ -116,11 +186,13 @@ def search_path(path, keyword): | |||
| search_path(each_path, keyword) | |||
| return None | |||
| @pytest.mark.level0 | |||
| @pytest.mark.platform_arm_ascend_training | |||
| @pytest.mark.platform_x86_ascend_training | |||
| @pytest.mark.env_onecard | |||
| def test_async_dump_net_multi_layer_mode1(): | |||
| context.set_context(mode=context.GRAPH_MODE, device_target="Ascend") | |||
| test_name = "test_async_dump_net_multi_layer_mode1" | |||
| json_file = os.path.join(os.getcwd(), "{}.json".format(test_name)) | |||
| device_id = context.get_context("device_id") | |||
| @@ -131,7 +203,8 @@ def test_async_dump_net_multi_layer_mode1(): | |||
| bias = Tensor(np.ones((1000,)).astype(np.float32)) | |||
| net = ReluReduceMeanDenseRelu(weight, bias, 2048, 1000) | |||
| criterion = SoftmaxCrossEntropyWithLogits(sparse=False) | |||
| optimizer = Momentum(learning_rate=0.1, momentum=0.1, params=filter(lambda x: x.requires_grad, net.get_parameters())) | |||
| optimizer = Momentum(learning_rate=0.1, momentum=0.1, | |||
| params=filter(lambda x: x.requires_grad, net.get_parameters())) | |||
| net_with_criterion = WithLossCell(net, criterion) | |||
| train_network = TrainOneStepCell(net_with_criterion, optimizer) | |||
| train_network.set_train() | |||
| @@ -37,11 +37,11 @@ TEST_F(TestMemoryDumper, test_DumpToFileAbsPath) { | |||
| } | |||
| int ret; | |||
| char filename[] = "/tmp/dumpToFileTestFile"; | |||
| ret = DumpJsonParser::DumpToFile(filename, data, len * sizeof(int)); | |||
| const std::string filename = "/tmp/dumpToFileTestFile"; | |||
| ret = DumpJsonParser::DumpToFile(filename, data, len * sizeof(int), ShapeVector {10, 100}, kNumberTypeInt32); | |||
| ASSERT_EQ(ret, true); | |||
| int fd = open(filename, O_RDONLY); | |||
| int fd = open((filename + ".bin").c_str(), O_RDONLY); | |||
| int readBack[1000] = {0}; | |||
| int readSize = read(fd, readBack, len * sizeof(int)); | |||
| (void)close(fd); | |||
| @@ -69,11 +69,11 @@ TEST_F(TestMemoryDumper, test_DumpToFileRelativePath) { | |||
| } | |||
| int ret; | |||
| char filename[] = "../../dumpToFileTestFile"; | |||
| ret = DumpJsonParser::DumpToFile(filename, data, len * sizeof(int)); | |||
| const std::string filename = "../../dumpToFileTestFile"; | |||
| ret = DumpJsonParser::DumpToFile(filename, data, len * sizeof(int), ShapeVector{100, 10}, kNumberTypeInt32); | |||
| ASSERT_EQ(ret, true); | |||
| int fd = open(filename, O_RDONLY); | |||
| int fd = open((filename + ".bin").c_str(), O_RDONLY); | |||
| int readBack[1000] = {0}; | |||
| int readSize = read(fd, readBack, len * sizeof(int)); | |||
| (void)close(fd); | |||
| @@ -101,11 +101,11 @@ TEST_F(TestMemoryDumper, test_DumpToFileNotExistDir) { | |||
| data[i] = i % 10; | |||
| } | |||
| char filename[] = "./tmp/dumpToFileTestFile"; | |||
| int ret = DumpJsonParser::DumpToFile(filename, data, len * sizeof(int)); | |||
| const std::string filename = "./tmp/dumpToFileTestFile"; | |||
| int ret = DumpJsonParser::DumpToFile(filename, data, len * sizeof(int), ShapeVector {1,}, kNumberTypeInt32); | |||
| ASSERT_EQ(ret, true); | |||
| int fd = open(filename, O_RDONLY); | |||
| int fd = open((filename + ".bin").c_str(), O_RDONLY); | |||
| int readBack[1000] = {0}; | |||
| int readSize = read(fd, readBack, len * sizeof(int)); | |||
| (void)close(fd); | |||