#include <transformations/convert_opset3_to_opset2/convert_opset3_to_opset2.hpp>
#include <transformations/convert_opset2_to_opset1/convert_opset2_to_opset1.hpp>
#include <transformations/convert_opset1_to_legacy/convert_opset1_to_legacy.hpp>
+#include <transformations/common_optimizations/common_optimizations.hpp>
#include <vpu/ngraph/transformations/merge_subsequent_dsr_operations.hpp>
#include <vpu/ngraph/operations/dynamic_shape_resolver.hpp>
return runCommonPasses(network);
}
+bool FrontEnd::isLayerSupported(const std::string& type) {
+ return parsers.count(type) != 0;
+}
+
+ie::ICNNNetwork::Ptr FrontEnd::convertNetwork(ie::ICNNNetwork& network) {
+ std::shared_ptr<ie::ICNNNetwork> convertedNetwork;
+ // disable transformations for some cases
+ const auto transformationsPredicate = [](const std::shared_ptr<const ngraph::Node> &node) -> bool {
+ const bool casesWithDynamicOrStaticUsage = std::dynamic_pointer_cast<const ngraph::opset3::Gelu>(node) ||
+ std::dynamic_pointer_cast<const ngraph::opset4::SoftPlus>(node);
+
+ const bool casesWithOnlyDynamicUsage = (std::dynamic_pointer_cast<const ngraph::opset3::MatMul>(node) ||
+ std::dynamic_pointer_cast<const ngraph::opset3::StridedSlice>(node)) &&
+ std::dynamic_pointer_cast<const ngraph::vpu::op::DynamicShapeResolver>(node->input_value(0).get_node_shared_ptr());
+
+ return casesWithDynamicOrStaticUsage || casesWithOnlyDynamicUsage;
+ };
+
+ auto nGraphFunc = network.getFunction();
+ // Disable shape inference (WA for generic operations)
+ ngraph::op::GenericIE::DisableReshape noReshape(nGraphFunc);
+
+ ngraph::pass::Manager manager;
+
+ manager.register_pass<ngraph::pass::CommonOptimizations>();
+ manager.register_pass<ngraph::pass::ConvertOpSet3ToOpSet2>();
+ manager.register_pass<ngraph::pass::ConvertOpSet2ToOpSet1>();
+ manager.register_pass<ngraph::pass::ConvertOpSet1ToLegacy>();
+ manager.set_callback(transformationsPredicate);
+ manager.run_passes(nGraphFunc);
+
+ ngraph::pass::Manager ti_manager;
+ ti_manager.register_pass<ngraph::pass::ApplyTransformationsToTIBody>(manager);
+ ti_manager.run_passes(nGraphFunc);
+
+ vpu::MergeSubsequentDSROperations().run_on_function(nGraphFunc);
+
+ convertedNetwork = InferenceEngine::details::convertFunctionToICNNNetwork(nGraphFunc, network);
+ return convertedNetwork;
+}
+
std::set<std::string> FrontEnd::checkSupportedLayers(ie::ICNNNetwork& network) {
VPU_PROFILE(checkSupportedLayers);
{ defaultOnUnsupportedLayerCallback(model, layer, inputs, outputs, extraMessage); });
}
-
ModelPtr FrontEnd::runCommonPasses(ie::ICNNNetwork& network, const UnsupportedLayerCallback& unsupportedLayer, const SupportedLayerCallback& supportedLayer) {
// NGraph -> CNN conversion may be called in 2 different moments: at
// the beginning if conversion was forced by configuration or after detect
env.log->trace("Update IE Network");
VPU_LOGGER_SECTION(env.log);
- auto convertNetwork = [&convertedNetwork, &originalOrConvertNetwork]() {
- // disable transformations for some cases
- const auto transformationsPredicate = [](const std::shared_ptr<const ngraph::Node> &node) -> bool {
- const bool casesWithDynamicOrStaticUsage = std::dynamic_pointer_cast<const ngraph::opset3::Gelu>(node) ||
- std::dynamic_pointer_cast<const ngraph::opset4::SoftPlus>(node);
-
- const bool casesWithOnlyDynamicUsage = (std::dynamic_pointer_cast<const ngraph::opset3::MatMul>(node) ||
- std::dynamic_pointer_cast<const ngraph::opset3::StridedSlice>(node)) &&
- std::dynamic_pointer_cast<const ngraph::vpu::op::DynamicShapeResolver>(node->input_value(0).get_node_shared_ptr());
-
- return casesWithDynamicOrStaticUsage || casesWithOnlyDynamicUsage;
- };
-
- auto nGraphFunc = originalOrConvertNetwork->getFunction();
- // Disable shape inference (WA for generic operations)
- ngraph::op::GenericIE::DisableReshape noReshape(nGraphFunc);
-
- ngraph::pass::Manager manager;
- manager.register_pass<ngraph::pass::ConvertOpSet3ToOpSet2>();
- manager.register_pass<ngraph::pass::ConvertOpSet2ToOpSet1>();
- manager.register_pass<ngraph::pass::ConvertOpSet1ToLegacy>();
- manager.set_callback(transformationsPredicate);
- manager.run_passes(nGraphFunc);
-
- ngraph::pass::Manager ti_manager;
- ti_manager.register_pass<ngraph::pass::ApplyTransformationsToTIBody>(manager);
- ti_manager.run_passes(nGraphFunc);
-
- vpu::MergeSubsequentDSROperations().run_on_function(nGraphFunc);
-
- convertedNetwork = InferenceEngine::details::convertFunctionToICNNNetwork(nGraphFunc, *originalOrConvertNetwork);
- originalOrConvertNetwork = convertedNetwork.get();
- };
-
if (originalOrConvertNetwork->getFunction() && env.config.forceDeprecatedCnnConversion) {
- convertNetwork();
+ convertedNetwork = convertNetwork(*originalOrConvertNetwork);
+ originalOrConvertNetwork = convertedNetwork.get();
}
detectNetworkBatch(*originalOrConvertNetwork, model);
if (originalOrConvertNetwork->getFunction()) {
- convertNetwork();
+ convertedNetwork = convertNetwork(*originalOrConvertNetwork);
+ originalOrConvertNetwork = convertedNetwork.get();
}
ie::NetPass::ConvertPrecision(*originalOrConvertNetwork, ie::Precision::I64, ie::Precision::I32);
#include <vpu/vpu_plugin_config.hpp>
#include <vpu/parsed_config.hpp>
+#include <vpu/frontend/frontend.hpp>
#include <vpu/utils/profiling.hpp>
#include <vpu/utils/error.hpp>
#include <transformations/tensor_iterator_transformations/apply_transformations_to_ti_body.hpp>
#include <transformations/common_optimizations/common_optimizations.hpp>
+#include <transformations/rt_info/fused_names_attribute.hpp>
#include <vpu/ngraph/transformations/convert_nms_4_to_nms_dynamic.hpp>
+#include <ngraph/op/util/op_types.hpp>
+#include <ngraph/opsets/opset3.hpp>
#include "vpu/ngraph/transformations/dynamic_to_static_shape.hpp"
#include "vpu/ngraph/transformations/eliminate_shapeof_after_dsr.hpp"
using namespace InferenceEngine::VPUConfigParams;
using namespace vpu::MyriadPlugin;
+
ExecutableNetworkInternal::Ptr Engine::LoadExeNetworkImpl(
const ICNNNetwork& network,
const std::map<std::string, std::string>& config) {
VPU_THROW_UNLESS(!(std::find(deviceIDs.begin(), deviceIDs.end(), deviceName) == deviceIDs.end()), "Myriad device: {} not found.", deviceName);
}
- if (network.getFunction()) {
- THROW_IE_EXCEPTION << NOT_IMPLEMENTED_str << " ngraph::Function is not supported natively";
- }
+ if (auto function = network.getFunction()) {
+ std::unordered_set<std::string> originalOps;
+ for (auto& node : function->get_ops()) {
+ originalOps.emplace(node->get_friendly_name());
+ }
- const auto log = std::make_shared<Logger>(
- "GraphCompiler",
- parsedConfigCopy.logLevel(),
- defaultOutput(parsedConfigCopy.compilerLogFilePath()));
+ auto clonedNetwork = cloneNetwork(network);
+ auto convertedNetwork = vpu::FrontEnd::convertNetwork(*clonedNetwork);
+
+ std::unordered_set<std::string> supported;
+ std::unordered_set<std::string> unsupported;
+
+ std::unordered_set<std::string> splitNames;
+ std::unordered_set<std::string> concatNames;
+
+ ngraph::NodeVector splits;
+ ngraph::NodeVector concats;
+
+ const auto isLayerSupported = [this, &splitNames, &concatNames, &concats, &splits](CNNNetworkIterator& layer) -> bool {
+ auto node = (*layer)->getNode();
+ if (std::dynamic_pointer_cast<const ::ngraph::opset3::Split>(node) != nullptr) {
+ splitNames.emplace(node->get_friendly_name());
+ splits.push_back(node);
+ return false;
+ } else if (std::dynamic_pointer_cast<const ::ngraph::opset3::Concat>(node) != nullptr) {
+ concatNames.emplace(node->get_friendly_name());
+ concats.push_back(node);
+ return false;
+ } else {
+ auto stageBuilder = std::make_shared<StageBuilder>();
+ auto frontEnd = std::make_shared<FrontEnd>(stageBuilder, GetCore());
+ return frontEnd->isLayerSupported((*layer)->type);
+ }
+ };
+
+ for (CNNNetworkIterator itLayer{convertedNetwork.get()};
+ itLayer != CNNNetworkIterator();
+ itLayer++) {
+ const auto fusedNode = (*itLayer)->getNode();
+ if (fusedNode == nullptr) {
+ continue;
+ }
+
+ for (auto& fusedLayerName : ngraph::getFusedNamesVector(fusedNode)) {
+ if (contains(originalOps, fusedLayerName)) {
+ if (isLayerSupported(itLayer)) {
+ supported.emplace(fusedLayerName);
+ } else {
+ unsupported.emplace(fusedLayerName);
+ }
+ }
+ }
+ }
- const auto layerNames = getSupportedLayers(
- network,
- static_cast<Platform>(parsedConfigCopy.platform()),
- parsedConfigCopy.compileConfig(),
- log,
- GetCore());
+ for (const auto& layerName : supported) {
+ if (contains(unsupported, layerName)) {
+ supported.erase(layerName);
+ }
+ }
+
+ unsupported.clear();
+
+ std::function<void(std::shared_ptr<ngraph::Node>)> markParentSplitAsUnsupported = [&markParentSplitAsUnsupported, &supported, &splitNames]
+ (const std::shared_ptr<ngraph::Node>& split) {
+ const auto inputs = split->inputs();
+ for (const auto& input : inputs) {
+ const auto& parentName = input.get_source_output().get_node()->get_friendly_name();
+ if (contains(supported, parentName) &&
+ contains(splitNames, parentName)) {
+ markParentSplitAsUnsupported(input.get_source_output().get_node_shared_ptr());
+ }
+ }
+ const auto& name = split->get_friendly_name();
+ if (contains(supported, name)) {
+ supported.erase(name);
+ }
+ };
+
+ for (const auto& split : splits) {
+ // We will mark split as a supported only if all consumers is supported
+ bool is_supported = true;
+ const auto outputs = split->outputs();
+ for (const auto& output : outputs) {
+ for (const auto& consumer : output.get_target_inputs()) {
+ const auto& name = consumer.get_node()->get_friendly_name();
+ if (!contains(supported, name) &&
+ !contains(concatNames, name) &&
+ !contains(splitNames, name)) {
+ is_supported = false;
+ break;
+ }
+ }
+ }
+ if (is_supported) {
+ supported.emplace(split->get_friendly_name());
+ } else {
+ // If Split is not supported and it's parent is also Split, mark parent as unsupported
+ markParentSplitAsUnsupported(split);
+ }
+ }
- for (const auto& layerName : layerNames) {
- res.supportedLayersMap.insert({ layerName, GetName() });
+ for (const auto& concat : concats) {
+ // We will mark concat as a supported only if all parent layers is supported
+ bool is_supported = true;
+ const auto inputs = concat->inputs();
+ for (const auto& input : inputs) {
+ const auto& name = input.get_source_output().get_node()->get_friendly_name();
+ if (!contains(supported, name) &&
+ !contains(concatNames, name)) {
+ is_supported = false;
+ break;
+ }
+ }
+ if (is_supported) {
+ supported.emplace(concat->get_friendly_name());
+ }
+ }
+
+ for (const auto& node : function->get_ops()) {
+ if (contains(supported, node->get_friendly_name())) {
+ for (const auto& inputNodeOutput : node->input_values()) {
+ if (ngraph::op::is_constant(inputNodeOutput.get_node()) || ngraph::op::is_parameter(inputNodeOutput.get_node())) {
+ supported.emplace(inputNodeOutput.get_node()->get_friendly_name());
+ }
+ }
+ for (const auto& outputs : node->outputs()) {
+ for (const auto& outputNodeInput : outputs.get_target_inputs()) {
+ if (ngraph::op::is_output(outputNodeInput.get_node())) {
+ supported.emplace(outputNodeInput.get_node()->get_friendly_name());
+ }
+ }
+ }
+ }
+ }
+
+ for (const auto& layerName : supported) {
+ res.supportedLayersMap.emplace(layerName, GetName());
+ }
+ } else {
+ const auto log = std::make_shared<Logger>(
+ "GraphCompiler",
+ parsedConfigCopy.logLevel(),
+ defaultOutput(parsedConfigCopy.compilerLogFilePath()));
+
+ const auto layerNames = getSupportedLayers(
+ network,
+ static_cast<Platform>(parsedConfigCopy.platform()),
+ parsedConfigCopy.compileConfig(),
+ log,
+ GetCore());
+
+ for (const auto& layerName : layerNames) {
+ res.supportedLayersMap.insert({ layerName, GetName() });
+ }
}
}