diff --git a/inference-engine/samples/blob_dumper/CMakeLists.txt b/inference-engine/samples/blob_dumper/CMakeLists.txt new file mode 100644 index 00000000000000..f3bd68e078a436 --- /dev/null +++ b/inference-engine/samples/blob_dumper/CMakeLists.txt @@ -0,0 +1,24 @@ +# Copyright (C) 2018-2020 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 +# + +file (GLOB SRC ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp) + +file (GLOB HDR ${CMAKE_CURRENT_SOURCE_DIR}/*.hpp) + +include_directories($) + +set(TARGET_NAME "blob_dumper") + +ie_add_sample(NAME blob_dumper + SOURCES ${SRC} + HEADERS ${HDR} + DEPENDENCIES format_reader inference_engine inference_engine_legacy + OPENCV_DEPENDENCIES imgcodecs) + +if ( CMAKE_COMPILER_IS_GNUCC ) + target_compile_options(blob_dumper PRIVATE "-Wno-strict-aliasing") +endif() + +include_directories(SYSTEM ${IE_MAIN_SOURCE_DIR}/src/legacy_api/include/legacy) +target_include_directories(${TARGET_NAME} PUBLIC ${PUBLIC_HEADERS_DIR} $) diff --git a/inference-engine/samples/blob_dumper/README.md b/inference-engine/samples/blob_dumper/README.md new file mode 100644 index 00000000000000..163961b956f93c --- /dev/null +++ b/inference-engine/samples/blob_dumper/README.md @@ -0,0 +1 @@ +# BlobDumper C++ Tool \ No newline at end of file diff --git a/inference-engine/samples/blob_dumper/blob_dump.cpp b/inference-engine/samples/blob_dumper/blob_dump.cpp new file mode 100644 index 00000000000000..0490f7e5556a11 --- /dev/null +++ b/inference-engine/samples/blob_dumper/blob_dump.cpp @@ -0,0 +1,391 @@ +// Copyright (C) 2018-2020 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "blob_dump.h" +//#include "blob_factory.hpp" +//#include "mkldnn_memory.h" + +// It's so bad to include by relative path :-( +//#include "../../thirdparty/mkl-dnn/src/common/memory_desc_wrapper.hpp" + +#include +#include + +using namespace InferenceEngine; + +// IEB file format routine +static unsigned char IEB_MAGIC[4] = {'I', 'E', 'B', '0'}; +static unsigned char NO_SCALES = 0xFF; + +struct IEB_HEADER { + unsigned char magic[4]; + unsigned char ver[2]; + + unsigned char precision; // 0-8 + unsigned char ndims; + unsigned int dims[7]; // max is 7-D blob + + unsigned char scaling_axis; // FF - no scaling + unsigned char reserved[3]; + + unsigned long data_offset; + unsigned long data_size; + unsigned long scaling_data_offset; + unsigned long scaling_data_size; +}; + +static IEB_HEADER prepare_header(const TensorDesc& desc) { + IEB_HEADER header = {}; + + header.magic[0] = IEB_MAGIC[0]; + header.magic[1] = IEB_MAGIC[1]; + header.magic[2] = IEB_MAGIC[2]; + header.magic[3] = IEB_MAGIC[3]; + + // IEB file format version 0.1 + header.ver[0] = 0; + header.ver[1] = 1; + + header.precision = desc.getPrecision(); + + if (desc.getDims().size() > 7) + THROW_IE_EXCEPTION << "Dumper support max 7D blobs"; + + header.ndims = desc.getDims().size(); + for (int i = 0; i < header.ndims; i++) + header.dims[i] = desc.getDims()[i]; + + header.scaling_axis = NO_SCALES; + + return header; +} + +//static TensorDesc parse_header(IEB_HEADER &header) { +// if (header.magic[0] != IEB_MAGIC[0] || +// header.magic[1] != IEB_MAGIC[1] || +// header.magic[2] != IEB_MAGIC[2] || +// header.magic[3] != IEB_MAGIC[3]) +// THROW_IE_EXCEPTION << "Dumper cannot parse file. Wrong format."; +// +// if (header.ver[0] != 0 || +// header.ver[1] != 1) +// THROW_IE_EXCEPTION << "Dumper cannot parse file. Unsupported IEB format version."; +// +// Precision prc = Precision(static_cast(header.precision)); +// SizeVector dims(header.ndims); +// for (int i = 0; i < header.ndims; i++) +// dims[i] = header.dims[i]; +// +// return TensorDesc {prc, dims, TensorDesc::getLayoutByDims(dims) }; +//} + + +bool is_plain(const Blob::Ptr &blob) { + bool res = true; + + auto orig_strides = blob->getTensorDesc().getBlockingDesc().getStrides(); + auto orig_order = blob->getTensorDesc().getBlockingDesc().getOrder(); + auto dims = blob->getTensorDesc().getDims(); + + for (size_t stride = 1, i = dims.size() - 1; i >= 0; --i) { + if (stride != orig_strides[i] || i != orig_order[i]) res = false; + stride *= dims[i]; + } + + return res; +} + +//static Blob::Ptr prepare_plain_data(Blob::Ptr blob) { +// // check if it already plain +// if (is_plain(blob)) return blob; +// +// Blob::Ptr pln_blob = make_plain_blob(blob->getTensorDesc().getPrecision(), blob->getTensorDesc().getDims()); +// pln_blob->allocate(); +// +// // Copy to plain +// MKLDNNMemoryDesc mdesc(blob->getTensorDesc()); +// mkldnn::memory::desc desc = mdesc; +// mkldnn::impl::memory_desc_wrapper blob_wrp(desc.data); +// +// size_t data_size = blob->size(); +// +// // TODO: make it with blob_copy utility +// switch (blob->getTensorDesc().getPrecision()) { +// case Precision::FP32: +// case Precision::I32: { +// auto *pln_blob_ptr = pln_blob->buffer().as(); +// auto *blob_ptr = blob->buffer().as(); +// for (size_t i = 0; i < data_size; i++) +// pln_blob_ptr[i] = blob_ptr[blob_wrp.off_l(i)]; +// break; +// } +// case Precision::I16: +// case Precision::U16: +// case Precision::BF16: { +// auto *pln_blob_ptr = pln_blob->buffer().as(); +// auto *blob_ptr = blob->buffer().as(); +// for (size_t i = 0; i < data_size; i++) pln_blob_ptr[i] = blob_ptr[blob_wrp.off_l(i)]; +// break; +// } +// case Precision::I8: +// case Precision::U8: { +// auto *pln_blob_ptr = pln_blob->buffer().as(); +// auto *blob_ptr = blob->buffer().as(); +// for (size_t i = 0; i < data_size; i++) +// pln_blob_ptr[i] = blob_ptr[blob_wrp.off_l(i)]; +// break; +// } +// default: +// THROW_IE_EXCEPTION << "Dumper. Unsupported precision"; +// } +// +// return pln_blob; +//} + +void BlobDumper::dump(std::ostream &stream) { + if (!_blob) + THROW_IE_EXCEPTION << "Dumper cannot dump empty Blob"; + + if (_blob->buffer().as() == nullptr) + THROW_IE_EXCEPTION << "Dumper cannot dump. Blob is not allocated."; + + IEB_HEADER header = prepare_header(_blob->getTensorDesc()); + // Blob::Ptr pln_blob = prepare_plain_data(_blob); + Blob::Ptr pln_blob = _blob; + + header.data_offset = sizeof(header); + header.data_size = pln_blob->byteSize(); + header.scaling_data_offset = 0; + header.scaling_data_size = 0; + + if (_scales) { + header.scaling_axis = 1; + header.scaling_data_offset = header.data_offset + header.data_size; + header.scaling_data_size = _scales->byteSize(); + } + + stream.write(reinterpret_cast(&header), sizeof(header)); + stream.write(pln_blob->buffer().as(), pln_blob->byteSize()); + + if (_scales) { + stream.write(_scales->buffer().as(), _scales->byteSize()); + } +} + +void BlobDumper::dumpAsTxt(std::ostream &stream) { + if (!_blob) + return; + + if (_blob->buffer().as() == nullptr) + THROW_IE_EXCEPTION << "Dumper cannot dump. Blob is not allocated."; + + SizeVector dims = _blob->getTensorDesc().getDims(); + + // Header like "U8 4D shape: 2 3 224 224 () + stream << _blob->getTensorDesc().getPrecision().name() << " " + << dims.size() << "D " + << "shape: "; + for (size_t d : dims) stream << d << " "; + stream << "(" << _blob->size() << ")" << std::endl; + + // Dump data + //MKLDNNMemoryDesc mdesc(_blob->getTensorDesc()); + //mkldnn::memory::desc desc = mdesc; + //mkldnn::impl::memory_desc_wrapper blob_wrp(desc.data); + + size_t data_size = _blob->size(); + const auto precision = _blob->getTensorDesc().getPrecision(); + switch (precision) { + case Precision::FP32: { + auto *blob_ptr = _blob->buffer().as(); + for (size_t i = 0; i < data_size; i++) { + const auto value = blob_ptr[i]; + stream << std::setprecision(9) << (abs(value) <= 1e-10 ? 0.f : value) << std::endl; + } + break; + } + case Precision::BF16: + { + auto *blob_ptr = _blob->buffer().as(); + for (size_t i = 0; i < data_size; i++) { + int i16n = blob_ptr[i]; + i16n = i16n << 16; + float fn = *(reinterpret_cast(&i16n)); + stream << std::setprecision(9) << fn << std::endl; + } + break; + } + case Precision::I32: { + auto *blob_ptr = _blob->buffer().as(); + for (size_t i = 0; i < data_size; i++) + stream << blob_ptr[i] << std::endl; + break; + } + case Precision::I16: { + auto *blob_ptr = _blob->buffer().as(); + for (size_t i = 0; i < data_size; i++) + stream << static_cast(blob_ptr[i]) << std::endl; + break; + } + case Precision::I64: { + auto *blob_ptr = _blob->buffer().as(); + for (size_t i = 0; i < data_size; i++) + stream << static_cast(blob_ptr[i]) << std::endl; + break; + } + case Precision::U16: { + auto *blob_ptr = _blob->buffer().as(); + for (size_t i = 0; i < data_size; i++) + stream << static_cast(blob_ptr[i]) << std::endl; + break; + } + case Precision::I8: { + auto *blob_ptr = _blob->buffer().as(); + for (size_t i = 0; i < data_size; i++) + stream << static_cast(blob_ptr[i]) << std::endl; + break; + } + case Precision::U8: { + auto *blob_ptr = _blob->buffer().as(); + for (size_t i = 0; i < data_size; i++) + stream << static_cast(blob_ptr[i]) << std::endl; + break; + } + default: + THROW_IE_EXCEPTION << "Dumper. Unsupported precision"; + } +} + +//BlobDumper BlobDumper::read(std::istream &stream) { +// //IEB_HEADER header; +// stream.read(reinterpret_cast(&header), sizeof(header)); +// +// //TensorDesc desc = parse_header(header); +// //Blob::Ptr blob = make_blob_with_precision(desc); +// //blob->allocate(); +// +// //stream.seekg(header.data_offset, stream.beg); +// //stream.read(blob->buffer().as(), header.data_size); +// +// //BlobDumper res(blob); +// +// //// Parse scales fields. +// //if (header.scaling_axis != NO_SCALES) { +// // if (header.scaling_axis != 1) +// // THROW_IE_EXCEPTION << "Dumper support scaling only for channel dims."; +// +// // size_t scl_size = header.scaling_data_size / sizeof(float); +// // auto scl = make_blob_with_precision({Precision::FP32, {scl_size}, C}); +// // scl->allocate(); +// +// // stream.seekg(header.scaling_data_offset, stream.beg); +// // stream.read(scl->buffer().as(), header.scaling_data_size); +// +// // res._scales = scl; +// //} +// //return res; +// +// return nullptr; +//} + +//BlobDumper BlobDumper::read(const std::string &file_path) { +// std::ifstream file; +// file.open(file_path); +// if (!file.is_open()) +// THROW_IE_EXCEPTION << "Dumper cannot open file " << file_path; +// +// auto res = read(file); +// file.close(); +// return res; +//} + +void BlobDumper::dump(const std::string &dump_path) { + std::ofstream dump_file; + dump_file.open(dump_path); + if (!dump_file.is_open()) + THROW_IE_EXCEPTION << "Dumper cannot create dump file: " << dump_path; + + dump(dump_file); + dump_file.close(); +} + +void BlobDumper::dumpAsTxt(const std::string dump_path) { + std::ofstream dump_file; + dump_file.open(dump_path); + if (!dump_file.is_open()) + THROW_IE_EXCEPTION << "Dumper cannot create dump file: " << dump_path; + + dumpAsTxt(dump_file); + dump_file.close(); +} + +Blob::Ptr BlobDumper::get() { + return _blob; +} + +template +static void plain_copy(const Blob::Ptr &from, const Blob::Ptr &scls, Blob::Ptr &to) { + auto dims = from->getTensorDesc().getDims(); + + size_t data_size = from->size(); + size_t outer_size = dims[0]; + size_t c_size = dims.size() > 1 ? dims[1] : 1; + size_t inner_size = dims.size() == 4 ? dims[2]*dims[3] : + dims.size() == 3 ? dims[2] : 1; + + auto to_data = to->buffer().as(); + auto from_data = from->buffer().as(); + + if (scls) { + auto scls_data = scls->buffer().as(); + + for (size_t o=0; o < outer_size; o++) + for (size_t c=0; c < c_size; c++) + for (size_t i=0; i < inner_size; i++) + *to_data++ = static_cast(*from_data++) * scls_data[c]; + } else { + for (size_t i=0; i < data_size; i++) + *to_data++ = static_cast(*from_data++); + } +} + +Blob::Ptr BlobDumper::getRealValue() { + //if (_blob->getTensorDesc().getPrecision() == Precision::FP32 && !_scales) + // return _blob; + + //auto res = make_plain_blob(Precision::FP32, _blob->getTensorDesc().getDims()); + //res->allocate(); + + //switch (_blob->getTensorDesc().getPrecision()) { + // case Precision::U8: plain_copy(_blob, _scales, res); break; + // case Precision::FP32: plain_copy(_blob, _scales, res); break; + // case Precision::I8: plain_copy(_blob, _scales, res); break; + // default: THROW_IE_EXCEPTION << "Unsupported precesion for getRealValue method."; + //} + + //return res; + return nullptr; +} + + +BlobDumper& BlobDumper::withScales(InferenceEngine::Blob::Ptr scales) { + if ( _blob->getTensorDesc().getDims().size() < 2 || + scales->getTensorDesc().getDims().size() != 1 || + scales->getTensorDesc().getDims()[0] != _blob->getTensorDesc().getDims()[1] || + scales->getTensorDesc().getPrecision() != Precision::FP32) + THROW_IE_EXCEPTION << "Dumper cannot use passed scales. Blob has incompatible shape."; + + _scales = scales; + return *this; +} + +BlobDumper& BlobDumper::withoutScales() { + _scales.reset(); + return *this; +} + + +const InferenceEngine::Blob::Ptr& BlobDumper::getScales() const { + return _scales; +} diff --git a/inference-engine/samples/blob_dumper/blob_dump.h b/inference-engine/samples/blob_dumper/blob_dump.h new file mode 100644 index 00000000000000..290ca463d3f94d --- /dev/null +++ b/inference-engine/samples/blob_dumper/blob_dump.h @@ -0,0 +1,46 @@ +// Copyright (C) 2018-2020 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +#include "ie_blob.h" + +#include + +/** + * Utility class to dump blob contant in plain format. + * Every layout information will be lost. + * + * In case of low precision blob it allow to store + * with using scaling factors per channel. + * NB! Channel is a second dimension for all blob types. + */ +class BlobDumper { + InferenceEngine::Blob::Ptr _blob; + InferenceEngine::Blob::Ptr _scales; + +public: + BlobDumper() = default; + BlobDumper(const BlobDumper&) = default; + BlobDumper& operator = (BlobDumper&&) = default; + + explicit BlobDumper(const InferenceEngine::Blob::Ptr blob):_blob(blob) {} + + //static BlobDumper read(const std::string &file_path); + //static BlobDumper read(std::istream &stream); + + void dump(const std::string &file_path); + void dump(std::ostream &stream); + + void dumpAsTxt(const std::string file_path); + void dumpAsTxt(std::ostream &stream); + + BlobDumper& withScales(InferenceEngine::Blob::Ptr scales); + BlobDumper& withoutScales(); + + const InferenceEngine::Blob::Ptr& getScales() const; + + InferenceEngine::Blob::Ptr get(); + InferenceEngine::Blob::Ptr getRealValue(); +}; diff --git a/inference-engine/samples/blob_dumper/blob_dumper.hpp b/inference-engine/samples/blob_dumper/blob_dumper.hpp new file mode 100644 index 00000000000000..8523cd25a26559 --- /dev/null +++ b/inference-engine/samples/blob_dumper/blob_dumper.hpp @@ -0,0 +1,55 @@ +// Copyright (C) 2018-2020 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +#include +#include +#include +#include + +/// @brief message for help argument +static const char help_message[] = "Print a usage message"; + +/// @brief message for model argument +static const char model_message[] = "Required. Path to an .xml/.onnx/.prototxt file with a trained model or to a .blob files with a trained compiled model."; + +/// @brief message for dump directory argument +static const char dump_dir_message[] = "Required. Directory to store dumps."; + +/// @brief message for reduce argument +static const char reduce_message[] = "Optional. Reduce blobs."; + +/// @brief Define flag for showing help message
+DEFINE_bool(h, false, help_message); + +/// @brief Declare flag for showing help message
+DECLARE_bool(help); + +/// @brief Define parameter for set model file
+/// It is a required parameter +DEFINE_string(model, "", model_message); + +/// @brief Define parameter for set model file
+/// It is a required parameter +DEFINE_string(dump_dir, "", dump_dir_message); + +/// @brief Define parameter for set model file
+/// It is a optional parameter +DEFINE_bool(reduce, false, reduce_message); + + +/** +* @brief This function show a help message +*/ +static void showUsage() { + std::cout << std::endl; + std::cout << "benchmark_app [OPTION]" << std::endl; + std::cout << "Options:" << std::endl; + std::cout << std::endl; + std::cout << " -h, --help " << help_message << std::endl; + std::cout << " -model \"\" " << model_message << std::endl; + std::cout << " -dump_dir \"\" " << dump_dir_message << std::endl; + std::cout << " -reduce " << reduce_message << std::endl; +} diff --git a/inference-engine/samples/blob_dumper/main.cpp b/inference-engine/samples/blob_dumper/main.cpp new file mode 100644 index 00000000000000..a1b109f56a3e2c --- /dev/null +++ b/inference-engine/samples/blob_dumper/main.cpp @@ -0,0 +1,319 @@ +// Copyright (C) 2018-2020 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "blob_factory.hpp" +#include "blob_dumper.hpp" +#include "blob_dump.h" + +using namespace InferenceEngine; + +bool ParseAndCheckCommandLine(int argc, char *argv[]) { + // ---------------------------Parsing and validating input arguments-------------------------------------- + slog::info << "Parsing input parameters" << slog::endl; + gflags::ParseCommandLineNonHelpFlags(&argc, &argv, true); + if (FLAGS_help || FLAGS_h) { + showUsage(); + showAvailableDevices(); + return false; + } + + if (FLAGS_model.empty()) { + throw std::logic_error("Model is required but not set. Please set -model option."); + } + + if (FLAGS_dump_dir.empty()) { + throw std::logic_error("Dump directory is required but not set. Please set -dump_dir option."); + } + + return true; +} + +template +bool isScalarLike(const Blob::Ptr& blob) { + const auto* buffer = blob->buffer().as(); + const size_t blobSize = blob->size(); + for (size_t i = 1; i < blobSize; i++) { + if (buffer[i] != buffer[0]) { + return false; + } + } + return true; +} + +bool isScalarLike(const Blob::Ptr& blob) { + size_t data_size = blob->size(); + if (data_size == 1ul) { + return true; + } + + const auto precision = blob->getTensorDesc().getPrecision(); + switch (precision) { + case Precision::FP32: { + if (!isScalarLike(blob)) { + return false; + } + break; + } + case Precision::I32: { + if (!isScalarLike(blob)) { + return false; + } + break; + } + case Precision::BF16: + case Precision::I16: { + if (!isScalarLike(blob)) { + return false; + } + break; + } + case Precision::I64: { + if (!isScalarLike(blob)) { + return false; + } + break; + } + case Precision::U16: { + if (!isScalarLike(blob)) { + return false; + } + break; + } + case Precision::I8: { + if (!isScalarLike(blob)) { + return false; + } + break; + } + case Precision::U8: { + if (!isScalarLike(blob)) { + return false; + } + break; + } + default: + THROW_IE_EXCEPTION << "Dumper. Unsupported precision"; + } + + return true; +} + +template +void setFirstValue(const Blob::Ptr& originalBlob, Blob::Ptr& resultBlob) { + const auto *originalBuffer = originalBlob->buffer().as(); + auto *resultBuffer = resultBlob->buffer().as(); + resultBuffer[0] = originalBuffer[0]; +} + +void setValue(const Blob::Ptr& originalBlob, Blob::Ptr& resultBlob) { + const auto precision = resultBlob->getTensorDesc().getPrecision(); + switch (precision) { + case Precision::FP32: { + setFirstValue(originalBlob, resultBlob); + break; + } + case Precision::I32: { + setFirstValue(originalBlob, resultBlob); + break; + } + case Precision::BF16: + case Precision::I16: { + setFirstValue(originalBlob, resultBlob); + break; + } + case Precision::I64: { + setFirstValue(originalBlob, resultBlob); + break; + } + case Precision::U16: { + setFirstValue(originalBlob, resultBlob); + break; + } + case Precision::I8: { + setFirstValue(originalBlob, resultBlob); + break; + } + case Precision::U8: { + setFirstValue(originalBlob, resultBlob); + break; + } + default: + THROW_IE_EXCEPTION << "Dumper. Unsupported precision"; + } +} + +Blob::Ptr reduce(const Blob::Ptr& originalBlob) { + if (!isScalarLike(originalBlob)) { + return originalBlob; + } + + const auto desc = originalBlob->getTensorDesc(); + Blob::Ptr newBlob = make_plain_blob(desc.getPrecision(), {}); + newBlob->allocate(); + setValue(originalBlob, newBlob); + return newBlob; +} + +/** +* @brief The entry point of the blob_dumper application +*/ +int main(int argc, char *argv[]) { + try { + if (!ParseAndCheckCommandLine(argc, argv)) { + return 0; + } + + Core ie; + CNNNetwork cnnNetwork = ie.ReadNetwork(FLAGS_model); + + IE_SUPPRESS_DEPRECATED_START + std::vector layers = InferenceEngine::details::CNNNetSortTopologically(cnnNetwork); + IE_SUPPRESS_DEPRECATED_END + + auto getInsDataIndex = [](const CNNLayerPtr& child, const CNNLayerPtr& parent) -> int { + for (size_t i = 0; i < child->insData.size(); ++i) { + const CNNLayerPtr layer = getCreatorLayer(child->insData[i].lock()).lock(); + if (layer.get() == parent.get()) { + return i; + } + } + + THROW_IE_EXCEPTION << "not found"; + }; + + for (auto layer : layers) { + if (!layer->blobs.empty()) { + for (auto blobIt : layer->blobs) { + CNNLayerPtr childLayerToBuildName; + std::string nodeName = layer->name; + if (layer->type == "Const") { + //if (layer->name == "564/add__Const_564/fq_input_0_ScaleShift_564/add_") { + // std::cout << ""; + //} + const std::map& inputTo = getInputTo(layer->outData[0]); + childLayerToBuildName = (inputTo.size() == 1ul) ? inputTo.begin()->second : nullptr; + if (childLayerToBuildName == nullptr) { + CNNLayerPtr fakeQuantize = nullptr; + for (const auto it : inputTo) { + const auto childLayer = it.second; + if (childLayer->type != "FakeQuantize") { + fakeQuantize = nullptr; + break; + } + + if (fakeQuantize == nullptr) { + fakeQuantize = childLayer; + } + else if (childLayer.get() == fakeQuantize.get()) { + break; + } + } + + childLayerToBuildName = inputTo.begin()->second; + } + + if (childLayerToBuildName == nullptr) { + nodeName = layer->name; + } + else { + int index = getInsDataIndex(childLayerToBuildName, layer); + if (childLayerToBuildName->type == "Eltwise") { + const std::map& childInputTo = getInputTo(childLayerToBuildName->outData[0]); + const auto conv = (childInputTo.size() == 1ul) ? childInputTo.begin()->second : nullptr; + if (conv->type == "Convolution") { + nodeName = conv->name + "_eltwise"; + } + else { + nodeName = childLayerToBuildName->name + "_const_input_" + std::to_string(index); + } + } + else { + nodeName = childLayerToBuildName->name + "_const_input_" + std::to_string(index); + } + } + } + else if (layer->type == "ScaleShift") { + const std::map& inputTo = getInputTo(layer->outData[0]); + childLayerToBuildName = (inputTo.size() == 1ul) ? inputTo.begin()->second : nullptr; + if (childLayerToBuildName != nullptr) { + int index = getInsDataIndex(childLayerToBuildName, layer); + nodeName = childLayerToBuildName->name + "_scaleshift_input_" + std::to_string(index); + } + } + + std::stringstream ss; + for (size_t i = 0; i < layer->outData.size(); ++i) { + ss << "_" << layer->outData[i]->getPrecision(); + } + nodeName += ss.str(); + + // std::cout << layer->name << ": " << layer->type << std::endl; + + std::replace(nodeName.begin(), nodeName.end(), '\\', '_'); + std::replace(nodeName.begin(), nodeName.end(), '/', '_'); + std::replace(nodeName.begin(), nodeName.end(), ' ', '_'); + std::replace(nodeName.begin(), nodeName.end(), ':', '-'); + + if ((layer->type == "FakeQuantize") || ((childLayerToBuildName != nullptr) && (childLayerToBuildName->type == "FakeQuantize"))) { + const size_t index = nodeName.find("_original", 0); + if (index != -1) { + nodeName.replace(index, std::string("_original").size(), ""); + } + } + + const std::string blobName = blobIt.first; + const std::string dumpFilePath = FLAGS_dump_dir + "\\" + nodeName + "_" + blobName + ".ieb"; + + Blob::Ptr blob = blobIt.second; + if (FLAGS_reduce) { + blob = reduce(blob); + } + + BlobDumper dumper(blob); + dumper.dumpAsTxt(dumpFilePath); + } + } else { + auto nodeName = layer->name; + std::replace(nodeName.begin(), nodeName.end(), '\\', '_'); + std::replace(nodeName.begin(), nodeName.end(), '/', '_'); + std::replace(nodeName.begin(), nodeName.end(), ' ', '_'); + std::replace(nodeName.begin(), nodeName.end(), ':', '-'); + + std::stringstream ss; + for (size_t i = 0; i < layer->outData.size(); ++i) { + ss << "_" << layer->outData[i]->getPrecision(); + } + nodeName += ss.str(); + + const std::string dumpFilePath = FLAGS_dump_dir + "\\" + nodeName + ".ieb"; + + BlobDumper dumper(nullptr); + dumper.dumpAsTxt(dumpFilePath); + } + } + } catch (const std::exception& ex) { + slog::err << ex.what() << slog::endl; + return 3; + } + + return 0; +}