Return serialization to IR v7 under conditional compilation (#1820)
This commit is contained in:
@@ -91,6 +91,8 @@ ie_option (ENABLE_OPENCV "enables OpenCV" ON)
|
||||
|
||||
ie_option (ENABLE_PYTHON "enables ie python bridge build" OFF)
|
||||
|
||||
ie_option (ENABLE_V7_SERIALIZE "enables serialization to IR v7" OFF)
|
||||
|
||||
ie_option (ENABLE_JAVA "enables ie java bridge build" OFF)
|
||||
|
||||
ie_dependent_option(ENABLE_CPPLINT "Enable cpplint checks during the build" ON "UNIX;NOT ANDROID" OFF)
|
||||
|
||||
@@ -76,6 +76,11 @@ if(ENABLE_SSE42)
|
||||
add_definitions(-DHAVE_SSE=1)
|
||||
endif()
|
||||
|
||||
if(ENABLE_V7_SERIALIZE)
|
||||
set_source_files_properties("${CMAKE_CURRENT_SOURCE_DIR}/src/cnn_network_ngraph_impl.cpp"
|
||||
PROPERTIES COMPILE_DEFINITIONS ENABLE_V7_SERIALIZE)
|
||||
endif()
|
||||
|
||||
addVersionDefines(ie_version.cpp CI_BUILD_NUMBER)
|
||||
|
||||
set (PUBLIC_HEADERS_DIR "${IE_MAIN_SOURCE_DIR}/include")
|
||||
|
||||
@@ -394,8 +394,9 @@ CNNNetworkNGraphImpl::reshape(const std::map<std::string, std::vector<size_t>>&
|
||||
|
||||
StatusCode CNNNetworkNGraphImpl::serialize(const std::string& xmlPath, const std::string& binPath,
|
||||
ResponseDesc* resp) const noexcept {
|
||||
if (!cnnNetwork) {
|
||||
// TODO: once Serialization::Serialize supports true IR v10
|
||||
auto network = cnnNetwork;
|
||||
if (!network) {
|
||||
// TODO: once Serialization::SerializeV10 supports true IR v10
|
||||
// remove this conversion and WA for execution graph
|
||||
try {
|
||||
bool isExecutionGraph = true;
|
||||
@@ -407,9 +408,13 @@ StatusCode CNNNetworkNGraphImpl::serialize(const std::string& xmlPath, const std
|
||||
}
|
||||
}
|
||||
if (isExecutionGraph) {
|
||||
Serialization::Serialize(xmlPath, binPath, (InferenceEngine::ICNNNetwork&)*this);
|
||||
Serialization::SerializeV10(xmlPath, binPath, (InferenceEngine::ICNNNetwork&)*this);
|
||||
return OK;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_V7_SERIALIZE
|
||||
network = std::make_shared<details::CNNNetworkImpl>(*this);
|
||||
#endif
|
||||
} catch (const InferenceEngineException& e) {
|
||||
return DescriptionBuffer(GENERAL_ERROR, resp) << e.what();
|
||||
} catch (const std::exception& e) {
|
||||
@@ -419,7 +424,11 @@ StatusCode CNNNetworkNGraphImpl::serialize(const std::string& xmlPath, const std
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef ENABLE_V7_SERIALIZE
|
||||
return network->serialize(xmlPath, binPath, resp);
|
||||
#else
|
||||
return DescriptionBuffer(NOT_IMPLEMENTED, resp) << "The serialize for IR v10 is not implemented";
|
||||
#endif
|
||||
}
|
||||
|
||||
StatusCode CNNNetworkNGraphImpl::setBatchSize(size_t size, ResponseDesc* responseDesc) noexcept {
|
||||
|
||||
@@ -135,8 +135,8 @@ void FillXmlDocWithExecutionNGraph(const InferenceEngine::ICNNNetwork& network,
|
||||
|
||||
} // namespace
|
||||
|
||||
void Serialize(const std::string& xmlPath, const std::string& binPath,
|
||||
const InferenceEngine::ICNNNetwork& network) {
|
||||
void SerializeV10(const std::string& xmlPath, const std::string& binPath,
|
||||
const InferenceEngine::ICNNNetwork& network) {
|
||||
if (auto function = network.getFunction()) {
|
||||
// A flag for serializing executable graph information (not complete IR)
|
||||
bool execGraphInfoSerialization = true;
|
||||
|
||||
@@ -12,13 +12,13 @@ namespace InferenceEngine {
|
||||
namespace Serialization {
|
||||
|
||||
/**
|
||||
* @brief Serializes a network into IE IR v10 XML file and binary weights file
|
||||
* @param xmlPath Path to XML file
|
||||
* @param binPath Path to BIN file
|
||||
* @param network network to be serialized
|
||||
*/
|
||||
INFERENCE_ENGINE_API_CPP(void) Serialize(const std::string& xmlPath, const std::string& binPath,
|
||||
const InferenceEngine::ICNNNetwork& network);
|
||||
* @brief Serializes a network into IE IR v10 XML file and binary weights file
|
||||
* @param xmlPath Path to XML file
|
||||
* @param binPath Path to BIN file
|
||||
* @param network network to be serialized
|
||||
*/
|
||||
void SerializeV10(const std::string& xmlPath, const std::string& binPath,
|
||||
const InferenceEngine::ICNNNetwork& network);
|
||||
|
||||
} // namespace Serialization
|
||||
} // namespace InferenceEngine
|
||||
|
||||
@@ -19,6 +19,11 @@ set(PUBLIC_HEADERS_DIR "${CMAKE_CURRENT_SOURCE_DIR}/include")
|
||||
source_group("src" FILES ${LIBRARY_SRC})
|
||||
source_group("include" FILES ${PUBLIC_HEADERS})
|
||||
|
||||
if(ENABLE_V7_SERIALIZE)
|
||||
set_source_files_properties("${CMAKE_CURRENT_SOURCE_DIR}/src/cnn_network_impl.cpp"
|
||||
PROPERTIES COMPILE_DEFINITIONS ENABLE_V7_SERIALIZE)
|
||||
endif()
|
||||
|
||||
# Create object library
|
||||
|
||||
add_library(${TARGET_NAME}_obj OBJECT
|
||||
|
||||
@@ -395,26 +395,10 @@ StatusCode CNNNetworkImpl::AddExtension(const InferenceEngine::IShapeInferExtens
|
||||
StatusCode CNNNetworkImpl::serialize(const std::string& xmlPath, const std::string& binPath, ResponseDesc* resp) const
|
||||
noexcept {
|
||||
try {
|
||||
// A flag for serializing executable graph information (not complete IR)
|
||||
bool execGraphInfoSerialization = false;
|
||||
|
||||
const std::vector<CNNLayerPtr> ordered = Serialization::TopologicalSort((InferenceEngine::ICNNNetwork&)*this);
|
||||
// If first layer has perfCounter parameter set then it's executable graph info serialization.
|
||||
// All other layers must also have this parameter set.
|
||||
if (ordered[0]->params.find(ExecGraphInfoSerialization::PERF_COUNTER) != ordered[0]->params.end()) {
|
||||
execGraphInfoSerialization = true;
|
||||
for (const auto& layer : ordered) {
|
||||
if (layer->params.find(ExecGraphInfoSerialization::PERF_COUNTER) == layer->params.end()) {
|
||||
THROW_IE_EXCEPTION << "Each node must have " << ExecGraphInfoSerialization::PERF_COUNTER
|
||||
<< " parameter set in case of executable graph info serialization";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (execGraphInfoSerialization) {
|
||||
Serialization::Serialize(xmlPath, (InferenceEngine::ICNNNetwork&)*this);
|
||||
return OK;
|
||||
}
|
||||
#ifdef ENABLE_V7_SERIALIZE
|
||||
Serialization::Serialize(xmlPath, binPath, (InferenceEngine::ICNNNetwork&)*this);
|
||||
return OK;
|
||||
#endif
|
||||
} catch (const InferenceEngineException& e) {
|
||||
return DescriptionBuffer(GENERAL_ERROR, resp) << e.what();
|
||||
} catch (const std::exception& e) {
|
||||
|
||||
@@ -11,12 +11,291 @@
|
||||
#include <unordered_set>
|
||||
#include <sstream>
|
||||
|
||||
#include "caseless.hpp"
|
||||
#include "legacy/ie_layers.h"
|
||||
#include "xml_parse_utils.h"
|
||||
#include "exec_graph_info.hpp"
|
||||
#include "network_serializer_v7.hpp"
|
||||
|
||||
namespace InferenceEngine {
|
||||
namespace Serialization {
|
||||
|
||||
namespace {
|
||||
template <typename T>
|
||||
std::string arrayToIRProperty(const T& property) {
|
||||
std::string sProperty;
|
||||
for (size_t i = 0; i < property.size(); i++) {
|
||||
sProperty = sProperty + std::to_string(property[i]) + std::string((i != property.size() - 1) ? "," : "");
|
||||
}
|
||||
return sProperty;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
std::string arrayRevertToIRProperty(const T& property) {
|
||||
std::string sProperty;
|
||||
for (size_t i = 0; i < property.size(); i++) {
|
||||
sProperty = sProperty + std::to_string(property[property.size() - i - 1]) +
|
||||
std::string((i != property.size() - 1) ? "," : "");
|
||||
}
|
||||
return sProperty;
|
||||
}
|
||||
|
||||
std::size_t updatePreProcInfo(const InferenceEngine::ICNNNetwork& network, pugi::xml_node& netXml,
|
||||
const std::size_t weightsDataOffset) {
|
||||
InputsDataMap inputInfo;
|
||||
network.getInputsInfo(inputInfo);
|
||||
|
||||
// Assume that you preprocess only one input
|
||||
auto dataOffset = weightsDataOffset;
|
||||
for (auto ii : inputInfo) {
|
||||
const PreProcessInfo& pp = ii.second->getPreProcess();
|
||||
size_t nInChannels = pp.getNumberOfChannels();
|
||||
if (nInChannels) {
|
||||
pugi::xml_node preproc = netXml.append_child("pre-process");
|
||||
|
||||
preproc.append_attribute("reference-layer-name").set_value(ii.first.c_str());
|
||||
preproc.append_attribute("mean-precision").set_value(Precision(Precision::FP32).name());
|
||||
|
||||
for (size_t ch = 0; ch < nInChannels; ch++) {
|
||||
const PreProcessChannel::Ptr& preProcessChannel = pp[ch];
|
||||
auto channel = preproc.append_child("channel");
|
||||
channel.append_attribute("id").set_value(ch);
|
||||
|
||||
auto mean = channel.append_child("mean");
|
||||
|
||||
if (!preProcessChannel->meanData) {
|
||||
mean.append_attribute("value").set_value(preProcessChannel->meanValue);
|
||||
} else {
|
||||
auto size = preProcessChannel->meanData->byteSize();
|
||||
mean.append_attribute("size").set_value(size);
|
||||
mean.append_attribute("offset").set_value(dataOffset);
|
||||
dataOffset += size;
|
||||
}
|
||||
|
||||
if (1.f != preProcessChannel->stdScale) {
|
||||
channel.append_child("scale").append_attribute("value").set_value(
|
||||
CNNLayer::ie_serialize_float(preProcessChannel->stdScale).c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return dataOffset;
|
||||
}
|
||||
|
||||
void UpdateStdLayerParams(const CNNLayer::Ptr& layer) {
|
||||
auto layerPtr = layer.get();
|
||||
auto& params = layer->params;
|
||||
using ::InferenceEngine::details::CaselessEq;
|
||||
if (CaselessEq<std::string>()(layer->type, "power")) {
|
||||
auto* lr = dynamic_cast<PowerLayer*>(layerPtr);
|
||||
if (lr == nullptr) {
|
||||
THROW_IE_EXCEPTION << "Layer " << layerPtr->name << " is not instance of PowerLayer class";
|
||||
}
|
||||
params["scale"] = CNNLayer::ie_serialize_float(lr->scale);
|
||||
params["shift"] = CNNLayer::ie_serialize_float(lr->offset);
|
||||
params["power"] = CNNLayer::ie_serialize_float(lr->power);
|
||||
} else if (CaselessEq<std::string>()(layer->type, "convolution") ||
|
||||
CaselessEq<std::string>()(layer->type, "deconvolution")) {
|
||||
auto* lr = dynamic_cast<ConvolutionLayer*>(layerPtr);
|
||||
if (lr == nullptr) {
|
||||
THROW_IE_EXCEPTION << "Layer " << layerPtr->name << " is not instance of ConvolutionLayer class";
|
||||
}
|
||||
params["kernel"] = arrayRevertToIRProperty(lr->_kernel);
|
||||
params["pads_begin"] = arrayRevertToIRProperty(lr->_padding);
|
||||
params["pads_end"] = arrayRevertToIRProperty(lr->_pads_end);
|
||||
params["strides"] = arrayRevertToIRProperty(lr->_stride);
|
||||
params["dilations"] = arrayRevertToIRProperty(lr->_dilation);
|
||||
params["output"] = std::to_string(lr->_out_depth);
|
||||
params["group"] = std::to_string(lr->_group);
|
||||
} else if (CaselessEq<std::string>()(layer->type, "deformable_convolution")) {
|
||||
auto* lr = dynamic_cast<DeformableConvolutionLayer*>(layerPtr);
|
||||
if (lr == nullptr) {
|
||||
THROW_IE_EXCEPTION << "Layer " << layerPtr->name << " is not instance of DeformableConvolutionLayer class";
|
||||
}
|
||||
params["kernel"] = arrayRevertToIRProperty(lr->_kernel);
|
||||
params["pads_begin"] = arrayRevertToIRProperty(lr->_padding);
|
||||
params["pads_end"] = arrayRevertToIRProperty(lr->_pads_end);
|
||||
params["strides"] = arrayRevertToIRProperty(lr->_stride);
|
||||
params["dilations"] = arrayRevertToIRProperty(lr->_dilation);
|
||||
params["output"] = std::to_string(lr->_out_depth);
|
||||
params["group"] = std::to_string(lr->_group);
|
||||
params["deformable_group"] = std::to_string(lr->_deformable_group);
|
||||
} else if (CaselessEq<std::string>()(layer->type, "relu")) {
|
||||
auto* lr = dynamic_cast<ReLULayer*>(layerPtr);
|
||||
if (lr == nullptr) {
|
||||
THROW_IE_EXCEPTION << "Layer " << layerPtr->name << " is not instance of ReLULayer class";
|
||||
}
|
||||
if (lr->negative_slope != 0.0f) {
|
||||
params["negative_slope"] = CNNLayer::ie_serialize_float(lr->negative_slope);
|
||||
}
|
||||
} else if (CaselessEq<std::string>()(layer->type, "norm") || CaselessEq<std::string>()(layer->type, "lrn")) {
|
||||
auto* lr = dynamic_cast<NormLayer*>(layerPtr);
|
||||
if (lr == nullptr) {
|
||||
THROW_IE_EXCEPTION << "Layer " << layerPtr->name << " is not instance of NormLayer class";
|
||||
}
|
||||
params["alpha"] = CNNLayer::ie_serialize_float(lr->_alpha);
|
||||
params["beta"] = CNNLayer::ie_serialize_float(lr->_beta);
|
||||
params["local-size"] = std::to_string(lr->_size);
|
||||
params["region"] = lr->_isAcrossMaps ? "across" : "same";
|
||||
} else if (CaselessEq<std::string>()(layer->type, "pooling")) {
|
||||
auto* lr = dynamic_cast<PoolingLayer*>(layerPtr);
|
||||
if (lr == nullptr) {
|
||||
THROW_IE_EXCEPTION << "Layer " << layerPtr->name << " is not instance of PoolingLayer class";
|
||||
}
|
||||
params["kernel"] = arrayRevertToIRProperty(lr->_kernel);
|
||||
params["pads_begin"] = arrayRevertToIRProperty(lr->_padding);
|
||||
params["pads_end"] = arrayRevertToIRProperty(lr->_pads_end);
|
||||
params["strides"] = arrayRevertToIRProperty(lr->_stride);
|
||||
|
||||
switch (lr->_type) {
|
||||
case PoolingLayer::MAX:
|
||||
params["pool-method"] = "max";
|
||||
break;
|
||||
case PoolingLayer::AVG:
|
||||
params["pool-method"] = "avg";
|
||||
break;
|
||||
|
||||
default:
|
||||
THROW_IE_EXCEPTION << "Found unsupported pooling method: " << lr->_type;
|
||||
}
|
||||
} else if (CaselessEq<std::string>()(layer->type, "split")) {
|
||||
auto* lr = dynamic_cast<SplitLayer*>(layerPtr);
|
||||
if (lr == nullptr) {
|
||||
THROW_IE_EXCEPTION << "Layer " << layerPtr->name << " is not instance of SplitLayer class";
|
||||
}
|
||||
params["axis"] = std::to_string(lr->_axis);
|
||||
} else if (CaselessEq<std::string>()(layer->type, "concat")) {
|
||||
auto* lr = dynamic_cast<ConcatLayer*>(layerPtr);
|
||||
if (lr == nullptr) {
|
||||
THROW_IE_EXCEPTION << "Layer " << layerPtr->name << " is not instance of ConcatLayer class";
|
||||
}
|
||||
params["axis"] = std::to_string(lr->_axis);
|
||||
} else if (CaselessEq<std::string>()(layer->type, "FullyConnected") ||
|
||||
CaselessEq<std::string>()(layer->type, "InnerProduct")) {
|
||||
auto* lr = dynamic_cast<FullyConnectedLayer*>(layerPtr);
|
||||
if (lr == nullptr) {
|
||||
THROW_IE_EXCEPTION << "Layer " << layerPtr->name << " is not instance of FullyConnectedLayer class";
|
||||
}
|
||||
params["out-size"] = std::to_string(lr->_out_num);
|
||||
} else if (CaselessEq<std::string>()(layer->type, "softmax")) {
|
||||
auto* lr = dynamic_cast<SoftMaxLayer*>(layerPtr);
|
||||
if (lr == nullptr) {
|
||||
THROW_IE_EXCEPTION << "Layer " << layerPtr->name << " is not instance of SoftMaxLayer class";
|
||||
}
|
||||
params["axis"] = std::to_string(lr->axis);
|
||||
} else if (CaselessEq<std::string>()(layer->type, "reshape")) {
|
||||
// need to add here support of flatten layer if it is created from API
|
||||
auto* lr = dynamic_cast<ReshapeLayer*>(layerPtr);
|
||||
if (lr == nullptr) {
|
||||
THROW_IE_EXCEPTION << "Layer " << layerPtr->name << " is not instance of ReshapeLayer class";
|
||||
}
|
||||
params["dim"] = arrayToIRProperty(lr->shape);
|
||||
} else if (CaselessEq<std::string>()(layer->type, "Eltwise")) {
|
||||
auto* lr = dynamic_cast<EltwiseLayer*>(layerPtr);
|
||||
if (lr == nullptr) {
|
||||
THROW_IE_EXCEPTION << "Layer " << layerPtr->name << " is not instance of EltwiseLayer class";
|
||||
}
|
||||
|
||||
std::string op;
|
||||
|
||||
switch (lr->_operation) {
|
||||
case EltwiseLayer::Sum:
|
||||
op = "sum";
|
||||
break;
|
||||
case EltwiseLayer::Prod:
|
||||
op = "prod";
|
||||
break;
|
||||
case EltwiseLayer::Max:
|
||||
op = "max";
|
||||
break;
|
||||
case EltwiseLayer::Sub:
|
||||
op = "sub";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
params["operation"] = op;
|
||||
} else if (CaselessEq<std::string>()(layer->type, "scaleshift")) {
|
||||
auto* lr = dynamic_cast<ScaleShiftLayer*>(layerPtr);
|
||||
if (lr == nullptr) {
|
||||
THROW_IE_EXCEPTION << "Layer " << layerPtr->name << " is not instance of ScaleShiftLayer class";
|
||||
}
|
||||
params["broadcast"] = std::to_string(lr->_broadcast);
|
||||
} else if (CaselessEq<std::string>()(layer->type, "crop")) {
|
||||
auto* lr = dynamic_cast<CropLayer*>(layerPtr);
|
||||
if (lr == nullptr) {
|
||||
THROW_IE_EXCEPTION << "Layer " << layerPtr->name << " is not instance of CropLayer class";
|
||||
}
|
||||
params["axis"] = arrayToIRProperty(lr->axis);
|
||||
params["offset"] = arrayToIRProperty(lr->offset);
|
||||
params["dim"] = arrayToIRProperty(lr->dim);
|
||||
} else if (CaselessEq<std::string>()(layer->type, "tile")) {
|
||||
auto* lr = dynamic_cast<TileLayer*>(layerPtr);
|
||||
if (lr == nullptr) {
|
||||
THROW_IE_EXCEPTION << "Layer " << layerPtr->name << " is not instance of TileLayer class";
|
||||
}
|
||||
params["axis"] = std::to_string(lr->axis);
|
||||
params["tiles"] = std::to_string(lr->tiles);
|
||||
} else if (CaselessEq<std::string>()(layer->type, "prelu")) {
|
||||
auto* lr = dynamic_cast<PReLULayer*>(layerPtr);
|
||||
if (lr == nullptr) {
|
||||
THROW_IE_EXCEPTION << "Layer " << layerPtr->name << " is not instance of PReLULayer class";
|
||||
}
|
||||
params["channel_shared"] = std::to_string(lr->_channel_shared);
|
||||
} else if (CaselessEq<std::string>()(layer->type, "clamp")) {
|
||||
auto* lr = dynamic_cast<ClampLayer*>(layerPtr);
|
||||
if (lr == nullptr) {
|
||||
THROW_IE_EXCEPTION << "Layer " << layerPtr->name << " is not instance of ClampLayer class";
|
||||
}
|
||||
params["min"] = CNNLayer::ie_serialize_float(lr->min_value);
|
||||
params["max"] = CNNLayer::ie_serialize_float(lr->max_value);
|
||||
} else if (CaselessEq<std::string>()(layer->type, "BatchNormalization")) {
|
||||
auto* lr = dynamic_cast<BatchNormalizationLayer*>(layerPtr);
|
||||
if (lr == nullptr) {
|
||||
THROW_IE_EXCEPTION << "Layer " << layerPtr->name << " is not instance of BatchNormalizationLayer class";
|
||||
}
|
||||
params["epsilon"] = CNNLayer::ie_serialize_float(lr->epsilon);
|
||||
} else if (CaselessEq<std::string>()(layer->type, "grn")) {
|
||||
auto* lr = dynamic_cast<GRNLayer*>(layerPtr);
|
||||
if (lr == nullptr) {
|
||||
THROW_IE_EXCEPTION << "Layer " << layerPtr->name << " is not instance of GRNLayer class";
|
||||
}
|
||||
params["bias"] = CNNLayer::ie_serialize_float(lr->bias);
|
||||
} else if (CaselessEq<std::string>()(layer->type, "mvn")) {
|
||||
auto* lr = dynamic_cast<MVNLayer*>(layerPtr);
|
||||
if (lr == nullptr) {
|
||||
THROW_IE_EXCEPTION << "Layer " << layerPtr->name << " is not instance of MVNLayer class";
|
||||
}
|
||||
params["across_channels"] = std::to_string(lr->across_channels);
|
||||
params["normalize_variance"] = std::to_string(lr->normalize);
|
||||
} else if (CaselessEq<std::string>()(layer->type, "LSTMCell")) {
|
||||
auto* lr = dynamic_cast<RNNCellBase*>(layerPtr);
|
||||
if (lr == nullptr) {
|
||||
THROW_IE_EXCEPTION << "Layer " << layerPtr->name << " is not instance of LSTMCell class";
|
||||
}
|
||||
params["hidden_size"] = std::to_string(lr->hidden_size);
|
||||
} else if (CaselessEq<std::string>()(layer->type, "rnn") ||
|
||||
CaselessEq<std::string>()(layer->type, "TensorIterator")) {
|
||||
THROW_IE_EXCEPTION << "Not covered layers for writing to IR";
|
||||
}
|
||||
|
||||
if (layer->params.find("quantization_level") != layer->params.end()) {
|
||||
params["quantization_level"] = layer->params["quantization_level"];
|
||||
}
|
||||
|
||||
// update of weightable layers
|
||||
auto* pwlayer = dynamic_cast<WeightableLayer*>(layerPtr);
|
||||
if (pwlayer) {
|
||||
if (pwlayer->_weights) {
|
||||
pwlayer->blobs["weights"] = pwlayer->_weights;
|
||||
}
|
||||
if (pwlayer->_biases) {
|
||||
pwlayer->blobs["biases"] = pwlayer->_biases;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<CNNLayerPtr> TopologicalSort(const ICNNNetwork& network) {
|
||||
std::vector<CNNLayerPtr> ordered;
|
||||
std::unordered_set<std::string> used;
|
||||
@@ -98,11 +377,18 @@ std::vector<CNNLayerPtr> TopologicalSort(const ICNNNetwork& network) {
|
||||
return ordered;
|
||||
}
|
||||
|
||||
std::size_t FillXmlDoc(const InferenceEngine::ICNNNetwork& network, pugi::xml_document& doc) {
|
||||
std::size_t FillXmlDoc(const InferenceEngine::ICNNNetwork& network, pugi::xml_document& doc,
|
||||
const bool execGraphInfoSerialization, const bool dumpWeights) {
|
||||
const std::vector<CNNLayerPtr> ordered = TopologicalSort(network);
|
||||
pugi::xml_node netXml = doc.append_child("net");
|
||||
netXml.append_attribute("name").set_value(network.getName().c_str());
|
||||
|
||||
// no need to print this information for executable graph information serialization because it is not IR.
|
||||
if (!execGraphInfoSerialization) {
|
||||
netXml.append_attribute("version").set_value("6");
|
||||
netXml.append_attribute("batch").set_value(network.getBatchSize());
|
||||
}
|
||||
|
||||
pugi::xml_node layers = netXml.append_child("layers");
|
||||
|
||||
std::map<CNNLayer::Ptr, size_t> matching;
|
||||
@@ -122,6 +408,10 @@ std::size_t FillXmlDoc(const InferenceEngine::ICNNNetwork& network, pugi::xml_do
|
||||
layer.append_attribute("precision").set_value(precision.name());
|
||||
layer.append_attribute("id").set_value(i);
|
||||
|
||||
if (!execGraphInfoSerialization) {
|
||||
UpdateStdLayerParams(node);
|
||||
}
|
||||
|
||||
const auto& params = node->params;
|
||||
if (!params.empty()) {
|
||||
pugi::xml_node data = layer.append_child(dataName.c_str());
|
||||
@@ -158,6 +448,19 @@ std::size_t FillXmlDoc(const InferenceEngine::ICNNNetwork& network, pugi::xml_do
|
||||
}
|
||||
}
|
||||
}
|
||||
if (dumpWeights && !node->blobs.empty()) {
|
||||
auto blobsNode = layer.append_child("blobs");
|
||||
for (const auto& dataIt : node->blobs) {
|
||||
if (!dataIt.second) continue;
|
||||
size_t dataSize = dataIt.second->byteSize();
|
||||
pugi::xml_node data = blobsNode.append_child(dataIt.first.c_str());
|
||||
data.append_attribute("offset").set_value(dataOffset);
|
||||
data.append_attribute("size").set_value(dataSize);
|
||||
data.append_attribute("precision").set_value(dataIt.second->getTensorDesc().getPrecision().name());
|
||||
|
||||
dataOffset += dataSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pugi::xml_node edges = netXml.append_child("edges");
|
||||
@@ -197,13 +500,89 @@ std::size_t FillXmlDoc(const InferenceEngine::ICNNNetwork& network, pugi::xml_do
|
||||
return dataOffset;
|
||||
}
|
||||
|
||||
void Serialize(const std::string& xmlPath, const InferenceEngine::ICNNNetwork& network) {
|
||||
void SerializeBlobs(std::ostream& stream, const InferenceEngine::ICNNNetwork& network) {
|
||||
const std::vector<CNNLayerPtr> ordered = TopologicalSort(network);
|
||||
for (auto&& node : ordered) {
|
||||
if (!node->blobs.empty()) {
|
||||
for (const auto& dataIt : node->blobs) {
|
||||
if (!dataIt.second) continue;
|
||||
const char* dataPtr = dataIt.second->buffer().as<char*>();
|
||||
size_t dataSize = dataIt.second->byteSize();
|
||||
stream.write(dataPtr, dataSize);
|
||||
if (!stream.good()) {
|
||||
THROW_IE_EXCEPTION << "Error during writing blob weights";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
InputsDataMap inputInfo;
|
||||
network.getInputsInfo(inputInfo);
|
||||
|
||||
for (auto ii : inputInfo) {
|
||||
const PreProcessInfo& pp = ii.second->getPreProcess();
|
||||
size_t nInChannels = pp.getNumberOfChannels();
|
||||
if (nInChannels) {
|
||||
for (size_t ch = 0; ch < nInChannels; ch++) {
|
||||
const PreProcessChannel::Ptr& preProcessChannel = pp[ch];
|
||||
if (preProcessChannel->meanData) {
|
||||
const char* dataPtr = preProcessChannel->meanData->buffer().as<char*>();
|
||||
size_t dataSize = preProcessChannel->meanData->byteSize();
|
||||
stream.write(dataPtr, dataSize);
|
||||
if (!stream.good()) {
|
||||
THROW_IE_EXCEPTION << "Error during writing mean data";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void Serialize(const std::string& xmlPath, const std::string& binPath,
|
||||
const InferenceEngine::ICNNNetwork& network) {
|
||||
// A flag for serializing executable graph information (not complete IR)
|
||||
bool execGraphInfoSerialization = false;
|
||||
pugi::xml_document doc;
|
||||
FillXmlDoc(network, doc);
|
||||
|
||||
const std::vector<CNNLayerPtr> ordered = TopologicalSort(network);
|
||||
// If first layer has perfCounter parameter set then it's executable graph info serialization.
|
||||
// All other layers must also have this parameter set.
|
||||
if (ordered[0]->params.find(ExecGraphInfoSerialization::PERF_COUNTER) != ordered[0]->params.end()) {
|
||||
execGraphInfoSerialization = true;
|
||||
for (const auto& layer : ordered) {
|
||||
if (layer->params.find(ExecGraphInfoSerialization::PERF_COUNTER) == layer->params.end()) {
|
||||
THROW_IE_EXCEPTION << "Each node must have " << ExecGraphInfoSerialization::PERF_COUNTER
|
||||
<< " parameter set in case of executable graph info serialization";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool dumpWeights = !execGraphInfoSerialization & !binPath.empty();
|
||||
FillXmlDoc(network, doc, execGraphInfoSerialization, dumpWeights);
|
||||
|
||||
if (!doc.save_file(xmlPath.c_str())) {
|
||||
THROW_IE_EXCEPTION << "file '" << xmlPath << "' was not serialized";
|
||||
}
|
||||
|
||||
if (dumpWeights) {
|
||||
std::ofstream ofsBin;
|
||||
ofsBin.open(binPath, std::ofstream::out | std::ofstream::binary);
|
||||
if (!ofsBin.is_open()) {
|
||||
THROW_IE_EXCEPTION << "File '" << binPath << "' is not opened as out file stream";
|
||||
}
|
||||
try {
|
||||
SerializeBlobs(ofsBin, network);
|
||||
} catch (std::exception& e) {
|
||||
ofsBin.close();
|
||||
throw e;
|
||||
}
|
||||
ofsBin.close();
|
||||
if (!ofsBin.good()) {
|
||||
THROW_IE_EXCEPTION << "Error during '" << binPath << "' closing";
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace Serialization
|
||||
} // namespace InferenceEngine
|
||||
} // namespace InferenceEngine
|
||||
@@ -14,18 +14,13 @@ namespace InferenceEngine {
|
||||
namespace Serialization {
|
||||
|
||||
/**
|
||||
* @brief Serialize execution network into IE IR-like XML file
|
||||
* @param xmlPath Path to XML file
|
||||
* @param network network to be serialized
|
||||
*/
|
||||
INFERENCE_ENGINE_API_CPP(void) Serialize(const std::string& xmlPath, const InferenceEngine::ICNNNetwork& network);
|
||||
|
||||
/**
|
||||
* @brief Returns set of topologically sorted layers
|
||||
* @param network network to be sorted
|
||||
* @return `std::vector` of topologically sorted CNN layers
|
||||
*/
|
||||
INFERENCE_ENGINE_API_CPP(std::vector<CNNLayerPtr>) TopologicalSort(const InferenceEngine::ICNNNetwork& network);
|
||||
* @brief Serialize network into IE IR XML file and binary weights file
|
||||
* @param xmlPath Path to XML file
|
||||
* @param binPath Path to BIN file
|
||||
* @param network network to be serialized
|
||||
*/
|
||||
void Serialize(const std::string& xmlPath, const std::string& binPath,
|
||||
const InferenceEngine::ICNNNetwork& network);
|
||||
|
||||
} // namespace Serialization
|
||||
} // namespace InferenceEngine
|
||||
} // namespace InferenceEngine
|
||||
@@ -60,9 +60,6 @@ TEST_P(ExecGraphInputsFusingBinConv, CheckNumInputsInBinConvFusingWithConv) {
|
||||
// try to convert to old representation and check that conversion passed well
|
||||
std::shared_ptr<InferenceEngine::details::CNNNetworkImpl> convertedExecGraph;
|
||||
ASSERT_NO_THROW(convertedExecGraph = std::make_shared<InferenceEngine::details::CNNNetworkImpl>(execGraphInfo));
|
||||
// serialization for IR-v7 like execution graph is still supported for compatibility
|
||||
ASSERT_NO_THROW(convertedExecGraph->serialize("exeNetwork.xml", "exeNetwork.bin", nullptr));
|
||||
ASSERT_EQ(0, std::remove("exeNetwork.xml"));
|
||||
|
||||
for (const auto & op : function->get_ops()) {
|
||||
const auto & rtInfo = op->get_rt_info();
|
||||
|
||||
Reference in New Issue
Block a user