From aa12ff7708482b0aaaddda5dfe63093cd9d3aaf9 Mon Sep 17 00:00:00 2001 From: Michael Nosov Date: Thu, 29 Apr 2021 20:19:46 +0300 Subject: [PATCH 01/22] NGraph - FrontEndManager - common API Added Mock frontend for unit testing --- ngraph/CMakeLists.txt | 8 + ngraph/frontend/CMakeLists.txt | 2 + ngraph/frontend/generic/CMakeLists.txt | 55 +++ .../frontend_manager/frontend_manager.hpp | 364 +++++++++++++++++ .../frontend_manager_defs.hpp | 15 + .../frontend/generic/src/frontend_manager.cpp | 380 ++++++++++++++++++ ngraph/frontend/generic/src/plugin_loader.cpp | 122 ++++++ ngraph/frontend/generic/src/plugin_loader.hpp | 56 +++ ngraph/test/CMakeLists.txt | 19 + ngraph/test/frontend/CMakeLists.txt | 13 + ngraph/test/frontend/frontend_manager.cpp | 105 +++++ ngraph/test/frontend/mock_frontend.cpp | 36 ++ .../frontend/shared/include/basic_api.hpp | 33 ++ .../shared/include/cut_specific_model.hpp | 45 +++ .../frontend/shared/include/partial_shape.hpp | 51 +++ ngraph/test/frontend/shared/include/utils.hpp | 29 ++ ngraph/test/frontend/shared/src/basic_api.cpp | 190 +++++++++ .../shared/src/cut_specific_model.cpp | 278 +++++++++++++ .../frontend/shared/src/partial_shape.cpp | 95 +++++ 19 files changed, 1896 insertions(+) create mode 100644 ngraph/frontend/generic/CMakeLists.txt create mode 100644 ngraph/frontend/generic/include/frontend_manager/frontend_manager.hpp create mode 100644 ngraph/frontend/generic/include/frontend_manager/frontend_manager_defs.hpp create mode 100644 ngraph/frontend/generic/src/frontend_manager.cpp create mode 100644 ngraph/frontend/generic/src/plugin_loader.cpp create mode 100644 ngraph/frontend/generic/src/plugin_loader.hpp create mode 100644 ngraph/test/frontend/CMakeLists.txt create mode 100644 ngraph/test/frontend/frontend_manager.cpp create mode 100644 ngraph/test/frontend/mock_frontend.cpp create mode 100644 ngraph/test/frontend/shared/include/basic_api.hpp create mode 100644 ngraph/test/frontend/shared/include/cut_specific_model.hpp create mode 100644 ngraph/test/frontend/shared/include/partial_shape.hpp create mode 100644 ngraph/test/frontend/shared/include/utils.hpp create mode 100644 ngraph/test/frontend/shared/src/basic_api.cpp create mode 100644 ngraph/test/frontend/shared/src/cut_specific_model.cpp create mode 100644 ngraph/test/frontend/shared/src/partial_shape.cpp diff --git a/ngraph/CMakeLists.txt b/ngraph/CMakeLists.txt index ae54a346eed54c..6841171196416c 100644 --- a/ngraph/CMakeLists.txt +++ b/ngraph/CMakeLists.txt @@ -26,6 +26,14 @@ set(NGRAPH_INCLUDE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/core/include ) +set(FRONTEND_INCLUDE_PATH + ${CMAKE_CURRENT_SOURCE_DIR}/frontend/generic/include +) + +set(FRONTEND_BASE_PATH + ${CMAKE_CURRENT_SOURCE_DIR}/frontend +) + if (APPLE) # Enable MACOS_RPATH by default. cmake_policy(SET CMP0042 NEW) diff --git a/ngraph/frontend/CMakeLists.txt b/ngraph/frontend/CMakeLists.txt index 3e21b4b50171ec..ed5595296ed9d9 100644 --- a/ngraph/frontend/CMakeLists.txt +++ b/ngraph/frontend/CMakeLists.txt @@ -2,6 +2,8 @@ # SPDX-License-Identifier: Apache-2.0 # +add_subdirectory(generic) + if (NGRAPH_ONNX_IMPORT_ENABLE) add_subdirectory(onnx_common) add_subdirectory(onnx_import) diff --git a/ngraph/frontend/generic/CMakeLists.txt b/ngraph/frontend/generic/CMakeLists.txt new file mode 100644 index 00000000000000..72fe8e7dcea8e6 --- /dev/null +++ b/ngraph/frontend/generic/CMakeLists.txt @@ -0,0 +1,55 @@ +# Copyright (C) 2018-2021 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 +# + +file(GLOB_RECURSE LIBRARY_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cc) +file(GLOB_RECURSE LIBRARY_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/src/*.hpp ${CMAKE_CURRENT_SOURCE_DIR}/src/*.h) +file(GLOB_RECURSE LIBRARY_PUBLIC_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/include/*.hpp) + +set(FRONTEND_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/include) + +source_group("src" FILES ${LIBRARY_SRC}) +source_group("include" FILES ${LIBRARY_HEADERS}) +source_group("public include" FILES ${LIBRARY_PUBLIC_HEADERS}) + +# Create shared library +add_library(frontend_manager SHARED ${LIBRARY_SRC} ${LIBRARY_HEADERS} ${LIBRARY_PUBLIC_HEADERS} ${PROTO_SRCS} ${PROTO_HDRS}) +add_library(ngraph::frontend_manager ALIAS frontend_manager) + +target_link_libraries(frontend_manager PRIVATE ${CMAKE_DL_LIBS}) + +if(COMMAND ie_add_vs_version_file) + ie_add_vs_version_file(NAME frontend_manager + FILEDESCRIPTION "Manager of OpenVINO nGraph Front Ends") +endif() + +set(FRONTEND_INSTALL_INCLUDE "${NGRAPH_INSTALL_INCLUDE}/ngraph/frontend/generic") +target_include_directories(frontend_manager SYSTEM PUBLIC $ + $ ${ONNX_IMPORT_INCLUDE_DIR} ${TENSORFLOW_FRONTEND_INCLUDE_DIR}) +target_include_directories(frontend_manager SYSTEM PRIVATE ${NGRAPH_INCLUDE_PATH} ${ONNX_IMPORT_INCLUDE_PATH} ${ONNX_IMPORT_INCLUDE_DIR} + ${FRONTEND_INCLUDE_DIR} ${TENSORFLOW_FRONTEND_INCLUDE_DIR}) + +target_include_directories(frontend_manager PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src ${ONNX_IMPORT_INCLUDE_DIR} ${TENSORFLOW_FRONTEND_INCLUDE_DIR}) + +if (CMAKE_CXX_COMPILER_ID MATCHES "^(Apple)?Clang$") + target_compile_options(frontend_manager PRIVATE -Wno-undef -Wno-reserved-id-macro -Wno-switch-enum + -Wno-invalid-offsetof -Wno-shorten-64-to-32 -Wno-unused-macros -Wno-missing-variable-declarations + -Wno-unused-private-field -Wno-shadow -Wno-deprecated PUBLIC -Wno-undefined-func-template) +endif() + +install(TARGETS frontend_manager EXPORT ngraphTargets + RUNTIME DESTINATION ${NGRAPH_INSTALL_LIB} COMPONENT ngraph + ARCHIVE DESTINATION ${NGRAPH_INSTALL_LIB} COMPONENT ngraph + LIBRARY DESTINATION ${NGRAPH_INSTALL_LIB} COMPONENT ngraph) + +install(DIRECTORY ${FRONTEND_INCLUDE_DIR}/frontend_manager + DESTINATION ${FRONTEND_INSTALL_INCLUDE} + COMPONENT ngraph + FILES_MATCHING + PATTERN "*.hpp" + PATTERN "*.h" +) + +if (NGRAPH_EXPORT_TARGETS_ENABLE) + export(TARGETS frontend_manager NAMESPACE ngraph:: APPEND FILE "${NGRAPH_TARGETS_FILE}") +endif() diff --git a/ngraph/frontend/generic/include/frontend_manager/frontend_manager.hpp b/ngraph/frontend/generic/include/frontend_manager/frontend_manager.hpp new file mode 100644 index 00000000000000..e3917fa8de4fb0 --- /dev/null +++ b/ngraph/frontend/generic/include/frontend_manager/frontend_manager.hpp @@ -0,0 +1,364 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +#include +#include +#include "ngraph/function.hpp" +#include "frontend_manager_defs.hpp" + +namespace ngraph +{ + namespace frontend + { + + +/// \brief An interface for identifying a place in a graph and iterate over it; can refer to an operation node, tensor, port etc. +/// +/// \note Each front end implementation provides specialization of this interface to represent a place +/// in a model graph. Various methods in the front end classes accept and retrieve instances +/// of Place to point to particular node part which should be modified or satisfies some criteria. +/// For example, this class is used to report model inputs and outputs, for searching operations and tensors +/// by name, for setting shape etc. +/// +/// Place can refer to Tensor, Input Edge, Input Port, Operation, Output Port, Output Edge +/// +/// [Tensor A] +/// | +/// | [Input Edge] +/// | +/// V +/// ------------------- +/// [ [Input Port 0] ] +/// [ ] +/// [ Operation A ] +/// [ ] +/// [ [Output Port 0] ] +/// ------------------- +/// | +/// | [Output Edge] +/// | +/// V +/// [Tensor B] +/// | +/// | [Input Edge] +/// | +/// V +/// ------------------- +/// [ [Input Port 0] ] +/// [ ] +/// [ Operation B ] +/// [ ] +/// [ [Output Port 0] ] +/// ------------------- +/// | +/// | [Output Edge] +/// | +/// V +/// [Tensor C] +/// + class FRONTEND_API Place + { + public: + + typedef std::shared_ptr Ptr; + + virtual ~Place() = default; + + /// \brief All associated names (synonyms) that identify this place in the graph in a framework specific way + /// \return A vector of strings each representing a name that identifies this place in the graph. + /// Can be empty if there are no names associated with this place or name cannot be attached. + virtual std::vector getNames() const; + + /// \brief Returns references to all operation nodes that consume data from this place + /// \note It can be called for any kind of graph place searching for the first consuming opertions. + /// + /// \param outputPortIndex If place is an operational node it specifies which output port should be considered + /// \return A vector with all operation node references that consumes data from this place + virtual std::vector getConsumingOperations(int outputPortIndex = -1) const; + + /// \brief Returns a tensor place that gets data from this place; applicable for operations, output ports and output edges + /// + /// \param outputPortIndex Output port index if the current place is an operation node and has multiple output ports + /// \return A tensor place which hold the resulting value for this place + virtual Ptr getTargetTensor(int outputPortIndex = -1) const; + + /// \brief Returns a tensor place that supplies data for this place; applicable for operations, input ports and input edges + /// + /// \param inputPortIndex Input port index for operational nodes + /// \return A tensor place which supplies data for this place + virtual Ptr getSourceTensor(int inputPortIndex = -1) const; + + /// \brief Get an operation node place that immediately produces data for this place + /// + /// \param inputPortIndex If a given place is itself an operation node, this specifies a port index + /// \return An operation place that produces data for this place + virtual Ptr getProducingOperation(int inputPortIndex = -1) const; + + /// Returns a port that produces data for this place + virtual Ptr getProducingPort() const; + + /// For operation node returns reference to an input port with specified index + virtual Ptr getInputPort(int inputPortIndex = -1) const; + + /// For operation node returns reference to an input port with specified name and index + virtual Ptr getInputPort(const std::string& inputName, int inputPortIndex = -1) const; + + /// For operation node returns reference to an output port with specified index + virtual Ptr getOutputPort(int outputPortIndex = -1) const; + + /// For operation node returns reference to an output port with specified name and index + virtual Ptr getOutputPort(const std::string& outputName, int outputPortIndex = -1) const; + + /// Returns all input ports that consume data flows through this place + virtual std::vector getConsumingPorts() const; + + /// Returns true if this place is input for a model. + virtual bool isInput() const; + + /// Returns true if this place is output for a model. + virtual bool isOutput() const; + + /// Returns true if another place is the same as this place. + virtual bool isEqual(Ptr another) const; + + /// \brief Returns true if another place points to the same data. + /// \note The same data means all places on path: output port -> output edge -> tensor -> input edge -> input port. + virtual bool isEqualData(Ptr another) const; + }; + + +/// \brief InputModel class represents an original, not yet converted model graph in a framework format given +/// services to find places of interest in a graph or specialize/edit the model before conversion. +/// +/// \note Class methods are divided into several groups: searching for places, naming and annotation, +/// topology editing, setting tensor properties. +/// +/// Editing requests may affect ability to convert the original model to nGraph function. Aim to provide +/// these editing capabilities is to unlock conversion for models that are not natively supported "as-is" +/// because of undefined shapes, types or operations. +/// +/// Specific front-end implementation is supposed to have a lazy implementation for all methods, not doing +/// a complete load of a model without an explicit method call. For example, the list of all inputs +/// are not pre-fetched by InputModel derived class instance creation, but only when getInputs method is called. +/// But it is not an obligation, the most convenient way should be chosen depending on the framework model +/// representation. +/// +/// All editing requests affect the model representation that is held behind the scene and successive method +/// calls observe a new graph structure. + class FRONTEND_API InputModel + { + public: + + typedef std::shared_ptr Ptr; + + virtual ~InputModel() = default; + + ///// Searching for places ///// + + + /// \brief Returns all inputs for a model + /// An input is a place in a graph where data is supposed to flow inside graph from outside. + /// It can be a tensor, port, operation; which kind of place can be an output is FW dependent. + /// Usually framework models have a dedicated artifact to code model input, it can be a tensor without producer, + /// that writes to it in ONNX, or a special operation like Placeholder in TensorFlow. + /// \return A vector of input place references + virtual std::vector getInputs() const; + + /// \brief Returns all output for a model + /// An output is a terminal place in a graph where data escapes the flow. It can be a tensor, port, operation; + /// which kind of place can be an output is FW dependent. In comparison to a graph input, the output is less + /// formally defined thing and determination of initial list of outputs may include some conventions defined + /// by a frontend itself, not a framework. For example, all output ports without consumers may be considered + /// as outputs. + /// \return A vector of output place references + virtual std::vector getOutputs() const; + + /// Returns a tensor place by a tensor name following framework conventions, or nullptr if a tensor with this name doesn't exist. + virtual Place::Ptr getPlaceByTensorName(const std::string& tensorName) const; + + /// Returns an operation place by a tensor name following framework conventions, or nullptr if an operation with this name doesn't exist. + virtual Place::Ptr getPlaceByOperationName(const std::string& operationName); + + /// Returns an input port. + virtual Place::Ptr getPlaceByOperationAndInputPort(const std::string& operationName, int inputPortIndex); + + /// Returns an output port. + virtual Place::Ptr getPlaceByOperationAndOutputPort(const std::string& operationName, int outputPortIndex); + + + ///// Naming and annotation ///// + + virtual void setNameForTensor(Place::Ptr tensor, const std::string& newName); + + virtual void addNameForTensor(Place::Ptr tensor, const std::string& newName); + + virtual void setNameForOperation(Place::Ptr operation, const std::string& newName); + + virtual void freeNameForTensor(const std::string& name); + + virtual void freeNameForOperation(const std::string& name); + + virtual void setNameForDimension(Place::Ptr place, size_t shapeDimIndex, const std::string& dimName); + + + ///// Topology Editing ///// + + /// Cut immediately before this place and assign this place as new input; prune all nodes that don't contribute to any output. + virtual void cutAndAddNewInput(Place::Ptr place, const std::string& newNameOptional = ""); + + /// Cut immediately after this place and assign this place as new output; prune all nodes that don't contribute to any output. + virtual void cutAndAddNewOutput(Place::Ptr place, const std::string& newNameOptional = ""); + + /// \brief Assign this place as new output or add necessary nodes to represent a new output. + /// + /// \param place Anchor point to add an output + /// \return new output place, may be the same as a given place + virtual Place::Ptr addOutput(Place::Ptr place); + + /// Removes any sinks directly attached to this place with all inbound data flow if it is not required by any other output. + virtual void removeOutput(Place::Ptr place); + + /// Removes an input place and all data flow that depends on it. + // TODO: remove it as something not practically useful in the API? + virtual void removeInput(Place::Ptr place); + + /// Replaces all existing outputs with new ones removing all data flow that is not required for new outputs. + /// + /// \param outputs Vector with places that will become new outputs; may intersect existing outputs. + virtual void overrideAllOutputs(const std::vector& outputs); + + /// \brief Modifies the graph to use new inputs instead of existing ones. New inputs should completely satisfy all existing outputs. + virtual void overrideAllInputs(const std::vector& inputs); + + /// Leaves only subgraph that are defined by new inputs and new outputs. + virtual void extractSubgraph(const std::vector& inputs, const std::vector& outputs); + + ///// Setting tensor properties ///// + + /// Sets shape that would be used by default for this place; place should be uniquely refer to some data. + // TODO: define clearly which scenario requires it -- currently it should satisfy requirement to have statically defined shapes for tensors + virtual void setDefaultShape(Place::Ptr place, const ngraph::Shape&); + + /// Defines all possible shape that may be used for this place; place should be uniquely refer to some data. + /// This partial shape will be converted to corresponding shape of results ngraph nodes and will define shape inference + /// when the model is converted to ngraph. + virtual void setPartialShape(Place::Ptr place, const ngraph::PartialShape&); + + /// Returns current partial shape used for this place + virtual ngraph::PartialShape getPartialShape(Place::Ptr place) const; + + /// Sets new element type for a place. + virtual void setElementType(Place::Ptr place, const ngraph::element::Type&); + + /// Freezes a tensor with statically defined value or replace existing value for already constant node or tensor. + virtual void setTensorValue(Place::Ptr place, const void *value); + + /// Defines partial value (lower bound and upper bound) for a tensor place. + // TODO: more details for minValue and maxValue format; who defines shape? + virtual void setTensorPartialValue(Place::Ptr place, const void *minValue, const void *maxValue); + + // TODO: Document "inputs/output assymetry" in more details + + // Traversing + // TODO: remove or add something; most likely will have only a single method that provides a list of operation nodes sorted topologically + + // Support querying + // TODO: remove or add something; there are no candidates, all queries can be satisfied without any API extension here + }; + + class FRONTEND_API FrontEnd + { + public: + typedef std::shared_ptr Ptr; + + FrontEnd(); + + virtual ~FrontEnd(); + + virtual InputModel::Ptr loadFromFile(const std::string& path) const; + + virtual InputModel::Ptr loadFromFiles(const std::vector& paths) const; + + virtual InputModel::Ptr loadFromMemory(const void *model) const; + + virtual InputModel::Ptr loadFromMemoryFragments(const std::vector& modelParts) const; + + virtual InputModel::Ptr loadFromStream(std::istream& path) const; + + virtual InputModel::Ptr loadFromStreams(const std::vector& paths) const; + + // Extra ctors may be provided by FW-specialized data structure for graph representaion + + /// Completely convert and normalize entire function, throws if it is not possible + virtual std::shared_ptr convert(InputModel::Ptr model) const; + + /// Completely convert the remaining, not converted part of a function. + virtual std::shared_ptr + convert(std::shared_ptr partiallyConverted) const; + + /// Convert only those parts of the model that can be converted leaving others as-is. + /// Converted parts are not normalized by additional transformations; normalize function + /// or another form of convert function should be called to finalize the conversion process. + virtual std::shared_ptr convertPartially(InputModel::Ptr model) const; + + /// Convert operations with one-to-one mapping with decoding nodes. + /// Each decoding node is an nGraph node representing a single FW operation node with all attributes + /// represented in FW-independent way. + virtual std::shared_ptr decode(InputModel::Ptr model) const; + + /// Runs normalization passes on function that was loaded with partial conversion + virtual void normalize(std::shared_ptr function) const; + }; + + enum class FrontEndCapabilities + { + FEC_DEFAULT = 0, // Just reading and conversion, w/o any modifications; intended to be used in Reader + FEC_CUT = 1, + FEC_NAMES = 2, + FEC_REPLACE = 4, + FEC_TRAVERSE = 8, + FEC_WILDCARDS = 16, + }; + +// -------------- FrontEndManager ----------------- + using FrontEndFactory = std::function; + + class FRONTEND_API FrontEndManager + { + public: + FrontEndManager(const std::string& dirName={}); + + ~FrontEndManager(); + + FrontEnd::Ptr loadByFramework(const std::string& framework, + FrontEndCapabilities fec = FrontEndCapabilities::FEC_DEFAULT); + + FrontEnd::Ptr loadByModel(const std::string& path, + FrontEndCapabilities fec = FrontEndCapabilities::FEC_DEFAULT); + + std::vector availableFrontEnds() const; + + void registerFrontEnd(const std::string& name, FrontEndFactory creator); + + private: + class Impl; + + std::unique_ptr m_impl; + }; + +// --------- Plugin exporting information -------------- + + using FrontEndVersion = const char *; + + struct FrontEndPluginInfo + { + std::string m_name; + FrontEndFactory m_creator; + }; + + } // namespace frontend + +} // namespace ngraph diff --git a/ngraph/frontend/generic/include/frontend_manager/frontend_manager_defs.hpp b/ngraph/frontend/generic/include/frontend_manager/frontend_manager_defs.hpp new file mode 100644 index 00000000000000..4a30c3ba404d25 --- /dev/null +++ b/ngraph/frontend/generic/include/frontend_manager/frontend_manager_defs.hpp @@ -0,0 +1,15 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +#include "ngraph/visibility.hpp" + +#define OV_FRONTEND_API_VERSION "0.0.1" + +#ifdef frontend_manager_EXPORTS // defined if cmake is building the frontend_manager DLL (instead of using it) +#define FRONTEND_API NGRAPH_HELPER_DLL_EXPORT +#else +#define FRONTEND_API NGRAPH_HELPER_DLL_IMPORT +#endif // frontend_manager_EXPORTS diff --git a/ngraph/frontend/generic/src/frontend_manager.cpp b/ngraph/frontend/generic/src/frontend_manager.cpp new file mode 100644 index 00000000000000..911a07b0c678ee --- /dev/null +++ b/ngraph/frontend/generic/src/frontend_manager.cpp @@ -0,0 +1,380 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include + +#include "frontend_manager/frontend_manager.hpp" +#include "plugin_loader.hpp" + +namespace ngraph +{ + namespace frontend + { + +#define FRONT_END_NOT_IMPLEMENTED(NAME) throw std::runtime_error(#NAME " is not implemented for this FrontEnd class") +#define FRONT_END_ASSERT(EXPRESSION) \ + { if (!(EXPRESSION)) throw "AssertionFailed"; } + + //----------- FrontEndManager --------------------------- + class FrontEndManager::Impl + { + std::vector m_loadedLibs; // must be a first class member (destroyed last) + std::map m_factories; + public: + Impl(const std::string& dirName) + { + registerPlugins(dirName); + } + + ~Impl() = default; + + FrontEnd::Ptr loadByFramework(const std::string& framework, FrontEndCapabilities fec) + { + FRONT_END_ASSERT(m_factories.count(framework)) + return m_factories[framework](fec); + } + + std::vector availableFrontEnds() const + { + std::vector keys; + + std::transform(m_factories.begin(), m_factories.end(), + std::back_inserter(keys), + [](const std::pair& item) + { + return item.first; + }); + return keys; + } + + FrontEnd::Ptr loadByModel(const std::string& path, FrontEndCapabilities fec) + { + FRONT_END_NOT_IMPLEMENTED(loadByModel); + } + + void registerFrontEnd(const std::string& name, FrontEndFactory creator) + { + m_factories.insert({name, creator}); + } + + private: + void registerPlugins(const std::string& dirName) + { + auto registerFromDir = [&](const std::string& dir) + { + auto plugins = loadPlugins(dir); + for (auto& plugin : plugins) + { + registerFrontEnd(plugin.m_pluginInfo.m_name, plugin.m_pluginInfo.m_creator); + m_loadedLibs.push_back(std::move(plugin.m_libHandle)); + } + }; + if (!dirName.empty()) + { + registerFromDir(dirName); + registerFromDir(dirName+"/lib"); + } + registerFromDir("./frontends"); + registerFromDir("./lib/frontends"); + } + }; + + FrontEndManager::FrontEndManager(const std::string& dirName) : m_impl(new Impl(dirName)) + { + } + + FrontEndManager::~FrontEndManager() = default; + + FrontEnd::Ptr FrontEndManager::loadByFramework(const std::string& framework, FrontEndCapabilities fec) + { + return m_impl->loadByFramework(framework, fec); + } + + FrontEnd::Ptr FrontEndManager::loadByModel(const std::string& path, FrontEndCapabilities fec) + { + return m_impl->loadByModel(path, fec); + } + + std::vector FrontEndManager::availableFrontEnds() const + { + return m_impl->availableFrontEnds(); + } + + void FrontEndManager::registerFrontEnd(const std::string& name, FrontEndFactory creator) + { + m_impl->registerFrontEnd(name, creator); + } + + //----------- FrontEnd --------------------------- + + FrontEnd::FrontEnd() = default; + + FrontEnd::~FrontEnd() = default; + + InputModel::Ptr FrontEnd::loadFromFile(const std::string& paths) const + { + FRONT_END_NOT_IMPLEMENTED(loadFromFile); + } + + InputModel::Ptr FrontEnd::loadFromFiles(const std::vector& paths) const + { + FRONT_END_NOT_IMPLEMENTED(loadFromFiles); + } + + InputModel::Ptr FrontEnd::loadFromMemory(const void *model) const + { + FRONT_END_NOT_IMPLEMENTED(loadFromMemory); + } + + InputModel::Ptr FrontEnd::loadFromMemoryFragments(const std::vector& modelParts) const + { + FRONT_END_NOT_IMPLEMENTED(loadFromMemoryFragments); + } + + InputModel::Ptr FrontEnd::loadFromStream(std::istream& path) const + { + FRONT_END_NOT_IMPLEMENTED(loadFromStream); + } + + InputModel::Ptr FrontEnd::loadFromStreams(const std::vector& paths) const + { + FRONT_END_NOT_IMPLEMENTED(loadFromStreams); + } + + std::shared_ptr FrontEnd::convert(InputModel::Ptr model) const + { + FRONT_END_NOT_IMPLEMENTED(convert); + } + + std::shared_ptr FrontEnd::convert(std::shared_ptr) const + { + FRONT_END_NOT_IMPLEMENTED(convert); + } + + std::shared_ptr FrontEnd::convertPartially(InputModel::Ptr model) const + { + FRONT_END_NOT_IMPLEMENTED(convertPartially); + } + + std::shared_ptr FrontEnd::decode(InputModel::Ptr model) const + { + FRONT_END_NOT_IMPLEMENTED(convertDecodingOnly); + } + + void FrontEnd::normalize(std::shared_ptr function) const + { + FRONT_END_NOT_IMPLEMENTED(normalize); + } + + //----------- InputModel --------------------------- + std::vector InputModel::getInputs() const + { + FRONT_END_NOT_IMPLEMENTED(getInputs); + } + + std::vector InputModel::getOutputs() const + { + FRONT_END_NOT_IMPLEMENTED(getOutputs); + } + + Place::Ptr InputModel::getPlaceByTensorName(const std::string& tensorName) const + { + FRONT_END_NOT_IMPLEMENTED(getPlaceByTensorName); + } + + Place::Ptr InputModel::getPlaceByOperationName(const std::string& operationName) + { + FRONT_END_NOT_IMPLEMENTED(getPlaceByOperationName); + } + + Place::Ptr InputModel::getPlaceByOperationAndInputPort(const std::string& operationName, int inputPortIndex) + { + FRONT_END_NOT_IMPLEMENTED(getPlaceByOperationAndInputPort); + } + + Place::Ptr InputModel::getPlaceByOperationAndOutputPort(const std::string& operationName, int outputPortIndex) + { + FRONT_END_NOT_IMPLEMENTED(getPlaceByOperationAndOutputPort); + } + + void InputModel::setNameForTensor(Place::Ptr tensor, const std::string& newName) + { + FRONT_END_NOT_IMPLEMENTED(setNameForTensor); + } + + void InputModel::addNameForTensor(Place::Ptr tensor, const std::string& newName) + { + FRONT_END_NOT_IMPLEMENTED(addNameForTensor); + } + + void InputModel::setNameForOperation(Place::Ptr operation, const std::string& newName) + { + FRONT_END_NOT_IMPLEMENTED(setNameForOperation); + } + + void InputModel::freeNameForTensor(const std::string& name) + { + FRONT_END_NOT_IMPLEMENTED(freeNameForTensor); + } + + void InputModel::freeNameForOperation(const std::string& name) + { + FRONT_END_NOT_IMPLEMENTED(freeNameForOperation); + } + + void InputModel::setNameForDimension(Place::Ptr place, size_t shapeDimIndex, const std::string& dimName) + { + FRONT_END_NOT_IMPLEMENTED(setNameForDimension); + } + + void InputModel::cutAndAddNewInput(Place::Ptr place, const std::string& newNameOptional) + { + FRONT_END_NOT_IMPLEMENTED(cutAndAddNewInput); + } + + void InputModel::cutAndAddNewOutput(Place::Ptr place, const std::string& newNameOptional) + { + FRONT_END_NOT_IMPLEMENTED(cutAndAddNewOutput); + } + + Place::Ptr InputModel::addOutput(Place::Ptr place) + { + FRONT_END_NOT_IMPLEMENTED(addOutput); + } + + void InputModel::removeOutput(Place::Ptr place) + { + FRONT_END_NOT_IMPLEMENTED(removeOutput); + } + + void InputModel::removeInput(Place::Ptr place) + { + FRONT_END_NOT_IMPLEMENTED(removeInput); + } + + void InputModel::overrideAllOutputs(const std::vector& outputs) + { + FRONT_END_NOT_IMPLEMENTED(overrideAllOutputs); + } + + void InputModel::overrideAllInputs(const std::vector& inputs) + { + FRONT_END_NOT_IMPLEMENTED(overrideAllInputs); + } + + void + InputModel::extractSubgraph(const std::vector& inputs, const std::vector& outputs) + { + FRONT_END_NOT_IMPLEMENTED(extractSubgraph); + } + + // Setting tensor properties + void InputModel::setDefaultShape(Place::Ptr place, const ngraph::Shape&) + { + FRONT_END_NOT_IMPLEMENTED(setDefaultShape); + } + + void InputModel::setPartialShape(Place::Ptr place, const ngraph::PartialShape&) + { + FRONT_END_NOT_IMPLEMENTED(setPartialShape); + } + + ngraph::PartialShape InputModel::getPartialShape(Place::Ptr place) const + { + FRONT_END_NOT_IMPLEMENTED(setPartialShape); + } + + void InputModel::setElementType(Place::Ptr place, const ngraph::element::Type&) + { + FRONT_END_NOT_IMPLEMENTED(setElementType); + } + + void InputModel::setTensorValue(Place::Ptr place, const void *) + { + FRONT_END_NOT_IMPLEMENTED(setTensorValue); + } + + void InputModel::setTensorPartialValue(Place::Ptr place, const void *minValue, const void *maxValue) + { + FRONT_END_NOT_IMPLEMENTED(setTensorPartialValue); + } + + //----------- Place --------------------------- + std::vector Place::getNames() const + { + FRONT_END_NOT_IMPLEMENTED(getNames); + } + + std::vector Place::getConsumingOperations(int outputPortIndex) const + { + FRONT_END_NOT_IMPLEMENTED(getConsumingOperations); + } + + Place::Ptr Place::getTargetTensor(int outputPortIndex) const + { + FRONT_END_NOT_IMPLEMENTED(getTargetTensor); + } + + Place::Ptr Place::getProducingOperation(int inputPortIndex) const + { + FRONT_END_NOT_IMPLEMENTED(getProducingOperation); + } + + Place::Ptr Place::getProducingPort() const + { + FRONT_END_NOT_IMPLEMENTED(getProducingPort); + } + + Place::Ptr Place::getInputPort(int inputPortIndex) const + { + FRONT_END_NOT_IMPLEMENTED(getInputPort); + } + + Place::Ptr Place::getInputPort(const std::string& intputName, int inputPortIndex) const + { + FRONT_END_NOT_IMPLEMENTED(getInputPort); + } + + Place::Ptr Place::getOutputPort(int outputPortIndex) const + { + FRONT_END_NOT_IMPLEMENTED(getOutputPort); + } + + Place::Ptr Place::getOutputPort(const std::string& outputName, int outputPortIndex) const + { + FRONT_END_NOT_IMPLEMENTED(getOutputPort); + } + + std::vector Place::getConsumingPorts() const + { + FRONT_END_NOT_IMPLEMENTED(getConsumingPorts); + } + + bool Place::isInput() const + { + FRONT_END_NOT_IMPLEMENTED(isInput); + } + + bool Place::isOutput() const + { + FRONT_END_NOT_IMPLEMENTED(isOutput); + } + + bool Place::isEqual(Ptr another) const + { + FRONT_END_NOT_IMPLEMENTED(isEqual); + } + + bool Place::isEqualData(Ptr another) const + { + FRONT_END_NOT_IMPLEMENTED(isEqualData); + } + + Place::Ptr Place::getSourceTensor(int inputPortIndex) const + { + FRONT_END_NOT_IMPLEMENTED(getSourceTensor); + } + + } // namespace frontend +} // namespace ngraph diff --git a/ngraph/frontend/generic/src/plugin_loader.cpp b/ngraph/frontend/generic/src/plugin_loader.cpp new file mode 100644 index 00000000000000..54402b6cf79f7e --- /dev/null +++ b/ngraph/frontend/generic/src/plugin_loader.cpp @@ -0,0 +1,122 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#ifdef _WIN32 +#include +#include +const char FileSeparator[] = "\\"; +#else // _WIN32 + +#include +#include +#include + +const char FileSeparator[] = "/"; +#endif // _WIN32 + +#include +#include +#include + +#include "plugin_loader.hpp" + +using namespace ngraph; +using namespace ngraph::frontend; + +#ifdef WIN32 +#define DLOPEN(fileStr) LoadLibrary(TEXT(fileStr.c_str())) +#define DLSYM(obj, func) GetProcAddress(obj, func) +#define DLCLOSE(obj) FreeLibrary(obj) +#else +#define DLOPEN(fileStr) dlopen(file.c_str(), RTLD_LAZY) +#define DLSYM(obj, func) dlsym(obj, func) +#define DLCLOSE(obj) dlclose(obj) +#endif + +// TODO: change to std::filesystem for C++17 +static std::vector listFiles(const std::string& path) +{ + std::vector res; +#ifndef WIN32 + struct dirent *ent; + DIR *dir = opendir(path.c_str()); + if (dir != nullptr) + { + std::unique_ptr closeGuard(dir, [](DIR *d) + { closedir(d); }); + while ((ent = readdir(dir)) != NULL) + { + auto file = path + FileSeparator + std::string(ent->d_name); + struct stat stat_path; + stat(file.c_str(), &stat_path); + if (!S_ISDIR(stat_path.st_mode) && file.find("_frontend.so") != std::string::npos) + { + res.push_back(std::move(file)); + } + } + } +#else + std::string searchPath = path + FileSeparator + "*_frontend.dll"; + WIN32_FIND_DATA fd; + HANDLE handle = ::FindFirstFile(searchPath.c_str(), &fd); + if (handle != INVALID_HANDLE_VALUE) + { + do + { + if (!(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ) + { + res.push_back(path + FileSeparator + fd.cFileName); + } + } while(::FindNextFile(handle, &fd)); + ::FindClose(handle); + } +#endif + return res; +} + +std::vector ngraph::frontend::loadPlugins(const std::string& dirName) +{ + auto files = listFiles(dirName); + std::vector res; + // std::cout << "Loading directory: " << dirName << "\n"; + for (const auto& file : files) + { + // std::cout << "Checking plugin: " << file << "\n"; + auto shared_object = DLOPEN(file); + if (!shared_object) + { + continue; + } + + PluginHandle guard([shared_object, file]() + { + std::cout << "Closing plugin library " << file << std::endl; + DLCLOSE(shared_object); + }); + + auto infoAddr = reinterpret_cast(DLSYM(shared_object, "GetAPIVersion")); + if (!infoAddr) + { + continue; + } + FrontEndVersion plugInfo{reinterpret_cast(infoAddr())}; + + if (std::string(plugInfo) != OV_FRONTEND_API_VERSION) + { + // Plugin has incompatible API version, do not load it + continue; + } + + auto creatorAddr = reinterpret_cast(DLSYM(shared_object, "GetFrontEndData")); + if (!creatorAddr) + { + continue; + } + + std::unique_ptr fact{reinterpret_cast(creatorAddr())}; + + res.push_back(PluginData(std::move(guard), std::move(*fact))); + } + return res; +} diff --git a/ngraph/frontend/generic/src/plugin_loader.hpp b/ngraph/frontend/generic/src/plugin_loader.hpp new file mode 100644 index 00000000000000..d709c931d92a75 --- /dev/null +++ b/ngraph/frontend/generic/src/plugin_loader.hpp @@ -0,0 +1,56 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +#include + +namespace ngraph +{ + namespace frontend + { + + /// Plugin library handle wrapper. On destruction calls internal function which frees library handle + class PluginHandle + { + public: + PluginHandle(std::function callOnDestruct) : m_callOnDestruct(callOnDestruct) + { + } + + PluginHandle(const PluginHandle&) = delete; + + PluginHandle& operator=(const PluginHandle&) = delete; + + PluginHandle(PluginHandle&&) = default; + + PluginHandle& operator=(PluginHandle&&) = default; + + ~PluginHandle() + { + if (m_callOnDestruct) + { + m_callOnDestruct(); + } + } + + private: + std::function m_callOnDestruct; + }; + + struct PluginData + { + PluginData(PluginHandle&& h, FrontEndPluginInfo&& info) : m_libHandle(std::move(h)), m_pluginInfo(info) + { + } + + PluginHandle m_libHandle; // Shall be destroyed when plugin is not needed anymore to free memory + FrontEndPluginInfo m_pluginInfo; + }; + + // Searches for available plugins in a specified directory + std::vector loadPlugins(const std::string& dirName); + + } // namespace frontend +} // namespace ngraph diff --git a/ngraph/test/CMakeLists.txt b/ngraph/test/CMakeLists.txt index dd7f23d04d2eac..18874769849ce6 100644 --- a/ngraph/test/CMakeLists.txt +++ b/ngraph/test/CMakeLists.txt @@ -461,6 +461,18 @@ foreach(BACKEND_NAME ${ACTIVE_BACKEND_LIST}) message(STATUS "Adding unit test for backend ${BACKEND_NAME}") endforeach() +# SOURCE FOR FRONTEND TESTING + +# ---TODO FIXME --DO_NOT_RELEASE-- (mnosov) +set(SRC ${CMAKE_CURRENT_SOURCE_DIR}/main.cpp) # DEBUG trick to disable all unit tests for faster build +# --- END OF --DO_NOT_RELEASE-- + +file(GLOB FRONTEND_TESTS_SRC ${CMAKE_CURRENT_SOURCE_DIR}/frontend/frontend_manager.cpp) +set(SRC ${FRONTEND_TESTS_SRC} ${SRC}) + +file(GLOB FRONTEND_SHARED_TESTS_SRC ${CMAKE_CURRENT_SOURCE_DIR}/frontend/shared/src/*.cpp) +set(SRC ${FRONTEND_SHARED_TESTS_SRC} ${SRC}) + add_executable(unit-test ${SRC}) target_include_directories(unit-test PRIVATE ".") @@ -532,3 +544,10 @@ if (NGRAPH_INTERPRETER_ENABLE) target_compile_definitions(unit-test PRIVATE NGRAPH_INTERPRETER_ENABLE) target_link_libraries(unit-test PRIVATE interpreter_backend) endif() + +############ FRONTEND ############ +target_include_directories(unit-test PRIVATE ${FRONTEND_INCLUDE_PATH}) +target_link_libraries(unit-test PRIVATE frontend_manager) + +add_subdirectory(frontend) +### END FRONTEND ### \ No newline at end of file diff --git a/ngraph/test/frontend/CMakeLists.txt b/ngraph/test/frontend/CMakeLists.txt new file mode 100644 index 00000000000000..db96f3d18c17da --- /dev/null +++ b/ngraph/test/frontend/CMakeLists.txt @@ -0,0 +1,13 @@ +# Copyright (C) 2018-2021 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 +# + +set(SRC ${CMAKE_CURRENT_SOURCE_DIR}/mock_frontend.cpp) +add_library(mock1_frontend SHARED ${SRC}) + +target_compile_definitions(mock1_frontend PRIVATE "-DMOCK_VARIANT=\"1\"") + +target_include_directories(mock1_frontend PRIVATE ".") + +target_include_directories(mock1_frontend PRIVATE ${FRONTEND_INCLUDE_PATH} ${NGRAPH_INCLUDE_PATH}) +target_link_libraries(mock1_frontend PRIVATE frontend_manager) diff --git a/ngraph/test/frontend/frontend_manager.cpp b/ngraph/test/frontend/frontend_manager.cpp new file mode 100644 index 00000000000000..48cc31cd5d654b --- /dev/null +++ b/ngraph/test/frontend/frontend_manager.cpp @@ -0,0 +1,105 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include +#include + +#include "gtest/gtest.h" +#include "gmock/gmock.h" + +using namespace ngraph; +using namespace ngraph::frontend; + +TEST(FrontEndManagerTest, testAvailableFrontEnds) +{ + FrontEndManager fem; + ASSERT_NO_THROW(fem.registerFrontEnd("mock", [](FrontEndCapabilities fec) { + return std::make_shared(); + })); + auto frontends = fem.availableFrontEnds(); + ASSERT_NE(std::find(frontends.begin(), frontends.end(), "mock"), frontends.end()); + FrontEnd::Ptr fe; + ASSERT_NO_THROW(fe = fem.loadByFramework("mock")); +} + +TEST(FrontEndManagerTest, testMockPluginFrontEnd) +{ + FrontEndManager fem("."); // specify current lib dir + auto frontends = fem.availableFrontEnds(); + ASSERT_NE(std::find(frontends.begin(), frontends.end(), "mock1"), frontends.end()); +} + +TEST(FrontEndManagerTest, testDefaultFrontEnd) +{ + FrontEndManager fem; + ASSERT_ANY_THROW(fem.loadByModel("")); + + std::unique_ptr fePtr (new FrontEnd()); // to verify base destructor + FrontEnd::Ptr fe = std::make_shared(); + ASSERT_ANY_THROW(fe->loadFromFile("")); + ASSERT_ANY_THROW(fe->loadFromFiles({"", ""})); + ASSERT_ANY_THROW(fe->loadFromMemory(nullptr)); + ASSERT_ANY_THROW(fe->loadFromMemoryFragments({nullptr, nullptr})); + std::stringstream str; + ASSERT_ANY_THROW(fe->loadFromStream(str)); + ASSERT_ANY_THROW(fe->loadFromStreams({&str, &str})); + ASSERT_ANY_THROW(fe->convert(std::shared_ptr(nullptr))); + ASSERT_ANY_THROW(fe->convert(InputModel::Ptr(nullptr))); + ASSERT_ANY_THROW(fe->convertPartially(nullptr)); + ASSERT_ANY_THROW(fe->decode(nullptr)); + ASSERT_ANY_THROW(fe->normalize(nullptr)); +} + +TEST(FrontEndManagerTest, testDefaultInputModel) +{ + std::unique_ptr imPtr (new InputModel()); // to verify base destructor + InputModel::Ptr im = std::make_shared(); + ASSERT_ANY_THROW(im->getInputs()); + ASSERT_ANY_THROW(im->getOutputs()); + ASSERT_ANY_THROW(im->overrideAllInputs({nullptr})); + ASSERT_ANY_THROW(im->overrideAllOutputs({nullptr})); + ASSERT_ANY_THROW(im->extractSubgraph({nullptr}, {nullptr})); + ASSERT_ANY_THROW(im->getPlaceByTensorName("")); + ASSERT_ANY_THROW(im->getPlaceByOperationName("")); + ASSERT_ANY_THROW(im->getPlaceByOperationAndInputPort("", 0)); + ASSERT_ANY_THROW(im->getPlaceByOperationAndOutputPort("", 0)); + ASSERT_ANY_THROW(im->setNameForTensor(nullptr, "")); + ASSERT_ANY_THROW(im->addNameForTensor(nullptr, "")); + ASSERT_ANY_THROW(im->setNameForOperation(nullptr, "")); + ASSERT_ANY_THROW(im->freeNameForTensor("")); + ASSERT_ANY_THROW(im->freeNameForOperation("")); + ASSERT_ANY_THROW(im->setNameForDimension(nullptr, 0, "")); + ASSERT_ANY_THROW(im->cutAndAddNewInput(nullptr, "")); + ASSERT_ANY_THROW(im->cutAndAddNewOutput(nullptr, "")); + ASSERT_ANY_THROW(im->addOutput(nullptr)); + ASSERT_ANY_THROW(im->removeOutput(nullptr)); + ASSERT_ANY_THROW(im->removeInput(nullptr)); + ASSERT_ANY_THROW(im->setDefaultShape(nullptr, ngraph::Shape{})); + ASSERT_ANY_THROW(im->setPartialShape(nullptr, ngraph::Shape{})); + ASSERT_ANY_THROW(im->getPartialShape(nullptr)); + ASSERT_ANY_THROW(im->setElementType(nullptr, ngraph::element::Type{})); + ASSERT_ANY_THROW(im->setTensorValue(nullptr, nullptr)); + ASSERT_ANY_THROW(im->setTensorPartialValue(nullptr, nullptr, nullptr)); +} + +TEST(FrontEndManagerTest, testDefaultPlace) +{ + std::unique_ptr placePtr (new Place()); // to verify base destructor + Place::Ptr place = std::make_shared(); + ASSERT_ANY_THROW(place->getNames()); + ASSERT_ANY_THROW(place->getConsumingOperations()); + ASSERT_ANY_THROW(place->getTargetTensor()); + ASSERT_ANY_THROW(place->getSourceTensor()); + ASSERT_ANY_THROW(place->getProducingOperation()); + ASSERT_ANY_THROW(place->getProducingPort()); + ASSERT_ANY_THROW(place->getInputPort()); + ASSERT_ANY_THROW(place->getInputPort("")); + ASSERT_ANY_THROW(place->getOutputPort()); + ASSERT_ANY_THROW(place->getOutputPort("")); + ASSERT_ANY_THROW(place->getConsumingPorts()); + ASSERT_ANY_THROW(place->isInput()); + ASSERT_ANY_THROW(place->isOutput()); + ASSERT_ANY_THROW(place->isEqual(nullptr)); + ASSERT_ANY_THROW(place->isEqualData(nullptr)); +} diff --git a/ngraph/test/frontend/mock_frontend.cpp b/ngraph/test/frontend/mock_frontend.cpp new file mode 100644 index 00000000000000..98315411bb5da2 --- /dev/null +++ b/ngraph/test/frontend/mock_frontend.cpp @@ -0,0 +1,36 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "ngraph/visibility.hpp" +#include "frontend_manager/frontend_manager_defs.hpp" +#include "frontend_manager/frontend_manager.hpp" + +#ifdef mock1_frontend_EXPORTS // defined if we are building the plugin DLL (instead of using it) +#define MOCK_API NGRAPH_HELPER_DLL_EXPORT +#else +#define MOCK_API NGRAPH_HELPER_DLL_IMPORT +#endif // mock1_frontend_EXPORTS + +using namespace ngraph; +using namespace ngraph::frontend; + +class FrontEndMock: public FrontEnd +{ +}; + +extern "C" MOCK_API char* GetAPIVersion() +{ + return OV_FRONTEND_API_VERSION; +} + +extern "C" MOCK_API void* GetFrontEndData() +{ + FrontEndPluginInfo* res = new FrontEndPluginInfo(); + res->m_name = "mock1"; + res->m_creator = [](ngraph::frontend::FrontEndCapabilities) + { + return std::make_shared(); + }; + return res; +} \ No newline at end of file diff --git a/ngraph/test/frontend/shared/include/basic_api.hpp b/ngraph/test/frontend/shared/include/basic_api.hpp new file mode 100644 index 00000000000000..cf2f37f13aa0cf --- /dev/null +++ b/ngraph/test/frontend/shared/include/basic_api.hpp @@ -0,0 +1,33 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +#include + +#include + +using BasicTestParam = std::tuple; // Model name + +class FrontEndBasicTest : public ::testing::TestWithParam +{ +public: + std::string m_feName; + std::string m_pathToModels; + std::string m_modelFile; + ngraph::frontend::FrontEndManager m_fem; + ngraph::frontend::FrontEnd::Ptr m_frontEnd; + ngraph::frontend::InputModel::Ptr m_inputModel; + + static std::string getTestCaseName(const testing::TestParamInfo& obj); + + void SetUp() override; + +protected: + void initParamTest(); + + void doLoadFromFile(); +}; diff --git a/ngraph/test/frontend/shared/include/cut_specific_model.hpp b/ngraph/test/frontend/shared/include/cut_specific_model.hpp new file mode 100644 index 00000000000000..fefae85da44013 --- /dev/null +++ b/ngraph/test/frontend/shared/include/cut_specific_model.hpp @@ -0,0 +1,45 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +#include + +#include + +struct CutModelParam +{ + std::string m_frontEndName; + std::string m_modelsPath; + std::string m_modelName; + std::vector m_oldInputs; + std::vector m_newInputs; + std::vector m_oldOutputs; + std::vector m_newOutputs; + std::string m_tensorValueName; + std::vector m_tensorValue; + std::string m_op_before_name; +}; + +class FrontEndCutModelTest : public ::testing::TestWithParam +{ +public: + CutModelParam m_param; + ngraph::frontend::FrontEndManager m_fem; + ngraph::frontend::FrontEnd::Ptr m_frontEnd; + ngraph::frontend::InputModel::Ptr m_inputModel; + + static std::string getTestCaseName(const testing::TestParamInfo& obj); + + void SetUp() override; + +protected: + void initParamTest(); + + void doLoadFromFile(); + + std::vector constructNewInputs() const; + + std::vector constructNewOutputs() const; +}; diff --git a/ngraph/test/frontend/shared/include/partial_shape.hpp b/ngraph/test/frontend/shared/include/partial_shape.hpp new file mode 100644 index 00000000000000..f06f40cf576655 --- /dev/null +++ b/ngraph/test/frontend/shared/include/partial_shape.hpp @@ -0,0 +1,51 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +#include + +#include + +struct BaseFEParam +{ + BaseFEParam() + {} + + BaseFEParam(const std::string& name, const std::string& path) : + m_frontEndName(name), m_modelsPath(path) + {} + + std::string m_frontEndName; + std::string m_modelsPath; +}; + +struct PartShape +{ + std::string m_modelName; + std::string m_tensorName; + std::vector m_oldPartialShape; + std::vector m_newPartialShape; +}; + +using PartialShapeParam = std::tuple; + +class FrontEndPartialShapeTest : public ::testing::TestWithParam +{ +public: + BaseFEParam m_baseParam; + PartShape m_partShape; + ngraph::frontend::FrontEndManager m_fem; + ngraph::frontend::FrontEnd::Ptr m_frontEnd; + ngraph::frontend::InputModel::Ptr m_inputModel; + + static std::string getTestCaseName(const testing::TestParamInfo& obj); + + void SetUp() override; + +protected: + void initParamTest(); + + void doLoadFromFile(); +}; diff --git a/ngraph/test/frontend/shared/include/utils.hpp b/ngraph/test/frontend/shared/include/utils.hpp new file mode 100644 index 00000000000000..6bb4106c02e042 --- /dev/null +++ b/ngraph/test/frontend/shared/include/utils.hpp @@ -0,0 +1,29 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +#include + +// Helper functions +namespace FrontEndTestUtils +{ + inline std::string fileToTestName(const std::string& fileName) + { + // TODO: GCC 4.8 has limited support of regex + // return std::regex_replace(fileName, std::regex("[/\\.]"), "_"); + std::string res = fileName; + for (auto& c : res) + { + if (c == '/') + { + c = '_'; + } else if (c == '.') + { + c = '_'; + } + } + return res; + } +} \ No newline at end of file diff --git a/ngraph/test/frontend/shared/src/basic_api.cpp b/ngraph/test/frontend/shared/src/basic_api.cpp new file mode 100644 index 00000000000000..cbd72cb13f77aa --- /dev/null +++ b/ngraph/test/frontend/shared/src/basic_api.cpp @@ -0,0 +1,190 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include +#include "../include/basic_api.hpp" +#include "../include/utils.hpp" + +using namespace ngraph; +using namespace ngraph::frontend; + +std::string FrontEndBasicTest::getTestCaseName(const testing::TestParamInfo& obj) +{ + std::string fe, path, fileName; + std::tie(fe, path, fileName) = obj.param; + return fe + "_" + FrontEndTestUtils::fileToTestName(fileName); +} + +void FrontEndBasicTest::SetUp() +{ + initParamTest(); +} + +void FrontEndBasicTest::initParamTest() +{ + std::tie(m_feName, m_pathToModels, m_modelFile) = GetParam(); + m_modelFile = std::string(TEST_FILES) + m_pathToModels + m_modelFile; +} + +void FrontEndBasicTest::doLoadFromFile() +{ + std::vector frontends; + ASSERT_NO_THROW(frontends = m_fem.availableFrontEnds()); + ASSERT_NO_THROW(m_frontEnd = m_fem.loadByFramework(m_feName)); + ASSERT_NE(m_frontEnd, nullptr); + ASSERT_NO_THROW(m_inputModel = m_frontEnd->loadFromFile(m_modelFile)); + ASSERT_NE(m_inputModel, nullptr); +} + +TEST_P(FrontEndBasicTest, testLoadFromFile) +{ + ASSERT_NO_THROW(doLoadFromFile()); + std::shared_ptr function; + ASSERT_NO_THROW(function = m_frontEnd->convert(m_inputModel)); + ASSERT_NE(function, nullptr); +} + +TEST_P(FrontEndBasicTest, testInputModel_getInputsOutputs) +{ + ASSERT_NO_THROW(doLoadFromFile()); + + using CustomCheck = std::function; + auto checkPlaces = [&](const std::vector& places, CustomCheck cb) + { + EXPECT_GT(places.size(), 0); + std::set placesSet(places.begin(), places.end()); + EXPECT_EQ(placesSet.size(), places.size()); + std::for_each(places.begin(), places.end(), [&](Place::Ptr place) + { + ASSERT_NE(place, nullptr); + std::vector names; + ASSERT_NO_THROW(names = place->getNames()); + EXPECT_GT(names.size(), 0); + cb(place); + }); + }; + std::vector inputs; + ASSERT_NO_THROW(inputs = m_inputModel->getInputs()); + checkPlaces(inputs, [&](Place::Ptr place) + { + EXPECT_TRUE(place->isInput()); + }); + + std::vector outputs; + ASSERT_NO_THROW(outputs = m_inputModel->getOutputs()); + checkPlaces(outputs, [&](Place::Ptr place) + { + EXPECT_TRUE(place->isOutput()); + }); +} + +TEST_P(FrontEndBasicTest, testInputModel_getPlaceByTensorName) +{ + ASSERT_NO_THROW(doLoadFromFile()); + + auto testGetPlaceByTensorName = [&](const std::vector& places) + { + EXPECT_GT(places.size(), 0); + for (auto place : places) + { + ASSERT_NE(place, nullptr); + std::vector names; + ASSERT_NO_THROW(names = place->getNames()); + for (auto name : names) + { + EXPECT_NE(name, std::string()); + Place::Ptr placeByName; + ASSERT_NO_THROW(placeByName = m_inputModel->getPlaceByTensorName(name)); + ASSERT_NE(placeByName, nullptr); + EXPECT_TRUE(placeByName->isEqual(place)); + } + } + }; + + std::vector outputs; + ASSERT_NO_THROW(outputs = m_inputModel->getOutputs()); + testGetPlaceByTensorName(outputs); + + std::vector inputs; + ASSERT_NO_THROW(inputs = m_inputModel->getInputs()); + testGetPlaceByTensorName(inputs); +} + +TEST_P(FrontEndBasicTest, testInputModel_overrideAll) +{ + ASSERT_NO_THROW(doLoadFromFile()); + + using GetPlaces = std::function()>; + using OverridePlaces = std::function&)>; + auto verifyOverride = [](GetPlaces getCB, OverridePlaces overrideCB) + { + std::vector places; + ASSERT_NO_THROW(places = getCB()); + std::set placesSet(places.begin(), places.end()); + + auto placesReversed = places; + std::reverse(placesReversed.begin(), placesReversed.end()); + ASSERT_NO_THROW(overrideCB(placesReversed)); + ASSERT_NO_THROW(places = getCB()); + EXPECT_GT(places.size(), 0); + std::set placesSetAfter(places.begin(), places.end()); + EXPECT_EQ(placesSet.size(), placesSet.size()); + std::for_each(places.begin(), places.end(), [&](Place::Ptr place) + { + EXPECT_GT(placesSet.count(place), 0); + }); + }; + verifyOverride([&]() + { return m_inputModel->getInputs(); }, + [&](const std::vector& p) + { m_inputModel->overrideAllInputs(p); }); + + verifyOverride([&]() + { return m_inputModel->getOutputs(); }, + [&](const std::vector& p) + { m_inputModel->overrideAllOutputs(p); }); +} + +TEST_P(FrontEndBasicTest, testInputModel_overrideAll_empty) +{ + ASSERT_NO_THROW(doLoadFromFile()); + using GetPlaces = std::function()>; + using OverrideEmpty = std::function; + using CustomCheck = std::function; + auto verifyOverride = [](GetPlaces getCB, OverrideEmpty overrideCB, CustomCheck customCB) + { + std::vector places; + std::vector newPlaces; + ASSERT_NO_THROW(places = getCB()); + ASSERT_NO_THROW(overrideCB()); + ASSERT_NO_THROW(newPlaces = getCB()); + ASSERT_EQ(newPlaces.size(), 0); + std::for_each(places.begin(), places.end(), [&](Place::Ptr place) + { + std::vector names; + ASSERT_NO_THROW(names = place->getNames()); + for (auto name : names) + { + customCB(name); + } + }); + }; + verifyOverride([&]() + { return m_inputModel->getOutputs(); }, + [&]() + { m_inputModel->overrideAllOutputs({}); }, + [&](const std::string& name) + { + EXPECT_FALSE(m_inputModel->getPlaceByTensorName(name)->isOutput()); + }); + + verifyOverride([&]() + { return m_inputModel->getInputs(); }, + [&]() + { m_inputModel->overrideAllInputs({}); }, + [&](const std::string& name) + { + EXPECT_FALSE(m_inputModel->getPlaceByTensorName(name)->isInput()); + }); +} diff --git a/ngraph/test/frontend/shared/src/cut_specific_model.cpp b/ngraph/test/frontend/shared/src/cut_specific_model.cpp new file mode 100644 index 00000000000000..022d748e4f2289 --- /dev/null +++ b/ngraph/test/frontend/shared/src/cut_specific_model.cpp @@ -0,0 +1,278 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include +#include +#include "../include/cut_specific_model.hpp" +#include "../include/utils.hpp" +#include "ngraph/opsets/opset7.hpp" + +using namespace ngraph; +using namespace ngraph::frontend; + +static std::string joinStrings(const std::vector& strings) +{ + std::ostringstream res; + std::copy(strings.begin(), strings.end(), + std::ostream_iterator(res, "_")); + return res.str(); +} + +std::string FrontEndCutModelTest::getTestCaseName(const testing::TestParamInfo& obj) +{ + std::string res = obj.param.m_frontEndName + "_" + obj.param.m_modelName; + res += "I" + joinStrings(obj.param.m_oldInputs) + joinStrings(obj.param.m_newInputs); + res += "O" + joinStrings(obj.param.m_oldOutputs) + joinStrings(obj.param.m_newOutputs); + return FrontEndTestUtils::fileToTestName(res); +} + +void FrontEndCutModelTest::SetUp() +{ + initParamTest(); +} + +void FrontEndCutModelTest::initParamTest() +{ + m_param = GetParam(); + m_param.m_modelName = std::string(TEST_FILES) + m_param.m_modelsPath + m_param.m_modelName; + std::cout << "Model: " << m_param.m_modelName << std::endl; +} + +void FrontEndCutModelTest::doLoadFromFile() +{ + std::vector frontends; + FrontEnd::Ptr fe; + ASSERT_NO_THROW(frontends = m_fem.availableFrontEnds()); + ASSERT_NO_THROW(m_frontEnd = m_fem.loadByFramework(m_param.m_frontEndName)); + ASSERT_NE(m_frontEnd, nullptr); + ASSERT_NO_THROW(m_inputModel = m_frontEnd->loadFromFile(m_param.m_modelName)); + ASSERT_NE(m_inputModel, nullptr); +} + +std::vector FrontEndCutModelTest::constructNewInputs() const +{ + std::vector newInputs; + for (const auto& name : m_param.m_newInputs) + { + newInputs.push_back(m_inputModel->getPlaceByTensorName(name)); + } + return newInputs; +} + +std::vector FrontEndCutModelTest::constructNewOutputs() const +{ + std::vector newOutputs; + for (const auto& name : m_param.m_newOutputs) + { + newOutputs.push_back(m_inputModel->getPlaceByTensorName(name)); + } + return newOutputs; +} + +/////////////////////////////////////////////////////////////////// + +TEST_P(FrontEndCutModelTest, testOverrideInputs) +{ + ASSERT_NO_THROW(doLoadFromFile()); + std::vector newPlaces; + ASSERT_NO_THROW(newPlaces = constructNewInputs()); + ASSERT_NO_THROW(m_inputModel->overrideAllInputs(newPlaces)); + ASSERT_NO_THROW(m_inputModel->getInputs()); + EXPECT_EQ(m_param.m_newInputs.size(), m_inputModel->getInputs().size()); + for (auto newInput : m_inputModel->getInputs()) + { + std::vector names; + ASSERT_NO_THROW(names = newInput->getNames()); + bool found = false; + for (const auto& name: m_param.m_newInputs) + { + if (std::find(names.begin(), names.begin(), name) != names.end()) + { + found = true; + break; + } + } + EXPECT_TRUE(found) << joinStrings(names) << " were not found in new inputs"; + } +} + +TEST_P(FrontEndCutModelTest, testOverrideOutputs) +{ + ASSERT_NO_THROW(doLoadFromFile()); + std::vector newPlaces; + ASSERT_NO_THROW(newPlaces = constructNewOutputs()); + ASSERT_NO_THROW(m_inputModel->overrideAllOutputs(newPlaces)); + ASSERT_NO_THROW(m_inputModel->getOutputs()); + EXPECT_EQ(m_param.m_newOutputs.size(), m_inputModel->getOutputs().size()); + for (auto newOutput : m_inputModel->getOutputs()) + { + std::vector names; + ASSERT_NO_THROW(names = newOutput->getNames()); + bool found = false; + for (const auto& name: m_param.m_newOutputs) + { + if (std::find(names.begin(), names.begin(), name) != names.end()) + { + found = true; + break; + } + } + EXPECT_TRUE(found) << joinStrings(names) << " were not found in new outputs"; + } +} + +TEST_P(FrontEndCutModelTest, testOldInputs) +{ + ASSERT_NO_THROW(doLoadFromFile()); + std::shared_ptr function; + ASSERT_NO_THROW(function = m_frontEnd->convert(m_inputModel)); + auto ops = function->get_ordered_ops(); + + // Ensure that it contains expected old inputs + for (const auto& name : m_param.m_oldInputs) + { + EXPECT_TRUE(std::find_if(ops.begin(), ops.end(), + [&](const std::shared_ptr& node) + { + return node->get_friendly_name().find(name) != std::string::npos; + }) != ops.end()) << "Name not found:" << name; + } +} + +TEST_P(FrontEndCutModelTest, testOldOutputs) +{ + ASSERT_NO_THROW(doLoadFromFile()); + std::shared_ptr function; + ASSERT_NO_THROW(function = m_frontEnd->convert(m_inputModel)); + auto ops = function->get_ordered_ops(); + // Ensure that it contains expected old outputs + for (const auto& name : m_param.m_oldOutputs) + { + EXPECT_TRUE(std::find_if(ops.begin(), ops.end(), + [&](const std::shared_ptr& node) + { + return node->get_friendly_name().find(name) != std::string::npos; + }) != ops.end()) << "Name not found:" << name; + } +} + +TEST_P(FrontEndCutModelTest, testNewInputs_func) +{ + ASSERT_NO_THROW(doLoadFromFile()); + std::vector newPlaces; + ASSERT_NO_THROW(newPlaces = constructNewInputs()); + ASSERT_NO_THROW(m_inputModel->overrideAllInputs(newPlaces)); + + std::shared_ptr function; + ASSERT_NO_THROW(function = m_frontEnd->convert(m_inputModel)); + auto ops = function->get_ordered_ops(); + + // Ensure that it doesn't contain old inputs + for (const auto& name : m_param.m_oldInputs) + { + EXPECT_TRUE(std::find_if(ops.begin(), ops.end(), + [&](const std::shared_ptr& node) + { + return node->get_friendly_name().find(name) != std::string::npos; + }) == ops.end()) << "Name shall not exist:" << name; + } + + // Ensure that it contains expected new inputs + for (const auto& name : m_param.m_newInputs) + { + EXPECT_TRUE(std::find_if(ops.begin(), ops.end(), + [&](const std::shared_ptr& node) + { + return node->get_friendly_name().find(name) != std::string::npos; + }) != ops.end()) << "Name not found:" << name; + } +} + +TEST_P(FrontEndCutModelTest, testNewOutputs_func) +{ + ASSERT_NO_THROW(doLoadFromFile()); + std::vector newPlaces; + ASSERT_NO_THROW(newPlaces = constructNewOutputs()); + ASSERT_NO_THROW(m_inputModel->overrideAllOutputs(newPlaces)); + + std::shared_ptr function; + ASSERT_NO_THROW(function = m_frontEnd->convert(m_inputModel)); + auto ops = function->get_ordered_ops(); + + // Ensure that it doesn't contain old outputs + for (const auto& name : m_param.m_oldOutputs) + { + EXPECT_TRUE(std::find_if(ops.begin(), ops.end(), + [&](const std::shared_ptr& node) + { + return node->get_friendly_name().find(name) != std::string::npos; + }) == ops.end()) << "Name shall not exist:" << name; + } + + // Ensure that it contains expected new outputs + for (const auto& name : m_param.m_newOutputs) + { + EXPECT_TRUE(std::find_if(ops.begin(), ops.end(), + [&](const std::shared_ptr& node) + { + return node->get_friendly_name().find(name) != std::string::npos; + }) != ops.end()) << "Name not found:" << name; + } +} + +TEST_P(FrontEndCutModelTest, testExtractSubgraph) +{ + ASSERT_NO_THROW(doLoadFromFile()); + std::vector newInputs, newOutputs; + ASSERT_NO_THROW(newInputs = constructNewInputs()); + ASSERT_NO_THROW(newOutputs = constructNewOutputs()); + ASSERT_NO_THROW(m_inputModel->extractSubgraph(newInputs, newOutputs)); + + std::shared_ptr function; + ASSERT_NO_THROW(function = m_frontEnd->convert(m_inputModel)); + auto ops = function->get_ordered_ops(); + + // Ensure that it doesn't contain expected old outputs + for (const auto& name : m_param.m_oldOutputs) + { + EXPECT_TRUE(std::find_if(ops.begin(), ops.end(), + [&](const std::shared_ptr& node) + { + return node->get_friendly_name().find(name) != std::string::npos; + }) == ops.end()) << "Name shall not exist:" << name; + } + + // Ensure that it contains expected new outputs + for (const auto& name : m_param.m_newOutputs) + { + EXPECT_TRUE(std::find_if(ops.begin(), ops.end(), + [&](const std::shared_ptr& node) + { + return node->get_friendly_name().find(name) != std::string::npos; + }) != ops.end()) << "Name not found:" << name; + } +} + +TEST_P(FrontEndCutModelTest, testSetTensorValue) +{ + ASSERT_NO_THROW(doLoadFromFile()); + Place::Ptr place; + ASSERT_NO_THROW(place = m_inputModel->getPlaceByTensorName(m_param.m_tensorValueName)); + ASSERT_NO_THROW(m_inputModel->setTensorValue(place, &m_param.m_tensorValue[0])); + + std::shared_ptr function; + ASSERT_NO_THROW(function = m_frontEnd->convert(m_inputModel)); + auto ops = function->get_ordered_ops(); + + auto const_name = m_param.m_tensorValueName; + auto const_node_it = std::find_if(ops.begin(), ops.end(), + [&](const std::shared_ptr& node) + { + return node->get_friendly_name().find(const_name) != std::string::npos; + }); + ASSERT_TRUE(const_node_it != ops.end()) << "Name shall exist:" << const_name; + auto data = std::dynamic_pointer_cast(*const_node_it)->get_vector(); + EXPECT_EQ(data.size(), m_param.m_tensorValue.size()) << "Data size must be equal to expected size"; + EXPECT_TRUE(std::equal(data.begin(), data.end(), m_param.m_tensorValue.begin())) << "Data must be equal"; +} diff --git a/ngraph/test/frontend/shared/src/partial_shape.cpp b/ngraph/test/frontend/shared/src/partial_shape.cpp new file mode 100644 index 00000000000000..8eb5bb5dc04925 --- /dev/null +++ b/ngraph/test/frontend/shared/src/partial_shape.cpp @@ -0,0 +1,95 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include +#include +#include "../include/partial_shape.hpp" +#include "../include/utils.hpp" + +using namespace ngraph; +using namespace ngraph::frontend; + +std::string FrontEndPartialShapeTest::getTestCaseName(const testing::TestParamInfo& obj) +{ + BaseFEParam base; + PartShape part; + std::tie(base, part) = obj.param; + std::string res = base.m_frontEndName + "_" + part.m_modelName + "_" + part.m_tensorName; + for (auto s : part.m_newPartialShape) + { + res += "_" + std::to_string(s); + } + return FrontEndTestUtils::fileToTestName(res); +} + +void FrontEndPartialShapeTest::SetUp() +{ + initParamTest(); +} + +void FrontEndPartialShapeTest::initParamTest() +{ + std::tie(m_baseParam, m_partShape) = GetParam(); + m_partShape.m_modelName = std::string(TEST_FILES) + m_baseParam.m_modelsPath + m_partShape.m_modelName; + std::cout << "Model: " << m_partShape.m_modelName << std::endl; +} + +void FrontEndPartialShapeTest::doLoadFromFile() +{ + std::vector frontends; + FrontEnd::Ptr fe; + ASSERT_NO_THROW(frontends = m_fem.availableFrontEnds()); + ASSERT_NO_THROW(m_frontEnd = m_fem.loadByFramework(m_baseParam.m_frontEndName)); + ASSERT_NE(m_frontEnd, nullptr); + ASSERT_NO_THROW(m_inputModel = m_frontEnd->loadFromFile(m_partShape.m_modelName)); + ASSERT_NE(m_inputModel, nullptr); +} + +/////////////////////////////////////////////////////////////////// + +TEST_P(FrontEndPartialShapeTest, testCheckOldPartialShape) +{ + ASSERT_NO_THROW(doLoadFromFile()); + + std::shared_ptr function; + ASSERT_NO_THROW(function = m_frontEnd->convert(m_inputModel)); + auto ops = function->get_ordered_ops(); + auto it = std::find_if(ops.begin(), ops.end(), + [&](const std::shared_ptr& node) + { + return node->get_friendly_name().find(m_partShape.m_tensorName) != std::string::npos; + }); + ASSERT_NE(it, ops.end()); + auto shape = (*it)->get_output_partial_shape(0).get_shape(); + ASSERT_EQ(shape.size(), m_partShape.m_oldPartialShape.size()); + for (std::size_t i = 0; i < shape.size(); i++) + { + EXPECT_EQ(shape.at(i), m_partShape.m_oldPartialShape.at(i)); + } +} + +TEST_P(FrontEndPartialShapeTest, testSetNewPartialShape) +{ + ASSERT_NO_THROW(doLoadFromFile()); + Place::Ptr place; + ASSERT_NO_THROW(place = m_inputModel->getPlaceByTensorName(m_partShape.m_tensorName)); + ASSERT_NE(place, nullptr); + ASSERT_NO_THROW(m_inputModel->setPartialShape(place, PartialShape{m_partShape.m_newPartialShape})); + + std::shared_ptr function; + ASSERT_NO_THROW(function = m_frontEnd->convert(m_inputModel)); + auto ops = function->get_ordered_ops(); + auto it = std::find_if(ops.begin(), ops.end(), + [&](const std::shared_ptr& node) + { + return node->get_friendly_name().find(m_partShape.m_tensorName) != std::string::npos; + }); + ASSERT_NE(it, ops.end()); + auto shape = (*it)->get_output_partial_shape(0).get_shape(); + ASSERT_EQ(shape.size(), m_partShape.m_newPartialShape.size()); + for (std::size_t i = 0; i < shape.size(); i++) + { + EXPECT_EQ(shape.at(i), m_partShape.m_newPartialShape.at(i)); + } +} From 4ce398e25d1aef945d687e68d73691ece98a1d5c Mon Sep 17 00:00:00 2001 From: Michael Nosov Date: Fri, 30 Apr 2021 01:36:16 +0300 Subject: [PATCH 02/22] Comment out installation rules --- ngraph/frontend/generic/CMakeLists.txt | 33 +++++++++++++------------- ngraph/test/CMakeLists.txt | 5 ---- 2 files changed, 17 insertions(+), 21 deletions(-) diff --git a/ngraph/frontend/generic/CMakeLists.txt b/ngraph/frontend/generic/CMakeLists.txt index 72fe8e7dcea8e6..a15cae67542132 100644 --- a/ngraph/frontend/generic/CMakeLists.txt +++ b/ngraph/frontend/generic/CMakeLists.txt @@ -37,19 +37,20 @@ if (CMAKE_CXX_COMPILER_ID MATCHES "^(Apple)?Clang$") -Wno-unused-private-field -Wno-shadow -Wno-deprecated PUBLIC -Wno-undefined-func-template) endif() -install(TARGETS frontend_manager EXPORT ngraphTargets - RUNTIME DESTINATION ${NGRAPH_INSTALL_LIB} COMPONENT ngraph - ARCHIVE DESTINATION ${NGRAPH_INSTALL_LIB} COMPONENT ngraph - LIBRARY DESTINATION ${NGRAPH_INSTALL_LIB} COMPONENT ngraph) - -install(DIRECTORY ${FRONTEND_INCLUDE_DIR}/frontend_manager - DESTINATION ${FRONTEND_INSTALL_INCLUDE} - COMPONENT ngraph - FILES_MATCHING - PATTERN "*.hpp" - PATTERN "*.h" -) - -if (NGRAPH_EXPORT_TARGETS_ENABLE) - export(TARGETS frontend_manager NAMESPACE ngraph:: APPEND FILE "${NGRAPH_TARGETS_FILE}") -endif() +# TODO: uncomment to include frontend_manager to installation package +#install(TARGETS frontend_manager EXPORT ngraphTargets +# RUNTIME DESTINATION ${NGRAPH_INSTALL_LIB} COMPONENT ngraph +# ARCHIVE DESTINATION ${NGRAPH_INSTALL_LIB} COMPONENT ngraph +# LIBRARY DESTINATION ${NGRAPH_INSTALL_LIB} COMPONENT ngraph) +# +#install(DIRECTORY ${FRONTEND_INCLUDE_DIR}/frontend_manager +# DESTINATION ${FRONTEND_INSTALL_INCLUDE} +# COMPONENT ngraph +# FILES_MATCHING +# PATTERN "*.hpp" +# PATTERN "*.h" +#) +# +#if (NGRAPH_EXPORT_TARGETS_ENABLE) +# export(TARGETS frontend_manager NAMESPACE ngraph:: APPEND FILE "${NGRAPH_TARGETS_FILE}") +#endif() diff --git a/ngraph/test/CMakeLists.txt b/ngraph/test/CMakeLists.txt index 18874769849ce6..4de7f6e572e50a 100644 --- a/ngraph/test/CMakeLists.txt +++ b/ngraph/test/CMakeLists.txt @@ -462,11 +462,6 @@ foreach(BACKEND_NAME ${ACTIVE_BACKEND_LIST}) endforeach() # SOURCE FOR FRONTEND TESTING - -# ---TODO FIXME --DO_NOT_RELEASE-- (mnosov) -set(SRC ${CMAKE_CURRENT_SOURCE_DIR}/main.cpp) # DEBUG trick to disable all unit tests for faster build -# --- END OF --DO_NOT_RELEASE-- - file(GLOB FRONTEND_TESTS_SRC ${CMAKE_CURRENT_SOURCE_DIR}/frontend/frontend_manager.cpp) set(SRC ${FRONTEND_TESTS_SRC} ${SRC}) From cd166a969fb3d995d500349823607eb198783d33 Mon Sep 17 00:00:00 2001 From: Michael Nosov Date: Fri, 30 Apr 2021 16:20:45 +0300 Subject: [PATCH 03/22] Fixed review comment Introduced environment variable OV_FRONTEND_PATH for frontend paths --- .../frontend_manager/frontend_manager.hpp | 6 +-- .../frontend_manager_defs.hpp | 2 +- .../frontend/generic/src/frontend_manager.cpp | 38 ++++++++++++------- ngraph/frontend/generic/src/plugin_loader.cpp | 18 ++++----- ngraph/frontend/generic/src/plugin_loader.hpp | 8 ++++ ngraph/test/frontend/CMakeLists.txt | 3 +- ngraph/test/frontend/frontend_manager.cpp | 19 +++++++++- ngraph/test/frontend/mock_frontend.cpp | 2 +- .../frontend/shared/include/basic_api.hpp | 2 +- .../shared/include/cut_specific_model.hpp | 2 +- .../frontend/shared/include/partial_shape.hpp | 2 +- ngraph/test/frontend/shared/include/utils.hpp | 2 +- ngraph/test/frontend/shared/src/basic_api.cpp | 2 +- .../shared/src/cut_specific_model.cpp | 2 +- .../frontend/shared/src/partial_shape.cpp | 2 +- 15 files changed, 70 insertions(+), 40 deletions(-) diff --git a/ngraph/frontend/generic/include/frontend_manager/frontend_manager.hpp b/ngraph/frontend/generic/include/frontend_manager/frontend_manager.hpp index e3917fa8de4fb0..05abab9a496d4a 100644 --- a/ngraph/frontend/generic/include/frontend_manager/frontend_manager.hpp +++ b/ngraph/frontend/generic/include/frontend_manager/frontend_manager.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2018-2021 Intel Corporation +// Copyright (C) 2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // @@ -329,7 +329,7 @@ namespace ngraph class FRONTEND_API FrontEndManager { public: - FrontEndManager(const std::string& dirName={}); + FrontEndManager(); ~FrontEndManager(); @@ -351,7 +351,7 @@ namespace ngraph // --------- Plugin exporting information -------------- - using FrontEndVersion = const char *; + using FrontEndVersion = uint64_t; struct FrontEndPluginInfo { diff --git a/ngraph/frontend/generic/include/frontend_manager/frontend_manager_defs.hpp b/ngraph/frontend/generic/include/frontend_manager/frontend_manager_defs.hpp index 4a30c3ba404d25..6a272380f0af89 100644 --- a/ngraph/frontend/generic/include/frontend_manager/frontend_manager_defs.hpp +++ b/ngraph/frontend/generic/include/frontend_manager/frontend_manager_defs.hpp @@ -6,7 +6,7 @@ #include "ngraph/visibility.hpp" -#define OV_FRONTEND_API_VERSION "0.0.1" +#define OV_FRONTEND_API_VERSION 1 // Increment each time when FrontEnd/InputModel/Place interface is changed #ifdef frontend_manager_EXPORTS // defined if cmake is building the frontend_manager DLL (instead of using it) #define FRONTEND_API NGRAPH_HELPER_DLL_EXPORT diff --git a/ngraph/frontend/generic/src/frontend_manager.cpp b/ngraph/frontend/generic/src/frontend_manager.cpp index 911a07b0c678ee..246571c5fd1b2b 100644 --- a/ngraph/frontend/generic/src/frontend_manager.cpp +++ b/ngraph/frontend/generic/src/frontend_manager.cpp @@ -1,8 +1,9 @@ -// Copyright (C) 2018-2021 Intel Corporation +// Copyright (C) 2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // #include +#include #include "frontend_manager/frontend_manager.hpp" #include "plugin_loader.hpp" @@ -22,9 +23,9 @@ namespace ngraph std::vector m_loadedLibs; // must be a first class member (destroyed last) std::map m_factories; public: - Impl(const std::string& dirName) + Impl() { - registerPlugins(dirName); + registerPlugins(); } ~Impl() = default; @@ -59,28 +60,37 @@ namespace ngraph } private: - void registerPlugins(const std::string& dirName) + void registerPlugins() { auto registerFromDir = [&](const std::string& dir) { - auto plugins = loadPlugins(dir); - for (auto& plugin : plugins) + if (!dir.empty()) { - registerFrontEnd(plugin.m_pluginInfo.m_name, plugin.m_pluginInfo.m_creator); - m_loadedLibs.push_back(std::move(plugin.m_libHandle)); + auto plugins = loadPlugins(dir); + for (auto& plugin : plugins) + { + registerFrontEnd(plugin.m_pluginInfo.m_name, plugin.m_pluginInfo.m_creator); + m_loadedLibs.push_back(std::move(plugin.m_libHandle)); + } } }; - if (!dirName.empty()) + std::string envPath = ngraph::getenv_string("OV_FRONTEND_PATH"); + if (!envPath.empty()) { - registerFromDir(dirName); - registerFromDir(dirName+"/lib"); + auto start = 0u; + auto sepPos = envPath.find(PathSeparator, start); + while (sepPos != std::string::npos) + { + registerFromDir(envPath.substr(start, sepPos - start)); + start = sepPos + 1; + sepPos = envPath.find(PathSeparator, start); + } + registerFromDir(envPath.substr(start, sepPos)); } - registerFromDir("./frontends"); - registerFromDir("./lib/frontends"); } }; - FrontEndManager::FrontEndManager(const std::string& dirName) : m_impl(new Impl(dirName)) + FrontEndManager::FrontEndManager() : m_impl(new Impl()) { } diff --git a/ngraph/frontend/generic/src/plugin_loader.cpp b/ngraph/frontend/generic/src/plugin_loader.cpp index 54402b6cf79f7e..ad75edd2ac44f3 100644 --- a/ngraph/frontend/generic/src/plugin_loader.cpp +++ b/ngraph/frontend/generic/src/plugin_loader.cpp @@ -3,16 +3,12 @@ // #ifdef _WIN32 -#include -#include -const char FileSeparator[] = "\\"; + #include + #include #else // _WIN32 - -#include -#include -#include - -const char FileSeparator[] = "/"; + #include + #include + #include #endif // _WIN32 #include @@ -91,7 +87,7 @@ std::vector ngraph::frontend::loadPlugins(const std::string& dirName PluginHandle guard([shared_object, file]() { - std::cout << "Closing plugin library " << file << std::endl; + // std::cout << "Closing plugin library " << file << std::endl; DLCLOSE(shared_object); }); @@ -102,7 +98,7 @@ std::vector ngraph::frontend::loadPlugins(const std::string& dirName } FrontEndVersion plugInfo{reinterpret_cast(infoAddr())}; - if (std::string(plugInfo) != OV_FRONTEND_API_VERSION) + if (plugInfo != OV_FRONTEND_API_VERSION) { // Plugin has incompatible API version, do not load it continue; diff --git a/ngraph/frontend/generic/src/plugin_loader.hpp b/ngraph/frontend/generic/src/plugin_loader.hpp index d709c931d92a75..de25b20ab08985 100644 --- a/ngraph/frontend/generic/src/plugin_loader.hpp +++ b/ngraph/frontend/generic/src/plugin_loader.hpp @@ -6,6 +6,14 @@ #include +#ifdef _WIN32 +const char FileSeparator[] = "\\"; +const char PathSeparator[] = ";"; +#else // _WIN32 +const char FileSeparator[] = "/"; +const char PathSeparator[] = ":"; +#endif + namespace ngraph { namespace frontend diff --git a/ngraph/test/frontend/CMakeLists.txt b/ngraph/test/frontend/CMakeLists.txt index db96f3d18c17da..c4826dc2bb9cf8 100644 --- a/ngraph/test/frontend/CMakeLists.txt +++ b/ngraph/test/frontend/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (C) 2018-2021 Intel Corporation +# Copyright (C) 2021 Intel Corporation # SPDX-License-Identifier: Apache-2.0 # @@ -11,3 +11,4 @@ target_include_directories(mock1_frontend PRIVATE ".") target_include_directories(mock1_frontend PRIVATE ${FRONTEND_INCLUDE_PATH} ${NGRAPH_INCLUDE_PATH}) target_link_libraries(mock1_frontend PRIVATE frontend_manager) +add_dependencies(unit-test mock1_frontend) diff --git a/ngraph/test/frontend/frontend_manager.cpp b/ngraph/test/frontend/frontend_manager.cpp index 48cc31cd5d654b..ac607b6883ab9e 100644 --- a/ngraph/test/frontend/frontend_manager.cpp +++ b/ngraph/test/frontend/frontend_manager.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2018-2021 Intel Corporation +// Copyright (C) 2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // @@ -11,6 +11,16 @@ using namespace ngraph; using namespace ngraph::frontend; +static int set_test_env(const char* name, const char* value) +{ +#ifdef _WIN32 + return _putenv_s(name, value); +#elif defined(__linux) || defined(__APPLE__) + std::string var = std::string(name) + "=" + value; + return setenv(name, value, 0); +#endif +} + TEST(FrontEndManagerTest, testAvailableFrontEnds) { FrontEndManager fem; @@ -25,7 +35,12 @@ TEST(FrontEndManagerTest, testAvailableFrontEnds) TEST(FrontEndManagerTest, testMockPluginFrontEnd) { - FrontEndManager fem("."); // specify current lib dir +#ifdef _WIN32 + set_test_env("OV_FRONTEND_PATH", ".;.\\lib"); +#else // _WIN32 + set_test_env("OV_FRONTEND_PATH", ".:./lib"); +#endif + FrontEndManager fem; auto frontends = fem.availableFrontEnds(); ASSERT_NE(std::find(frontends.begin(), frontends.end(), "mock1"), frontends.end()); } diff --git a/ngraph/test/frontend/mock_frontend.cpp b/ngraph/test/frontend/mock_frontend.cpp index 98315411bb5da2..6fc553444515da 100644 --- a/ngraph/test/frontend/mock_frontend.cpp +++ b/ngraph/test/frontend/mock_frontend.cpp @@ -19,7 +19,7 @@ class FrontEndMock: public FrontEnd { }; -extern "C" MOCK_API char* GetAPIVersion() +extern "C" MOCK_API FrontEndVersion GetAPIVersion() { return OV_FRONTEND_API_VERSION; } diff --git a/ngraph/test/frontend/shared/include/basic_api.hpp b/ngraph/test/frontend/shared/include/basic_api.hpp index cf2f37f13aa0cf..3227e99ce3b00a 100644 --- a/ngraph/test/frontend/shared/include/basic_api.hpp +++ b/ngraph/test/frontend/shared/include/basic_api.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2018-2021 Intel Corporation +// Copyright (C) 2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // diff --git a/ngraph/test/frontend/shared/include/cut_specific_model.hpp b/ngraph/test/frontend/shared/include/cut_specific_model.hpp index fefae85da44013..1d82ea7e51c49a 100644 --- a/ngraph/test/frontend/shared/include/cut_specific_model.hpp +++ b/ngraph/test/frontend/shared/include/cut_specific_model.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2018-2021 Intel Corporation +// Copyright (C) 2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // diff --git a/ngraph/test/frontend/shared/include/partial_shape.hpp b/ngraph/test/frontend/shared/include/partial_shape.hpp index f06f40cf576655..b6f50e08d569a4 100644 --- a/ngraph/test/frontend/shared/include/partial_shape.hpp +++ b/ngraph/test/frontend/shared/include/partial_shape.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2018-2021 Intel Corporation +// Copyright (C) 2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // diff --git a/ngraph/test/frontend/shared/include/utils.hpp b/ngraph/test/frontend/shared/include/utils.hpp index 6bb4106c02e042..00fb7be62caa7a 100644 --- a/ngraph/test/frontend/shared/include/utils.hpp +++ b/ngraph/test/frontend/shared/include/utils.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2018-2021 Intel Corporation +// Copyright (C) 2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // diff --git a/ngraph/test/frontend/shared/src/basic_api.cpp b/ngraph/test/frontend/shared/src/basic_api.cpp index cbd72cb13f77aa..9d6a52e724ab09 100644 --- a/ngraph/test/frontend/shared/src/basic_api.cpp +++ b/ngraph/test/frontend/shared/src/basic_api.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2018-2021 Intel Corporation +// Copyright (C) 2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // diff --git a/ngraph/test/frontend/shared/src/cut_specific_model.cpp b/ngraph/test/frontend/shared/src/cut_specific_model.cpp index 022d748e4f2289..090c8698585d20 100644 --- a/ngraph/test/frontend/shared/src/cut_specific_model.cpp +++ b/ngraph/test/frontend/shared/src/cut_specific_model.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2018-2021 Intel Corporation +// Copyright (C) 2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // diff --git a/ngraph/test/frontend/shared/src/partial_shape.cpp b/ngraph/test/frontend/shared/src/partial_shape.cpp index 8eb5bb5dc04925..254d26eff98de3 100644 --- a/ngraph/test/frontend/shared/src/partial_shape.cpp +++ b/ngraph/test/frontend/shared/src/partial_shape.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2018-2021 Intel Corporation +// Copyright (C) 2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // From 7cde9c9a0730592d9bea3014dfcdc6f5182e198a Mon Sep 17 00:00:00 2001 From: Michael Nosov Date: Fri, 30 Apr 2021 16:42:34 +0300 Subject: [PATCH 04/22] Additional cmake cleanup --- ngraph/frontend/generic/CMakeLists.txt | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/ngraph/frontend/generic/CMakeLists.txt b/ngraph/frontend/generic/CMakeLists.txt index a15cae67542132..2a867b7037d122 100644 --- a/ngraph/frontend/generic/CMakeLists.txt +++ b/ngraph/frontend/generic/CMakeLists.txt @@ -13,10 +13,10 @@ source_group("include" FILES ${LIBRARY_HEADERS}) source_group("public include" FILES ${LIBRARY_PUBLIC_HEADERS}) # Create shared library -add_library(frontend_manager SHARED ${LIBRARY_SRC} ${LIBRARY_HEADERS} ${LIBRARY_PUBLIC_HEADERS} ${PROTO_SRCS} ${PROTO_HDRS}) +add_library(frontend_manager SHARED ${LIBRARY_SRC} ${LIBRARY_HEADERS} ${LIBRARY_PUBLIC_HEADERS}) add_library(ngraph::frontend_manager ALIAS frontend_manager) -target_link_libraries(frontend_manager PRIVATE ${CMAKE_DL_LIBS}) +target_link_libraries(frontend_manager PRIVATE ${CMAKE_DL_LIBS} ${NGRAPH_LIBRARIES}) if(COMMAND ie_add_vs_version_file) ie_add_vs_version_file(NAME frontend_manager @@ -25,11 +25,10 @@ endif() set(FRONTEND_INSTALL_INCLUDE "${NGRAPH_INSTALL_INCLUDE}/ngraph/frontend/generic") target_include_directories(frontend_manager SYSTEM PUBLIC $ - $ ${ONNX_IMPORT_INCLUDE_DIR} ${TENSORFLOW_FRONTEND_INCLUDE_DIR}) -target_include_directories(frontend_manager SYSTEM PRIVATE ${NGRAPH_INCLUDE_PATH} ${ONNX_IMPORT_INCLUDE_PATH} ${ONNX_IMPORT_INCLUDE_DIR} - ${FRONTEND_INCLUDE_DIR} ${TENSORFLOW_FRONTEND_INCLUDE_DIR}) + $) +target_include_directories(frontend_manager SYSTEM PRIVATE ${NGRAPH_INCLUDE_PATH} ${FRONTEND_INCLUDE_DIR}) -target_include_directories(frontend_manager PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src ${ONNX_IMPORT_INCLUDE_DIR} ${TENSORFLOW_FRONTEND_INCLUDE_DIR}) +target_include_directories(frontend_manager PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src) if (CMAKE_CXX_COMPILER_ID MATCHES "^(Apple)?Clang$") target_compile_options(frontend_manager PRIVATE -Wno-undef -Wno-reserved-id-macro -Wno-switch-enum From 90a4e2a82f3cf5cdc949da5b1373c58ce5216266 Mon Sep 17 00:00:00 2001 From: Michael Nosov Date: Fri, 30 Apr 2021 16:49:35 +0300 Subject: [PATCH 05/22] More fixes of cmakelists --- ngraph/frontend/generic/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ngraph/frontend/generic/CMakeLists.txt b/ngraph/frontend/generic/CMakeLists.txt index 2a867b7037d122..e42f64a99ba433 100644 --- a/ngraph/frontend/generic/CMakeLists.txt +++ b/ngraph/frontend/generic/CMakeLists.txt @@ -16,7 +16,7 @@ source_group("public include" FILES ${LIBRARY_PUBLIC_HEADERS}) add_library(frontend_manager SHARED ${LIBRARY_SRC} ${LIBRARY_HEADERS} ${LIBRARY_PUBLIC_HEADERS}) add_library(ngraph::frontend_manager ALIAS frontend_manager) -target_link_libraries(frontend_manager PRIVATE ${CMAKE_DL_LIBS} ${NGRAPH_LIBRARIES}) +target_link_libraries(frontend_manager PRIVATE ${CMAKE_DL_LIBS} ngraph) if(COMMAND ie_add_vs_version_file) ie_add_vs_version_file(NAME frontend_manager From fa893d363f1f4cc5da46bf5078cb13d10ef981b7 Mon Sep 17 00:00:00 2001 From: Michael Nosov Date: Fri, 30 Apr 2021 15:15:50 +0300 Subject: [PATCH 06/22] Changing template file name for frontends --- ngraph/frontend/generic/src/plugin_loader.cpp | 4 +-- ngraph/test/frontend/CMakeLists.txt | 12 +++---- ngraph/test/frontend/frontend_manager.cpp | 36 +++++++++++++++++-- ngraph/test/frontend/mock_frontend.cpp | 4 +-- 4 files changed, 44 insertions(+), 12 deletions(-) diff --git a/ngraph/frontend/generic/src/plugin_loader.cpp b/ngraph/frontend/generic/src/plugin_loader.cpp index ad75edd2ac44f3..8f47fdafd6b42e 100644 --- a/ngraph/frontend/generic/src/plugin_loader.cpp +++ b/ngraph/frontend/generic/src/plugin_loader.cpp @@ -46,14 +46,14 @@ static std::vector listFiles(const std::string& path) auto file = path + FileSeparator + std::string(ent->d_name); struct stat stat_path; stat(file.c_str(), &stat_path); - if (!S_ISDIR(stat_path.st_mode) && file.find("_frontend.so") != std::string::npos) + if (!S_ISDIR(stat_path.st_mode) && file.find("_ngraph_frontend.so") != std::string::npos) { res.push_back(std::move(file)); } } } #else - std::string searchPath = path + FileSeparator + "*_frontend.dll"; + std::string searchPath = path + FileSeparator + "*_ngraph_frontend*.dll"; WIN32_FIND_DATA fd; HANDLE handle = ::FindFirstFile(searchPath.c_str(), &fd); if (handle != INVALID_HANDLE_VALUE) diff --git a/ngraph/test/frontend/CMakeLists.txt b/ngraph/test/frontend/CMakeLists.txt index c4826dc2bb9cf8..33c72277c2b13b 100644 --- a/ngraph/test/frontend/CMakeLists.txt +++ b/ngraph/test/frontend/CMakeLists.txt @@ -3,12 +3,12 @@ # set(SRC ${CMAKE_CURRENT_SOURCE_DIR}/mock_frontend.cpp) -add_library(mock1_frontend SHARED ${SRC}) +add_library(mock1_ngraph_frontend SHARED ${SRC}) -target_compile_definitions(mock1_frontend PRIVATE "-DMOCK_VARIANT=\"1\"") +target_compile_definitions(mock1_ngraph_frontend PRIVATE "-DMOCK_VARIANT=\"1\"") -target_include_directories(mock1_frontend PRIVATE ".") +target_include_directories(mock1_ngraph_frontend PRIVATE ".") -target_include_directories(mock1_frontend PRIVATE ${FRONTEND_INCLUDE_PATH} ${NGRAPH_INCLUDE_PATH}) -target_link_libraries(mock1_frontend PRIVATE frontend_manager) -add_dependencies(unit-test mock1_frontend) +target_include_directories(mock1_ngraph_frontend PRIVATE ${FRONTEND_INCLUDE_PATH} ${NGRAPH_INCLUDE_PATH}) +target_link_libraries(mock1_ngraph_frontend PRIVATE frontend_manager) +add_dependencies(unit-test mock1_ngraph_frontend) diff --git a/ngraph/test/frontend/frontend_manager.cpp b/ngraph/test/frontend/frontend_manager.cpp index ac607b6883ab9e..f4481405db402f 100644 --- a/ngraph/test/frontend/frontend_manager.cpp +++ b/ngraph/test/frontend/frontend_manager.cpp @@ -8,6 +8,15 @@ #include "gtest/gtest.h" #include "gmock/gmock.h" +#ifdef _WIN32 + #include + #pragma comment(lib, "shlwapi.lib") +#else + #include // dirname + #include // readlink + #include // PATH_MAX +#endif + using namespace ngraph; using namespace ngraph::frontend; @@ -21,6 +30,25 @@ static int set_test_env(const char* name, const char* value) #endif } +static std::string currentExeDir() +{ +#ifdef _WIN32 + char exePath[MAX_PATH]; + auto length = GetModuleFileNameA(NULL, exePath, MAX_PATH); + PathRemoveFileSpec(exePath); + return exePath; +#else + char result[PATH_MAX]; + ssize_t count = readlink("/proc/self/exe", result, PATH_MAX); + const char *path = nullptr; + if (count != -1) + { + path = dirname(result); + } + return path; +#endif +} + TEST(FrontEndManagerTest, testAvailableFrontEnds) { FrontEndManager fem; @@ -35,11 +63,15 @@ TEST(FrontEndManagerTest, testAvailableFrontEnds) TEST(FrontEndManagerTest, testMockPluginFrontEnd) { + std::string currentDir = currentExeDir(); + std::string fePath; #ifdef _WIN32 - set_test_env("OV_FRONTEND_PATH", ".;.\\lib"); + fePath = currentDir + ";" + currentDir+"\\lib"; #else // _WIN32 - set_test_env("OV_FRONTEND_PATH", ".:./lib"); + fePath = currentDir + ":" + currentDir+"/lib"; #endif + set_test_env("OV_FRONTEND_PATH", fePath.c_str()); + FrontEndManager fem; auto frontends = fem.availableFrontEnds(); ASSERT_NE(std::find(frontends.begin(), frontends.end(), "mock1"), frontends.end()); diff --git a/ngraph/test/frontend/mock_frontend.cpp b/ngraph/test/frontend/mock_frontend.cpp index 6fc553444515da..9d1caaf22149d1 100644 --- a/ngraph/test/frontend/mock_frontend.cpp +++ b/ngraph/test/frontend/mock_frontend.cpp @@ -6,11 +6,11 @@ #include "frontend_manager/frontend_manager_defs.hpp" #include "frontend_manager/frontend_manager.hpp" -#ifdef mock1_frontend_EXPORTS // defined if we are building the plugin DLL (instead of using it) +#ifdef mock1_ngraph_frontend_EXPORTS // defined if we are building the plugin DLL (instead of using it) #define MOCK_API NGRAPH_HELPER_DLL_EXPORT #else #define MOCK_API NGRAPH_HELPER_DLL_IMPORT -#endif // mock1_frontend_EXPORTS +#endif // mock1_ngraph_frontend_EXPORTS using namespace ngraph; using namespace ngraph::frontend; From 718a1d0d8389a0d499a45ab671c41f09d9dd6085 Mon Sep 17 00:00:00 2001 From: Michael Nosov Date: Fri, 30 Apr 2021 20:22:07 +0300 Subject: [PATCH 07/22] Changed copyrights --- .../generic/include/frontend_manager/frontend_manager.hpp | 2 +- .../generic/include/frontend_manager/frontend_manager_defs.hpp | 2 +- ngraph/frontend/generic/src/frontend_manager.cpp | 2 +- ngraph/frontend/generic/src/plugin_loader.cpp | 2 +- ngraph/frontend/generic/src/plugin_loader.hpp | 2 +- ngraph/test/frontend/CMakeLists.txt | 2 +- ngraph/test/frontend/frontend_manager.cpp | 3 +-- ngraph/test/frontend/mock_frontend.cpp | 2 +- ngraph/test/frontend/shared/include/basic_api.hpp | 2 +- ngraph/test/frontend/shared/include/cut_specific_model.hpp | 2 +- ngraph/test/frontend/shared/include/partial_shape.hpp | 2 +- ngraph/test/frontend/shared/include/utils.hpp | 2 +- ngraph/test/frontend/shared/src/basic_api.cpp | 2 +- ngraph/test/frontend/shared/src/cut_specific_model.cpp | 2 +- ngraph/test/frontend/shared/src/partial_shape.cpp | 2 +- 15 files changed, 15 insertions(+), 16 deletions(-) diff --git a/ngraph/frontend/generic/include/frontend_manager/frontend_manager.hpp b/ngraph/frontend/generic/include/frontend_manager/frontend_manager.hpp index 05abab9a496d4a..bf097e04082e1d 100644 --- a/ngraph/frontend/generic/include/frontend_manager/frontend_manager.hpp +++ b/ngraph/frontend/generic/include/frontend_manager/frontend_manager.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2021 Intel Corporation +// Copyright (C) 2018-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // diff --git a/ngraph/frontend/generic/include/frontend_manager/frontend_manager_defs.hpp b/ngraph/frontend/generic/include/frontend_manager/frontend_manager_defs.hpp index 6a272380f0af89..a06dccda35ff40 100644 --- a/ngraph/frontend/generic/include/frontend_manager/frontend_manager_defs.hpp +++ b/ngraph/frontend/generic/include/frontend_manager/frontend_manager_defs.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2021 Intel Corporation +// Copyright (C) 2018-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // diff --git a/ngraph/frontend/generic/src/frontend_manager.cpp b/ngraph/frontend/generic/src/frontend_manager.cpp index 246571c5fd1b2b..bd3da0d9a8b46c 100644 --- a/ngraph/frontend/generic/src/frontend_manager.cpp +++ b/ngraph/frontend/generic/src/frontend_manager.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2021 Intel Corporation +// Copyright (C) 2018-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // diff --git a/ngraph/frontend/generic/src/plugin_loader.cpp b/ngraph/frontend/generic/src/plugin_loader.cpp index 8f47fdafd6b42e..5097fb73a4427f 100644 --- a/ngraph/frontend/generic/src/plugin_loader.cpp +++ b/ngraph/frontend/generic/src/plugin_loader.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2021 Intel Corporation +// Copyright (C) 2018-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // diff --git a/ngraph/frontend/generic/src/plugin_loader.hpp b/ngraph/frontend/generic/src/plugin_loader.hpp index de25b20ab08985..2df0d9d4a8119b 100644 --- a/ngraph/frontend/generic/src/plugin_loader.hpp +++ b/ngraph/frontend/generic/src/plugin_loader.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2021 Intel Corporation +// Copyright (C) 2018-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // diff --git a/ngraph/test/frontend/CMakeLists.txt b/ngraph/test/frontend/CMakeLists.txt index 33c72277c2b13b..d532d6f4825b78 100644 --- a/ngraph/test/frontend/CMakeLists.txt +++ b/ngraph/test/frontend/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (C) 2021 Intel Corporation +# Copyright (C) 2018-2021 Intel Corporation # SPDX-License-Identifier: Apache-2.0 # diff --git a/ngraph/test/frontend/frontend_manager.cpp b/ngraph/test/frontend/frontend_manager.cpp index f4481405db402f..dda5a28c7ef5f7 100644 --- a/ngraph/test/frontend/frontend_manager.cpp +++ b/ngraph/test/frontend/frontend_manager.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2021 Intel Corporation +// Copyright (C) 2018-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // @@ -14,7 +14,6 @@ #else #include // dirname #include // readlink - #include // PATH_MAX #endif using namespace ngraph; diff --git a/ngraph/test/frontend/mock_frontend.cpp b/ngraph/test/frontend/mock_frontend.cpp index 9d1caaf22149d1..f7d07289cabb0f 100644 --- a/ngraph/test/frontend/mock_frontend.cpp +++ b/ngraph/test/frontend/mock_frontend.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2021 Intel Corporation +// Copyright (C) 2018-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // diff --git a/ngraph/test/frontend/shared/include/basic_api.hpp b/ngraph/test/frontend/shared/include/basic_api.hpp index 3227e99ce3b00a..cf2f37f13aa0cf 100644 --- a/ngraph/test/frontend/shared/include/basic_api.hpp +++ b/ngraph/test/frontend/shared/include/basic_api.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2021 Intel Corporation +// Copyright (C) 2018-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // diff --git a/ngraph/test/frontend/shared/include/cut_specific_model.hpp b/ngraph/test/frontend/shared/include/cut_specific_model.hpp index 1d82ea7e51c49a..fefae85da44013 100644 --- a/ngraph/test/frontend/shared/include/cut_specific_model.hpp +++ b/ngraph/test/frontend/shared/include/cut_specific_model.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2021 Intel Corporation +// Copyright (C) 2018-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // diff --git a/ngraph/test/frontend/shared/include/partial_shape.hpp b/ngraph/test/frontend/shared/include/partial_shape.hpp index b6f50e08d569a4..f06f40cf576655 100644 --- a/ngraph/test/frontend/shared/include/partial_shape.hpp +++ b/ngraph/test/frontend/shared/include/partial_shape.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2021 Intel Corporation +// Copyright (C) 2018-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // diff --git a/ngraph/test/frontend/shared/include/utils.hpp b/ngraph/test/frontend/shared/include/utils.hpp index 00fb7be62caa7a..6bb4106c02e042 100644 --- a/ngraph/test/frontend/shared/include/utils.hpp +++ b/ngraph/test/frontend/shared/include/utils.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2021 Intel Corporation +// Copyright (C) 2018-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // diff --git a/ngraph/test/frontend/shared/src/basic_api.cpp b/ngraph/test/frontend/shared/src/basic_api.cpp index 9d6a52e724ab09..cbd72cb13f77aa 100644 --- a/ngraph/test/frontend/shared/src/basic_api.cpp +++ b/ngraph/test/frontend/shared/src/basic_api.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2021 Intel Corporation +// Copyright (C) 2018-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // diff --git a/ngraph/test/frontend/shared/src/cut_specific_model.cpp b/ngraph/test/frontend/shared/src/cut_specific_model.cpp index 090c8698585d20..022d748e4f2289 100644 --- a/ngraph/test/frontend/shared/src/cut_specific_model.cpp +++ b/ngraph/test/frontend/shared/src/cut_specific_model.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2021 Intel Corporation +// Copyright (C) 2018-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // diff --git a/ngraph/test/frontend/shared/src/partial_shape.cpp b/ngraph/test/frontend/shared/src/partial_shape.cpp index 254d26eff98de3..8eb5bb5dc04925 100644 --- a/ngraph/test/frontend/shared/src/partial_shape.cpp +++ b/ngraph/test/frontend/shared/src/partial_shape.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2021 Intel Corporation +// Copyright (C) 2018-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // From 8e28efd5f84e5d96eb36b6c6e3903404fc3e96f6 Mon Sep 17 00:00:00 2001 From: Michael Nosov Date: Fri, 30 Apr 2021 22:59:30 +0300 Subject: [PATCH 08/22] Reuse ngraph-utils for file-related operations --- ngraph/frontend/generic/src/plugin_loader.cpp | 48 ++++++++----------- ngraph/test/frontend/frontend_manager.cpp | 38 ++------------- 2 files changed, 24 insertions(+), 62 deletions(-) diff --git a/ngraph/frontend/generic/src/plugin_loader.cpp b/ngraph/frontend/generic/src/plugin_loader.cpp index 5097fb73a4427f..65aac0d83ccc22 100644 --- a/ngraph/frontend/generic/src/plugin_loader.cpp +++ b/ngraph/frontend/generic/src/plugin_loader.cpp @@ -14,6 +14,7 @@ #include #include #include +#include "ngraph/file_util.hpp" #include "plugin_loader.hpp" @@ -34,40 +35,31 @@ using namespace ngraph::frontend; static std::vector listFiles(const std::string& path) { std::vector res; -#ifndef WIN32 - struct dirent *ent; - DIR *dir = opendir(path.c_str()); - if (dir != nullptr) + try { - std::unique_ptr closeGuard(dir, [](DIR *d) - { closedir(d); }); - while ((ent = readdir(dir)) != NULL) + ngraph::file_util::iterate_files(path, [&res](const std::string& file, bool is_dir) { - auto file = path + FileSeparator + std::string(ent->d_name); - struct stat stat_path; - stat(file.c_str(), &stat_path); - if (!S_ISDIR(stat_path.st_mode) && file.find("_ngraph_frontend.so") != std::string::npos) + if (!is_dir) { - res.push_back(std::move(file)); +#ifdef _WIN32 + if (file.find("_ngraph_frontend") != std::string::npos && + file.find(".dll") != std::string::npos) + { + res.push_back(file); + } +#else + if (file.find("_ngraph_frontend.so") != std::string::npos) + { + res.push_back(file); + } +#endif } - } + }, false, true); } -#else - std::string searchPath = path + FileSeparator + "*_ngraph_frontend*.dll"; - WIN32_FIND_DATA fd; - HANDLE handle = ::FindFirstFile(searchPath.c_str(), &fd); - if (handle != INVALID_HANDLE_VALUE) + catch(...) { - do - { - if (!(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ) - { - res.push_back(path + FileSeparator + fd.cFileName); - } - } while(::FindNextFile(handle, &fd)); - ::FindClose(handle); + // Ignore exceptions } -#endif return res; } @@ -75,10 +67,8 @@ std::vector ngraph::frontend::loadPlugins(const std::string& dirName { auto files = listFiles(dirName); std::vector res; - // std::cout << "Loading directory: " << dirName << "\n"; for (const auto& file : files) { - // std::cout << "Checking plugin: " << file << "\n"; auto shared_object = DLOPEN(file); if (!shared_object) { diff --git a/ngraph/test/frontend/frontend_manager.cpp b/ngraph/test/frontend/frontend_manager.cpp index dda5a28c7ef5f7..cfd59a57200780 100644 --- a/ngraph/test/frontend/frontend_manager.cpp +++ b/ngraph/test/frontend/frontend_manager.cpp @@ -8,13 +8,8 @@ #include "gtest/gtest.h" #include "gmock/gmock.h" -#ifdef _WIN32 - #include - #pragma comment(lib, "shlwapi.lib") -#else - #include // dirname - #include // readlink -#endif +#include "backend.hpp" +#include "ngraph/file_util.hpp" using namespace ngraph; using namespace ngraph::frontend; @@ -29,25 +24,6 @@ static int set_test_env(const char* name, const char* value) #endif } -static std::string currentExeDir() -{ -#ifdef _WIN32 - char exePath[MAX_PATH]; - auto length = GetModuleFileNameA(NULL, exePath, MAX_PATH); - PathRemoveFileSpec(exePath); - return exePath; -#else - char result[PATH_MAX]; - ssize_t count = readlink("/proc/self/exe", result, PATH_MAX); - const char *path = nullptr; - if (count != -1) - { - path = dirname(result); - } - return path; -#endif -} - TEST(FrontEndManagerTest, testAvailableFrontEnds) { FrontEndManager fem; @@ -62,18 +38,14 @@ TEST(FrontEndManagerTest, testAvailableFrontEnds) TEST(FrontEndManagerTest, testMockPluginFrontEnd) { - std::string currentDir = currentExeDir(); - std::string fePath; -#ifdef _WIN32 - fePath = currentDir + ";" + currentDir+"\\lib"; -#else // _WIN32 - fePath = currentDir + ":" + currentDir+"/lib"; -#endif + std::string fePath = + ngraph::file_util::get_directory(ngraph::runtime::Backend::get_backend_shared_library_search_directory()); set_test_env("OV_FRONTEND_PATH", fePath.c_str()); FrontEndManager fem; auto frontends = fem.availableFrontEnds(); ASSERT_NE(std::find(frontends.begin(), frontends.end(), "mock1"), frontends.end()); + set_test_env("OV_FRONTEND_PATH", ""); } TEST(FrontEndManagerTest, testDefaultFrontEnd) From 36c6534c32d89d88f3768c5795b85bb44b8b458f Mon Sep 17 00:00:00 2001 From: Michael Nosov Date: Sat, 1 May 2021 13:08:37 +0300 Subject: [PATCH 09/22] Correct of frontend file extension for macos More code coverage --- ngraph/frontend/generic/src/plugin_loader.cpp | 15 +++++++-------- ngraph/frontend/generic/src/plugin_loader.hpp | 4 ++-- ngraph/test/frontend/frontend_manager.cpp | 7 +++++++ 3 files changed, 16 insertions(+), 10 deletions(-) diff --git a/ngraph/frontend/generic/src/plugin_loader.cpp b/ngraph/frontend/generic/src/plugin_loader.cpp index 65aac0d83ccc22..71724407ea53b8 100644 --- a/ngraph/frontend/generic/src/plugin_loader.cpp +++ b/ngraph/frontend/generic/src/plugin_loader.cpp @@ -39,20 +39,19 @@ static std::vector listFiles(const std::string& path) { ngraph::file_util::iterate_files(path, [&res](const std::string& file, bool is_dir) { - if (!is_dir) + if (!is_dir && file.find("_ngraph_frontend") != std::string::npos) { #ifdef _WIN32 - if (file.find("_ngraph_frontend") != std::string::npos && - file.find(".dll") != std::string::npos) - { - res.push_back(file); - } + std::string ext = ".dll"; +#elif defined(__APPLE__) + std::string ext = ".dylib"; #else - if (file.find("_ngraph_frontend.so") != std::string::npos) + std::string ext = ".so"; +#endif + if (file.find(ext) != std::string::npos) { res.push_back(file); } -#endif } }, false, true); } diff --git a/ngraph/frontend/generic/src/plugin_loader.hpp b/ngraph/frontend/generic/src/plugin_loader.hpp index 2df0d9d4a8119b..51da663fc8520a 100644 --- a/ngraph/frontend/generic/src/plugin_loader.hpp +++ b/ngraph/frontend/generic/src/plugin_loader.hpp @@ -9,10 +9,10 @@ #ifdef _WIN32 const char FileSeparator[] = "\\"; const char PathSeparator[] = ";"; -#else // _WIN32 +#else const char FileSeparator[] = "/"; const char PathSeparator[] = ":"; -#endif +#endif // _WIN32 namespace ngraph { diff --git a/ngraph/test/frontend/frontend_manager.cpp b/ngraph/test/frontend/frontend_manager.cpp index cfd59a57200780..b7e8769d118d1e 100644 --- a/ngraph/test/frontend/frontend_manager.cpp +++ b/ngraph/test/frontend/frontend_manager.cpp @@ -11,6 +11,12 @@ #include "backend.hpp" #include "ngraph/file_util.hpp" +#ifdef _WIN32 +const char FrontEndPathSeparator[] = ";"; +#else +const char FrontEndPathSeparator[] = ":"; +#endif // _WIN32 + using namespace ngraph; using namespace ngraph::frontend; @@ -40,6 +46,7 @@ TEST(FrontEndManagerTest, testMockPluginFrontEnd) { std::string fePath = ngraph::file_util::get_directory(ngraph::runtime::Backend::get_backend_shared_library_search_directory()); + fePath = fePath + FrontEndPathSeparator + "someInvalidPath"; set_test_env("OV_FRONTEND_PATH", fePath.c_str()); FrontEndManager fem; From fc9d05cb2008ed1169f64cd11248e9014f89b73f Mon Sep 17 00:00:00 2001 From: Michael Nosov Date: Wed, 5 May 2021 18:09:25 +0300 Subject: [PATCH 10/22] Renamed all methods to according to ngraph-style In case of unset or empty OV_FRONTENT_PATH - load plugins from current working directory --- .../frontend_manager/frontend_manager.hpp | 114 +++++----- .../frontend/generic/src/frontend_manager.cpp | 204 +++++++++--------- ngraph/test/frontend/frontend_manager.cpp | 107 ++++----- ngraph/test/frontend/shared/src/basic_api.cpp | 48 ++--- .../shared/src/cut_specific_model.cpp | 40 ++-- .../frontend/shared/src/partial_shape.cpp | 10 +- 6 files changed, 264 insertions(+), 259 deletions(-) diff --git a/ngraph/frontend/generic/include/frontend_manager/frontend_manager.hpp b/ngraph/frontend/generic/include/frontend_manager/frontend_manager.hpp index bf097e04082e1d..06b00cf3625446 100644 --- a/ngraph/frontend/generic/include/frontend_manager/frontend_manager.hpp +++ b/ngraph/frontend/generic/include/frontend_manager/frontend_manager.hpp @@ -70,63 +70,63 @@ namespace ngraph /// \brief All associated names (synonyms) that identify this place in the graph in a framework specific way /// \return A vector of strings each representing a name that identifies this place in the graph. /// Can be empty if there are no names associated with this place or name cannot be attached. - virtual std::vector getNames() const; + virtual std::vector get_names() const; /// \brief Returns references to all operation nodes that consume data from this place /// \note It can be called for any kind of graph place searching for the first consuming opertions. /// /// \param outputPortIndex If place is an operational node it specifies which output port should be considered /// \return A vector with all operation node references that consumes data from this place - virtual std::vector getConsumingOperations(int outputPortIndex = -1) const; + virtual std::vector get_consuming_operations(int outputPortIndex = -1) const; /// \brief Returns a tensor place that gets data from this place; applicable for operations, output ports and output edges /// /// \param outputPortIndex Output port index if the current place is an operation node and has multiple output ports /// \return A tensor place which hold the resulting value for this place - virtual Ptr getTargetTensor(int outputPortIndex = -1) const; + virtual Ptr get_target_tensor(int outputPortIndex = -1) const; /// \brief Returns a tensor place that supplies data for this place; applicable for operations, input ports and input edges /// /// \param inputPortIndex Input port index for operational nodes /// \return A tensor place which supplies data for this place - virtual Ptr getSourceTensor(int inputPortIndex = -1) const; + virtual Ptr get_source_tensor(int inputPortIndex = -1) const; /// \brief Get an operation node place that immediately produces data for this place /// /// \param inputPortIndex If a given place is itself an operation node, this specifies a port index /// \return An operation place that produces data for this place - virtual Ptr getProducingOperation(int inputPortIndex = -1) const; + virtual Ptr get_producing_operation(int inputPortIndex = -1) const; /// Returns a port that produces data for this place - virtual Ptr getProducingPort() const; + virtual Ptr get_producing_port() const; /// For operation node returns reference to an input port with specified index - virtual Ptr getInputPort(int inputPortIndex = -1) const; + virtual Ptr get_input_port(int inputPortIndex = -1) const; /// For operation node returns reference to an input port with specified name and index - virtual Ptr getInputPort(const std::string& inputName, int inputPortIndex = -1) const; + virtual Ptr get_input_port(const std::string& inputName, int inputPortIndex = -1) const; /// For operation node returns reference to an output port with specified index - virtual Ptr getOutputPort(int outputPortIndex = -1) const; + virtual Ptr get_output_port(int outputPortIndex = -1) const; /// For operation node returns reference to an output port with specified name and index - virtual Ptr getOutputPort(const std::string& outputName, int outputPortIndex = -1) const; + virtual Ptr get_output_port(const std::string& outputName, int outputPortIndex = -1) const; /// Returns all input ports that consume data flows through this place - virtual std::vector getConsumingPorts() const; + virtual std::vector get_consuming_ports() const; /// Returns true if this place is input for a model. - virtual bool isInput() const; + virtual bool is_input() const; /// Returns true if this place is output for a model. - virtual bool isOutput() const; + virtual bool is_output() const; /// Returns true if another place is the same as this place. - virtual bool isEqual(Ptr another) const; + virtual bool is_equal(Ptr another) const; /// \brief Returns true if another place points to the same data. /// \note The same data means all places on path: output port -> output edge -> tensor -> input edge -> input port. - virtual bool isEqualData(Ptr another) const; + virtual bool is_equal_data(Ptr another) const; }; @@ -142,7 +142,7 @@ namespace ngraph /// /// Specific front-end implementation is supposed to have a lazy implementation for all methods, not doing /// a complete load of a model without an explicit method call. For example, the list of all inputs -/// are not pre-fetched by InputModel derived class instance creation, but only when getInputs method is called. +/// are not pre-fetched by InputModel derived class instance creation, but only when get_inputs method is called. /// But it is not an obligation, the most convenient way should be chosen depending on the framework model /// representation. /// @@ -165,7 +165,7 @@ namespace ngraph /// Usually framework models have a dedicated artifact to code model input, it can be a tensor without producer, /// that writes to it in ONNX, or a special operation like Placeholder in TensorFlow. /// \return A vector of input place references - virtual std::vector getInputs() const; + virtual std::vector get_inputs() const; /// \brief Returns all output for a model /// An output is a terminal place in a graph where data escapes the flow. It can be a tensor, port, operation; @@ -174,91 +174,91 @@ namespace ngraph /// by a frontend itself, not a framework. For example, all output ports without consumers may be considered /// as outputs. /// \return A vector of output place references - virtual std::vector getOutputs() const; + virtual std::vector get_outputs() const; /// Returns a tensor place by a tensor name following framework conventions, or nullptr if a tensor with this name doesn't exist. - virtual Place::Ptr getPlaceByTensorName(const std::string& tensorName) const; + virtual Place::Ptr get_place_by_tensor_name(const std::string& tensorName) const; /// Returns an operation place by a tensor name following framework conventions, or nullptr if an operation with this name doesn't exist. - virtual Place::Ptr getPlaceByOperationName(const std::string& operationName); + virtual Place::Ptr get_place_by_operation_name(const std::string& operationName); /// Returns an input port. - virtual Place::Ptr getPlaceByOperationAndInputPort(const std::string& operationName, int inputPortIndex); + virtual Place::Ptr get_place_by_operation_and_input_port(const std::string& operationName, int inputPortIndex); /// Returns an output port. - virtual Place::Ptr getPlaceByOperationAndOutputPort(const std::string& operationName, int outputPortIndex); + virtual Place::Ptr get_place_by_operation_and_output_port(const std::string& operationName, int outputPortIndex); ///// Naming and annotation ///// - virtual void setNameForTensor(Place::Ptr tensor, const std::string& newName); + virtual void set_name_for_tensor(Place::Ptr tensor, const std::string& newName); - virtual void addNameForTensor(Place::Ptr tensor, const std::string& newName); + virtual void add_name_for_tensor(Place::Ptr tensor, const std::string& newName); - virtual void setNameForOperation(Place::Ptr operation, const std::string& newName); + virtual void set_name_for_operation(Place::Ptr operation, const std::string& newName); - virtual void freeNameForTensor(const std::string& name); + virtual void free_name_for_tensor(const std::string& name); - virtual void freeNameForOperation(const std::string& name); + virtual void free_name_for_operation(const std::string& name); - virtual void setNameForDimension(Place::Ptr place, size_t shapeDimIndex, const std::string& dimName); + virtual void set_name_for_dimension(Place::Ptr place, size_t shapeDimIndex, const std::string& dimName); ///// Topology Editing ///// /// Cut immediately before this place and assign this place as new input; prune all nodes that don't contribute to any output. - virtual void cutAndAddNewInput(Place::Ptr place, const std::string& newNameOptional = ""); + virtual void cut_and_add_new_input(Place::Ptr place, const std::string& newNameOptional = ""); /// Cut immediately after this place and assign this place as new output; prune all nodes that don't contribute to any output. - virtual void cutAndAddNewOutput(Place::Ptr place, const std::string& newNameOptional = ""); + virtual void cut_and_add_new_output(Place::Ptr place, const std::string& newNameOptional = ""); /// \brief Assign this place as new output or add necessary nodes to represent a new output. /// /// \param place Anchor point to add an output /// \return new output place, may be the same as a given place - virtual Place::Ptr addOutput(Place::Ptr place); + virtual Place::Ptr add_output(Place::Ptr place); /// Removes any sinks directly attached to this place with all inbound data flow if it is not required by any other output. - virtual void removeOutput(Place::Ptr place); + virtual void remove_output(Place::Ptr place); /// Removes an input place and all data flow that depends on it. // TODO: remove it as something not practically useful in the API? - virtual void removeInput(Place::Ptr place); + virtual void remove_input(Place::Ptr place); /// Replaces all existing outputs with new ones removing all data flow that is not required for new outputs. /// /// \param outputs Vector with places that will become new outputs; may intersect existing outputs. - virtual void overrideAllOutputs(const std::vector& outputs); + virtual void override_all_outputs(const std::vector& outputs); /// \brief Modifies the graph to use new inputs instead of existing ones. New inputs should completely satisfy all existing outputs. - virtual void overrideAllInputs(const std::vector& inputs); + virtual void override_all_inputs(const std::vector& inputs); /// Leaves only subgraph that are defined by new inputs and new outputs. - virtual void extractSubgraph(const std::vector& inputs, const std::vector& outputs); + virtual void extract_subgraph(const std::vector& inputs, const std::vector& outputs); ///// Setting tensor properties ///// /// Sets shape that would be used by default for this place; place should be uniquely refer to some data. // TODO: define clearly which scenario requires it -- currently it should satisfy requirement to have statically defined shapes for tensors - virtual void setDefaultShape(Place::Ptr place, const ngraph::Shape&); + virtual void set_default_shape(Place::Ptr place, const ngraph::Shape&); /// Defines all possible shape that may be used for this place; place should be uniquely refer to some data. /// This partial shape will be converted to corresponding shape of results ngraph nodes and will define shape inference /// when the model is converted to ngraph. - virtual void setPartialShape(Place::Ptr place, const ngraph::PartialShape&); + virtual void set_partial_shape(Place::Ptr place, const ngraph::PartialShape&); /// Returns current partial shape used for this place - virtual ngraph::PartialShape getPartialShape(Place::Ptr place) const; + virtual ngraph::PartialShape get_partial_shape(Place::Ptr place) const; /// Sets new element type for a place. - virtual void setElementType(Place::Ptr place, const ngraph::element::Type&); + virtual void set_element_type(Place::Ptr place, const ngraph::element::Type&); /// Freezes a tensor with statically defined value or replace existing value for already constant node or tensor. - virtual void setTensorValue(Place::Ptr place, const void *value); + virtual void set_tensor_value(Place::Ptr place, const void *value); /// Defines partial value (lower bound and upper bound) for a tensor place. // TODO: more details for minValue and maxValue format; who defines shape? - virtual void setTensorPartialValue(Place::Ptr place, const void *minValue, const void *maxValue); + virtual void set_tensor_partial_value(Place::Ptr place, const void *minValue, const void *maxValue); // TODO: Document "inputs/output assymetry" in more details @@ -278,17 +278,17 @@ namespace ngraph virtual ~FrontEnd(); - virtual InputModel::Ptr loadFromFile(const std::string& path) const; + virtual InputModel::Ptr load_from_file(const std::string& path) const; - virtual InputModel::Ptr loadFromFiles(const std::vector& paths) const; + virtual InputModel::Ptr load_from_files(const std::vector& paths) const; - virtual InputModel::Ptr loadFromMemory(const void *model) const; + virtual InputModel::Ptr load_from_memory(const void *model) const; - virtual InputModel::Ptr loadFromMemoryFragments(const std::vector& modelParts) const; + virtual InputModel::Ptr load_from_memory_fragments(const std::vector& modelParts) const; - virtual InputModel::Ptr loadFromStream(std::istream& path) const; + virtual InputModel::Ptr load_from_stream(std::istream& path) const; - virtual InputModel::Ptr loadFromStreams(const std::vector& paths) const; + virtual InputModel::Ptr load_from_streams(const std::vector& paths) const; // Extra ctors may be provided by FW-specialized data structure for graph representaion @@ -296,13 +296,13 @@ namespace ngraph virtual std::shared_ptr convert(InputModel::Ptr model) const; /// Completely convert the remaining, not converted part of a function. - virtual std::shared_ptr - convert(std::shared_ptr partiallyConverted) const; + virtual std::shared_ptr convert( + std::shared_ptr partiallyConverted) const; /// Convert only those parts of the model that can be converted leaving others as-is. /// Converted parts are not normalized by additional transformations; normalize function /// or another form of convert function should be called to finalize the conversion process. - virtual std::shared_ptr convertPartially(InputModel::Ptr model) const; + virtual std::shared_ptr convert_partially(InputModel::Ptr model) const; /// Convert operations with one-to-one mapping with decoding nodes. /// Each decoding node is an nGraph node representing a single FW operation node with all attributes @@ -333,15 +333,15 @@ namespace ngraph ~FrontEndManager(); - FrontEnd::Ptr loadByFramework(const std::string& framework, - FrontEndCapabilities fec = FrontEndCapabilities::FEC_DEFAULT); + FrontEnd::Ptr load_by_framework(const std::string& framework, + FrontEndCapabilities fec = FrontEndCapabilities::FEC_DEFAULT); - FrontEnd::Ptr loadByModel(const std::string& path, - FrontEndCapabilities fec = FrontEndCapabilities::FEC_DEFAULT); + FrontEnd::Ptr load_by_model(const std::string& path, + FrontEndCapabilities fec = FrontEndCapabilities::FEC_DEFAULT); - std::vector availableFrontEnds() const; + std::vector get_available_front_ends() const; - void registerFrontEnd(const std::string& name, FrontEndFactory creator); + void register_front_end(const std::string& name, FrontEndFactory creator); private: class Impl; diff --git a/ngraph/frontend/generic/src/frontend_manager.cpp b/ngraph/frontend/generic/src/frontend_manager.cpp index bd3da0d9a8b46c..02260d53cdfe07 100644 --- a/ngraph/frontend/generic/src/frontend_manager.cpp +++ b/ngraph/frontend/generic/src/frontend_manager.cpp @@ -87,6 +87,10 @@ namespace ngraph } registerFromDir(envPath.substr(start, sepPos)); } + else + { + registerFromDir("."); + } } }; @@ -96,22 +100,22 @@ namespace ngraph FrontEndManager::~FrontEndManager() = default; - FrontEnd::Ptr FrontEndManager::loadByFramework(const std::string& framework, FrontEndCapabilities fec) + FrontEnd::Ptr FrontEndManager::load_by_framework(const std::string& framework, FrontEndCapabilities fec) { return m_impl->loadByFramework(framework, fec); } - FrontEnd::Ptr FrontEndManager::loadByModel(const std::string& path, FrontEndCapabilities fec) + FrontEnd::Ptr FrontEndManager::load_by_model(const std::string& path, FrontEndCapabilities fec) { return m_impl->loadByModel(path, fec); } - std::vector FrontEndManager::availableFrontEnds() const + std::vector FrontEndManager::get_available_front_ends() const { return m_impl->availableFrontEnds(); } - void FrontEndManager::registerFrontEnd(const std::string& name, FrontEndFactory creator) + void FrontEndManager::register_front_end(const std::string& name, FrontEndFactory creator) { m_impl->registerFrontEnd(name, creator); } @@ -122,34 +126,34 @@ namespace ngraph FrontEnd::~FrontEnd() = default; - InputModel::Ptr FrontEnd::loadFromFile(const std::string& paths) const + InputModel::Ptr FrontEnd::load_from_file(const std::string& path) const { - FRONT_END_NOT_IMPLEMENTED(loadFromFile); + FRONT_END_NOT_IMPLEMENTED(load_from_file); } - InputModel::Ptr FrontEnd::loadFromFiles(const std::vector& paths) const + InputModel::Ptr FrontEnd::load_from_files(const std::vector& paths) const { - FRONT_END_NOT_IMPLEMENTED(loadFromFiles); + FRONT_END_NOT_IMPLEMENTED(load_from_files); } - InputModel::Ptr FrontEnd::loadFromMemory(const void *model) const + InputModel::Ptr FrontEnd::load_from_memory(const void *model) const { - FRONT_END_NOT_IMPLEMENTED(loadFromMemory); + FRONT_END_NOT_IMPLEMENTED(load_from_memory); } - InputModel::Ptr FrontEnd::loadFromMemoryFragments(const std::vector& modelParts) const + InputModel::Ptr FrontEnd::load_from_memory_fragments(const std::vector& modelParts) const { - FRONT_END_NOT_IMPLEMENTED(loadFromMemoryFragments); + FRONT_END_NOT_IMPLEMENTED(load_from_memory_fragments); } - InputModel::Ptr FrontEnd::loadFromStream(std::istream& path) const + InputModel::Ptr FrontEnd::load_from_stream(std::istream& path) const { - FRONT_END_NOT_IMPLEMENTED(loadFromStream); + FRONT_END_NOT_IMPLEMENTED(load_from_stream); } - InputModel::Ptr FrontEnd::loadFromStreams(const std::vector& paths) const + InputModel::Ptr FrontEnd::load_from_streams(const std::vector& paths) const { - FRONT_END_NOT_IMPLEMENTED(loadFromStreams); + FRONT_END_NOT_IMPLEMENTED(load_from_streams); } std::shared_ptr FrontEnd::convert(InputModel::Ptr model) const @@ -162,9 +166,9 @@ namespace ngraph FRONT_END_NOT_IMPLEMENTED(convert); } - std::shared_ptr FrontEnd::convertPartially(InputModel::Ptr model) const + std::shared_ptr FrontEnd::convert_partially(InputModel::Ptr model) const { - FRONT_END_NOT_IMPLEMENTED(convertPartially); + FRONT_END_NOT_IMPLEMENTED(convert_partially); } std::shared_ptr FrontEnd::decode(InputModel::Ptr model) const @@ -178,212 +182,212 @@ namespace ngraph } //----------- InputModel --------------------------- - std::vector InputModel::getInputs() const + std::vector InputModel::get_inputs() const { - FRONT_END_NOT_IMPLEMENTED(getInputs); + FRONT_END_NOT_IMPLEMENTED(get_inputs); } - std::vector InputModel::getOutputs() const + std::vector InputModel::get_outputs() const { - FRONT_END_NOT_IMPLEMENTED(getOutputs); + FRONT_END_NOT_IMPLEMENTED(get_outputs); } - Place::Ptr InputModel::getPlaceByTensorName(const std::string& tensorName) const + Place::Ptr InputModel::get_place_by_tensor_name(const std::string& tensorName) const { - FRONT_END_NOT_IMPLEMENTED(getPlaceByTensorName); + FRONT_END_NOT_IMPLEMENTED(get_place_by_tensor_name); } - Place::Ptr InputModel::getPlaceByOperationName(const std::string& operationName) + Place::Ptr InputModel::get_place_by_operation_name(const std::string& operationName) { - FRONT_END_NOT_IMPLEMENTED(getPlaceByOperationName); + FRONT_END_NOT_IMPLEMENTED(get_place_by_operation_name); } - Place::Ptr InputModel::getPlaceByOperationAndInputPort(const std::string& operationName, int inputPortIndex) + Place::Ptr InputModel::get_place_by_operation_and_input_port(const std::string& operationName, int inputPortIndex) { - FRONT_END_NOT_IMPLEMENTED(getPlaceByOperationAndInputPort); + FRONT_END_NOT_IMPLEMENTED(get_place_by_operation_and_input_port); } - Place::Ptr InputModel::getPlaceByOperationAndOutputPort(const std::string& operationName, int outputPortIndex) + Place::Ptr InputModel::get_place_by_operation_and_output_port(const std::string& operationName, int outputPortIndex) { - FRONT_END_NOT_IMPLEMENTED(getPlaceByOperationAndOutputPort); + FRONT_END_NOT_IMPLEMENTED(get_place_by_operation_and_output_port); } - void InputModel::setNameForTensor(Place::Ptr tensor, const std::string& newName) + void InputModel::set_name_for_tensor(Place::Ptr tensor, const std::string& newName) { - FRONT_END_NOT_IMPLEMENTED(setNameForTensor); + FRONT_END_NOT_IMPLEMENTED(set_name_for_tensor); } - void InputModel::addNameForTensor(Place::Ptr tensor, const std::string& newName) + void InputModel::add_name_for_tensor(Place::Ptr tensor, const std::string& newName) { - FRONT_END_NOT_IMPLEMENTED(addNameForTensor); + FRONT_END_NOT_IMPLEMENTED(add_name_for_tensor); } - void InputModel::setNameForOperation(Place::Ptr operation, const std::string& newName) + void InputModel::set_name_for_operation(Place::Ptr operation, const std::string& newName) { - FRONT_END_NOT_IMPLEMENTED(setNameForOperation); + FRONT_END_NOT_IMPLEMENTED(set_name_for_operation); } - void InputModel::freeNameForTensor(const std::string& name) + void InputModel::free_name_for_tensor(const std::string& name) { - FRONT_END_NOT_IMPLEMENTED(freeNameForTensor); + FRONT_END_NOT_IMPLEMENTED(free_name_for_tensor); } - void InputModel::freeNameForOperation(const std::string& name) + void InputModel::free_name_for_operation(const std::string& name) { - FRONT_END_NOT_IMPLEMENTED(freeNameForOperation); + FRONT_END_NOT_IMPLEMENTED(free_name_for_operation); } - void InputModel::setNameForDimension(Place::Ptr place, size_t shapeDimIndex, const std::string& dimName) + void InputModel::set_name_for_dimension(Place::Ptr place, size_t shapeDimIndex, const std::string& dimName) { - FRONT_END_NOT_IMPLEMENTED(setNameForDimension); + FRONT_END_NOT_IMPLEMENTED(set_name_for_dimension); } - void InputModel::cutAndAddNewInput(Place::Ptr place, const std::string& newNameOptional) + void InputModel::cut_and_add_new_input(Place::Ptr place, const std::string& newNameOptional) { - FRONT_END_NOT_IMPLEMENTED(cutAndAddNewInput); + FRONT_END_NOT_IMPLEMENTED(cut_and_add_new_input); } - void InputModel::cutAndAddNewOutput(Place::Ptr place, const std::string& newNameOptional) + void InputModel::cut_and_add_new_output(Place::Ptr place, const std::string& newNameOptional) { - FRONT_END_NOT_IMPLEMENTED(cutAndAddNewOutput); + FRONT_END_NOT_IMPLEMENTED(cut_and_add_new_output); } - Place::Ptr InputModel::addOutput(Place::Ptr place) + Place::Ptr InputModel::add_output(Place::Ptr place) { - FRONT_END_NOT_IMPLEMENTED(addOutput); + FRONT_END_NOT_IMPLEMENTED(add_output); } - void InputModel::removeOutput(Place::Ptr place) + void InputModel::remove_output(Place::Ptr place) { - FRONT_END_NOT_IMPLEMENTED(removeOutput); + FRONT_END_NOT_IMPLEMENTED(remove_output); } - void InputModel::removeInput(Place::Ptr place) + void InputModel::remove_input(Place::Ptr place) { - FRONT_END_NOT_IMPLEMENTED(removeInput); + FRONT_END_NOT_IMPLEMENTED(remove_input); } - void InputModel::overrideAllOutputs(const std::vector& outputs) + void InputModel::override_all_outputs(const std::vector& outputs) { - FRONT_END_NOT_IMPLEMENTED(overrideAllOutputs); + FRONT_END_NOT_IMPLEMENTED(override_all_outputs); } - void InputModel::overrideAllInputs(const std::vector& inputs) + void InputModel::override_all_inputs(const std::vector& inputs) { - FRONT_END_NOT_IMPLEMENTED(overrideAllInputs); + FRONT_END_NOT_IMPLEMENTED(override_all_inputs); } void - InputModel::extractSubgraph(const std::vector& inputs, const std::vector& outputs) + InputModel::extract_subgraph(const std::vector& inputs, const std::vector& outputs) { - FRONT_END_NOT_IMPLEMENTED(extractSubgraph); + FRONT_END_NOT_IMPLEMENTED(extract_subgraph); } // Setting tensor properties - void InputModel::setDefaultShape(Place::Ptr place, const ngraph::Shape&) + void InputModel::set_default_shape(Place::Ptr place, const ngraph::Shape&) { - FRONT_END_NOT_IMPLEMENTED(setDefaultShape); + FRONT_END_NOT_IMPLEMENTED(set_default_shape); } - void InputModel::setPartialShape(Place::Ptr place, const ngraph::PartialShape&) + void InputModel::set_partial_shape(Place::Ptr place, const ngraph::PartialShape&) { - FRONT_END_NOT_IMPLEMENTED(setPartialShape); + FRONT_END_NOT_IMPLEMENTED(set_partial_shape); } - ngraph::PartialShape InputModel::getPartialShape(Place::Ptr place) const + ngraph::PartialShape InputModel::get_partial_shape(Place::Ptr place) const { - FRONT_END_NOT_IMPLEMENTED(setPartialShape); + FRONT_END_NOT_IMPLEMENTED(set_partial_shape); } - void InputModel::setElementType(Place::Ptr place, const ngraph::element::Type&) + void InputModel::set_element_type(Place::Ptr place, const ngraph::element::Type&) { - FRONT_END_NOT_IMPLEMENTED(setElementType); + FRONT_END_NOT_IMPLEMENTED(set_element_type); } - void InputModel::setTensorValue(Place::Ptr place, const void *) + void InputModel::set_tensor_value(Place::Ptr place, const void *value) { - FRONT_END_NOT_IMPLEMENTED(setTensorValue); + FRONT_END_NOT_IMPLEMENTED(set_tensor_value); } - void InputModel::setTensorPartialValue(Place::Ptr place, const void *minValue, const void *maxValue) + void InputModel::set_tensor_partial_value(Place::Ptr place, const void *minValue, const void *maxValue) { - FRONT_END_NOT_IMPLEMENTED(setTensorPartialValue); + FRONT_END_NOT_IMPLEMENTED(set_tensor_partial_value); } //----------- Place --------------------------- - std::vector Place::getNames() const + std::vector Place::get_names() const { - FRONT_END_NOT_IMPLEMENTED(getNames); + FRONT_END_NOT_IMPLEMENTED(get_names); } - std::vector Place::getConsumingOperations(int outputPortIndex) const + std::vector Place::get_consuming_operations(int outputPortIndex) const { - FRONT_END_NOT_IMPLEMENTED(getConsumingOperations); + FRONT_END_NOT_IMPLEMENTED(get_consuming_operations); } - Place::Ptr Place::getTargetTensor(int outputPortIndex) const + Place::Ptr Place::get_target_tensor(int outputPortIndex) const { - FRONT_END_NOT_IMPLEMENTED(getTargetTensor); + FRONT_END_NOT_IMPLEMENTED(get_target_tensor); } - Place::Ptr Place::getProducingOperation(int inputPortIndex) const + Place::Ptr Place::get_producing_operation(int inputPortIndex) const { - FRONT_END_NOT_IMPLEMENTED(getProducingOperation); + FRONT_END_NOT_IMPLEMENTED(get_producing_operation); } - Place::Ptr Place::getProducingPort() const + Place::Ptr Place::get_producing_port() const { - FRONT_END_NOT_IMPLEMENTED(getProducingPort); + FRONT_END_NOT_IMPLEMENTED(get_producing_port); } - Place::Ptr Place::getInputPort(int inputPortIndex) const + Place::Ptr Place::get_input_port(int inputPortIndex) const { - FRONT_END_NOT_IMPLEMENTED(getInputPort); + FRONT_END_NOT_IMPLEMENTED(get_input_port); } - Place::Ptr Place::getInputPort(const std::string& intputName, int inputPortIndex) const + Place::Ptr Place::get_input_port(const std::string& inputName, int inputPortIndex) const { - FRONT_END_NOT_IMPLEMENTED(getInputPort); + FRONT_END_NOT_IMPLEMENTED(get_input_port); } - Place::Ptr Place::getOutputPort(int outputPortIndex) const + Place::Ptr Place::get_output_port(int outputPortIndex) const { - FRONT_END_NOT_IMPLEMENTED(getOutputPort); + FRONT_END_NOT_IMPLEMENTED(get_output_port); } - Place::Ptr Place::getOutputPort(const std::string& outputName, int outputPortIndex) const + Place::Ptr Place::get_output_port(const std::string& outputName, int outputPortIndex) const { - FRONT_END_NOT_IMPLEMENTED(getOutputPort); + FRONT_END_NOT_IMPLEMENTED(get_output_port); } - std::vector Place::getConsumingPorts() const + std::vector Place::get_consuming_ports() const { - FRONT_END_NOT_IMPLEMENTED(getConsumingPorts); + FRONT_END_NOT_IMPLEMENTED(get_consuming_ports); } - bool Place::isInput() const + bool Place::is_input() const { - FRONT_END_NOT_IMPLEMENTED(isInput); + FRONT_END_NOT_IMPLEMENTED(is_input); } - bool Place::isOutput() const + bool Place::is_output() const { - FRONT_END_NOT_IMPLEMENTED(isOutput); + FRONT_END_NOT_IMPLEMENTED(is_output); } - bool Place::isEqual(Ptr another) const + bool Place::is_equal(Ptr another) const { - FRONT_END_NOT_IMPLEMENTED(isEqual); + FRONT_END_NOT_IMPLEMENTED(is_equal); } - bool Place::isEqualData(Ptr another) const + bool Place::is_equal_data(Ptr another) const { - FRONT_END_NOT_IMPLEMENTED(isEqualData); + FRONT_END_NOT_IMPLEMENTED(is_equal_data); } - Place::Ptr Place::getSourceTensor(int inputPortIndex) const + Place::Ptr Place::get_source_tensor(int inputPortIndex) const { - FRONT_END_NOT_IMPLEMENTED(getSourceTensor); + FRONT_END_NOT_IMPLEMENTED(get_source_tensor); } } // namespace frontend diff --git a/ngraph/test/frontend/frontend_manager.cpp b/ngraph/test/frontend/frontend_manager.cpp index b7e8769d118d1e..ebc5dcdb6c9824 100644 --- a/ngraph/test/frontend/frontend_manager.cpp +++ b/ngraph/test/frontend/frontend_manager.cpp @@ -33,13 +33,14 @@ static int set_test_env(const char* name, const char* value) TEST(FrontEndManagerTest, testAvailableFrontEnds) { FrontEndManager fem; - ASSERT_NO_THROW(fem.registerFrontEnd("mock", [](FrontEndCapabilities fec) { + ASSERT_NO_THROW(fem.register_front_end("mock", [](FrontEndCapabilities fec) + { return std::make_shared(); })); - auto frontends = fem.availableFrontEnds(); + auto frontends = fem.get_available_front_ends(); ASSERT_NE(std::find(frontends.begin(), frontends.end(), "mock"), frontends.end()); FrontEnd::Ptr fe; - ASSERT_NO_THROW(fe = fem.loadByFramework("mock")); + ASSERT_NO_THROW(fe = fem.load_by_framework("mock")); } TEST(FrontEndManagerTest, testMockPluginFrontEnd) @@ -50,7 +51,7 @@ TEST(FrontEndManagerTest, testMockPluginFrontEnd) set_test_env("OV_FRONTEND_PATH", fePath.c_str()); FrontEndManager fem; - auto frontends = fem.availableFrontEnds(); + auto frontends = fem.get_available_front_ends(); ASSERT_NE(std::find(frontends.begin(), frontends.end(), "mock1"), frontends.end()); set_test_env("OV_FRONTEND_PATH", ""); } @@ -58,20 +59,20 @@ TEST(FrontEndManagerTest, testMockPluginFrontEnd) TEST(FrontEndManagerTest, testDefaultFrontEnd) { FrontEndManager fem; - ASSERT_ANY_THROW(fem.loadByModel("")); + ASSERT_ANY_THROW(fem.load_by_model("")); std::unique_ptr fePtr (new FrontEnd()); // to verify base destructor FrontEnd::Ptr fe = std::make_shared(); - ASSERT_ANY_THROW(fe->loadFromFile("")); - ASSERT_ANY_THROW(fe->loadFromFiles({"", ""})); - ASSERT_ANY_THROW(fe->loadFromMemory(nullptr)); - ASSERT_ANY_THROW(fe->loadFromMemoryFragments({nullptr, nullptr})); + ASSERT_ANY_THROW(fe->load_from_file("")); + ASSERT_ANY_THROW(fe->load_from_files({"", ""})); + ASSERT_ANY_THROW(fe->load_from_memory(nullptr)); + ASSERT_ANY_THROW(fe->load_from_memory_fragments({nullptr, nullptr})); std::stringstream str; - ASSERT_ANY_THROW(fe->loadFromStream(str)); - ASSERT_ANY_THROW(fe->loadFromStreams({&str, &str})); + ASSERT_ANY_THROW(fe->load_from_stream(str)); + ASSERT_ANY_THROW(fe->load_from_streams({&str, &str})); ASSERT_ANY_THROW(fe->convert(std::shared_ptr(nullptr))); ASSERT_ANY_THROW(fe->convert(InputModel::Ptr(nullptr))); - ASSERT_ANY_THROW(fe->convertPartially(nullptr)); + ASSERT_ANY_THROW(fe->convert_partially(nullptr)); ASSERT_ANY_THROW(fe->decode(nullptr)); ASSERT_ANY_THROW(fe->normalize(nullptr)); } @@ -80,51 +81,51 @@ TEST(FrontEndManagerTest, testDefaultInputModel) { std::unique_ptr imPtr (new InputModel()); // to verify base destructor InputModel::Ptr im = std::make_shared(); - ASSERT_ANY_THROW(im->getInputs()); - ASSERT_ANY_THROW(im->getOutputs()); - ASSERT_ANY_THROW(im->overrideAllInputs({nullptr})); - ASSERT_ANY_THROW(im->overrideAllOutputs({nullptr})); - ASSERT_ANY_THROW(im->extractSubgraph({nullptr}, {nullptr})); - ASSERT_ANY_THROW(im->getPlaceByTensorName("")); - ASSERT_ANY_THROW(im->getPlaceByOperationName("")); - ASSERT_ANY_THROW(im->getPlaceByOperationAndInputPort("", 0)); - ASSERT_ANY_THROW(im->getPlaceByOperationAndOutputPort("", 0)); - ASSERT_ANY_THROW(im->setNameForTensor(nullptr, "")); - ASSERT_ANY_THROW(im->addNameForTensor(nullptr, "")); - ASSERT_ANY_THROW(im->setNameForOperation(nullptr, "")); - ASSERT_ANY_THROW(im->freeNameForTensor("")); - ASSERT_ANY_THROW(im->freeNameForOperation("")); - ASSERT_ANY_THROW(im->setNameForDimension(nullptr, 0, "")); - ASSERT_ANY_THROW(im->cutAndAddNewInput(nullptr, "")); - ASSERT_ANY_THROW(im->cutAndAddNewOutput(nullptr, "")); - ASSERT_ANY_THROW(im->addOutput(nullptr)); - ASSERT_ANY_THROW(im->removeOutput(nullptr)); - ASSERT_ANY_THROW(im->removeInput(nullptr)); - ASSERT_ANY_THROW(im->setDefaultShape(nullptr, ngraph::Shape{})); - ASSERT_ANY_THROW(im->setPartialShape(nullptr, ngraph::Shape{})); - ASSERT_ANY_THROW(im->getPartialShape(nullptr)); - ASSERT_ANY_THROW(im->setElementType(nullptr, ngraph::element::Type{})); - ASSERT_ANY_THROW(im->setTensorValue(nullptr, nullptr)); - ASSERT_ANY_THROW(im->setTensorPartialValue(nullptr, nullptr, nullptr)); + ASSERT_ANY_THROW(im->get_inputs()); + ASSERT_ANY_THROW(im->get_outputs()); + ASSERT_ANY_THROW(im->override_all_inputs({nullptr})); + ASSERT_ANY_THROW(im->override_all_outputs({nullptr})); + ASSERT_ANY_THROW(im->extract_subgraph({nullptr}, {nullptr})); + ASSERT_ANY_THROW(im->get_place_by_tensor_name("")); + ASSERT_ANY_THROW(im->get_place_by_operation_name("")); + ASSERT_ANY_THROW(im->get_place_by_operation_and_input_port("", 0)); + ASSERT_ANY_THROW(im->get_place_by_operation_and_output_port("", 0)); + ASSERT_ANY_THROW(im->set_name_for_tensor(nullptr, "")); + ASSERT_ANY_THROW(im->add_name_for_tensor(nullptr, "")); + ASSERT_ANY_THROW(im->set_name_for_operation(nullptr, "")); + ASSERT_ANY_THROW(im->free_name_for_tensor("")); + ASSERT_ANY_THROW(im->free_name_for_operation("")); + ASSERT_ANY_THROW(im->set_name_for_dimension(nullptr, 0, "")); + ASSERT_ANY_THROW(im->cut_and_add_new_input(nullptr, "")); + ASSERT_ANY_THROW(im->cut_and_add_new_output(nullptr, "")); + ASSERT_ANY_THROW(im->add_output(nullptr)); + ASSERT_ANY_THROW(im->remove_output(nullptr)); + ASSERT_ANY_THROW(im->remove_input(nullptr)); + ASSERT_ANY_THROW(im->set_default_shape(nullptr, ngraph::Shape{})); + ASSERT_ANY_THROW(im->set_partial_shape(nullptr, ngraph::Shape{})); + ASSERT_ANY_THROW(im->get_partial_shape(nullptr)); + ASSERT_ANY_THROW(im->set_element_type(nullptr, ngraph::element::Type{})); + ASSERT_ANY_THROW(im->set_tensor_value(nullptr, nullptr)); + ASSERT_ANY_THROW(im->set_tensor_partial_value(nullptr, nullptr, nullptr)); } TEST(FrontEndManagerTest, testDefaultPlace) { std::unique_ptr placePtr (new Place()); // to verify base destructor Place::Ptr place = std::make_shared(); - ASSERT_ANY_THROW(place->getNames()); - ASSERT_ANY_THROW(place->getConsumingOperations()); - ASSERT_ANY_THROW(place->getTargetTensor()); - ASSERT_ANY_THROW(place->getSourceTensor()); - ASSERT_ANY_THROW(place->getProducingOperation()); - ASSERT_ANY_THROW(place->getProducingPort()); - ASSERT_ANY_THROW(place->getInputPort()); - ASSERT_ANY_THROW(place->getInputPort("")); - ASSERT_ANY_THROW(place->getOutputPort()); - ASSERT_ANY_THROW(place->getOutputPort("")); - ASSERT_ANY_THROW(place->getConsumingPorts()); - ASSERT_ANY_THROW(place->isInput()); - ASSERT_ANY_THROW(place->isOutput()); - ASSERT_ANY_THROW(place->isEqual(nullptr)); - ASSERT_ANY_THROW(place->isEqualData(nullptr)); + ASSERT_ANY_THROW(place->get_names()); + ASSERT_ANY_THROW(place->get_consuming_operations()); + ASSERT_ANY_THROW(place->get_target_tensor()); + ASSERT_ANY_THROW(place->get_source_tensor()); + ASSERT_ANY_THROW(place->get_producing_operation()); + ASSERT_ANY_THROW(place->get_producing_port()); + ASSERT_ANY_THROW(place->get_input_port()); + ASSERT_ANY_THROW(place->get_input_port("")); + ASSERT_ANY_THROW(place->get_output_port()); + ASSERT_ANY_THROW(place->get_output_port("")); + ASSERT_ANY_THROW(place->get_consuming_ports()); + ASSERT_ANY_THROW(place->is_input()); + ASSERT_ANY_THROW(place->is_output()); + ASSERT_ANY_THROW(place->is_equal(nullptr)); + ASSERT_ANY_THROW(place->is_equal_data(nullptr)); } diff --git a/ngraph/test/frontend/shared/src/basic_api.cpp b/ngraph/test/frontend/shared/src/basic_api.cpp index cbd72cb13f77aa..1bce97cb6a6ef2 100644 --- a/ngraph/test/frontend/shared/src/basic_api.cpp +++ b/ngraph/test/frontend/shared/src/basic_api.cpp @@ -30,10 +30,10 @@ void FrontEndBasicTest::initParamTest() void FrontEndBasicTest::doLoadFromFile() { std::vector frontends; - ASSERT_NO_THROW(frontends = m_fem.availableFrontEnds()); - ASSERT_NO_THROW(m_frontEnd = m_fem.loadByFramework(m_feName)); + ASSERT_NO_THROW(frontends = m_fem.get_available_front_ends()); + ASSERT_NO_THROW(m_frontEnd = m_fem.load_by_framework(m_feName)); ASSERT_NE(m_frontEnd, nullptr); - ASSERT_NO_THROW(m_inputModel = m_frontEnd->loadFromFile(m_modelFile)); + ASSERT_NO_THROW(m_inputModel = m_frontEnd->load_from_file(m_modelFile)); ASSERT_NE(m_inputModel, nullptr); } @@ -59,23 +59,23 @@ TEST_P(FrontEndBasicTest, testInputModel_getInputsOutputs) { ASSERT_NE(place, nullptr); std::vector names; - ASSERT_NO_THROW(names = place->getNames()); + ASSERT_NO_THROW(names = place->get_names()); EXPECT_GT(names.size(), 0); cb(place); }); }; std::vector inputs; - ASSERT_NO_THROW(inputs = m_inputModel->getInputs()); + ASSERT_NO_THROW(inputs = m_inputModel->get_inputs()); checkPlaces(inputs, [&](Place::Ptr place) { - EXPECT_TRUE(place->isInput()); + EXPECT_TRUE(place->is_input()); }); std::vector outputs; - ASSERT_NO_THROW(outputs = m_inputModel->getOutputs()); + ASSERT_NO_THROW(outputs = m_inputModel->get_outputs()); checkPlaces(outputs, [&](Place::Ptr place) { - EXPECT_TRUE(place->isOutput()); + EXPECT_TRUE(place->is_output()); }); } @@ -90,24 +90,24 @@ TEST_P(FrontEndBasicTest, testInputModel_getPlaceByTensorName) { ASSERT_NE(place, nullptr); std::vector names; - ASSERT_NO_THROW(names = place->getNames()); + ASSERT_NO_THROW(names = place->get_names()); for (auto name : names) { EXPECT_NE(name, std::string()); Place::Ptr placeByName; - ASSERT_NO_THROW(placeByName = m_inputModel->getPlaceByTensorName(name)); + ASSERT_NO_THROW(placeByName = m_inputModel->get_place_by_tensor_name(name)); ASSERT_NE(placeByName, nullptr); - EXPECT_TRUE(placeByName->isEqual(place)); + EXPECT_TRUE(placeByName->is_equal(place)); } } }; std::vector outputs; - ASSERT_NO_THROW(outputs = m_inputModel->getOutputs()); + ASSERT_NO_THROW(outputs = m_inputModel->get_outputs()); testGetPlaceByTensorName(outputs); std::vector inputs; - ASSERT_NO_THROW(inputs = m_inputModel->getInputs()); + ASSERT_NO_THROW(inputs = m_inputModel->get_inputs()); testGetPlaceByTensorName(inputs); } @@ -136,14 +136,14 @@ TEST_P(FrontEndBasicTest, testInputModel_overrideAll) }); }; verifyOverride([&]() - { return m_inputModel->getInputs(); }, + { return m_inputModel->get_inputs(); }, [&](const std::vector& p) - { m_inputModel->overrideAllInputs(p); }); + { m_inputModel->override_all_inputs(p); }); verifyOverride([&]() - { return m_inputModel->getOutputs(); }, + { return m_inputModel->get_outputs(); }, [&](const std::vector& p) - { m_inputModel->overrideAllOutputs(p); }); + { m_inputModel->override_all_outputs(p); }); } TEST_P(FrontEndBasicTest, testInputModel_overrideAll_empty) @@ -163,7 +163,7 @@ TEST_P(FrontEndBasicTest, testInputModel_overrideAll_empty) std::for_each(places.begin(), places.end(), [&](Place::Ptr place) { std::vector names; - ASSERT_NO_THROW(names = place->getNames()); + ASSERT_NO_THROW(names = place->get_names()); for (auto name : names) { customCB(name); @@ -171,20 +171,20 @@ TEST_P(FrontEndBasicTest, testInputModel_overrideAll_empty) }); }; verifyOverride([&]() - { return m_inputModel->getOutputs(); }, + { return m_inputModel->get_outputs(); }, [&]() - { m_inputModel->overrideAllOutputs({}); }, + { m_inputModel->override_all_outputs({}); }, [&](const std::string& name) { - EXPECT_FALSE(m_inputModel->getPlaceByTensorName(name)->isOutput()); + EXPECT_FALSE(m_inputModel->get_place_by_tensor_name(name)->is_output()); }); verifyOverride([&]() - { return m_inputModel->getInputs(); }, + { return m_inputModel->get_inputs(); }, [&]() - { m_inputModel->overrideAllInputs({}); }, + { m_inputModel->override_all_inputs({}); }, [&](const std::string& name) { - EXPECT_FALSE(m_inputModel->getPlaceByTensorName(name)->isInput()); + EXPECT_FALSE(m_inputModel->get_place_by_tensor_name(name)->is_input()); }); } diff --git a/ngraph/test/frontend/shared/src/cut_specific_model.cpp b/ngraph/test/frontend/shared/src/cut_specific_model.cpp index 022d748e4f2289..d1ecbae8976705 100644 --- a/ngraph/test/frontend/shared/src/cut_specific_model.cpp +++ b/ngraph/test/frontend/shared/src/cut_specific_model.cpp @@ -43,10 +43,10 @@ void FrontEndCutModelTest::doLoadFromFile() { std::vector frontends; FrontEnd::Ptr fe; - ASSERT_NO_THROW(frontends = m_fem.availableFrontEnds()); - ASSERT_NO_THROW(m_frontEnd = m_fem.loadByFramework(m_param.m_frontEndName)); + ASSERT_NO_THROW(frontends = m_fem.get_available_front_ends()); + ASSERT_NO_THROW(m_frontEnd = m_fem.load_by_framework(m_param.m_frontEndName)); ASSERT_NE(m_frontEnd, nullptr); - ASSERT_NO_THROW(m_inputModel = m_frontEnd->loadFromFile(m_param.m_modelName)); + ASSERT_NO_THROW(m_inputModel = m_frontEnd->load_from_file(m_param.m_modelName)); ASSERT_NE(m_inputModel, nullptr); } @@ -55,7 +55,7 @@ std::vector FrontEndCutModelTest::constructNewInpu std::vector newInputs; for (const auto& name : m_param.m_newInputs) { - newInputs.push_back(m_inputModel->getPlaceByTensorName(name)); + newInputs.push_back(m_inputModel->get_place_by_tensor_name(name)); } return newInputs; } @@ -65,7 +65,7 @@ std::vector FrontEndCutModelTest::constructNewOutp std::vector newOutputs; for (const auto& name : m_param.m_newOutputs) { - newOutputs.push_back(m_inputModel->getPlaceByTensorName(name)); + newOutputs.push_back(m_inputModel->get_place_by_tensor_name(name)); } return newOutputs; } @@ -77,13 +77,13 @@ TEST_P(FrontEndCutModelTest, testOverrideInputs) ASSERT_NO_THROW(doLoadFromFile()); std::vector newPlaces; ASSERT_NO_THROW(newPlaces = constructNewInputs()); - ASSERT_NO_THROW(m_inputModel->overrideAllInputs(newPlaces)); - ASSERT_NO_THROW(m_inputModel->getInputs()); - EXPECT_EQ(m_param.m_newInputs.size(), m_inputModel->getInputs().size()); - for (auto newInput : m_inputModel->getInputs()) + ASSERT_NO_THROW(m_inputModel->override_all_inputs(newPlaces)); + ASSERT_NO_THROW(m_inputModel->get_inputs()); + EXPECT_EQ(m_param.m_newInputs.size(), m_inputModel->get_inputs().size()); + for (auto newInput : m_inputModel->get_inputs()) { std::vector names; - ASSERT_NO_THROW(names = newInput->getNames()); + ASSERT_NO_THROW(names = newInput->get_names()); bool found = false; for (const auto& name: m_param.m_newInputs) { @@ -102,13 +102,13 @@ TEST_P(FrontEndCutModelTest, testOverrideOutputs) ASSERT_NO_THROW(doLoadFromFile()); std::vector newPlaces; ASSERT_NO_THROW(newPlaces = constructNewOutputs()); - ASSERT_NO_THROW(m_inputModel->overrideAllOutputs(newPlaces)); - ASSERT_NO_THROW(m_inputModel->getOutputs()); - EXPECT_EQ(m_param.m_newOutputs.size(), m_inputModel->getOutputs().size()); - for (auto newOutput : m_inputModel->getOutputs()) + ASSERT_NO_THROW(m_inputModel->override_all_outputs(newPlaces)); + ASSERT_NO_THROW(m_inputModel->get_outputs()); + EXPECT_EQ(m_param.m_newOutputs.size(), m_inputModel->get_outputs().size()); + for (auto newOutput : m_inputModel->get_outputs()) { std::vector names; - ASSERT_NO_THROW(names = newOutput->getNames()); + ASSERT_NO_THROW(names = newOutput->get_names()); bool found = false; for (const auto& name: m_param.m_newOutputs) { @@ -162,7 +162,7 @@ TEST_P(FrontEndCutModelTest, testNewInputs_func) ASSERT_NO_THROW(doLoadFromFile()); std::vector newPlaces; ASSERT_NO_THROW(newPlaces = constructNewInputs()); - ASSERT_NO_THROW(m_inputModel->overrideAllInputs(newPlaces)); + ASSERT_NO_THROW(m_inputModel->override_all_inputs(newPlaces)); std::shared_ptr function; ASSERT_NO_THROW(function = m_frontEnd->convert(m_inputModel)); @@ -194,7 +194,7 @@ TEST_P(FrontEndCutModelTest, testNewOutputs_func) ASSERT_NO_THROW(doLoadFromFile()); std::vector newPlaces; ASSERT_NO_THROW(newPlaces = constructNewOutputs()); - ASSERT_NO_THROW(m_inputModel->overrideAllOutputs(newPlaces)); + ASSERT_NO_THROW(m_inputModel->override_all_outputs(newPlaces)); std::shared_ptr function; ASSERT_NO_THROW(function = m_frontEnd->convert(m_inputModel)); @@ -227,7 +227,7 @@ TEST_P(FrontEndCutModelTest, testExtractSubgraph) std::vector newInputs, newOutputs; ASSERT_NO_THROW(newInputs = constructNewInputs()); ASSERT_NO_THROW(newOutputs = constructNewOutputs()); - ASSERT_NO_THROW(m_inputModel->extractSubgraph(newInputs, newOutputs)); + ASSERT_NO_THROW(m_inputModel->extract_subgraph(newInputs, newOutputs)); std::shared_ptr function; ASSERT_NO_THROW(function = m_frontEnd->convert(m_inputModel)); @@ -258,8 +258,8 @@ TEST_P(FrontEndCutModelTest, testSetTensorValue) { ASSERT_NO_THROW(doLoadFromFile()); Place::Ptr place; - ASSERT_NO_THROW(place = m_inputModel->getPlaceByTensorName(m_param.m_tensorValueName)); - ASSERT_NO_THROW(m_inputModel->setTensorValue(place, &m_param.m_tensorValue[0])); + ASSERT_NO_THROW(place = m_inputModel->get_place_by_tensor_name(m_param.m_tensorValueName)); + ASSERT_NO_THROW(m_inputModel->set_tensor_value(place, &m_param.m_tensorValue[0])); std::shared_ptr function; ASSERT_NO_THROW(function = m_frontEnd->convert(m_inputModel)); diff --git a/ngraph/test/frontend/shared/src/partial_shape.cpp b/ngraph/test/frontend/shared/src/partial_shape.cpp index 8eb5bb5dc04925..e71368a487df55 100644 --- a/ngraph/test/frontend/shared/src/partial_shape.cpp +++ b/ngraph/test/frontend/shared/src/partial_shape.cpp @@ -39,10 +39,10 @@ void FrontEndPartialShapeTest::doLoadFromFile() { std::vector frontends; FrontEnd::Ptr fe; - ASSERT_NO_THROW(frontends = m_fem.availableFrontEnds()); - ASSERT_NO_THROW(m_frontEnd = m_fem.loadByFramework(m_baseParam.m_frontEndName)); + ASSERT_NO_THROW(frontends = m_fem.get_available_front_ends()); + ASSERT_NO_THROW(m_frontEnd = m_fem.load_by_framework(m_baseParam.m_frontEndName)); ASSERT_NE(m_frontEnd, nullptr); - ASSERT_NO_THROW(m_inputModel = m_frontEnd->loadFromFile(m_partShape.m_modelName)); + ASSERT_NO_THROW(m_inputModel = m_frontEnd->load_from_file(m_partShape.m_modelName)); ASSERT_NE(m_inputModel, nullptr); } @@ -73,9 +73,9 @@ TEST_P(FrontEndPartialShapeTest, testSetNewPartialShape) { ASSERT_NO_THROW(doLoadFromFile()); Place::Ptr place; - ASSERT_NO_THROW(place = m_inputModel->getPlaceByTensorName(m_partShape.m_tensorName)); + ASSERT_NO_THROW(place = m_inputModel->get_place_by_tensor_name(m_partShape.m_tensorName)); ASSERT_NE(place, nullptr); - ASSERT_NO_THROW(m_inputModel->setPartialShape(place, PartialShape{m_partShape.m_newPartialShape})); + ASSERT_NO_THROW(m_inputModel->set_partial_shape(place, PartialShape{m_partShape.m_newPartialShape})); std::shared_ptr function; ASSERT_NO_THROW(function = m_frontEnd->convert(m_inputModel)); From 6bd62c140e107c0d7e6b935c93dfdc9f6b9041ce Mon Sep 17 00:00:00 2001 From: Michael Nosov Date: Tue, 11 May 2021 20:08:50 +0300 Subject: [PATCH 11/22] Fix review comments Add clang format target for frontend_manager and mock frontend plugin --- ngraph/CMakeLists.txt | 1 + ngraph/frontend/generic/CMakeLists.txt | 36 +- .../frontend_manager/frontend_manager.hpp | 403 +++++++++++------- .../frontend_manager_defs.hpp | 6 +- .../frontend/generic/src/frontend_manager.cpp | 107 +++-- ngraph/frontend/generic/src/plugin_loader.cpp | 61 +-- ngraph/frontend/generic/src/plugin_loader.hpp | 18 +- ngraph/test/frontend/CMakeLists.txt | 2 + ngraph/test/frontend/mock_frontend.cpp | 16 +- 9 files changed, 363 insertions(+), 287 deletions(-) diff --git a/ngraph/CMakeLists.txt b/ngraph/CMakeLists.txt index 6841171196416c..686cb859b6b897 100644 --- a/ngraph/CMakeLists.txt +++ b/ngraph/CMakeLists.txt @@ -30,6 +30,7 @@ set(FRONTEND_INCLUDE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/frontend/generic/include ) +# Will be used by frontends to construct frontend-specific source location paths set(FRONTEND_BASE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/frontend ) diff --git a/ngraph/frontend/generic/CMakeLists.txt b/ngraph/frontend/generic/CMakeLists.txt index e42f64a99ba433..90a0d6edfdde16 100644 --- a/ngraph/frontend/generic/CMakeLists.txt +++ b/ngraph/frontend/generic/CMakeLists.txt @@ -2,8 +2,8 @@ # SPDX-License-Identifier: Apache-2.0 # -file(GLOB_RECURSE LIBRARY_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cc) -file(GLOB_RECURSE LIBRARY_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/src/*.hpp ${CMAKE_CURRENT_SOURCE_DIR}/src/*.h) +file(GLOB_RECURSE LIBRARY_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp) +file(GLOB_RECURSE LIBRARY_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/src/*.hpp) file(GLOB_RECURSE LIBRARY_PUBLIC_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/include/*.hpp) set(FRONTEND_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/include) @@ -18,38 +18,16 @@ add_library(ngraph::frontend_manager ALIAS frontend_manager) target_link_libraries(frontend_manager PRIVATE ${CMAKE_DL_LIBS} ngraph) +add_clang_format_target(frontend_manager_clang FOR_TARGETS frontend_manager) + if(COMMAND ie_add_vs_version_file) ie_add_vs_version_file(NAME frontend_manager - FILEDESCRIPTION "Manager of OpenVINO nGraph Front Ends") + FILEDESCRIPTION "Manager of OpenVINO nGraph Frontends") endif() set(FRONTEND_INSTALL_INCLUDE "${NGRAPH_INSTALL_INCLUDE}/ngraph/frontend/generic") -target_include_directories(frontend_manager SYSTEM PUBLIC $ +target_include_directories(frontend_manager PUBLIC $ $) -target_include_directories(frontend_manager SYSTEM PRIVATE ${NGRAPH_INCLUDE_PATH} ${FRONTEND_INCLUDE_DIR}) +target_include_directories(frontend_manager PRIVATE ${NGRAPH_INCLUDE_PATH} ${FRONTEND_INCLUDE_DIR}) target_include_directories(frontend_manager PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src) - -if (CMAKE_CXX_COMPILER_ID MATCHES "^(Apple)?Clang$") - target_compile_options(frontend_manager PRIVATE -Wno-undef -Wno-reserved-id-macro -Wno-switch-enum - -Wno-invalid-offsetof -Wno-shorten-64-to-32 -Wno-unused-macros -Wno-missing-variable-declarations - -Wno-unused-private-field -Wno-shadow -Wno-deprecated PUBLIC -Wno-undefined-func-template) -endif() - -# TODO: uncomment to include frontend_manager to installation package -#install(TARGETS frontend_manager EXPORT ngraphTargets -# RUNTIME DESTINATION ${NGRAPH_INSTALL_LIB} COMPONENT ngraph -# ARCHIVE DESTINATION ${NGRAPH_INSTALL_LIB} COMPONENT ngraph -# LIBRARY DESTINATION ${NGRAPH_INSTALL_LIB} COMPONENT ngraph) -# -#install(DIRECTORY ${FRONTEND_INCLUDE_DIR}/frontend_manager -# DESTINATION ${FRONTEND_INSTALL_INCLUDE} -# COMPONENT ngraph -# FILES_MATCHING -# PATTERN "*.hpp" -# PATTERN "*.h" -#) -# -#if (NGRAPH_EXPORT_TARGETS_ENABLE) -# export(TARGETS frontend_manager NAMESPACE ngraph:: APPEND FILE "${NGRAPH_TARGETS_FILE}") -#endif() diff --git a/ngraph/frontend/generic/include/frontend_manager/frontend_manager.hpp b/ngraph/frontend/generic/include/frontend_manager/frontend_manager.hpp index 06b00cf3625446..0aac6e1dc56e6b 100644 --- a/ngraph/frontend/generic/include/frontend_manager/frontend_manager.hpp +++ b/ngraph/frontend/generic/include/frontend_manager/frontend_manager.hpp @@ -6,86 +6,95 @@ #include #include -#include "ngraph/function.hpp" #include "frontend_manager_defs.hpp" +#include "ngraph/function.hpp" namespace ngraph { namespace frontend { - - -/// \brief An interface for identifying a place in a graph and iterate over it; can refer to an operation node, tensor, port etc. -/// -/// \note Each front end implementation provides specialization of this interface to represent a place -/// in a model graph. Various methods in the front end classes accept and retrieve instances -/// of Place to point to particular node part which should be modified or satisfies some criteria. -/// For example, this class is used to report model inputs and outputs, for searching operations and tensors -/// by name, for setting shape etc. -/// -/// Place can refer to Tensor, Input Edge, Input Port, Operation, Output Port, Output Edge -/// -/// [Tensor A] -/// | -/// | [Input Edge] -/// | -/// V -/// ------------------- -/// [ [Input Port 0] ] -/// [ ] -/// [ Operation A ] -/// [ ] -/// [ [Output Port 0] ] -/// ------------------- -/// | -/// | [Output Edge] -/// | -/// V -/// [Tensor B] -/// | -/// | [Input Edge] -/// | -/// V -/// ------------------- -/// [ [Input Port 0] ] -/// [ ] -/// [ Operation B ] -/// [ ] -/// [ [Output Port 0] ] -/// ------------------- -/// | -/// | [Output Edge] -/// | -/// V -/// [Tensor C] -/// + /// \brief An interface for identifying a place in a graph and iterate over it; can refer to + /// an operation node, tensor, port etc. + /// + /// \note Each front end implementation provides specialization of this interface to + /// represent a place in a model graph. Various methods in the front end classes accept and + /// retrieve instances of Place to point to particular node part which should be modified or + /// satisfies some criteria. For example, this class is used to report model inputs + /// and outputs, for searching operations and tensors by name, for setting shape etc. + /// + /// Place can refer to Tensor, Input Edge, Input Port, Operation, Output Port, Output Edge + /// + /// [Tensor A] + /// | + /// | [Input Edge] + /// | + /// V + /// ------------------- + /// [ [Input Port 0] ] + /// [ ] + /// [ Operation A ] + /// [ ] + /// [ [Output Port 0] ] + /// ------------------- + /// | + /// | [Output Edge] + /// | + /// V + /// [Tensor B] + /// | + /// | [Input Edge] + /// | + /// V + /// ------------------- + /// [ [Input Port 0] ] + /// [ ] + /// [ Operation B ] + /// [ ] + /// [ [Output Port 0] ] + /// ------------------- + /// | + /// | [Output Edge] + /// | + /// V + /// [Tensor C] + /// class FRONTEND_API Place { public: - typedef std::shared_ptr Ptr; virtual ~Place() = default; - /// \brief All associated names (synonyms) that identify this place in the graph in a framework specific way - /// \return A vector of strings each representing a name that identifies this place in the graph. - /// Can be empty if there are no names associated with this place or name cannot be attached. + /// \brief All associated names (synonyms) that identify this place in the graph in a + /// framework specific way + /// + /// \return A vector of strings each representing a name that identifies this place in + /// the graph. Can be empty if there are no names associated with this place or name + /// cannot be attached. virtual std::vector get_names() const; /// \brief Returns references to all operation nodes that consume data from this place - /// \note It can be called for any kind of graph place searching for the first consuming opertions. + /// \note It can be called for any kind of graph place searching for the first consuming + /// operations. /// - /// \param outputPortIndex If place is an operational node it specifies which output port should be considered - /// \return A vector with all operation node references that consumes data from this place + /// \param outputPortIndex If place is an operational node it specifies which output + /// port should be considered + /// + /// \return A vector with all operation node references that consumes data from this + /// place virtual std::vector get_consuming_operations(int outputPortIndex = -1) const; - /// \brief Returns a tensor place that gets data from this place; applicable for operations, output ports and output edges + /// \brief Returns a tensor place that gets data from this place; applicable for + /// operations, output ports and output edges + /// + /// \param outputPortIndex Output port index if the current place is an operation node + /// and has multiple output ports /// - /// \param outputPortIndex Output port index if the current place is an operation node and has multiple output ports /// \return A tensor place which hold the resulting value for this place virtual Ptr get_target_tensor(int outputPortIndex = -1) const; - /// \brief Returns a tensor place that supplies data for this place; applicable for operations, input ports and input edges + /// \brief Returns a tensor place that supplies data for this place; applicable for + /// operations, input ports and input edges /// /// \param inputPortIndex Input port index for operational nodes /// \return A tensor place which supplies data for this place @@ -93,7 +102,9 @@ namespace ngraph /// \brief Get an operation node place that immediately produces data for this place /// - /// \param inputPortIndex If a given place is itself an operation node, this specifies a port index + /// \param inputPortIndex If a given place is itself an operation node, this specifies a + /// port index + /// /// \return An operation place that produces data for this place virtual Ptr get_producing_operation(int inputPortIndex = -1) const; @@ -110,7 +121,8 @@ namespace ngraph virtual Ptr get_output_port(int outputPortIndex = -1) const; /// For operation node returns reference to an output port with specified name and index - virtual Ptr get_output_port(const std::string& outputName, int outputPortIndex = -1) const; + virtual Ptr get_output_port(const std::string& outputName, + int outputPortIndex = -1) const; /// Returns all input ports that consume data flows through this place virtual std::vector get_consuming_ports() const; @@ -125,150 +137,176 @@ namespace ngraph virtual bool is_equal(Ptr another) const; /// \brief Returns true if another place points to the same data. - /// \note The same data means all places on path: output port -> output edge -> tensor -> input edge -> input port. + /// \note The same data means all places on path: output port -> output edge -> tensor + /// -> input edge -> input port. virtual bool is_equal_data(Ptr another) const; }; - -/// \brief InputModel class represents an original, not yet converted model graph in a framework format given -/// services to find places of interest in a graph or specialize/edit the model before conversion. -/// -/// \note Class methods are divided into several groups: searching for places, naming and annotation, -/// topology editing, setting tensor properties. -/// -/// Editing requests may affect ability to convert the original model to nGraph function. Aim to provide -/// these editing capabilities is to unlock conversion for models that are not natively supported "as-is" -/// because of undefined shapes, types or operations. -/// -/// Specific front-end implementation is supposed to have a lazy implementation for all methods, not doing -/// a complete load of a model without an explicit method call. For example, the list of all inputs -/// are not pre-fetched by InputModel derived class instance creation, but only when get_inputs method is called. -/// But it is not an obligation, the most convenient way should be chosen depending on the framework model -/// representation. -/// -/// All editing requests affect the model representation that is held behind the scene and successive method -/// calls observe a new graph structure. + /// \brief InputModel class represents an original, not yet converted model graph in a + /// framework format given services to find places of interest in a graph or specialize/edit + /// the model before conversion. + /// + /// \note Class methods are divided into several groups: searching for places, naming and + /// annotation, topology editing, setting tensor properties. + /// + /// Editing requests may affect ability to convert the original model to nGraph function. + /// Aim to provide these editing capabilities is to unlock conversion for models that + /// are not natively supported "as-is" because of undefined shapes, types or operations. + /// + /// Specific front-end implementation is supposed to have a lazy implementation for + /// all methods, not doing a complete load of a model without an explicit method call. + /// For example, the list of all inputs are not pre-fetched by InputModel derived + /// class instance creation, but only when get_inputs method is called. But it is not + /// an obligation, the most convenient way should be chosen depending on the framework + /// model representation. + /// + /// All editing requests affect the model representation that is held behind the scene + /// successive method calls observe a new graph structure. class FRONTEND_API InputModel { public: - typedef std::shared_ptr Ptr; virtual ~InputModel() = default; ///// Searching for places ///// - /// \brief Returns all inputs for a model - /// An input is a place in a graph where data is supposed to flow inside graph from outside. - /// It can be a tensor, port, operation; which kind of place can be an output is FW dependent. - /// Usually framework models have a dedicated artifact to code model input, it can be a tensor without producer, - /// that writes to it in ONNX, or a special operation like Placeholder in TensorFlow. + /// An input is a place in a graph where data is supposed to flow inside graph from + /// outside. It can be a tensor, port, operation; which kind of place can be an output + /// is FW dependent. Usually framework models have a dedicated artifact to code model + /// input, it can be a tensor without producer, that writes to it in ONNX, or a special + /// operation like Placeholder in TensorFlow. + /// /// \return A vector of input place references virtual std::vector get_inputs() const; /// \brief Returns all output for a model - /// An output is a terminal place in a graph where data escapes the flow. It can be a tensor, port, operation; - /// which kind of place can be an output is FW dependent. In comparison to a graph input, the output is less - /// formally defined thing and determination of initial list of outputs may include some conventions defined - /// by a frontend itself, not a framework. For example, all output ports without consumers may be considered - /// as outputs. + /// An output is a terminal place in a graph where data escapes the flow. It can be a + /// tensor, port, operation; which kind of place can be an output is FW dependent. In + /// comparison to a graph input, the output is less formally defined thing and + /// determination of initial list of outputs may include some conventions defined by a + /// frontend itself, not a framework. For example, all output ports without consumers + /// may be considered as outputs. + /// /// \return A vector of output place references virtual std::vector get_outputs() const; - /// Returns a tensor place by a tensor name following framework conventions, or nullptr if a tensor with this name doesn't exist. + /// \brief Returns a tensor place by a tensor name following framework conventions, or + /// nullptr if a tensor with this name doesn't exist. virtual Place::Ptr get_place_by_tensor_name(const std::string& tensorName) const; - /// Returns an operation place by a tensor name following framework conventions, or nullptr if an operation with this name doesn't exist. + /// \brief Returns an operation place by a tensor name following framework conventions, + /// or nullptr if an operation with this name doesn't exist. virtual Place::Ptr get_place_by_operation_name(const std::string& operationName); - /// Returns an input port. - virtual Place::Ptr get_place_by_operation_and_input_port(const std::string& operationName, int inputPortIndex); - - /// Returns an output port. - virtual Place::Ptr get_place_by_operation_and_output_port(const std::string& operationName, int outputPortIndex); + /// \brief Returns an input port. + virtual Place::Ptr + get_place_by_operation_and_input_port(const std::string& operationName, + int inputPortIndex); + /// \brief Returns an output port. + virtual Place::Ptr + get_place_by_operation_and_output_port(const std::string& operationName, + int outputPortIndex); ///// Naming and annotation ///// + /// \brief Sets name for tensor. Overwrites existing names of this place virtual void set_name_for_tensor(Place::Ptr tensor, const std::string& newName); + /// \brief Adds new name for tenso virtual void add_name_for_tensor(Place::Ptr tensor, const std::string& newName); + /// \brief Sets name for operation. Overwrites existing names of this place virtual void set_name_for_operation(Place::Ptr operation, const std::string& newName); + /// \brief Unassign specified name from tensor place(s) virtual void free_name_for_tensor(const std::string& name); + /// \brief Unassign specified name from operation place(s) virtual void free_name_for_operation(const std::string& name); - virtual void set_name_for_dimension(Place::Ptr place, size_t shapeDimIndex, const std::string& dimName); - + /// \brief Set name for a particular dimension of a place (e.g. batch dimension) + virtual void set_name_for_dimension(Place::Ptr place, + size_t shapeDimIndex, + const std::string& dimName); ///// Topology Editing ///// - /// Cut immediately before this place and assign this place as new input; prune all nodes that don't contribute to any output. - virtual void cut_and_add_new_input(Place::Ptr place, const std::string& newNameOptional = ""); + /// \brief Cut immediately before this place and assign this place as new input; prune + /// all nodes that don't contribute to any output. + virtual void cut_and_add_new_input(Place::Ptr place, + const std::string& newNameOptional = ""); - /// Cut immediately after this place and assign this place as new output; prune all nodes that don't contribute to any output. - virtual void cut_and_add_new_output(Place::Ptr place, const std::string& newNameOptional = ""); + /// \brief Cut immediately after this place and assign this place as new output; prune + /// all nodes that don't contribute to any output. + virtual void cut_and_add_new_output(Place::Ptr place, + const std::string& newNameOptional = ""); - /// \brief Assign this place as new output or add necessary nodes to represent a new output. + /// \brief Assign this place as new output or add necessary nodes to represent a new + /// output. /// /// \param place Anchor point to add an output /// \return new output place, may be the same as a given place virtual Place::Ptr add_output(Place::Ptr place); - /// Removes any sinks directly attached to this place with all inbound data flow if it is not required by any other output. + /// \brief Removes any sinks directly attached to this place with all inbound data flow + /// if it is not required by any other output. virtual void remove_output(Place::Ptr place); - /// Removes an input place and all data flow that depends on it. + /// \brief Removes an input place and all data flow that depends on it. // TODO: remove it as something not practically useful in the API? virtual void remove_input(Place::Ptr place); - /// Replaces all existing outputs with new ones removing all data flow that is not required for new outputs. + /// \brief Replaces all existing outputs with new ones removing all data flow that is + /// not required for new outputs. /// - /// \param outputs Vector with places that will become new outputs; may intersect existing outputs. + /// \param outputs Vector with places that will become new outputs; may intersect + /// existing outputs. virtual void override_all_outputs(const std::vector& outputs); - /// \brief Modifies the graph to use new inputs instead of existing ones. New inputs should completely satisfy all existing outputs. + /// \brief Modifies the graph to use new inputs instead of existing ones. New inputs + /// should completely satisfy all existing outputs. virtual void override_all_inputs(const std::vector& inputs); - /// Leaves only subgraph that are defined by new inputs and new outputs. - virtual void extract_subgraph(const std::vector& inputs, const std::vector& outputs); + /// \brief Leaves only subgraph that are defined by new inputs and new outputs. + virtual void extract_subgraph(const std::vector& inputs, + const std::vector& outputs); ///// Setting tensor properties ///// - /// Sets shape that would be used by default for this place; place should be uniquely refer to some data. - // TODO: define clearly which scenario requires it -- currently it should satisfy requirement to have statically defined shapes for tensors + /// Sets shape that would be used by default for this place; place should be uniquely + /// refer to some data. + // TODO: define clearly which scenario requires it -- currently it should satisfy + // requirement to have statically defined shapes for tensors virtual void set_default_shape(Place::Ptr place, const ngraph::Shape&); - /// Defines all possible shape that may be used for this place; place should be uniquely refer to some data. - /// This partial shape will be converted to corresponding shape of results ngraph nodes and will define shape inference - /// when the model is converted to ngraph. + /// \brief Defines all possible shape that may be used for this place; place should be + /// uniquely refer to some data. This partial shape will be converted to corresponding + /// shape of results ngraph nodes and will define shape inference when the model is + /// converted to ngraph. virtual void set_partial_shape(Place::Ptr place, const ngraph::PartialShape&); - /// Returns current partial shape used for this place + /// \brief Returns current partial shape used for this place virtual ngraph::PartialShape get_partial_shape(Place::Ptr place) const; - /// Sets new element type for a place. + /// \brief Sets new element type for a place. virtual void set_element_type(Place::Ptr place, const ngraph::element::Type&); - /// Freezes a tensor with statically defined value or replace existing value for already constant node or tensor. - virtual void set_tensor_value(Place::Ptr place, const void *value); + /// \brief Freezes a tensor with statically defined value or replace existing value for + /// already constant node or tensor. + virtual void set_tensor_value(Place::Ptr place, const void* value); - /// Defines partial value (lower bound and upper bound) for a tensor place. + /// \brief Defines partial value (lower bound and upper bound) for a tensor place. // TODO: more details for minValue and maxValue format; who defines shape? - virtual void set_tensor_partial_value(Place::Ptr place, const void *minValue, const void *maxValue); - - // TODO: Document "inputs/output assymetry" in more details - - // Traversing - // TODO: remove or add something; most likely will have only a single method that provides a list of operation nodes sorted topologically - - // Support querying - // TODO: remove or add something; there are no candidates, all queries can be satisfied without any API extension here + virtual void set_tensor_partial_value(Place::Ptr place, + const void* minValue, + const void* maxValue); }; + /// \brief An interface for identifying a frontend for a particular framework. + /// Provides an ability to load and convert of input model class FRONTEND_API FrontEnd { public: @@ -278,54 +316,85 @@ namespace ngraph virtual ~FrontEnd(); + /// \brief Loads an input model by specified model file path + /// If model is stored in several files (e.g. model topology and model weights) - + /// frontend implementation is responsible to handle this case, generally frontend may + /// retrieve other file names from main file virtual InputModel::Ptr load_from_file(const std::string& path) const; + /// \brief Loads an input model by specified number of model files + /// This shall be used for cases when client knows all model files (model, weights, etc) virtual InputModel::Ptr load_from_files(const std::vector& paths) const; - virtual InputModel::Ptr load_from_memory(const void *model) const; + /// \brief Loads an input model by already loaded memory buffer + /// Memory structure is frontend-defined and is not specified in generic API + virtual InputModel::Ptr load_from_memory(const void* model) const; - virtual InputModel::Ptr load_from_memory_fragments(const std::vector& modelParts) const; + /// \brief Loads an input model from set of memory buffers + /// Memory structure is frontend-defined and is not specified in generic API + virtual InputModel::Ptr + load_from_memory_fragments(const std::vector& modelParts) const; + /// \brief Loads an input model by input stream representing main model file virtual InputModel::Ptr load_from_stream(std::istream& path) const; - virtual InputModel::Ptr load_from_streams(const std::vector& paths) const; - - // Extra ctors may be provided by FW-specialized data structure for graph representaion + /// \brief Loads an input model by input streams representing all model files + virtual InputModel::Ptr + load_from_streams(const std::vector& paths) const; - /// Completely convert and normalize entire function, throws if it is not possible + /// \brief Completely convert and normalize entire function, throws if it is not + /// possible virtual std::shared_ptr convert(InputModel::Ptr model) const; - /// Completely convert the remaining, not converted part of a function. - virtual std::shared_ptr convert( - std::shared_ptr partiallyConverted) const; + /// \brief Completely convert the remaining, not converted part of a function. + virtual std::shared_ptr + convert(std::shared_ptr partiallyConverted) const; - /// Convert only those parts of the model that can be converted leaving others as-is. - /// Converted parts are not normalized by additional transformations; normalize function - /// or another form of convert function should be called to finalize the conversion process. - virtual std::shared_ptr convert_partially(InputModel::Ptr model) const; + /// \brief Convert only those parts of the model that can be converted leaving others + /// as-is. Converted parts are not normalized by additional transformations; normalize + /// function or another form of convert function should be called to finalize the + /// conversion process. + virtual std::shared_ptr + convert_partially(InputModel::Ptr model) const; - /// Convert operations with one-to-one mapping with decoding nodes. - /// Each decoding node is an nGraph node representing a single FW operation node with all attributes - /// represented in FW-independent way. + /// \brief Convert operations with one-to-one mapping with decoding nodes. + /// Each decoding node is an nGraph node representing a single FW operation node with + /// all attributes represented in FW-independent way. virtual std::shared_ptr decode(InputModel::Ptr model) const; - /// Runs normalization passes on function that was loaded with partial conversion + /// \brief Runs normalization passes on function that was loaded with partial conversion virtual void normalize(std::shared_ptr function) const; }; + /// Capabilities for requested FrontEnd + /// In general, frontend implementation may be divided into several libraries by capability + /// level It will allow faster load of frontend when only limited usage is expected by + /// client application as well as binary size can be minimized by removing not needed parts + /// from application's package enum class FrontEndCapabilities { - FEC_DEFAULT = 0, // Just reading and conversion, w/o any modifications; intended to be used in Reader + /// \brief Just reading and conversion, w/o any modifications; intended to be used in + /// Reader + FEC_DEFAULT = 0, + /// \brief Topology cutting capability FEC_CUT = 1, + /// \brief Query entities by names, renaming and adding new names for operations and + /// tensors FEC_NAMES = 2, + /// TODO FEC_REPLACE = 4, + /// \brief Traversing model's graph capability FEC_TRAVERSE = 8, + /// TODO FEC_WILDCARDS = 16, }; -// -------------- FrontEndManager ----------------- + // -------------- FrontEndManager ----------------- using FrontEndFactory = std::function; + /// \brief Frontend management class, loads available frontend plugins on construction + /// Allows load of frontends for particular framework, register new and list available + /// frontends This is a main frontend entry point for client applications class FRONTEND_API FrontEndManager { public: @@ -333,14 +402,29 @@ namespace ngraph ~FrontEndManager(); - FrontEnd::Ptr load_by_framework(const std::string& framework, - FrontEndCapabilities fec = FrontEndCapabilities::FEC_DEFAULT); - - FrontEnd::Ptr load_by_model(const std::string& path, - FrontEndCapabilities fec = FrontEndCapabilities::FEC_DEFAULT); - + /// \brief Loads frontend by name of framework and capabilities + /// \param framework Framework name. Throws exception if name is not in list of + /// available frontends \param fec Frontend capabilities. It is recommended to use only + /// those capabilities which are needed to minimize load time \return Frontend interface + /// for further loading of models + FrontEnd::Ptr + load_by_framework(const std::string& framework, + FrontEndCapabilities fec = FrontEndCapabilities::FEC_DEFAULT); + + /// \brief Loads frontend by model file path. Selects and loads appropriate frontend + /// depending on model file extension and other file info (header) \param framework + /// Framework name. Throws exception if name is not in list of available frontends + /// \param fec Frontend capabilities. It is recommended to use only those capabilities + /// which are needed to minimize load time + /// \return Frontend interface for further loading of model + FrontEnd::Ptr + load_by_model(const std::string& path, + FrontEndCapabilities fec = FrontEndCapabilities::FEC_DEFAULT); + + /// \brief Gets list of registered frontends std::vector get_available_front_ends() const; + /// \brief Register frontend with name and factory creation method void register_front_end(const std::string& name, FrontEndFactory creator); private: @@ -349,10 +433,17 @@ namespace ngraph std::unique_ptr m_impl; }; -// --------- Plugin exporting information -------------- + // --------- Plugin exporting information -------------- + /// \brief Each frontend plugin is responsible to export GetAPIVersion function returning + /// version of frontend API used for this plugin + /// If version is not matched with OV_FRONTEND_API_VERSION - plugin will not be loaded by + /// FrontEndManager using FrontEndVersion = uint64_t; + /// \brief Each frontend plugin is responsible to export GetFrontEndData function returning + /// heap-allocated pointer to this structure. Will be used by FrontEndManager during loading + /// of plugins struct FrontEndPluginInfo { std::string m_name; diff --git a/ngraph/frontend/generic/include/frontend_manager/frontend_manager_defs.hpp b/ngraph/frontend/generic/include/frontend_manager/frontend_manager_defs.hpp index a06dccda35ff40..f7c1f3de86419d 100644 --- a/ngraph/frontend/generic/include/frontend_manager/frontend_manager_defs.hpp +++ b/ngraph/frontend/generic/include/frontend_manager/frontend_manager_defs.hpp @@ -6,9 +6,11 @@ #include "ngraph/visibility.hpp" -#define OV_FRONTEND_API_VERSION 1 // Increment each time when FrontEnd/InputModel/Place interface is changed +// Increment each time when FrontEnd/InputModel/Place interface is changed +#define OV_FRONTEND_API_VERSION 1 -#ifdef frontend_manager_EXPORTS // defined if cmake is building the frontend_manager DLL (instead of using it) +// Defined if cmake is building the frontend_manager DLL (instead of using it) +#ifdef frontend_manager_EXPORTS #define FRONTEND_API NGRAPH_HELPER_DLL_EXPORT #else #define FRONTEND_API NGRAPH_HELPER_DLL_IMPORT diff --git a/ngraph/frontend/generic/src/frontend_manager.cpp b/ngraph/frontend/generic/src/frontend_manager.cpp index 02260d53cdfe07..02a369d325dbe8 100644 --- a/ngraph/frontend/generic/src/frontend_manager.cpp +++ b/ngraph/frontend/generic/src/frontend_manager.cpp @@ -2,8 +2,8 @@ // SPDX-License-Identifier: Apache-2.0 // -#include #include +#include #include "frontend_manager/frontend_manager.hpp" #include "plugin_loader.hpp" @@ -12,21 +12,22 @@ namespace ngraph { namespace frontend { - -#define FRONT_END_NOT_IMPLEMENTED(NAME) throw std::runtime_error(#NAME " is not implemented for this FrontEnd class") -#define FRONT_END_ASSERT(EXPRESSION) \ - { if (!(EXPRESSION)) throw "AssertionFailed"; } +#define FRONT_END_NOT_IMPLEMENTED(NAME) \ + throw std::runtime_error(#NAME " is not implemented for this FrontEnd class") +#define FRONT_END_ASSERT(EXPRESSION) \ + { \ + if (!(EXPRESSION)) \ + throw "AssertionFailed"; \ + } //----------- FrontEndManager --------------------------- class FrontEndManager::Impl { std::vector m_loadedLibs; // must be a first class member (destroyed last) std::map m_factories; + public: - Impl() - { - registerPlugins(); - } + Impl() { registerPlugins(); } ~Impl() = default; @@ -40,12 +41,11 @@ namespace ngraph { std::vector keys; - std::transform(m_factories.begin(), m_factories.end(), - std::back_inserter(keys), - [](const std::pair& item) - { - return item.first; - }); + std::transform( + m_factories.begin(), + m_factories.end(), + std::back_inserter(keys), + [](const std::pair& item) { return item.first; }); return keys; } @@ -62,14 +62,14 @@ namespace ngraph private: void registerPlugins() { - auto registerFromDir = [&](const std::string& dir) - { + auto registerFromDir = [&](const std::string& dir) { if (!dir.empty()) { auto plugins = loadPlugins(dir); for (auto& plugin : plugins) { - registerFrontEnd(plugin.m_pluginInfo.m_name, plugin.m_pluginInfo.m_creator); + registerFrontEnd(plugin.m_pluginInfo.m_name, + plugin.m_pluginInfo.m_creator); m_loadedLibs.push_back(std::move(plugin.m_libHandle)); } } @@ -94,18 +94,21 @@ namespace ngraph } }; - FrontEndManager::FrontEndManager() : m_impl(new Impl()) + FrontEndManager::FrontEndManager() + : m_impl(new Impl()) { } FrontEndManager::~FrontEndManager() = default; - FrontEnd::Ptr FrontEndManager::load_by_framework(const std::string& framework, FrontEndCapabilities fec) + FrontEnd::Ptr FrontEndManager::load_by_framework(const std::string& framework, + FrontEndCapabilities fec) { return m_impl->loadByFramework(framework, fec); } - FrontEnd::Ptr FrontEndManager::load_by_model(const std::string& path, FrontEndCapabilities fec) + FrontEnd::Ptr FrontEndManager::load_by_model(const std::string& path, + FrontEndCapabilities fec) { return m_impl->loadByModel(path, fec); } @@ -136,12 +139,13 @@ namespace ngraph FRONT_END_NOT_IMPLEMENTED(load_from_files); } - InputModel::Ptr FrontEnd::load_from_memory(const void *model) const + InputModel::Ptr FrontEnd::load_from_memory(const void* model) const { FRONT_END_NOT_IMPLEMENTED(load_from_memory); } - InputModel::Ptr FrontEnd::load_from_memory_fragments(const std::vector& modelParts) const + InputModel::Ptr + FrontEnd::load_from_memory_fragments(const std::vector& modelParts) const { FRONT_END_NOT_IMPLEMENTED(load_from_memory_fragments); } @@ -151,7 +155,7 @@ namespace ngraph FRONT_END_NOT_IMPLEMENTED(load_from_stream); } - InputModel::Ptr FrontEnd::load_from_streams(const std::vector& paths) const + InputModel::Ptr FrontEnd::load_from_streams(const std::vector& paths) const { FRONT_END_NOT_IMPLEMENTED(load_from_streams); } @@ -202,12 +206,16 @@ namespace ngraph FRONT_END_NOT_IMPLEMENTED(get_place_by_operation_name); } - Place::Ptr InputModel::get_place_by_operation_and_input_port(const std::string& operationName, int inputPortIndex) + Place::Ptr + InputModel::get_place_by_operation_and_input_port(const std::string& operationName, + int inputPortIndex) { FRONT_END_NOT_IMPLEMENTED(get_place_by_operation_and_input_port); } - Place::Ptr InputModel::get_place_by_operation_and_output_port(const std::string& operationName, int outputPortIndex) + Place::Ptr + InputModel::get_place_by_operation_and_output_port(const std::string& operationName, + int outputPortIndex) { FRONT_END_NOT_IMPLEMENTED(get_place_by_operation_and_output_port); } @@ -237,7 +245,9 @@ namespace ngraph FRONT_END_NOT_IMPLEMENTED(free_name_for_operation); } - void InputModel::set_name_for_dimension(Place::Ptr place, size_t shapeDimIndex, const std::string& dimName) + void InputModel::set_name_for_dimension(Place::Ptr place, + size_t shapeDimIndex, + const std::string& dimName) { FRONT_END_NOT_IMPLEMENTED(set_name_for_dimension); } @@ -247,7 +257,8 @@ namespace ngraph FRONT_END_NOT_IMPLEMENTED(cut_and_add_new_input); } - void InputModel::cut_and_add_new_output(Place::Ptr place, const std::string& newNameOptional) + void InputModel::cut_and_add_new_output(Place::Ptr place, + const std::string& newNameOptional) { FRONT_END_NOT_IMPLEMENTED(cut_and_add_new_output); } @@ -262,10 +273,7 @@ namespace ngraph FRONT_END_NOT_IMPLEMENTED(remove_output); } - void InputModel::remove_input(Place::Ptr place) - { - FRONT_END_NOT_IMPLEMENTED(remove_input); - } + void InputModel::remove_input(Place::Ptr place) { FRONT_END_NOT_IMPLEMENTED(remove_input); } void InputModel::override_all_outputs(const std::vector& outputs) { @@ -277,8 +285,8 @@ namespace ngraph FRONT_END_NOT_IMPLEMENTED(override_all_inputs); } - void - InputModel::extract_subgraph(const std::vector& inputs, const std::vector& outputs) + void InputModel::extract_subgraph(const std::vector& inputs, + const std::vector& outputs) { FRONT_END_NOT_IMPLEMENTED(extract_subgraph); } @@ -304,21 +312,20 @@ namespace ngraph FRONT_END_NOT_IMPLEMENTED(set_element_type); } - void InputModel::set_tensor_value(Place::Ptr place, const void *value) + void InputModel::set_tensor_value(Place::Ptr place, const void* value) { FRONT_END_NOT_IMPLEMENTED(set_tensor_value); } - void InputModel::set_tensor_partial_value(Place::Ptr place, const void *minValue, const void *maxValue) + void InputModel::set_tensor_partial_value(Place::Ptr place, + const void* minValue, + const void* maxValue) { FRONT_END_NOT_IMPLEMENTED(set_tensor_partial_value); } //----------- Place --------------------------- - std::vector Place::get_names() const - { - FRONT_END_NOT_IMPLEMENTED(get_names); - } + std::vector Place::get_names() const { FRONT_END_NOT_IMPLEMENTED(get_names); } std::vector Place::get_consuming_operations(int outputPortIndex) const { @@ -365,25 +372,13 @@ namespace ngraph FRONT_END_NOT_IMPLEMENTED(get_consuming_ports); } - bool Place::is_input() const - { - FRONT_END_NOT_IMPLEMENTED(is_input); - } + bool Place::is_input() const { FRONT_END_NOT_IMPLEMENTED(is_input); } - bool Place::is_output() const - { - FRONT_END_NOT_IMPLEMENTED(is_output); - } + bool Place::is_output() const { FRONT_END_NOT_IMPLEMENTED(is_output); } - bool Place::is_equal(Ptr another) const - { - FRONT_END_NOT_IMPLEMENTED(is_equal); - } + bool Place::is_equal(Ptr another) const { FRONT_END_NOT_IMPLEMENTED(is_equal); } - bool Place::is_equal_data(Ptr another) const - { - FRONT_END_NOT_IMPLEMENTED(is_equal_data); - } + bool Place::is_equal_data(Ptr another) const { FRONT_END_NOT_IMPLEMENTED(is_equal_data); } Place::Ptr Place::get_source_tensor(int inputPortIndex) const { diff --git a/ngraph/frontend/generic/src/plugin_loader.cpp b/ngraph/frontend/generic/src/plugin_loader.cpp index 71724407ea53b8..53a2957c93b976 100644 --- a/ngraph/frontend/generic/src/plugin_loader.cpp +++ b/ngraph/frontend/generic/src/plugin_loader.cpp @@ -3,17 +3,17 @@ // #ifdef _WIN32 - #include - #include -#else // _WIN32 - #include - #include - #include -#endif // _WIN32 +#include +#include +#else // _WIN32 +#include +#include +#include +#endif // _WIN32 #include -#include #include +#include #include "ngraph/file_util.hpp" #include "plugin_loader.hpp" @@ -37,25 +37,28 @@ static std::vector listFiles(const std::string& path) std::vector res; try { - ngraph::file_util::iterate_files(path, [&res](const std::string& file, bool is_dir) - { - if (!is_dir && file.find("_ngraph_frontend") != std::string::npos) - { + ngraph::file_util::iterate_files( + path, + [&res](const std::string& file, bool is_dir) { + if (!is_dir && file.find("_ngraph_frontend") != std::string::npos) + { #ifdef _WIN32 - std::string ext = ".dll"; + std::string ext = ".dll"; #elif defined(__APPLE__) - std::string ext = ".dylib"; + std::string ext = ".dylib"; #else - std::string ext = ".so"; + std::string ext = ".so"; #endif - if (file.find(ext) != std::string::npos) - { - res.push_back(file); + if (file.find(ext) != std::string::npos) + { + res.push_back(file); + } } - } - }, false, true); + }, + false, + true); } - catch(...) + catch (...) { // Ignore exceptions } @@ -74,13 +77,12 @@ std::vector ngraph::frontend::loadPlugins(const std::string& dirName continue; } - PluginHandle guard([shared_object, file]() - { - // std::cout << "Closing plugin library " << file << std::endl; - DLCLOSE(shared_object); - }); + PluginHandle guard([shared_object, file]() { + // std::cout << "Closing plugin library " << file << std::endl; + DLCLOSE(shared_object); + }); - auto infoAddr = reinterpret_cast(DLSYM(shared_object, "GetAPIVersion")); + auto infoAddr = reinterpret_cast(DLSYM(shared_object, "GetAPIVersion")); if (!infoAddr) { continue; @@ -93,13 +95,14 @@ std::vector ngraph::frontend::loadPlugins(const std::string& dirName continue; } - auto creatorAddr = reinterpret_cast(DLSYM(shared_object, "GetFrontEndData")); + auto creatorAddr = reinterpret_cast(DLSYM(shared_object, "GetFrontEndData")); if (!creatorAddr) { continue; } - std::unique_ptr fact{reinterpret_cast(creatorAddr())}; + std::unique_ptr fact{ + reinterpret_cast(creatorAddr())}; res.push_back(PluginData(std::move(guard), std::move(*fact))); } diff --git a/ngraph/frontend/generic/src/plugin_loader.hpp b/ngraph/frontend/generic/src/plugin_loader.hpp index 51da663fc8520a..1ab3fc73baa227 100644 --- a/ngraph/frontend/generic/src/plugin_loader.hpp +++ b/ngraph/frontend/generic/src/plugin_loader.hpp @@ -18,12 +18,13 @@ namespace ngraph { namespace frontend { - - /// Plugin library handle wrapper. On destruction calls internal function which frees library handle + /// Plugin library handle wrapper. On destruction calls internal function which frees + /// library handle class PluginHandle { public: - PluginHandle(std::function callOnDestruct) : m_callOnDestruct(callOnDestruct) + PluginHandle(std::function callOnDestruct) + : m_callOnDestruct(callOnDestruct) { } @@ -49,16 +50,19 @@ namespace ngraph struct PluginData { - PluginData(PluginHandle&& h, FrontEndPluginInfo&& info) : m_libHandle(std::move(h)), m_pluginInfo(info) + PluginData(PluginHandle&& h, FrontEndPluginInfo&& info) + : m_libHandle(std::move(h)) + , m_pluginInfo(info) { } - PluginHandle m_libHandle; // Shall be destroyed when plugin is not needed anymore to free memory + PluginHandle + m_libHandle; // Shall be destroyed when plugin is not needed anymore to free memory FrontEndPluginInfo m_pluginInfo; }; // Searches for available plugins in a specified directory std::vector loadPlugins(const std::string& dirName); - } // namespace frontend -} // namespace ngraph + } // namespace frontend +} // namespace ngraph diff --git a/ngraph/test/frontend/CMakeLists.txt b/ngraph/test/frontend/CMakeLists.txt index d532d6f4825b78..98f4095b37c5b5 100644 --- a/ngraph/test/frontend/CMakeLists.txt +++ b/ngraph/test/frontend/CMakeLists.txt @@ -12,3 +12,5 @@ target_include_directories(mock1_ngraph_frontend PRIVATE ".") target_include_directories(mock1_ngraph_frontend PRIVATE ${FRONTEND_INCLUDE_PATH} ${NGRAPH_INCLUDE_PATH}) target_link_libraries(mock1_ngraph_frontend PRIVATE frontend_manager) add_dependencies(unit-test mock1_ngraph_frontend) + +add_clang_format_target(mock1_ngraph_frontend_clang FOR_TARGETS mock1_ngraph_frontend) diff --git a/ngraph/test/frontend/mock_frontend.cpp b/ngraph/test/frontend/mock_frontend.cpp index f7d07289cabb0f..19d9058c189d5a 100644 --- a/ngraph/test/frontend/mock_frontend.cpp +++ b/ngraph/test/frontend/mock_frontend.cpp @@ -2,11 +2,12 @@ // SPDX-License-Identifier: Apache-2.0 // -#include "ngraph/visibility.hpp" -#include "frontend_manager/frontend_manager_defs.hpp" #include "frontend_manager/frontend_manager.hpp" +#include "frontend_manager/frontend_manager_defs.hpp" +#include "ngraph/visibility.hpp" -#ifdef mock1_ngraph_frontend_EXPORTS // defined if we are building the plugin DLL (instead of using it) +// Defined if we are building the plugin DLL (instead of using it) +#ifdef mock1_ngraph_frontend_EXPORTS #define MOCK_API NGRAPH_HELPER_DLL_EXPORT #else #define MOCK_API NGRAPH_HELPER_DLL_IMPORT @@ -15,7 +16,7 @@ using namespace ngraph; using namespace ngraph::frontend; -class FrontEndMock: public FrontEnd +class FrontEndMock : public FrontEnd { }; @@ -28,9 +29,8 @@ extern "C" MOCK_API void* GetFrontEndData() { FrontEndPluginInfo* res = new FrontEndPluginInfo(); res->m_name = "mock1"; - res->m_creator = [](ngraph::frontend::FrontEndCapabilities) - { - return std::make_shared(); - }; + res->m_creator = [](ngraph::frontend::FrontEndCapabilities) { + return std::make_shared(); + }; return res; } \ No newline at end of file From 481ecf1702d504627edc25f7a49949ab89f5e014 Mon Sep 17 00:00:00 2001 From: Michael Nosov Date: Wed, 12 May 2021 13:28:07 +0300 Subject: [PATCH 12/22] Update docs for FrontEndCapabilities --- .../generic/include/frontend_manager/frontend_manager.hpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/ngraph/frontend/generic/include/frontend_manager/frontend_manager.hpp b/ngraph/frontend/generic/include/frontend_manager/frontend_manager.hpp index 0aac6e1dc56e6b..1fd50dc95cf514 100644 --- a/ngraph/frontend/generic/include/frontend_manager/frontend_manager.hpp +++ b/ngraph/frontend/generic/include/frontend_manager/frontend_manager.hpp @@ -381,12 +381,8 @@ namespace ngraph /// \brief Query entities by names, renaming and adding new names for operations and /// tensors FEC_NAMES = 2, - /// TODO - FEC_REPLACE = 4, - /// \brief Traversing model's graph capability - FEC_TRAVERSE = 8, - /// TODO - FEC_WILDCARDS = 16, + /// \brief Partial model conversion and decoding capability + FEC_WILDCARDS = 4, }; // -------------- FrontEndManager ----------------- From c6184ad5a557e933e052a95f73b8f99dca61f6af Mon Sep 17 00:00:00 2001 From: Michael Nosov Date: Wed, 12 May 2021 15:09:46 +0300 Subject: [PATCH 13/22] Use constants for flags instead of 'enum' --- .../frontend_manager/frontend_manager.hpp | 20 +++++++++------- .../frontend/generic/src/frontend_manager.cpp | 8 +++---- ngraph/test/frontend/frontend_manager.cpp | 24 ++++++++++++++++++- ngraph/test/frontend/mock_frontend.cpp | 2 +- 4 files changed, 40 insertions(+), 14 deletions(-) diff --git a/ngraph/frontend/generic/include/frontend_manager/frontend_manager.hpp b/ngraph/frontend/generic/include/frontend_manager/frontend_manager.hpp index 1fd50dc95cf514..04f11211dfb10f 100644 --- a/ngraph/frontend/generic/include/frontend_manager/frontend_manager.hpp +++ b/ngraph/frontend/generic/include/frontend_manager/frontend_manager.hpp @@ -371,22 +371,26 @@ namespace ngraph /// level It will allow faster load of frontend when only limited usage is expected by /// client application as well as binary size can be minimized by removing not needed parts /// from application's package - enum class FrontEndCapabilities + namespace FrontEndCapabilities { /// \brief Just reading and conversion, w/o any modifications; intended to be used in /// Reader - FEC_DEFAULT = 0, + static const int FEC_DEFAULT = 0; + /// \brief Topology cutting capability - FEC_CUT = 1, + static const int FEC_CUT = 1; + /// \brief Query entities by names, renaming and adding new names for operations and /// tensors - FEC_NAMES = 2, + static const int FEC_NAMES = 2; + /// \brief Partial model conversion and decoding capability - FEC_WILDCARDS = 4, + static const int FEC_WILDCARDS = 4; }; // -------------- FrontEndManager ----------------- - using FrontEndFactory = std::function; + using FrontEndCapFlags = int; + using FrontEndFactory = std::function; /// \brief Frontend management class, loads available frontend plugins on construction /// Allows load of frontends for particular framework, register new and list available @@ -405,7 +409,7 @@ namespace ngraph /// for further loading of models FrontEnd::Ptr load_by_framework(const std::string& framework, - FrontEndCapabilities fec = FrontEndCapabilities::FEC_DEFAULT); + FrontEndCapFlags fec = FrontEndCapabilities::FEC_DEFAULT); /// \brief Loads frontend by model file path. Selects and loads appropriate frontend /// depending on model file extension and other file info (header) \param framework @@ -415,7 +419,7 @@ namespace ngraph /// \return Frontend interface for further loading of model FrontEnd::Ptr load_by_model(const std::string& path, - FrontEndCapabilities fec = FrontEndCapabilities::FEC_DEFAULT); + FrontEndCapFlags fec = FrontEndCapabilities::FEC_DEFAULT); /// \brief Gets list of registered frontends std::vector get_available_front_ends() const; diff --git a/ngraph/frontend/generic/src/frontend_manager.cpp b/ngraph/frontend/generic/src/frontend_manager.cpp index 02a369d325dbe8..227cd60bba70cb 100644 --- a/ngraph/frontend/generic/src/frontend_manager.cpp +++ b/ngraph/frontend/generic/src/frontend_manager.cpp @@ -31,7 +31,7 @@ namespace ngraph ~Impl() = default; - FrontEnd::Ptr loadByFramework(const std::string& framework, FrontEndCapabilities fec) + FrontEnd::Ptr loadByFramework(const std::string& framework, FrontEndCapFlags fec) { FRONT_END_ASSERT(m_factories.count(framework)) return m_factories[framework](fec); @@ -49,7 +49,7 @@ namespace ngraph return keys; } - FrontEnd::Ptr loadByModel(const std::string& path, FrontEndCapabilities fec) + FrontEnd::Ptr loadByModel(const std::string& path, FrontEndCapFlags fec) { FRONT_END_NOT_IMPLEMENTED(loadByModel); } @@ -102,13 +102,13 @@ namespace ngraph FrontEndManager::~FrontEndManager() = default; FrontEnd::Ptr FrontEndManager::load_by_framework(const std::string& framework, - FrontEndCapabilities fec) + FrontEndCapFlags fec) { return m_impl->loadByFramework(framework, fec); } FrontEnd::Ptr FrontEndManager::load_by_model(const std::string& path, - FrontEndCapabilities fec) + FrontEndCapFlags fec) { return m_impl->loadByModel(path, fec); } diff --git a/ngraph/test/frontend/frontend_manager.cpp b/ngraph/test/frontend/frontend_manager.cpp index ebc5dcdb6c9824..f9858b5a0472fe 100644 --- a/ngraph/test/frontend/frontend_manager.cpp +++ b/ngraph/test/frontend/frontend_manager.cpp @@ -33,7 +33,7 @@ static int set_test_env(const char* name, const char* value) TEST(FrontEndManagerTest, testAvailableFrontEnds) { FrontEndManager fem; - ASSERT_NO_THROW(fem.register_front_end("mock", [](FrontEndCapabilities fec) + ASSERT_NO_THROW(fem.register_front_end("mock", [](FrontEndCapFlags fec) { return std::make_shared(); })); @@ -43,6 +43,28 @@ TEST(FrontEndManagerTest, testAvailableFrontEnds) ASSERT_NO_THROW(fe = fem.load_by_framework("mock")); } +TEST(FrontEndManagerTest, testLoadWithFlags) +{ + int expFlags = FrontEndCapabilities::FEC_CUT | + FrontEndCapabilities::FEC_WILDCARDS | + FrontEndCapabilities::FEC_NAMES; + int actualFlags = FrontEndCapabilities::FEC_DEFAULT; + FrontEndManager fem; + ASSERT_NO_THROW(fem.register_front_end("mock", [&actualFlags](int fec) + { + actualFlags = fec; + return std::make_shared(); + })); + auto frontends = fem.get_available_front_ends(); + ASSERT_NE(std::find(frontends.begin(), frontends.end(), "mock"), frontends.end()); + FrontEnd::Ptr fe; + ASSERT_NO_THROW(fe = fem.load_by_framework("mock", expFlags)); + ASSERT_TRUE(actualFlags & FrontEndCapabilities::FEC_CUT); + ASSERT_TRUE(actualFlags & FrontEndCapabilities::FEC_WILDCARDS); + ASSERT_TRUE(actualFlags & FrontEndCapabilities::FEC_NAMES); + ASSERT_EQ(expFlags, actualFlags); +} + TEST(FrontEndManagerTest, testMockPluginFrontEnd) { std::string fePath = diff --git a/ngraph/test/frontend/mock_frontend.cpp b/ngraph/test/frontend/mock_frontend.cpp index 19d9058c189d5a..2b2cd6ef8c0658 100644 --- a/ngraph/test/frontend/mock_frontend.cpp +++ b/ngraph/test/frontend/mock_frontend.cpp @@ -29,7 +29,7 @@ extern "C" MOCK_API void* GetFrontEndData() { FrontEndPluginInfo* res = new FrontEndPluginInfo(); res->m_name = "mock1"; - res->m_creator = [](ngraph::frontend::FrontEndCapabilities) { + res->m_creator = [](FrontEndCapFlags) { return std::make_shared(); }; return res; From 46df0b3e3d9695a1e7f85580d1380a0a99684bf2 Mon Sep 17 00:00:00 2001 From: Michael Nosov Date: Wed, 12 May 2021 15:19:19 +0300 Subject: [PATCH 14/22] clang style fix --- .../generic/include/frontend_manager/frontend_manager.hpp | 7 +++---- ngraph/frontend/generic/src/frontend_manager.cpp | 3 +-- ngraph/test/frontend/mock_frontend.cpp | 4 +--- 3 files changed, 5 insertions(+), 9 deletions(-) diff --git a/ngraph/frontend/generic/include/frontend_manager/frontend_manager.hpp b/ngraph/frontend/generic/include/frontend_manager/frontend_manager.hpp index 04f11211dfb10f..af9429762915fb 100644 --- a/ngraph/frontend/generic/include/frontend_manager/frontend_manager.hpp +++ b/ngraph/frontend/generic/include/frontend_manager/frontend_manager.hpp @@ -386,7 +386,7 @@ namespace ngraph /// \brief Partial model conversion and decoding capability static const int FEC_WILDCARDS = 4; - }; + }; // namespace FrontEndCapabilities // -------------- FrontEndManager ----------------- using FrontEndCapFlags = int; @@ -417,9 +417,8 @@ namespace ngraph /// \param fec Frontend capabilities. It is recommended to use only those capabilities /// which are needed to minimize load time /// \return Frontend interface for further loading of model - FrontEnd::Ptr - load_by_model(const std::string& path, - FrontEndCapFlags fec = FrontEndCapabilities::FEC_DEFAULT); + FrontEnd::Ptr load_by_model(const std::string& path, + FrontEndCapFlags fec = FrontEndCapabilities::FEC_DEFAULT); /// \brief Gets list of registered frontends std::vector get_available_front_ends() const; diff --git a/ngraph/frontend/generic/src/frontend_manager.cpp b/ngraph/frontend/generic/src/frontend_manager.cpp index 227cd60bba70cb..039e5c3de995d0 100644 --- a/ngraph/frontend/generic/src/frontend_manager.cpp +++ b/ngraph/frontend/generic/src/frontend_manager.cpp @@ -107,8 +107,7 @@ namespace ngraph return m_impl->loadByFramework(framework, fec); } - FrontEnd::Ptr FrontEndManager::load_by_model(const std::string& path, - FrontEndCapFlags fec) + FrontEnd::Ptr FrontEndManager::load_by_model(const std::string& path, FrontEndCapFlags fec) { return m_impl->loadByModel(path, fec); } diff --git a/ngraph/test/frontend/mock_frontend.cpp b/ngraph/test/frontend/mock_frontend.cpp index 2b2cd6ef8c0658..34c8d420b031fc 100644 --- a/ngraph/test/frontend/mock_frontend.cpp +++ b/ngraph/test/frontend/mock_frontend.cpp @@ -29,8 +29,6 @@ extern "C" MOCK_API void* GetFrontEndData() { FrontEndPluginInfo* res = new FrontEndPluginInfo(); res->m_name = "mock1"; - res->m_creator = [](FrontEndCapFlags) { - return std::make_shared(); - }; + res->m_creator = [](FrontEndCapFlags) { return std::make_shared(); }; return res; } \ No newline at end of file From 44cf8f3864d151e0363157899b559f2a054b715a Mon Sep 17 00:00:00 2001 From: Michael Nosov Date: Thu, 13 May 2021 13:18:52 +0300 Subject: [PATCH 15/22] Fix comment: using namespace ngraph... --- .../frontend/generic/src/frontend_manager.cpp | 599 +++++++++--------- 1 file changed, 304 insertions(+), 295 deletions(-) diff --git a/ngraph/frontend/generic/src/frontend_manager.cpp b/ngraph/frontend/generic/src/frontend_manager.cpp index 039e5c3de995d0..ddd1a57942089c 100644 --- a/ngraph/frontend/generic/src/frontend_manager.cpp +++ b/ngraph/frontend/generic/src/frontend_manager.cpp @@ -8,10 +8,9 @@ #include "frontend_manager/frontend_manager.hpp" #include "plugin_loader.hpp" -namespace ngraph -{ - namespace frontend - { +using namespace ngraph; +using namespace ngraph::frontend; + #define FRONT_END_NOT_IMPLEMENTED(NAME) \ throw std::runtime_error(#NAME " is not implemented for this FrontEnd class") #define FRONT_END_ASSERT(EXPRESSION) \ @@ -20,369 +19,379 @@ namespace ngraph throw "AssertionFailed"; \ } - //----------- FrontEndManager --------------------------- - class FrontEndManager::Impl - { - std::vector m_loadedLibs; // must be a first class member (destroyed last) - std::map m_factories; +//----------- FrontEndManager --------------------------- +class FrontEndManager::Impl +{ + std::vector m_loadedLibs; // must be a first class member (destroyed last) + std::map m_factories; - public: - Impl() { registerPlugins(); } +public: + Impl() { registerPlugins(); } - ~Impl() = default; + ~Impl() = default; - FrontEnd::Ptr loadByFramework(const std::string& framework, FrontEndCapFlags fec) - { - FRONT_END_ASSERT(m_factories.count(framework)) - return m_factories[framework](fec); - } + FrontEnd::Ptr loadByFramework(const std::string& framework, FrontEndCapFlags fec) + { + FRONT_END_ASSERT(m_factories.count(framework)) + return m_factories[framework](fec); + } - std::vector availableFrontEnds() const - { - std::vector keys; - - std::transform( - m_factories.begin(), - m_factories.end(), - std::back_inserter(keys), - [](const std::pair& item) { return item.first; }); - return keys; - } + std::vector availableFrontEnds() const + { + std::vector keys; + + std::transform( + m_factories.begin(), + m_factories.end(), + std::back_inserter(keys), + [](const std::pair& item) { return item.first; }); + return keys; + } - FrontEnd::Ptr loadByModel(const std::string& path, FrontEndCapFlags fec) - { - FRONT_END_NOT_IMPLEMENTED(loadByModel); - } + FrontEnd::Ptr loadByModel(const std::string& path, FrontEndCapFlags fec) + { + FRONT_END_NOT_IMPLEMENTED(loadByModel); + } - void registerFrontEnd(const std::string& name, FrontEndFactory creator) - { - m_factories.insert({name, creator}); - } + void registerFrontEnd(const std::string& name, FrontEndFactory creator) + { + m_factories.insert({name, creator}); + } - private: - void registerPlugins() +private: + void registerPlugins() + { + auto registerFromDir = [&](const std::string& dir) { + if (!dir.empty()) { - auto registerFromDir = [&](const std::string& dir) { - if (!dir.empty()) - { - auto plugins = loadPlugins(dir); - for (auto& plugin : plugins) - { - registerFrontEnd(plugin.m_pluginInfo.m_name, - plugin.m_pluginInfo.m_creator); - m_loadedLibs.push_back(std::move(plugin.m_libHandle)); - } - } - }; - std::string envPath = ngraph::getenv_string("OV_FRONTEND_PATH"); - if (!envPath.empty()) - { - auto start = 0u; - auto sepPos = envPath.find(PathSeparator, start); - while (sepPos != std::string::npos) - { - registerFromDir(envPath.substr(start, sepPos - start)); - start = sepPos + 1; - sepPos = envPath.find(PathSeparator, start); - } - registerFromDir(envPath.substr(start, sepPos)); - } - else + auto plugins = loadPlugins(dir); + for (auto& plugin : plugins) { - registerFromDir("."); + registerFrontEnd(plugin.m_pluginInfo.m_name, plugin.m_pluginInfo.m_creator); + m_loadedLibs.push_back(std::move(plugin.m_libHandle)); } } }; - - FrontEndManager::FrontEndManager() - : m_impl(new Impl()) + std::string envPath = ngraph::getenv_string("OV_FRONTEND_PATH"); + if (!envPath.empty()) { + auto start = 0u; + auto sepPos = envPath.find(PathSeparator, start); + while (sepPos != std::string::npos) + { + registerFromDir(envPath.substr(start, sepPos - start)); + start = sepPos + 1; + sepPos = envPath.find(PathSeparator, start); + } + registerFromDir(envPath.substr(start, sepPos)); } - - FrontEndManager::~FrontEndManager() = default; - - FrontEnd::Ptr FrontEndManager::load_by_framework(const std::string& framework, - FrontEndCapFlags fec) + else { - return m_impl->loadByFramework(framework, fec); + registerFromDir("."); } + } +}; - FrontEnd::Ptr FrontEndManager::load_by_model(const std::string& path, FrontEndCapFlags fec) - { - return m_impl->loadByModel(path, fec); - } +FrontEndManager::FrontEndManager() + : m_impl(new Impl()) +{ +} - std::vector FrontEndManager::get_available_front_ends() const - { - return m_impl->availableFrontEnds(); - } +FrontEndManager::~FrontEndManager() = default; - void FrontEndManager::register_front_end(const std::string& name, FrontEndFactory creator) - { - m_impl->registerFrontEnd(name, creator); - } +FrontEnd::Ptr FrontEndManager::load_by_framework(const std::string& framework, FrontEndCapFlags fec) +{ + return m_impl->loadByFramework(framework, fec); +} - //----------- FrontEnd --------------------------- +FrontEnd::Ptr FrontEndManager::load_by_model(const std::string& path, FrontEndCapFlags fec) +{ + return m_impl->loadByModel(path, fec); +} - FrontEnd::FrontEnd() = default; +std::vector FrontEndManager::get_available_front_ends() const +{ + return m_impl->availableFrontEnds(); +} - FrontEnd::~FrontEnd() = default; +void FrontEndManager::register_front_end(const std::string& name, FrontEndFactory creator) +{ + m_impl->registerFrontEnd(name, creator); +} - InputModel::Ptr FrontEnd::load_from_file(const std::string& path) const - { - FRONT_END_NOT_IMPLEMENTED(load_from_file); - } +//----------- FrontEnd --------------------------- - InputModel::Ptr FrontEnd::load_from_files(const std::vector& paths) const - { - FRONT_END_NOT_IMPLEMENTED(load_from_files); - } +FrontEnd::FrontEnd() = default; - InputModel::Ptr FrontEnd::load_from_memory(const void* model) const - { - FRONT_END_NOT_IMPLEMENTED(load_from_memory); - } +FrontEnd::~FrontEnd() = default; - InputModel::Ptr - FrontEnd::load_from_memory_fragments(const std::vector& modelParts) const - { - FRONT_END_NOT_IMPLEMENTED(load_from_memory_fragments); - } +InputModel::Ptr FrontEnd::load_from_file(const std::string& path) const +{ + FRONT_END_NOT_IMPLEMENTED(load_from_file); +} - InputModel::Ptr FrontEnd::load_from_stream(std::istream& path) const - { - FRONT_END_NOT_IMPLEMENTED(load_from_stream); - } +InputModel::Ptr FrontEnd::load_from_files(const std::vector& paths) const +{ + FRONT_END_NOT_IMPLEMENTED(load_from_files); +} - InputModel::Ptr FrontEnd::load_from_streams(const std::vector& paths) const - { - FRONT_END_NOT_IMPLEMENTED(load_from_streams); - } +InputModel::Ptr FrontEnd::load_from_memory(const void* model) const +{ + FRONT_END_NOT_IMPLEMENTED(load_from_memory); +} - std::shared_ptr FrontEnd::convert(InputModel::Ptr model) const - { - FRONT_END_NOT_IMPLEMENTED(convert); - } +InputModel::Ptr + FrontEnd::load_from_memory_fragments(const std::vector& modelParts) const +{ + FRONT_END_NOT_IMPLEMENTED(load_from_memory_fragments); +} - std::shared_ptr FrontEnd::convert(std::shared_ptr) const - { - FRONT_END_NOT_IMPLEMENTED(convert); - } +InputModel::Ptr FrontEnd::load_from_stream(std::istream& path) const +{ + FRONT_END_NOT_IMPLEMENTED(load_from_stream); +} - std::shared_ptr FrontEnd::convert_partially(InputModel::Ptr model) const - { - FRONT_END_NOT_IMPLEMENTED(convert_partially); - } +InputModel::Ptr FrontEnd::load_from_streams(const std::vector& paths) const +{ + FRONT_END_NOT_IMPLEMENTED(load_from_streams); +} - std::shared_ptr FrontEnd::decode(InputModel::Ptr model) const - { - FRONT_END_NOT_IMPLEMENTED(convertDecodingOnly); - } +std::shared_ptr FrontEnd::convert(InputModel::Ptr model) const +{ + FRONT_END_NOT_IMPLEMENTED(convert); +} - void FrontEnd::normalize(std::shared_ptr function) const - { - FRONT_END_NOT_IMPLEMENTED(normalize); - } +std::shared_ptr FrontEnd::convert(std::shared_ptr) const +{ + FRONT_END_NOT_IMPLEMENTED(convert); +} - //----------- InputModel --------------------------- - std::vector InputModel::get_inputs() const - { - FRONT_END_NOT_IMPLEMENTED(get_inputs); - } +std::shared_ptr FrontEnd::convert_partially(InputModel::Ptr model) const +{ + FRONT_END_NOT_IMPLEMENTED(convert_partially); +} - std::vector InputModel::get_outputs() const - { - FRONT_END_NOT_IMPLEMENTED(get_outputs); - } +std::shared_ptr FrontEnd::decode(InputModel::Ptr model) const +{ + FRONT_END_NOT_IMPLEMENTED(convertDecodingOnly); +} - Place::Ptr InputModel::get_place_by_tensor_name(const std::string& tensorName) const - { - FRONT_END_NOT_IMPLEMENTED(get_place_by_tensor_name); - } +void FrontEnd::normalize(std::shared_ptr function) const +{ + FRONT_END_NOT_IMPLEMENTED(normalize); +} - Place::Ptr InputModel::get_place_by_operation_name(const std::string& operationName) - { - FRONT_END_NOT_IMPLEMENTED(get_place_by_operation_name); - } +//----------- InputModel --------------------------- +std::vector InputModel::get_inputs() const +{ + FRONT_END_NOT_IMPLEMENTED(get_inputs); +} - Place::Ptr - InputModel::get_place_by_operation_and_input_port(const std::string& operationName, - int inputPortIndex) - { - FRONT_END_NOT_IMPLEMENTED(get_place_by_operation_and_input_port); - } +std::vector InputModel::get_outputs() const +{ + FRONT_END_NOT_IMPLEMENTED(get_outputs); +} - Place::Ptr - InputModel::get_place_by_operation_and_output_port(const std::string& operationName, - int outputPortIndex) - { - FRONT_END_NOT_IMPLEMENTED(get_place_by_operation_and_output_port); - } +Place::Ptr InputModel::get_place_by_tensor_name(const std::string& tensorName) const +{ + FRONT_END_NOT_IMPLEMENTED(get_place_by_tensor_name); +} - void InputModel::set_name_for_tensor(Place::Ptr tensor, const std::string& newName) - { - FRONT_END_NOT_IMPLEMENTED(set_name_for_tensor); - } +Place::Ptr InputModel::get_place_by_operation_name(const std::string& operationName) +{ + FRONT_END_NOT_IMPLEMENTED(get_place_by_operation_name); +} - void InputModel::add_name_for_tensor(Place::Ptr tensor, const std::string& newName) - { - FRONT_END_NOT_IMPLEMENTED(add_name_for_tensor); - } +Place::Ptr InputModel::get_place_by_operation_and_input_port(const std::string& operationName, + int inputPortIndex) +{ + FRONT_END_NOT_IMPLEMENTED(get_place_by_operation_and_input_port); +} - void InputModel::set_name_for_operation(Place::Ptr operation, const std::string& newName) - { - FRONT_END_NOT_IMPLEMENTED(set_name_for_operation); - } +Place::Ptr InputModel::get_place_by_operation_and_output_port(const std::string& operationName, + int outputPortIndex) +{ + FRONT_END_NOT_IMPLEMENTED(get_place_by_operation_and_output_port); +} - void InputModel::free_name_for_tensor(const std::string& name) - { - FRONT_END_NOT_IMPLEMENTED(free_name_for_tensor); - } +void InputModel::set_name_for_tensor(Place::Ptr tensor, const std::string& newName) +{ + FRONT_END_NOT_IMPLEMENTED(set_name_for_tensor); +} - void InputModel::free_name_for_operation(const std::string& name) - { - FRONT_END_NOT_IMPLEMENTED(free_name_for_operation); - } +void InputModel::add_name_for_tensor(Place::Ptr tensor, const std::string& newName) +{ + FRONT_END_NOT_IMPLEMENTED(add_name_for_tensor); +} - void InputModel::set_name_for_dimension(Place::Ptr place, - size_t shapeDimIndex, - const std::string& dimName) - { - FRONT_END_NOT_IMPLEMENTED(set_name_for_dimension); - } +void InputModel::set_name_for_operation(Place::Ptr operation, const std::string& newName) +{ + FRONT_END_NOT_IMPLEMENTED(set_name_for_operation); +} - void InputModel::cut_and_add_new_input(Place::Ptr place, const std::string& newNameOptional) - { - FRONT_END_NOT_IMPLEMENTED(cut_and_add_new_input); - } +void InputModel::free_name_for_tensor(const std::string& name) +{ + FRONT_END_NOT_IMPLEMENTED(free_name_for_tensor); +} - void InputModel::cut_and_add_new_output(Place::Ptr place, - const std::string& newNameOptional) - { - FRONT_END_NOT_IMPLEMENTED(cut_and_add_new_output); - } +void InputModel::free_name_for_operation(const std::string& name) +{ + FRONT_END_NOT_IMPLEMENTED(free_name_for_operation); +} - Place::Ptr InputModel::add_output(Place::Ptr place) - { - FRONT_END_NOT_IMPLEMENTED(add_output); - } +void InputModel::set_name_for_dimension(Place::Ptr place, + size_t shapeDimIndex, + const std::string& dimName) +{ + FRONT_END_NOT_IMPLEMENTED(set_name_for_dimension); +} - void InputModel::remove_output(Place::Ptr place) - { - FRONT_END_NOT_IMPLEMENTED(remove_output); - } +void InputModel::cut_and_add_new_input(Place::Ptr place, const std::string& newNameOptional) +{ + FRONT_END_NOT_IMPLEMENTED(cut_and_add_new_input); +} - void InputModel::remove_input(Place::Ptr place) { FRONT_END_NOT_IMPLEMENTED(remove_input); } +void InputModel::cut_and_add_new_output(Place::Ptr place, const std::string& newNameOptional) +{ + FRONT_END_NOT_IMPLEMENTED(cut_and_add_new_output); +} - void InputModel::override_all_outputs(const std::vector& outputs) - { - FRONT_END_NOT_IMPLEMENTED(override_all_outputs); - } +Place::Ptr InputModel::add_output(Place::Ptr place) +{ + FRONT_END_NOT_IMPLEMENTED(add_output); +} - void InputModel::override_all_inputs(const std::vector& inputs) - { - FRONT_END_NOT_IMPLEMENTED(override_all_inputs); - } +void InputModel::remove_output(Place::Ptr place) +{ + FRONT_END_NOT_IMPLEMENTED(remove_output); +} - void InputModel::extract_subgraph(const std::vector& inputs, - const std::vector& outputs) - { - FRONT_END_NOT_IMPLEMENTED(extract_subgraph); - } +void InputModel::remove_input(Place::Ptr place) +{ + FRONT_END_NOT_IMPLEMENTED(remove_input); +} - // Setting tensor properties - void InputModel::set_default_shape(Place::Ptr place, const ngraph::Shape&) - { - FRONT_END_NOT_IMPLEMENTED(set_default_shape); - } +void InputModel::override_all_outputs(const std::vector& outputs) +{ + FRONT_END_NOT_IMPLEMENTED(override_all_outputs); +} - void InputModel::set_partial_shape(Place::Ptr place, const ngraph::PartialShape&) - { - FRONT_END_NOT_IMPLEMENTED(set_partial_shape); - } +void InputModel::override_all_inputs(const std::vector& inputs) +{ + FRONT_END_NOT_IMPLEMENTED(override_all_inputs); +} - ngraph::PartialShape InputModel::get_partial_shape(Place::Ptr place) const - { - FRONT_END_NOT_IMPLEMENTED(set_partial_shape); - } +void InputModel::extract_subgraph(const std::vector& inputs, + const std::vector& outputs) +{ + FRONT_END_NOT_IMPLEMENTED(extract_subgraph); +} - void InputModel::set_element_type(Place::Ptr place, const ngraph::element::Type&) - { - FRONT_END_NOT_IMPLEMENTED(set_element_type); - } +// Setting tensor properties +void InputModel::set_default_shape(Place::Ptr place, const ngraph::Shape&) +{ + FRONT_END_NOT_IMPLEMENTED(set_default_shape); +} - void InputModel::set_tensor_value(Place::Ptr place, const void* value) - { - FRONT_END_NOT_IMPLEMENTED(set_tensor_value); - } +void InputModel::set_partial_shape(Place::Ptr place, const ngraph::PartialShape&) +{ + FRONT_END_NOT_IMPLEMENTED(set_partial_shape); +} - void InputModel::set_tensor_partial_value(Place::Ptr place, - const void* minValue, - const void* maxValue) - { - FRONT_END_NOT_IMPLEMENTED(set_tensor_partial_value); - } +ngraph::PartialShape InputModel::get_partial_shape(Place::Ptr place) const +{ + FRONT_END_NOT_IMPLEMENTED(set_partial_shape); +} - //----------- Place --------------------------- - std::vector Place::get_names() const { FRONT_END_NOT_IMPLEMENTED(get_names); } +void InputModel::set_element_type(Place::Ptr place, const ngraph::element::Type&) +{ + FRONT_END_NOT_IMPLEMENTED(set_element_type); +} - std::vector Place::get_consuming_operations(int outputPortIndex) const - { - FRONT_END_NOT_IMPLEMENTED(get_consuming_operations); - } +void InputModel::set_tensor_value(Place::Ptr place, const void* value) +{ + FRONT_END_NOT_IMPLEMENTED(set_tensor_value); +} - Place::Ptr Place::get_target_tensor(int outputPortIndex) const - { - FRONT_END_NOT_IMPLEMENTED(get_target_tensor); - } +void InputModel::set_tensor_partial_value(Place::Ptr place, + const void* minValue, + const void* maxValue) +{ + FRONT_END_NOT_IMPLEMENTED(set_tensor_partial_value); +} - Place::Ptr Place::get_producing_operation(int inputPortIndex) const - { - FRONT_END_NOT_IMPLEMENTED(get_producing_operation); - } +//----------- Place --------------------------- +std::vector Place::get_names() const +{ + FRONT_END_NOT_IMPLEMENTED(get_names); +} - Place::Ptr Place::get_producing_port() const - { - FRONT_END_NOT_IMPLEMENTED(get_producing_port); - } +std::vector Place::get_consuming_operations(int outputPortIndex) const +{ + FRONT_END_NOT_IMPLEMENTED(get_consuming_operations); +} - Place::Ptr Place::get_input_port(int inputPortIndex) const - { - FRONT_END_NOT_IMPLEMENTED(get_input_port); - } +Place::Ptr Place::get_target_tensor(int outputPortIndex) const +{ + FRONT_END_NOT_IMPLEMENTED(get_target_tensor); +} - Place::Ptr Place::get_input_port(const std::string& inputName, int inputPortIndex) const - { - FRONT_END_NOT_IMPLEMENTED(get_input_port); - } +Place::Ptr Place::get_producing_operation(int inputPortIndex) const +{ + FRONT_END_NOT_IMPLEMENTED(get_producing_operation); +} - Place::Ptr Place::get_output_port(int outputPortIndex) const - { - FRONT_END_NOT_IMPLEMENTED(get_output_port); - } +Place::Ptr Place::get_producing_port() const +{ + FRONT_END_NOT_IMPLEMENTED(get_producing_port); +} - Place::Ptr Place::get_output_port(const std::string& outputName, int outputPortIndex) const - { - FRONT_END_NOT_IMPLEMENTED(get_output_port); - } +Place::Ptr Place::get_input_port(int inputPortIndex) const +{ + FRONT_END_NOT_IMPLEMENTED(get_input_port); +} - std::vector Place::get_consuming_ports() const - { - FRONT_END_NOT_IMPLEMENTED(get_consuming_ports); - } +Place::Ptr Place::get_input_port(const std::string& inputName, int inputPortIndex) const +{ + FRONT_END_NOT_IMPLEMENTED(get_input_port); +} - bool Place::is_input() const { FRONT_END_NOT_IMPLEMENTED(is_input); } +Place::Ptr Place::get_output_port(int outputPortIndex) const +{ + FRONT_END_NOT_IMPLEMENTED(get_output_port); +} - bool Place::is_output() const { FRONT_END_NOT_IMPLEMENTED(is_output); } +Place::Ptr Place::get_output_port(const std::string& outputName, int outputPortIndex) const +{ + FRONT_END_NOT_IMPLEMENTED(get_output_port); +} - bool Place::is_equal(Ptr another) const { FRONT_END_NOT_IMPLEMENTED(is_equal); } +std::vector Place::get_consuming_ports() const +{ + FRONT_END_NOT_IMPLEMENTED(get_consuming_ports); +} - bool Place::is_equal_data(Ptr another) const { FRONT_END_NOT_IMPLEMENTED(is_equal_data); } +bool Place::is_input() const +{ + FRONT_END_NOT_IMPLEMENTED(is_input); +} - Place::Ptr Place::get_source_tensor(int inputPortIndex) const - { - FRONT_END_NOT_IMPLEMENTED(get_source_tensor); - } +bool Place::is_output() const +{ + FRONT_END_NOT_IMPLEMENTED(is_output); +} - } // namespace frontend -} // namespace ngraph +bool Place::is_equal(Ptr another) const +{ + FRONT_END_NOT_IMPLEMENTED(is_equal); +} + +bool Place::is_equal_data(Ptr another) const +{ + FRONT_END_NOT_IMPLEMENTED(is_equal_data); +} + +Place::Ptr Place::get_source_tensor(int inputPortIndex) const +{ + FRONT_END_NOT_IMPLEMENTED(get_source_tensor); +} From 8722f3ba43522ae8e6240fa2331b60b0bc5909be Mon Sep 17 00:00:00 2001 From: Michael Nosov Date: Thu, 13 May 2021 13:20:26 +0300 Subject: [PATCH 16/22] Fix comment: use replace "frontend_manager" with ${TARGET_NAME} in CMakeLists.txt --- ngraph/frontend/generic/CMakeLists.txt | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/ngraph/frontend/generic/CMakeLists.txt b/ngraph/frontend/generic/CMakeLists.txt index 90a0d6edfdde16..114d48fd6a1f26 100644 --- a/ngraph/frontend/generic/CMakeLists.txt +++ b/ngraph/frontend/generic/CMakeLists.txt @@ -2,6 +2,8 @@ # SPDX-License-Identifier: Apache-2.0 # +set(TARGET_NAME "frontend_manager") + file(GLOB_RECURSE LIBRARY_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp) file(GLOB_RECURSE LIBRARY_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/src/*.hpp) file(GLOB_RECURSE LIBRARY_PUBLIC_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/include/*.hpp) @@ -13,21 +15,21 @@ source_group("include" FILES ${LIBRARY_HEADERS}) source_group("public include" FILES ${LIBRARY_PUBLIC_HEADERS}) # Create shared library -add_library(frontend_manager SHARED ${LIBRARY_SRC} ${LIBRARY_HEADERS} ${LIBRARY_PUBLIC_HEADERS}) -add_library(ngraph::frontend_manager ALIAS frontend_manager) +add_library(${TARGET_NAME} SHARED ${LIBRARY_SRC} ${LIBRARY_HEADERS} ${LIBRARY_PUBLIC_HEADERS}) +add_library(ngraph::${TARGET_NAME} ALIAS ${TARGET_NAME}) -target_link_libraries(frontend_manager PRIVATE ${CMAKE_DL_LIBS} ngraph) +target_link_libraries(${TARGET_NAME} PRIVATE ${CMAKE_DL_LIBS} ngraph) -add_clang_format_target(frontend_manager_clang FOR_TARGETS frontend_manager) +add_clang_format_target(${TARGET_NAME}_clang FOR_TARGETS ${TARGET_NAME}) if(COMMAND ie_add_vs_version_file) - ie_add_vs_version_file(NAME frontend_manager + ie_add_vs_version_file(NAME ${TARGET_NAME} FILEDESCRIPTION "Manager of OpenVINO nGraph Frontends") endif() set(FRONTEND_INSTALL_INCLUDE "${NGRAPH_INSTALL_INCLUDE}/ngraph/frontend/generic") -target_include_directories(frontend_manager PUBLIC $ +target_include_directories(${TARGET_NAME} PUBLIC $ $) -target_include_directories(frontend_manager PRIVATE ${NGRAPH_INCLUDE_PATH} ${FRONTEND_INCLUDE_DIR}) +target_include_directories(${TARGET_NAME} PRIVATE ${NGRAPH_INCLUDE_PATH} ${FRONTEND_INCLUDE_DIR}) -target_include_directories(frontend_manager PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src) +target_include_directories(${TARGET_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src) From bd8c73e966b110f36b7be91b4df028baed6b389e Mon Sep 17 00:00:00 2001 From: Michael Nosov Date: Thu, 13 May 2021 13:23:42 +0300 Subject: [PATCH 17/22] Comment fix: rename 'generic' folder to 'frontend_manager' --- ngraph/CMakeLists.txt | 2 +- ngraph/frontend/CMakeLists.txt | 2 +- ngraph/frontend/{generic => frontend_manager}/CMakeLists.txt | 2 +- .../include/frontend_manager/frontend_manager.hpp | 0 .../include/frontend_manager/frontend_manager_defs.hpp | 0 .../{generic => frontend_manager}/src/frontend_manager.cpp | 0 .../{generic => frontend_manager}/src/plugin_loader.cpp | 0 .../{generic => frontend_manager}/src/plugin_loader.hpp | 0 8 files changed, 3 insertions(+), 3 deletions(-) rename ngraph/frontend/{generic => frontend_manager}/CMakeLists.txt (98%) rename ngraph/frontend/{generic => frontend_manager}/include/frontend_manager/frontend_manager.hpp (100%) rename ngraph/frontend/{generic => frontend_manager}/include/frontend_manager/frontend_manager_defs.hpp (100%) rename ngraph/frontend/{generic => frontend_manager}/src/frontend_manager.cpp (100%) rename ngraph/frontend/{generic => frontend_manager}/src/plugin_loader.cpp (100%) rename ngraph/frontend/{generic => frontend_manager}/src/plugin_loader.hpp (100%) diff --git a/ngraph/CMakeLists.txt b/ngraph/CMakeLists.txt index 686cb859b6b897..2e9f8a680ad5cd 100644 --- a/ngraph/CMakeLists.txt +++ b/ngraph/CMakeLists.txt @@ -27,7 +27,7 @@ set(NGRAPH_INCLUDE_PATH ) set(FRONTEND_INCLUDE_PATH - ${CMAKE_CURRENT_SOURCE_DIR}/frontend/generic/include + ${CMAKE_CURRENT_SOURCE_DIR}/frontend/frontend_manager/include ) # Will be used by frontends to construct frontend-specific source location paths diff --git a/ngraph/frontend/CMakeLists.txt b/ngraph/frontend/CMakeLists.txt index ed5595296ed9d9..2b2f8e11e3addc 100644 --- a/ngraph/frontend/CMakeLists.txt +++ b/ngraph/frontend/CMakeLists.txt @@ -2,7 +2,7 @@ # SPDX-License-Identifier: Apache-2.0 # -add_subdirectory(generic) +add_subdirectory(frontend_manager) if (NGRAPH_ONNX_IMPORT_ENABLE) add_subdirectory(onnx_common) diff --git a/ngraph/frontend/generic/CMakeLists.txt b/ngraph/frontend/frontend_manager/CMakeLists.txt similarity index 98% rename from ngraph/frontend/generic/CMakeLists.txt rename to ngraph/frontend/frontend_manager/CMakeLists.txt index 114d48fd6a1f26..5efd560357b357 100644 --- a/ngraph/frontend/generic/CMakeLists.txt +++ b/ngraph/frontend/frontend_manager/CMakeLists.txt @@ -27,7 +27,7 @@ if(COMMAND ie_add_vs_version_file) FILEDESCRIPTION "Manager of OpenVINO nGraph Frontends") endif() -set(FRONTEND_INSTALL_INCLUDE "${NGRAPH_INSTALL_INCLUDE}/ngraph/frontend/generic") +set(FRONTEND_INSTALL_INCLUDE "${NGRAPH_INSTALL_INCLUDE}/ngraph/frontend/frontend_manager") target_include_directories(${TARGET_NAME} PUBLIC $ $) target_include_directories(${TARGET_NAME} PRIVATE ${NGRAPH_INCLUDE_PATH} ${FRONTEND_INCLUDE_DIR}) diff --git a/ngraph/frontend/generic/include/frontend_manager/frontend_manager.hpp b/ngraph/frontend/frontend_manager/include/frontend_manager/frontend_manager.hpp similarity index 100% rename from ngraph/frontend/generic/include/frontend_manager/frontend_manager.hpp rename to ngraph/frontend/frontend_manager/include/frontend_manager/frontend_manager.hpp diff --git a/ngraph/frontend/generic/include/frontend_manager/frontend_manager_defs.hpp b/ngraph/frontend/frontend_manager/include/frontend_manager/frontend_manager_defs.hpp similarity index 100% rename from ngraph/frontend/generic/include/frontend_manager/frontend_manager_defs.hpp rename to ngraph/frontend/frontend_manager/include/frontend_manager/frontend_manager_defs.hpp diff --git a/ngraph/frontend/generic/src/frontend_manager.cpp b/ngraph/frontend/frontend_manager/src/frontend_manager.cpp similarity index 100% rename from ngraph/frontend/generic/src/frontend_manager.cpp rename to ngraph/frontend/frontend_manager/src/frontend_manager.cpp diff --git a/ngraph/frontend/generic/src/plugin_loader.cpp b/ngraph/frontend/frontend_manager/src/plugin_loader.cpp similarity index 100% rename from ngraph/frontend/generic/src/plugin_loader.cpp rename to ngraph/frontend/frontend_manager/src/plugin_loader.cpp diff --git a/ngraph/frontend/generic/src/plugin_loader.hpp b/ngraph/frontend/frontend_manager/src/plugin_loader.hpp similarity index 100% rename from ngraph/frontend/generic/src/plugin_loader.hpp rename to ngraph/frontend/frontend_manager/src/plugin_loader.hpp From e85276ad759b520311366c3ff10c4a7e878a6295 Mon Sep 17 00:00:00 2001 From: Michael Nosov Date: Thu, 13 May 2021 14:29:49 +0300 Subject: [PATCH 18/22] Update documentation comments --- .../frontend_manager/frontend_manager.hpp | 122 +++++++++++++----- .../frontend_manager/src/frontend_manager.cpp | 10 -- ngraph/test/frontend/frontend_manager.cpp | 2 - 3 files changed, 93 insertions(+), 41 deletions(-) diff --git a/ngraph/frontend/frontend_manager/include/frontend_manager/frontend_manager.hpp b/ngraph/frontend/frontend_manager/include/frontend_manager/frontend_manager.hpp index af9429762915fb..c3f17a541d4d9d 100644 --- a/ngraph/frontend/frontend_manager/include/frontend_manager/frontend_manager.hpp +++ b/ngraph/frontend/frontend_manager/include/frontend_manager/frontend_manager.hpp @@ -78,7 +78,7 @@ namespace ngraph /// operations. /// /// \param outputPortIndex If place is an operational node it specifies which output - /// port should be considered + /// port should be considered. It is optional if place has only one output port /// /// \return A vector with all operation node references that consumes data from this /// place @@ -88,7 +88,7 @@ namespace ngraph /// operations, output ports and output edges /// /// \param outputPortIndex Output port index if the current place is an operation node - /// and has multiple output ports + /// and has multiple output ports. It is optional if place has only one output port /// /// \return A tensor place which hold the resulting value for this place virtual Ptr get_target_tensor(int outputPortIndex = -1) const; @@ -96,14 +96,15 @@ namespace ngraph /// \brief Returns a tensor place that supplies data for this place; applicable for /// operations, input ports and input edges /// - /// \param inputPortIndex Input port index for operational nodes + /// \param inputPortIndex Input port index for operational nodes. It is optional if + /// place has only one input port /// \return A tensor place which supplies data for this place virtual Ptr get_source_tensor(int inputPortIndex = -1) const; /// \brief Get an operation node place that immediately produces data for this place /// /// \param inputPortIndex If a given place is itself an operation node, this specifies a - /// port index + /// port index. It is optional if place has only one input port /// /// \return An operation place that produces data for this place virtual Ptr get_producing_operation(int inputPortIndex = -1) const; @@ -112,15 +113,25 @@ namespace ngraph virtual Ptr get_producing_port() const; /// For operation node returns reference to an input port with specified index + /// \param inputPortIndex Input port index. It is optional if place has only one input + /// port virtual Ptr get_input_port(int inputPortIndex = -1) const; /// For operation node returns reference to an input port with specified name and index + /// \param inputName Name of port group, each group can have multiple ports + /// \param inputPortIndex Input port index. It is optional if port group has only one + /// input port virtual Ptr get_input_port(const std::string& inputName, int inputPortIndex = -1) const; /// For operation node returns reference to an output port with specified index + /// \param outputPortIndex Output port index. It is optional if place has only one + /// output port virtual Ptr get_output_port(int outputPortIndex = -1) const; /// For operation node returns reference to an output port with specified name and index + /// \param outputName Name of output port group, each group can have multiple ports + /// \param outputPortIndex Output port index. It is optional if port group has only one + /// output port virtual Ptr get_output_port(const std::string& outputName, int outputPortIndex = -1) const; @@ -134,11 +145,13 @@ namespace ngraph virtual bool is_output() const; /// Returns true if another place is the same as this place. + /// \param another Another place object virtual bool is_equal(Ptr another) const; /// \brief Returns true if another place points to the same data. /// \note The same data means all places on path: output port -> output edge -> tensor /// -> input edge -> input port. + /// \param another Another place object virtual bool is_equal_data(Ptr another) const; }; @@ -194,18 +207,27 @@ namespace ngraph /// \brief Returns a tensor place by a tensor name following framework conventions, or /// nullptr if a tensor with this name doesn't exist. + /// \param tensorName Name of tensor + /// \return Tensor place corresponding to specifed tensor name virtual Place::Ptr get_place_by_tensor_name(const std::string& tensorName) const; - /// \brief Returns an operation place by a tensor name following framework conventions, - /// or nullptr if an operation with this name doesn't exist. + /// \brief Returns an operation place by an operation name following framework + /// conventions, or nullptr if an operation with this name doesn't exist. \param + /// operationName Name of operation \return Place representing operation virtual Place::Ptr get_place_by_operation_name(const std::string& operationName); - /// \brief Returns an input port. + /// \brief Returns an input port place by operation name and appropriate port index + /// \param operationName Name of operation + /// \param outputPortIndex Index of input port for this operation + /// \return Place representing input port of operation virtual Place::Ptr get_place_by_operation_and_input_port(const std::string& operationName, int inputPortIndex); - /// \brief Returns an output port. + /// \brief Returns an output port place by operation name and appropriate port index + /// \param operationNameNname of operation + /// \param outputPortIndex Index of output port for this operation + /// \return Place representing output port of operation virtual Place::Ptr get_place_by_operation_and_output_port(const std::string& operationName, int outputPortIndex); @@ -213,21 +235,32 @@ namespace ngraph ///// Naming and annotation ///// /// \brief Sets name for tensor. Overwrites existing names of this place + /// \param operation Tensor place + /// \param newName New name for this tensor virtual void set_name_for_tensor(Place::Ptr tensor, const std::string& newName); - /// \brief Adds new name for tenso + /// \brief Adds new name for tensor + /// \param operation Tensor place + /// \param newName New name to be added to this place virtual void add_name_for_tensor(Place::Ptr tensor, const std::string& newName); /// \brief Sets name for operation. Overwrites existing names of this place + /// \param operation Operation place + /// \param newName New name for this operation virtual void set_name_for_operation(Place::Ptr operation, const std::string& newName); /// \brief Unassign specified name from tensor place(s) + /// \param name Name of tensor virtual void free_name_for_tensor(const std::string& name); /// \brief Unassign specified name from operation place(s) + /// \param name Name of operation virtual void free_name_for_operation(const std::string& name); /// \brief Set name for a particular dimension of a place (e.g. batch dimension) + /// \param place Model's place + /// \param shapeDimIndex Dimension index + /// \param dimName Name to assign on this dimension virtual void set_name_for_dimension(Place::Ptr place, size_t shapeDimIndex, const std::string& dimName); @@ -236,11 +269,15 @@ namespace ngraph /// \brief Cut immediately before this place and assign this place as new input; prune /// all nodes that don't contribute to any output. + /// \param place New place to be assigned as input + /// \param newNameOptional Optional new name assigned to this input place virtual void cut_and_add_new_input(Place::Ptr place, const std::string& newNameOptional = ""); /// \brief Cut immediately after this place and assign this place as new output; prune /// all nodes that don't contribute to any output. + /// \param place New place to be assigned as output + /// \param newNameOptional Optional new name assigned to this output place virtual void cut_and_add_new_output(Place::Ptr place, const std::string& newNameOptional = ""); @@ -253,53 +290,59 @@ namespace ngraph /// \brief Removes any sinks directly attached to this place with all inbound data flow /// if it is not required by any other output. + /// \param place Model place virtual void remove_output(Place::Ptr place); - /// \brief Removes an input place and all data flow that depends on it. - // TODO: remove it as something not practically useful in the API? - virtual void remove_input(Place::Ptr place); - /// \brief Replaces all existing outputs with new ones removing all data flow that is /// not required for new outputs. /// /// \param outputs Vector with places that will become new outputs; may intersect /// existing outputs. + /// \param outputs Array of new output places virtual void override_all_outputs(const std::vector& outputs); /// \brief Modifies the graph to use new inputs instead of existing ones. New inputs /// should completely satisfy all existing outputs. + /// \param inputs Array of new input places virtual void override_all_inputs(const std::vector& inputs); /// \brief Leaves only subgraph that are defined by new inputs and new outputs. + /// \param inputs Array of new input places + /// \param outputs Array of new output places virtual void extract_subgraph(const std::vector& inputs, const std::vector& outputs); ///// Setting tensor properties ///// - /// Sets shape that would be used by default for this place; place should be uniquely - /// refer to some data. - // TODO: define clearly which scenario requires it -- currently it should satisfy - // requirement to have statically defined shapes for tensors - virtual void set_default_shape(Place::Ptr place, const ngraph::Shape&); - /// \brief Defines all possible shape that may be used for this place; place should be /// uniquely refer to some data. This partial shape will be converted to corresponding /// shape of results ngraph nodes and will define shape inference when the model is /// converted to ngraph. - virtual void set_partial_shape(Place::Ptr place, const ngraph::PartialShape&); + /// \param place Model place + /// \param shape Partial shape for this place + virtual void set_partial_shape(Place::Ptr place, const ngraph::PartialShape& shape); /// \brief Returns current partial shape used for this place + /// \param place Model place + /// \return Partial shape for this place virtual ngraph::PartialShape get_partial_shape(Place::Ptr place) const; - /// \brief Sets new element type for a place. - virtual void set_element_type(Place::Ptr place, const ngraph::element::Type&); + /// \brief Sets new element type for a place + /// \param place Model place + /// \param type New element type + virtual void set_element_type(Place::Ptr place, const ngraph::element::Type& type); /// \brief Freezes a tensor with statically defined value or replace existing value for - /// already constant node or tensor. + /// already constant node or tensor + /// \param place Tensor place + /// \param value Value for tensor place representing a memory buffer virtual void set_tensor_value(Place::Ptr place, const void* value); - /// \brief Defines partial value (lower bound and upper bound) for a tensor place. - // TODO: more details for minValue and maxValue format; who defines shape? + /// \brief Defines partial value (lower bound and upper bound) for a tensor place + /// TODO: more details for minValue and maxValue format; who defines shape? + /// \param place Tensor place + /// \param minValue Lower bound of partial value for tensor place + /// \param maxValue Upper bound of partial value for tensor place virtual void set_tensor_partial_value(Place::Ptr place, const void* minValue, const void* maxValue); @@ -320,33 +363,49 @@ namespace ngraph /// If model is stored in several files (e.g. model topology and model weights) - /// frontend implementation is responsible to handle this case, generally frontend may /// retrieve other file names from main file + /// \param path Main model file path + /// \return Loaded input model virtual InputModel::Ptr load_from_file(const std::string& path) const; /// \brief Loads an input model by specified number of model files /// This shall be used for cases when client knows all model files (model, weights, etc) + /// \param paths Array of model files + /// \return Loaded input model virtual InputModel::Ptr load_from_files(const std::vector& paths) const; /// \brief Loads an input model by already loaded memory buffer /// Memory structure is frontend-defined and is not specified in generic API + /// \param model Model memory buffer + /// \return Loaded input model virtual InputModel::Ptr load_from_memory(const void* model) const; /// \brief Loads an input model from set of memory buffers /// Memory structure is frontend-defined and is not specified in generic API + /// \param modelParts Array of model memory buffers + /// \return Loaded input model virtual InputModel::Ptr load_from_memory_fragments(const std::vector& modelParts) const; /// \brief Loads an input model by input stream representing main model file - virtual InputModel::Ptr load_from_stream(std::istream& path) const; + /// \param stream Input stream of main model + /// \return Loaded input model + virtual InputModel::Ptr load_from_stream(std::istream& stream) const; /// \brief Loads an input model by input streams representing all model files + /// \param streams Array of input streams for model + /// \return Loaded input model virtual InputModel::Ptr - load_from_streams(const std::vector& paths) const; + load_from_streams(const std::vector& streams) const; /// \brief Completely convert and normalize entire function, throws if it is not /// possible + /// \param model Input model + /// \return fully converted nGraph function virtual std::shared_ptr convert(InputModel::Ptr model) const; /// \brief Completely convert the remaining, not converted part of a function. + /// \param partiallyConverted partially converted nGraph function + /// \return fully converted nGraph function virtual std::shared_ptr convert(std::shared_ptr partiallyConverted) const; @@ -354,15 +413,20 @@ namespace ngraph /// as-is. Converted parts are not normalized by additional transformations; normalize /// function or another form of convert function should be called to finalize the /// conversion process. + /// \param model Input model + /// \return partially converted nGraph function virtual std::shared_ptr convert_partially(InputModel::Ptr model) const; /// \brief Convert operations with one-to-one mapping with decoding nodes. /// Each decoding node is an nGraph node representing a single FW operation node with /// all attributes represented in FW-independent way. + /// \param model Input model + /// \return nGraph function after decoding virtual std::shared_ptr decode(InputModel::Ptr model) const; /// \brief Runs normalization passes on function that was loaded with partial conversion + /// \param function partially converted nGraph function virtual void normalize(std::shared_ptr function) const; }; @@ -405,8 +469,8 @@ namespace ngraph /// \brief Loads frontend by name of framework and capabilities /// \param framework Framework name. Throws exception if name is not in list of /// available frontends \param fec Frontend capabilities. It is recommended to use only - /// those capabilities which are needed to minimize load time \return Frontend interface - /// for further loading of models + /// those capabilities which are needed to minimize load time + /// \return Frontend interface for further loading of models FrontEnd::Ptr load_by_framework(const std::string& framework, FrontEndCapFlags fec = FrontEndCapabilities::FEC_DEFAULT); diff --git a/ngraph/frontend/frontend_manager/src/frontend_manager.cpp b/ngraph/frontend/frontend_manager/src/frontend_manager.cpp index ddd1a57942089c..fc13e9ddf62c48 100644 --- a/ngraph/frontend/frontend_manager/src/frontend_manager.cpp +++ b/ngraph/frontend/frontend_manager/src/frontend_manager.cpp @@ -266,11 +266,6 @@ void InputModel::remove_output(Place::Ptr place) FRONT_END_NOT_IMPLEMENTED(remove_output); } -void InputModel::remove_input(Place::Ptr place) -{ - FRONT_END_NOT_IMPLEMENTED(remove_input); -} - void InputModel::override_all_outputs(const std::vector& outputs) { FRONT_END_NOT_IMPLEMENTED(override_all_outputs); @@ -288,11 +283,6 @@ void InputModel::extract_subgraph(const std::vector& inputs, } // Setting tensor properties -void InputModel::set_default_shape(Place::Ptr place, const ngraph::Shape&) -{ - FRONT_END_NOT_IMPLEMENTED(set_default_shape); -} - void InputModel::set_partial_shape(Place::Ptr place, const ngraph::PartialShape&) { FRONT_END_NOT_IMPLEMENTED(set_partial_shape); diff --git a/ngraph/test/frontend/frontend_manager.cpp b/ngraph/test/frontend/frontend_manager.cpp index f9858b5a0472fe..3e37b4d3b6e884 100644 --- a/ngraph/test/frontend/frontend_manager.cpp +++ b/ngraph/test/frontend/frontend_manager.cpp @@ -122,8 +122,6 @@ TEST(FrontEndManagerTest, testDefaultInputModel) ASSERT_ANY_THROW(im->cut_and_add_new_output(nullptr, "")); ASSERT_ANY_THROW(im->add_output(nullptr)); ASSERT_ANY_THROW(im->remove_output(nullptr)); - ASSERT_ANY_THROW(im->remove_input(nullptr)); - ASSERT_ANY_THROW(im->set_default_shape(nullptr, ngraph::Shape{})); ASSERT_ANY_THROW(im->set_partial_shape(nullptr, ngraph::Shape{})); ASSERT_ANY_THROW(im->get_partial_shape(nullptr)); ASSERT_ANY_THROW(im->set_element_type(nullptr, ngraph::element::Type{})); From 52de4e42fe9a4682b3156781fccc990663caf7cf Mon Sep 17 00:00:00 2001 From: Michael Nosov Date: Fri, 14 May 2021 19:24:08 +0300 Subject: [PATCH 19/22] Set FrontEndManager class as 'final' --- .../include/frontend_manager/frontend_manager.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ngraph/frontend/frontend_manager/include/frontend_manager/frontend_manager.hpp b/ngraph/frontend/frontend_manager/include/frontend_manager/frontend_manager.hpp index c3f17a541d4d9d..7120c4b8c4ca1e 100644 --- a/ngraph/frontend/frontend_manager/include/frontend_manager/frontend_manager.hpp +++ b/ngraph/frontend/frontend_manager/include/frontend_manager/frontend_manager.hpp @@ -459,7 +459,7 @@ namespace ngraph /// \brief Frontend management class, loads available frontend plugins on construction /// Allows load of frontends for particular framework, register new and list available /// frontends This is a main frontend entry point for client applications - class FRONTEND_API FrontEndManager + class FRONTEND_API FrontEndManager final { public: FrontEndManager(); From 13f1ffa80d417732b419613513ccb7693876f145 Mon Sep 17 00:00:00 2001 From: Michael Nosov Date: Wed, 26 May 2021 16:19:35 +0300 Subject: [PATCH 20/22] Apply review comments --- .../frontend_manager/frontend_manager.hpp | 155 ++++++++++++++---- .../frontend_manager/src/frontend_manager.cpp | 43 +++++ ngraph/test/frontend/frontend_manager.cpp | 16 ++ 3 files changed, 182 insertions(+), 32 deletions(-) diff --git a/ngraph/frontend/frontend_manager/include/frontend_manager/frontend_manager.hpp b/ngraph/frontend/frontend_manager/include/frontend_manager/frontend_manager.hpp index 7120c4b8c4ca1e..d8297362af259f 100644 --- a/ngraph/frontend/frontend_manager/include/frontend_manager/frontend_manager.hpp +++ b/ngraph/frontend/frontend_manager/include/frontend_manager/frontend_manager.hpp @@ -75,82 +75,152 @@ namespace ngraph /// \brief Returns references to all operation nodes that consume data from this place /// \note It can be called for any kind of graph place searching for the first consuming + /// operations. It is optional if place has only one output port + /// + /// \return A vector with all operation node references that consumes data from this + /// place + virtual std::vector get_consuming_operations() const; + + /// \brief Returns references to all operation nodes that consume data from this place + /// for specified output port + /// + /// \note It can be called for any kind of graph place searching for the first consuming /// operations. /// /// \param outputPortIndex If place is an operational node it specifies which output - /// port should be considered. It is optional if place has only one output port + /// port should be considered. /// /// \return A vector with all operation node references that consumes data from this /// place - virtual std::vector get_consuming_operations(int outputPortIndex = -1) const; + virtual std::vector get_consuming_operations(int outputPortIndex) const; + + /// \brief Returns a tensor place that gets data from this place; applicable for + /// operations, output ports and output edges which have only one output port + /// + /// \return A tensor place which hold the resulting value for this place + virtual Ptr get_target_tensor() const; /// \brief Returns a tensor place that gets data from this place; applicable for /// operations, output ports and output edges /// /// \param outputPortIndex Output port index if the current place is an operation node - /// and has multiple output ports. It is optional if place has only one output port + /// and has multiple output ports /// /// \return A tensor place which hold the resulting value for this place - virtual Ptr get_target_tensor(int outputPortIndex = -1) const; + virtual Ptr get_target_tensor(int outputPortIndex) const; + + /// \brief Returns a tensor place that supplies data for this place; applicable for + /// operations, input ports and input edges which have only one input port + /// + /// \return A tensor place which supplies data for this place + virtual Ptr get_source_tensor() const; /// \brief Returns a tensor place that supplies data for this place; applicable for /// operations, input ports and input edges /// - /// \param inputPortIndex Input port index for operational nodes. It is optional if - /// place has only one input port + /// \param inputPortIndex Input port index for operational nodes. + /// /// \return A tensor place which supplies data for this place - virtual Ptr get_source_tensor(int inputPortIndex = -1) const; + virtual Ptr get_source_tensor(int inputPortIndex) const; + + /// \brief Get an operation node place that immediately produces data for this place; + /// applicable if place has only one input port + /// + /// \return An operation place that produces data for this place + virtual Ptr get_producing_operation() const; /// \brief Get an operation node place that immediately produces data for this place /// /// \param inputPortIndex If a given place is itself an operation node, this specifies a - /// port index. It is optional if place has only one input port + /// port index /// /// \return An operation place that produces data for this place - virtual Ptr get_producing_operation(int inputPortIndex = -1) const; + virtual Ptr get_producing_operation(int inputPortIndex) const; /// Returns a port that produces data for this place virtual Ptr get_producing_port() const; - /// For operation node returns reference to an input port with specified index - /// \param inputPortIndex Input port index. It is optional if place has only one input - /// port - virtual Ptr get_input_port(int inputPortIndex = -1) const; + /// \brief For operation node returns reference to an input port; applicable if + /// operation node has only one input port + /// + /// \return Input port place + virtual Ptr get_input_port() const; + + /// \brief For operation node returns reference to an input port with specified index + /// + /// \param inputPortIndex Input port index + /// + /// \return Appropriate input port place + virtual Ptr get_input_port(int inputPortIndex) const; + + /// \brief For operation node returns reference to an input port with specified name; + /// applicable if port group has only one input port + /// + /// \param inputName Name of port group + /// + /// \return Appropriate input port place + virtual Ptr get_input_port(const std::string& inputName) const; - /// For operation node returns reference to an input port with specified name and index + /// \brief For operation node returns reference to an input port with specified name and + /// index + /// /// \param inputName Name of port group, each group can have multiple ports - /// \param inputPortIndex Input port index. It is optional if port group has only one - /// input port - virtual Ptr get_input_port(const std::string& inputName, int inputPortIndex = -1) const; + /// + /// \param inputPortIndex Input port index in a group + /// + /// \return Appropriate input port place + virtual Ptr get_input_port(const std::string& inputName, int inputPortIndex) const; - /// For operation node returns reference to an output port with specified index - /// \param outputPortIndex Output port index. It is optional if place has only one - /// output port - virtual Ptr get_output_port(int outputPortIndex = -1) const; + /// \brief For operation node returns reference to an output port; applicable for + /// operations with only one output port + /// + /// \return Appropriate output port place + virtual Ptr get_output_port() const; + + /// \brief For operation node returns reference to an output port with specified index + /// + /// \param outputPortIndex Output port index + /// + /// \return Appropriate output port place + virtual Ptr get_output_port(int outputPortIndex) const; - /// For operation node returns reference to an output port with specified name and index + /// \brief For operation node returns reference to an output port with specified name; + /// applicable if port group has only one output port + /// + /// \param outputName Name of output port group + /// + /// \return Appropriate output port place + virtual Ptr get_output_port(const std::string& outputName) const; + + /// \brief For operation node returns reference to an output port with specified name + /// and index + /// /// \param outputName Name of output port group, each group can have multiple ports - /// \param outputPortIndex Output port index. It is optional if port group has only one - /// output port - virtual Ptr get_output_port(const std::string& outputName, - int outputPortIndex = -1) const; + /// + /// \param outputPortIndex Output port index + /// + /// \return Appropriate output port place + virtual Ptr get_output_port(const std::string& outputName, int outputPortIndex) const; - /// Returns all input ports that consume data flows through this place + /// \brief Returns all input ports that consume data flows through this place virtual std::vector get_consuming_ports() const; - /// Returns true if this place is input for a model. + /// \brief Returns true if this place is input for a model. virtual bool is_input() const; - /// Returns true if this place is output for a model. + /// \brief Returns true if this place is output for a model. virtual bool is_output() const; - /// Returns true if another place is the same as this place. + /// \brief Returns true if another place is the same as this place. + /// /// \param another Another place object virtual bool is_equal(Ptr another) const; /// \brief Returns true if another place points to the same data. + /// /// \note The same data means all places on path: output port -> output edge -> tensor /// -> input edge -> input port. + /// /// \param another Another place object virtual bool is_equal_data(Ptr another) const; }; @@ -462,24 +532,40 @@ namespace ngraph class FRONTEND_API FrontEndManager final { public: + /// \brief Default constructor. Searches and loads of available frontends FrontEndManager(); + /// \brief Default move constructor + FrontEndManager(FrontEndManager&&); + + /// \brief Default move assignment operator + FrontEndManager& operator=(FrontEndManager&&); + + /// \brief Default destructor ~FrontEndManager(); /// \brief Loads frontend by name of framework and capabilities + /// /// \param framework Framework name. Throws exception if name is not in list of - /// available frontends \param fec Frontend capabilities. It is recommended to use only + /// available frontends + /// + /// \param fec Frontend capabilities. It is recommended to use only /// those capabilities which are needed to minimize load time + /// /// \return Frontend interface for further loading of models FrontEnd::Ptr load_by_framework(const std::string& framework, FrontEndCapFlags fec = FrontEndCapabilities::FEC_DEFAULT); /// \brief Loads frontend by model file path. Selects and loads appropriate frontend - /// depending on model file extension and other file info (header) \param framework + /// depending on model file extension and other file info (header) + /// + /// \param framework /// Framework name. Throws exception if name is not in list of available frontends + /// /// \param fec Frontend capabilities. It is recommended to use only those capabilities /// which are needed to minimize load time + /// /// \return Frontend interface for further loading of model FrontEnd::Ptr load_by_model(const std::string& path, FrontEndCapFlags fec = FrontEndCapabilities::FEC_DEFAULT); @@ -488,6 +574,11 @@ namespace ngraph std::vector get_available_front_ends() const; /// \brief Register frontend with name and factory creation method + /// + /// \param name Name of front end + /// + /// \param creator Creation factory callback. Will be called when frontend is about to + /// be created void register_front_end(const std::string& name, FrontEndFactory creator); private: diff --git a/ngraph/frontend/frontend_manager/src/frontend_manager.cpp b/ngraph/frontend/frontend_manager/src/frontend_manager.cpp index fc13e9ddf62c48..d8a4287e6d1358 100644 --- a/ngraph/frontend/frontend_manager/src/frontend_manager.cpp +++ b/ngraph/frontend/frontend_manager/src/frontend_manager.cpp @@ -97,6 +97,9 @@ FrontEndManager::FrontEndManager() { } +FrontEndManager::FrontEndManager(FrontEndManager&&) = default; +FrontEndManager& FrontEndManager::operator=(FrontEndManager&&) = default; + FrontEndManager::~FrontEndManager() = default; FrontEnd::Ptr FrontEndManager::load_by_framework(const std::string& framework, FrontEndCapFlags fec) @@ -316,16 +319,31 @@ std::vector Place::get_names() const FRONT_END_NOT_IMPLEMENTED(get_names); } +std::vector Place::get_consuming_operations() const +{ + FRONT_END_NOT_IMPLEMENTED(get_consuming_operations); +} + std::vector Place::get_consuming_operations(int outputPortIndex) const { FRONT_END_NOT_IMPLEMENTED(get_consuming_operations); } +Place::Ptr Place::get_target_tensor() const +{ + FRONT_END_NOT_IMPLEMENTED(get_target_tensor); +} + Place::Ptr Place::get_target_tensor(int outputPortIndex) const { FRONT_END_NOT_IMPLEMENTED(get_target_tensor); } +Place::Ptr Place::get_producing_operation() const +{ + FRONT_END_NOT_IMPLEMENTED(get_producing_operation); +} + Place::Ptr Place::get_producing_operation(int inputPortIndex) const { FRONT_END_NOT_IMPLEMENTED(get_producing_operation); @@ -336,21 +354,41 @@ Place::Ptr Place::get_producing_port() const FRONT_END_NOT_IMPLEMENTED(get_producing_port); } +Place::Ptr Place::get_input_port() const +{ + FRONT_END_NOT_IMPLEMENTED(get_input_port); +} + Place::Ptr Place::get_input_port(int inputPortIndex) const { FRONT_END_NOT_IMPLEMENTED(get_input_port); } +Place::Ptr Place::get_input_port(const std::string& inputName) const +{ + FRONT_END_NOT_IMPLEMENTED(get_input_port); +} + Place::Ptr Place::get_input_port(const std::string& inputName, int inputPortIndex) const { FRONT_END_NOT_IMPLEMENTED(get_input_port); } +Place::Ptr Place::get_output_port() const +{ + FRONT_END_NOT_IMPLEMENTED(get_output_port); +} + Place::Ptr Place::get_output_port(int outputPortIndex) const { FRONT_END_NOT_IMPLEMENTED(get_output_port); } +Place::Ptr Place::get_output_port(const std::string& outputName) const +{ + FRONT_END_NOT_IMPLEMENTED(get_output_port); +} + Place::Ptr Place::get_output_port(const std::string& outputName, int outputPortIndex) const { FRONT_END_NOT_IMPLEMENTED(get_output_port); @@ -381,6 +419,11 @@ bool Place::is_equal_data(Ptr another) const FRONT_END_NOT_IMPLEMENTED(is_equal_data); } +Place::Ptr Place::get_source_tensor() const +{ + FRONT_END_NOT_IMPLEMENTED(get_source_tensor); +} + Place::Ptr Place::get_source_tensor(int inputPortIndex) const { FRONT_END_NOT_IMPLEMENTED(get_source_tensor); diff --git a/ngraph/test/frontend/frontend_manager.cpp b/ngraph/test/frontend/frontend_manager.cpp index 3e37b4d3b6e884..82aebab622e6b5 100644 --- a/ngraph/test/frontend/frontend_manager.cpp +++ b/ngraph/test/frontend/frontend_manager.cpp @@ -41,6 +41,14 @@ TEST(FrontEndManagerTest, testAvailableFrontEnds) ASSERT_NE(std::find(frontends.begin(), frontends.end(), "mock"), frontends.end()); FrontEnd::Ptr fe; ASSERT_NO_THROW(fe = fem.load_by_framework("mock")); + + FrontEndManager fem2 = std::move(fem); + frontends = fem2.get_available_front_ends(); + ASSERT_NE(std::find(frontends.begin(), frontends.end(), "mock"), frontends.end()); + + fem2 = FrontEndManager(); + frontends = fem2.get_available_front_ends(); + ASSERT_EQ(std::find(frontends.begin(), frontends.end(), "mock"), frontends.end()); } TEST(FrontEndManagerTest, testLoadWithFlags) @@ -135,14 +143,22 @@ TEST(FrontEndManagerTest, testDefaultPlace) Place::Ptr place = std::make_shared(); ASSERT_ANY_THROW(place->get_names()); ASSERT_ANY_THROW(place->get_consuming_operations()); + ASSERT_ANY_THROW(place->get_consuming_operations(0)); ASSERT_ANY_THROW(place->get_target_tensor()); + ASSERT_ANY_THROW(place->get_target_tensor(0)); ASSERT_ANY_THROW(place->get_source_tensor()); + ASSERT_ANY_THROW(place->get_source_tensor(0)); ASSERT_ANY_THROW(place->get_producing_operation()); + ASSERT_ANY_THROW(place->get_producing_operation(0)); ASSERT_ANY_THROW(place->get_producing_port()); ASSERT_ANY_THROW(place->get_input_port()); + ASSERT_ANY_THROW(place->get_input_port(0)); ASSERT_ANY_THROW(place->get_input_port("")); + ASSERT_ANY_THROW(place->get_input_port("", 0)); ASSERT_ANY_THROW(place->get_output_port()); + ASSERT_ANY_THROW(place->get_output_port(0)); ASSERT_ANY_THROW(place->get_output_port("")); + ASSERT_ANY_THROW(place->get_output_port("", 0)); ASSERT_ANY_THROW(place->get_consuming_ports()); ASSERT_ANY_THROW(place->is_input()); ASSERT_ANY_THROW(place->is_output()); From a5396c499354398e75389d11f4e88729af206715 Mon Sep 17 00:00:00 2001 From: Michael Nosov Date: Wed, 26 May 2021 19:30:12 +0300 Subject: [PATCH 21/22] renamed get_place_by_name_and... to get_place_by_operation_name_and... --- .../include/frontend_manager/frontend_manager.hpp | 8 ++++---- .../frontend_manager/src/frontend_manager.cpp | 12 ++++++------ ngraph/test/frontend/frontend_manager.cpp | 4 ++-- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/ngraph/frontend/frontend_manager/include/frontend_manager/frontend_manager.hpp b/ngraph/frontend/frontend_manager/include/frontend_manager/frontend_manager.hpp index d8297362af259f..301bcbbd7fa640 100644 --- a/ngraph/frontend/frontend_manager/include/frontend_manager/frontend_manager.hpp +++ b/ngraph/frontend/frontend_manager/include/frontend_manager/frontend_manager.hpp @@ -291,16 +291,16 @@ namespace ngraph /// \param outputPortIndex Index of input port for this operation /// \return Place representing input port of operation virtual Place::Ptr - get_place_by_operation_and_input_port(const std::string& operationName, - int inputPortIndex); + get_place_by_operation_name_and_input_port(const std::string& operationName, + int inputPortIndex); /// \brief Returns an output port place by operation name and appropriate port index /// \param operationNameNname of operation /// \param outputPortIndex Index of output port for this operation /// \return Place representing output port of operation virtual Place::Ptr - get_place_by_operation_and_output_port(const std::string& operationName, - int outputPortIndex); + get_place_by_operation_name_and_output_port(const std::string& operationName, + int outputPortIndex); ///// Naming and annotation ///// diff --git a/ngraph/frontend/frontend_manager/src/frontend_manager.cpp b/ngraph/frontend/frontend_manager/src/frontend_manager.cpp index d8a4287e6d1358..c1a864ffd6e27d 100644 --- a/ngraph/frontend/frontend_manager/src/frontend_manager.cpp +++ b/ngraph/frontend/frontend_manager/src/frontend_manager.cpp @@ -205,16 +205,16 @@ Place::Ptr InputModel::get_place_by_operation_name(const std::string& operationN FRONT_END_NOT_IMPLEMENTED(get_place_by_operation_name); } -Place::Ptr InputModel::get_place_by_operation_and_input_port(const std::string& operationName, - int inputPortIndex) +Place::Ptr InputModel::get_place_by_operation_name_and_input_port(const std::string& operationName, + int inputPortIndex) { - FRONT_END_NOT_IMPLEMENTED(get_place_by_operation_and_input_port); + FRONT_END_NOT_IMPLEMENTED(get_place_by_operation_name_and_input_port); } -Place::Ptr InputModel::get_place_by_operation_and_output_port(const std::string& operationName, - int outputPortIndex) +Place::Ptr InputModel::get_place_by_operation_name_and_output_port(const std::string& operationName, + int outputPortIndex) { - FRONT_END_NOT_IMPLEMENTED(get_place_by_operation_and_output_port); + FRONT_END_NOT_IMPLEMENTED(get_place_by_operation_name_and_output_port); } void InputModel::set_name_for_tensor(Place::Ptr tensor, const std::string& newName) diff --git a/ngraph/test/frontend/frontend_manager.cpp b/ngraph/test/frontend/frontend_manager.cpp index 82aebab622e6b5..4500a2c509dfc6 100644 --- a/ngraph/test/frontend/frontend_manager.cpp +++ b/ngraph/test/frontend/frontend_manager.cpp @@ -118,8 +118,8 @@ TEST(FrontEndManagerTest, testDefaultInputModel) ASSERT_ANY_THROW(im->extract_subgraph({nullptr}, {nullptr})); ASSERT_ANY_THROW(im->get_place_by_tensor_name("")); ASSERT_ANY_THROW(im->get_place_by_operation_name("")); - ASSERT_ANY_THROW(im->get_place_by_operation_and_input_port("", 0)); - ASSERT_ANY_THROW(im->get_place_by_operation_and_output_port("", 0)); + ASSERT_ANY_THROW(im->get_place_by_operation_name_and_input_port("", 0)); + ASSERT_ANY_THROW(im->get_place_by_operation_name_and_output_port("", 0)); ASSERT_ANY_THROW(im->set_name_for_tensor(nullptr, "")); ASSERT_ANY_THROW(im->add_name_for_tensor(nullptr, "")); ASSERT_ANY_THROW(im->set_name_for_operation(nullptr, "")); From 63942405f961f0a7af7787a8e74133481d0a2d60 Mon Sep 17 00:00:00 2001 From: Michael Nosov Date: Mon, 31 May 2021 17:19:00 +0300 Subject: [PATCH 22/22] Separated frontend_manager.hpp into 4 header files --- .../include/frontend_manager/frontend.hpp | 102 ++++ .../frontend_manager/frontend_manager.hpp | 489 +----------------- .../include/frontend_manager/input_model.hpp | 213 ++++++++ .../include/frontend_manager/place.hpp | 228 ++++++++ 4 files changed, 544 insertions(+), 488 deletions(-) create mode 100644 ngraph/frontend/frontend_manager/include/frontend_manager/frontend.hpp create mode 100644 ngraph/frontend/frontend_manager/include/frontend_manager/input_model.hpp create mode 100644 ngraph/frontend/frontend_manager/include/frontend_manager/place.hpp diff --git a/ngraph/frontend/frontend_manager/include/frontend_manager/frontend.hpp b/ngraph/frontend/frontend_manager/include/frontend_manager/frontend.hpp new file mode 100644 index 00000000000000..97a18112d82959 --- /dev/null +++ b/ngraph/frontend/frontend_manager/include/frontend_manager/frontend.hpp @@ -0,0 +1,102 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +#include +#include +#include +#include "frontend_manager_defs.hpp" +#include "input_model.hpp" +#include "ngraph/function.hpp" + +namespace ngraph +{ + namespace frontend + { + /// \brief An interface for identifying a frontend for a particular framework. + /// Provides an ability to load and convert of input model + class FRONTEND_API FrontEnd + { + public: + typedef std::shared_ptr Ptr; + + FrontEnd(); + + virtual ~FrontEnd(); + + /// \brief Loads an input model by specified model file path + /// If model is stored in several files (e.g. model topology and model weights) - + /// frontend implementation is responsible to handle this case, generally frontend may + /// retrieve other file names from main file + /// \param path Main model file path + /// \return Loaded input model + virtual InputModel::Ptr load_from_file(const std::string& path) const; + + /// \brief Loads an input model by specified number of model files + /// This shall be used for cases when client knows all model files (model, weights, etc) + /// \param paths Array of model files + /// \return Loaded input model + virtual InputModel::Ptr load_from_files(const std::vector& paths) const; + + /// \brief Loads an input model by already loaded memory buffer + /// Memory structure is frontend-defined and is not specified in generic API + /// \param model Model memory buffer + /// \return Loaded input model + virtual InputModel::Ptr load_from_memory(const void* model) const; + + /// \brief Loads an input model from set of memory buffers + /// Memory structure is frontend-defined and is not specified in generic API + /// \param modelParts Array of model memory buffers + /// \return Loaded input model + virtual InputModel::Ptr + load_from_memory_fragments(const std::vector& modelParts) const; + + /// \brief Loads an input model by input stream representing main model file + /// \param stream Input stream of main model + /// \return Loaded input model + virtual InputModel::Ptr load_from_stream(std::istream& stream) const; + + /// \brief Loads an input model by input streams representing all model files + /// \param streams Array of input streams for model + /// \return Loaded input model + virtual InputModel::Ptr + load_from_streams(const std::vector& streams) const; + + /// \brief Completely convert and normalize entire function, throws if it is not + /// possible + /// \param model Input model + /// \return fully converted nGraph function + virtual std::shared_ptr convert(InputModel::Ptr model) const; + + /// \brief Completely convert the remaining, not converted part of a function. + /// \param partiallyConverted partially converted nGraph function + /// \return fully converted nGraph function + virtual std::shared_ptr + convert(std::shared_ptr partiallyConverted) const; + + /// \brief Convert only those parts of the model that can be converted leaving others + /// as-is. Converted parts are not normalized by additional transformations; normalize + /// function or another form of convert function should be called to finalize the + /// conversion process. + /// \param model Input model + /// \return partially converted nGraph function + virtual std::shared_ptr + convert_partially(InputModel::Ptr model) const; + + /// \brief Convert operations with one-to-one mapping with decoding nodes. + /// Each decoding node is an nGraph node representing a single FW operation node with + /// all attributes represented in FW-independent way. + /// \param model Input model + /// \return nGraph function after decoding + virtual std::shared_ptr decode(InputModel::Ptr model) const; + + /// \brief Runs normalization passes on function that was loaded with partial conversion + /// \param function partially converted nGraph function + virtual void normalize(std::shared_ptr function) const; + }; + + } // namespace frontend + +} // namespace ngraph diff --git a/ngraph/frontend/frontend_manager/include/frontend_manager/frontend_manager.hpp b/ngraph/frontend/frontend_manager/include/frontend_manager/frontend_manager.hpp index 301bcbbd7fa640..764931ea9a89b9 100644 --- a/ngraph/frontend/frontend_manager/include/frontend_manager/frontend_manager.hpp +++ b/ngraph/frontend/frontend_manager/include/frontend_manager/frontend_manager.hpp @@ -6,500 +6,13 @@ #include #include +#include "frontend.hpp" #include "frontend_manager_defs.hpp" -#include "ngraph/function.hpp" namespace ngraph { namespace frontend { - /// \brief An interface for identifying a place in a graph and iterate over it; can refer to - /// an operation node, tensor, port etc. - /// - /// \note Each front end implementation provides specialization of this interface to - /// represent a place in a model graph. Various methods in the front end classes accept and - /// retrieve instances of Place to point to particular node part which should be modified or - /// satisfies some criteria. For example, this class is used to report model inputs - /// and outputs, for searching operations and tensors by name, for setting shape etc. - /// - /// Place can refer to Tensor, Input Edge, Input Port, Operation, Output Port, Output Edge - /// - /// [Tensor A] - /// | - /// | [Input Edge] - /// | - /// V - /// ------------------- - /// [ [Input Port 0] ] - /// [ ] - /// [ Operation A ] - /// [ ] - /// [ [Output Port 0] ] - /// ------------------- - /// | - /// | [Output Edge] - /// | - /// V - /// [Tensor B] - /// | - /// | [Input Edge] - /// | - /// V - /// ------------------- - /// [ [Input Port 0] ] - /// [ ] - /// [ Operation B ] - /// [ ] - /// [ [Output Port 0] ] - /// ------------------- - /// | - /// | [Output Edge] - /// | - /// V - /// [Tensor C] - /// - class FRONTEND_API Place - { - public: - typedef std::shared_ptr Ptr; - - virtual ~Place() = default; - - /// \brief All associated names (synonyms) that identify this place in the graph in a - /// framework specific way - /// - /// \return A vector of strings each representing a name that identifies this place in - /// the graph. Can be empty if there are no names associated with this place or name - /// cannot be attached. - virtual std::vector get_names() const; - - /// \brief Returns references to all operation nodes that consume data from this place - /// \note It can be called for any kind of graph place searching for the first consuming - /// operations. It is optional if place has only one output port - /// - /// \return A vector with all operation node references that consumes data from this - /// place - virtual std::vector get_consuming_operations() const; - - /// \brief Returns references to all operation nodes that consume data from this place - /// for specified output port - /// - /// \note It can be called for any kind of graph place searching for the first consuming - /// operations. - /// - /// \param outputPortIndex If place is an operational node it specifies which output - /// port should be considered. - /// - /// \return A vector with all operation node references that consumes data from this - /// place - virtual std::vector get_consuming_operations(int outputPortIndex) const; - - /// \brief Returns a tensor place that gets data from this place; applicable for - /// operations, output ports and output edges which have only one output port - /// - /// \return A tensor place which hold the resulting value for this place - virtual Ptr get_target_tensor() const; - - /// \brief Returns a tensor place that gets data from this place; applicable for - /// operations, output ports and output edges - /// - /// \param outputPortIndex Output port index if the current place is an operation node - /// and has multiple output ports - /// - /// \return A tensor place which hold the resulting value for this place - virtual Ptr get_target_tensor(int outputPortIndex) const; - - /// \brief Returns a tensor place that supplies data for this place; applicable for - /// operations, input ports and input edges which have only one input port - /// - /// \return A tensor place which supplies data for this place - virtual Ptr get_source_tensor() const; - - /// \brief Returns a tensor place that supplies data for this place; applicable for - /// operations, input ports and input edges - /// - /// \param inputPortIndex Input port index for operational nodes. - /// - /// \return A tensor place which supplies data for this place - virtual Ptr get_source_tensor(int inputPortIndex) const; - - /// \brief Get an operation node place that immediately produces data for this place; - /// applicable if place has only one input port - /// - /// \return An operation place that produces data for this place - virtual Ptr get_producing_operation() const; - - /// \brief Get an operation node place that immediately produces data for this place - /// - /// \param inputPortIndex If a given place is itself an operation node, this specifies a - /// port index - /// - /// \return An operation place that produces data for this place - virtual Ptr get_producing_operation(int inputPortIndex) const; - - /// Returns a port that produces data for this place - virtual Ptr get_producing_port() const; - - /// \brief For operation node returns reference to an input port; applicable if - /// operation node has only one input port - /// - /// \return Input port place - virtual Ptr get_input_port() const; - - /// \brief For operation node returns reference to an input port with specified index - /// - /// \param inputPortIndex Input port index - /// - /// \return Appropriate input port place - virtual Ptr get_input_port(int inputPortIndex) const; - - /// \brief For operation node returns reference to an input port with specified name; - /// applicable if port group has only one input port - /// - /// \param inputName Name of port group - /// - /// \return Appropriate input port place - virtual Ptr get_input_port(const std::string& inputName) const; - - /// \brief For operation node returns reference to an input port with specified name and - /// index - /// - /// \param inputName Name of port group, each group can have multiple ports - /// - /// \param inputPortIndex Input port index in a group - /// - /// \return Appropriate input port place - virtual Ptr get_input_port(const std::string& inputName, int inputPortIndex) const; - - /// \brief For operation node returns reference to an output port; applicable for - /// operations with only one output port - /// - /// \return Appropriate output port place - virtual Ptr get_output_port() const; - - /// \brief For operation node returns reference to an output port with specified index - /// - /// \param outputPortIndex Output port index - /// - /// \return Appropriate output port place - virtual Ptr get_output_port(int outputPortIndex) const; - - /// \brief For operation node returns reference to an output port with specified name; - /// applicable if port group has only one output port - /// - /// \param outputName Name of output port group - /// - /// \return Appropriate output port place - virtual Ptr get_output_port(const std::string& outputName) const; - - /// \brief For operation node returns reference to an output port with specified name - /// and index - /// - /// \param outputName Name of output port group, each group can have multiple ports - /// - /// \param outputPortIndex Output port index - /// - /// \return Appropriate output port place - virtual Ptr get_output_port(const std::string& outputName, int outputPortIndex) const; - - /// \brief Returns all input ports that consume data flows through this place - virtual std::vector get_consuming_ports() const; - - /// \brief Returns true if this place is input for a model. - virtual bool is_input() const; - - /// \brief Returns true if this place is output for a model. - virtual bool is_output() const; - - /// \brief Returns true if another place is the same as this place. - /// - /// \param another Another place object - virtual bool is_equal(Ptr another) const; - - /// \brief Returns true if another place points to the same data. - /// - /// \note The same data means all places on path: output port -> output edge -> tensor - /// -> input edge -> input port. - /// - /// \param another Another place object - virtual bool is_equal_data(Ptr another) const; - }; - - /// \brief InputModel class represents an original, not yet converted model graph in a - /// framework format given services to find places of interest in a graph or specialize/edit - /// the model before conversion. - /// - /// \note Class methods are divided into several groups: searching for places, naming and - /// annotation, topology editing, setting tensor properties. - /// - /// Editing requests may affect ability to convert the original model to nGraph function. - /// Aim to provide these editing capabilities is to unlock conversion for models that - /// are not natively supported "as-is" because of undefined shapes, types or operations. - /// - /// Specific front-end implementation is supposed to have a lazy implementation for - /// all methods, not doing a complete load of a model without an explicit method call. - /// For example, the list of all inputs are not pre-fetched by InputModel derived - /// class instance creation, but only when get_inputs method is called. But it is not - /// an obligation, the most convenient way should be chosen depending on the framework - /// model representation. - /// - /// All editing requests affect the model representation that is held behind the scene - /// successive method calls observe a new graph structure. - class FRONTEND_API InputModel - { - public: - typedef std::shared_ptr Ptr; - - virtual ~InputModel() = default; - - ///// Searching for places ///// - - /// \brief Returns all inputs for a model - /// An input is a place in a graph where data is supposed to flow inside graph from - /// outside. It can be a tensor, port, operation; which kind of place can be an output - /// is FW dependent. Usually framework models have a dedicated artifact to code model - /// input, it can be a tensor without producer, that writes to it in ONNX, or a special - /// operation like Placeholder in TensorFlow. - /// - /// \return A vector of input place references - virtual std::vector get_inputs() const; - - /// \brief Returns all output for a model - /// An output is a terminal place in a graph where data escapes the flow. It can be a - /// tensor, port, operation; which kind of place can be an output is FW dependent. In - /// comparison to a graph input, the output is less formally defined thing and - /// determination of initial list of outputs may include some conventions defined by a - /// frontend itself, not a framework. For example, all output ports without consumers - /// may be considered as outputs. - /// - /// \return A vector of output place references - virtual std::vector get_outputs() const; - - /// \brief Returns a tensor place by a tensor name following framework conventions, or - /// nullptr if a tensor with this name doesn't exist. - /// \param tensorName Name of tensor - /// \return Tensor place corresponding to specifed tensor name - virtual Place::Ptr get_place_by_tensor_name(const std::string& tensorName) const; - - /// \brief Returns an operation place by an operation name following framework - /// conventions, or nullptr if an operation with this name doesn't exist. \param - /// operationName Name of operation \return Place representing operation - virtual Place::Ptr get_place_by_operation_name(const std::string& operationName); - - /// \brief Returns an input port place by operation name and appropriate port index - /// \param operationName Name of operation - /// \param outputPortIndex Index of input port for this operation - /// \return Place representing input port of operation - virtual Place::Ptr - get_place_by_operation_name_and_input_port(const std::string& operationName, - int inputPortIndex); - - /// \brief Returns an output port place by operation name and appropriate port index - /// \param operationNameNname of operation - /// \param outputPortIndex Index of output port for this operation - /// \return Place representing output port of operation - virtual Place::Ptr - get_place_by_operation_name_and_output_port(const std::string& operationName, - int outputPortIndex); - - ///// Naming and annotation ///// - - /// \brief Sets name for tensor. Overwrites existing names of this place - /// \param operation Tensor place - /// \param newName New name for this tensor - virtual void set_name_for_tensor(Place::Ptr tensor, const std::string& newName); - - /// \brief Adds new name for tensor - /// \param operation Tensor place - /// \param newName New name to be added to this place - virtual void add_name_for_tensor(Place::Ptr tensor, const std::string& newName); - - /// \brief Sets name for operation. Overwrites existing names of this place - /// \param operation Operation place - /// \param newName New name for this operation - virtual void set_name_for_operation(Place::Ptr operation, const std::string& newName); - - /// \brief Unassign specified name from tensor place(s) - /// \param name Name of tensor - virtual void free_name_for_tensor(const std::string& name); - - /// \brief Unassign specified name from operation place(s) - /// \param name Name of operation - virtual void free_name_for_operation(const std::string& name); - - /// \brief Set name for a particular dimension of a place (e.g. batch dimension) - /// \param place Model's place - /// \param shapeDimIndex Dimension index - /// \param dimName Name to assign on this dimension - virtual void set_name_for_dimension(Place::Ptr place, - size_t shapeDimIndex, - const std::string& dimName); - - ///// Topology Editing ///// - - /// \brief Cut immediately before this place and assign this place as new input; prune - /// all nodes that don't contribute to any output. - /// \param place New place to be assigned as input - /// \param newNameOptional Optional new name assigned to this input place - virtual void cut_and_add_new_input(Place::Ptr place, - const std::string& newNameOptional = ""); - - /// \brief Cut immediately after this place and assign this place as new output; prune - /// all nodes that don't contribute to any output. - /// \param place New place to be assigned as output - /// \param newNameOptional Optional new name assigned to this output place - virtual void cut_and_add_new_output(Place::Ptr place, - const std::string& newNameOptional = ""); - - /// \brief Assign this place as new output or add necessary nodes to represent a new - /// output. - /// - /// \param place Anchor point to add an output - /// \return new output place, may be the same as a given place - virtual Place::Ptr add_output(Place::Ptr place); - - /// \brief Removes any sinks directly attached to this place with all inbound data flow - /// if it is not required by any other output. - /// \param place Model place - virtual void remove_output(Place::Ptr place); - - /// \brief Replaces all existing outputs with new ones removing all data flow that is - /// not required for new outputs. - /// - /// \param outputs Vector with places that will become new outputs; may intersect - /// existing outputs. - /// \param outputs Array of new output places - virtual void override_all_outputs(const std::vector& outputs); - - /// \brief Modifies the graph to use new inputs instead of existing ones. New inputs - /// should completely satisfy all existing outputs. - /// \param inputs Array of new input places - virtual void override_all_inputs(const std::vector& inputs); - - /// \brief Leaves only subgraph that are defined by new inputs and new outputs. - /// \param inputs Array of new input places - /// \param outputs Array of new output places - virtual void extract_subgraph(const std::vector& inputs, - const std::vector& outputs); - - ///// Setting tensor properties ///// - - /// \brief Defines all possible shape that may be used for this place; place should be - /// uniquely refer to some data. This partial shape will be converted to corresponding - /// shape of results ngraph nodes and will define shape inference when the model is - /// converted to ngraph. - /// \param place Model place - /// \param shape Partial shape for this place - virtual void set_partial_shape(Place::Ptr place, const ngraph::PartialShape& shape); - - /// \brief Returns current partial shape used for this place - /// \param place Model place - /// \return Partial shape for this place - virtual ngraph::PartialShape get_partial_shape(Place::Ptr place) const; - - /// \brief Sets new element type for a place - /// \param place Model place - /// \param type New element type - virtual void set_element_type(Place::Ptr place, const ngraph::element::Type& type); - - /// \brief Freezes a tensor with statically defined value or replace existing value for - /// already constant node or tensor - /// \param place Tensor place - /// \param value Value for tensor place representing a memory buffer - virtual void set_tensor_value(Place::Ptr place, const void* value); - - /// \brief Defines partial value (lower bound and upper bound) for a tensor place - /// TODO: more details for minValue and maxValue format; who defines shape? - /// \param place Tensor place - /// \param minValue Lower bound of partial value for tensor place - /// \param maxValue Upper bound of partial value for tensor place - virtual void set_tensor_partial_value(Place::Ptr place, - const void* minValue, - const void* maxValue); - }; - - /// \brief An interface for identifying a frontend for a particular framework. - /// Provides an ability to load and convert of input model - class FRONTEND_API FrontEnd - { - public: - typedef std::shared_ptr Ptr; - - FrontEnd(); - - virtual ~FrontEnd(); - - /// \brief Loads an input model by specified model file path - /// If model is stored in several files (e.g. model topology and model weights) - - /// frontend implementation is responsible to handle this case, generally frontend may - /// retrieve other file names from main file - /// \param path Main model file path - /// \return Loaded input model - virtual InputModel::Ptr load_from_file(const std::string& path) const; - - /// \brief Loads an input model by specified number of model files - /// This shall be used for cases when client knows all model files (model, weights, etc) - /// \param paths Array of model files - /// \return Loaded input model - virtual InputModel::Ptr load_from_files(const std::vector& paths) const; - - /// \brief Loads an input model by already loaded memory buffer - /// Memory structure is frontend-defined and is not specified in generic API - /// \param model Model memory buffer - /// \return Loaded input model - virtual InputModel::Ptr load_from_memory(const void* model) const; - - /// \brief Loads an input model from set of memory buffers - /// Memory structure is frontend-defined and is not specified in generic API - /// \param modelParts Array of model memory buffers - /// \return Loaded input model - virtual InputModel::Ptr - load_from_memory_fragments(const std::vector& modelParts) const; - - /// \brief Loads an input model by input stream representing main model file - /// \param stream Input stream of main model - /// \return Loaded input model - virtual InputModel::Ptr load_from_stream(std::istream& stream) const; - - /// \brief Loads an input model by input streams representing all model files - /// \param streams Array of input streams for model - /// \return Loaded input model - virtual InputModel::Ptr - load_from_streams(const std::vector& streams) const; - - /// \brief Completely convert and normalize entire function, throws if it is not - /// possible - /// \param model Input model - /// \return fully converted nGraph function - virtual std::shared_ptr convert(InputModel::Ptr model) const; - - /// \brief Completely convert the remaining, not converted part of a function. - /// \param partiallyConverted partially converted nGraph function - /// \return fully converted nGraph function - virtual std::shared_ptr - convert(std::shared_ptr partiallyConverted) const; - - /// \brief Convert only those parts of the model that can be converted leaving others - /// as-is. Converted parts are not normalized by additional transformations; normalize - /// function or another form of convert function should be called to finalize the - /// conversion process. - /// \param model Input model - /// \return partially converted nGraph function - virtual std::shared_ptr - convert_partially(InputModel::Ptr model) const; - - /// \brief Convert operations with one-to-one mapping with decoding nodes. - /// Each decoding node is an nGraph node representing a single FW operation node with - /// all attributes represented in FW-independent way. - /// \param model Input model - /// \return nGraph function after decoding - virtual std::shared_ptr decode(InputModel::Ptr model) const; - - /// \brief Runs normalization passes on function that was loaded with partial conversion - /// \param function partially converted nGraph function - virtual void normalize(std::shared_ptr function) const; - }; - /// Capabilities for requested FrontEnd /// In general, frontend implementation may be divided into several libraries by capability /// level It will allow faster load of frontend when only limited usage is expected by diff --git a/ngraph/frontend/frontend_manager/include/frontend_manager/input_model.hpp b/ngraph/frontend/frontend_manager/include/frontend_manager/input_model.hpp new file mode 100644 index 00000000000000..6761e1dda383f2 --- /dev/null +++ b/ngraph/frontend/frontend_manager/include/frontend_manager/input_model.hpp @@ -0,0 +1,213 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +#include +#include +#include +#include "frontend_manager_defs.hpp" +#include "ngraph/partial_shape.hpp" +#include "ngraph/type/element_type.hpp" +#include "place.hpp" + +namespace ngraph +{ + namespace frontend + { + /// \brief InputModel class represents an original, not yet converted model graph in a + /// framework format given services to find places of interest in a graph or specialize/edit + /// the model before conversion. + /// + /// \note Class methods are divided into several groups: searching for places, naming and + /// annotation, topology editing, setting tensor properties. + /// + /// Editing requests may affect ability to convert the original model to nGraph function. + /// Aim to provide these editing capabilities is to unlock conversion for models that + /// are not natively supported "as-is" because of undefined shapes, types or operations. + /// + /// Specific front-end implementation is supposed to have a lazy implementation for + /// all methods, not doing a complete load of a model without an explicit method call. + /// For example, the list of all inputs are not pre-fetched by InputModel derived + /// class instance creation, but only when get_inputs method is called. But it is not + /// an obligation, the most convenient way should be chosen depending on the framework + /// model representation. + /// + /// All editing requests affect the model representation that is held behind the scene + /// successive method calls observe a new graph structure. + class FRONTEND_API InputModel + { + public: + typedef std::shared_ptr Ptr; + + virtual ~InputModel() = default; + + ///// Searching for places ///// + + /// \brief Returns all inputs for a model + /// An input is a place in a graph where data is supposed to flow inside graph from + /// outside. It can be a tensor, port, operation; which kind of place can be an output + /// is FW dependent. Usually framework models have a dedicated artifact to code model + /// input, it can be a tensor without producer, that writes to it in ONNX, or a special + /// operation like Placeholder in TensorFlow. + /// + /// \return A vector of input place references + virtual std::vector get_inputs() const; + + /// \brief Returns all output for a model + /// An output is a terminal place in a graph where data escapes the flow. It can be a + /// tensor, port, operation; which kind of place can be an output is FW dependent. In + /// comparison to a graph input, the output is less formally defined thing and + /// determination of initial list of outputs may include some conventions defined by a + /// frontend itself, not a framework. For example, all output ports without consumers + /// may be considered as outputs. + /// + /// \return A vector of output place references + virtual std::vector get_outputs() const; + + /// \brief Returns a tensor place by a tensor name following framework conventions, or + /// nullptr if a tensor with this name doesn't exist. + /// \param tensorName Name of tensor + /// \return Tensor place corresponding to specifed tensor name + virtual Place::Ptr get_place_by_tensor_name(const std::string& tensorName) const; + + /// \brief Returns an operation place by an operation name following framework + /// conventions, or nullptr if an operation with this name doesn't exist. \param + /// operationName Name of operation \return Place representing operation + virtual Place::Ptr get_place_by_operation_name(const std::string& operationName); + + /// \brief Returns an input port place by operation name and appropriate port index + /// \param operationName Name of operation + /// \param outputPortIndex Index of input port for this operation + /// \return Place representing input port of operation + virtual Place::Ptr + get_place_by_operation_name_and_input_port(const std::string& operationName, + int inputPortIndex); + + /// \brief Returns an output port place by operation name and appropriate port index + /// \param operationNameNname of operation + /// \param outputPortIndex Index of output port for this operation + /// \return Place representing output port of operation + virtual Place::Ptr + get_place_by_operation_name_and_output_port(const std::string& operationName, + int outputPortIndex); + + ///// Naming and annotation ///// + + /// \brief Sets name for tensor. Overwrites existing names of this place + /// \param operation Tensor place + /// \param newName New name for this tensor + virtual void set_name_for_tensor(Place::Ptr tensor, const std::string& newName); + + /// \brief Adds new name for tensor + /// \param operation Tensor place + /// \param newName New name to be added to this place + virtual void add_name_for_tensor(Place::Ptr tensor, const std::string& newName); + + /// \brief Sets name for operation. Overwrites existing names of this place + /// \param operation Operation place + /// \param newName New name for this operation + virtual void set_name_for_operation(Place::Ptr operation, const std::string& newName); + + /// \brief Unassign specified name from tensor place(s) + /// \param name Name of tensor + virtual void free_name_for_tensor(const std::string& name); + + /// \brief Unassign specified name from operation place(s) + /// \param name Name of operation + virtual void free_name_for_operation(const std::string& name); + + /// \brief Set name for a particular dimension of a place (e.g. batch dimension) + /// \param place Model's place + /// \param shapeDimIndex Dimension index + /// \param dimName Name to assign on this dimension + virtual void set_name_for_dimension(Place::Ptr place, + size_t shapeDimIndex, + const std::string& dimName); + + ///// Topology Editing ///// + + /// \brief Cut immediately before this place and assign this place as new input; prune + /// all nodes that don't contribute to any output. + /// \param place New place to be assigned as input + /// \param newNameOptional Optional new name assigned to this input place + virtual void cut_and_add_new_input(Place::Ptr place, + const std::string& newNameOptional = ""); + + /// \brief Cut immediately after this place and assign this place as new output; prune + /// all nodes that don't contribute to any output. + /// \param place New place to be assigned as output + /// \param newNameOptional Optional new name assigned to this output place + virtual void cut_and_add_new_output(Place::Ptr place, + const std::string& newNameOptional = ""); + + /// \brief Assign this place as new output or add necessary nodes to represent a new + /// output. + /// + /// \param place Anchor point to add an output + /// \return new output place, may be the same as a given place + virtual Place::Ptr add_output(Place::Ptr place); + + /// \brief Removes any sinks directly attached to this place with all inbound data flow + /// if it is not required by any other output. + /// \param place Model place + virtual void remove_output(Place::Ptr place); + + /// \brief Replaces all existing outputs with new ones removing all data flow that is + /// not required for new outputs. + /// + /// \param outputs Vector with places that will become new outputs; may intersect + /// existing outputs. + /// \param outputs Array of new output places + virtual void override_all_outputs(const std::vector& outputs); + + /// \brief Modifies the graph to use new inputs instead of existing ones. New inputs + /// should completely satisfy all existing outputs. + /// \param inputs Array of new input places + virtual void override_all_inputs(const std::vector& inputs); + + /// \brief Leaves only subgraph that are defined by new inputs and new outputs. + /// \param inputs Array of new input places + /// \param outputs Array of new output places + virtual void extract_subgraph(const std::vector& inputs, + const std::vector& outputs); + + ///// Setting tensor properties ///// + + /// \brief Defines all possible shape that may be used for this place; place should be + /// uniquely refer to some data. This partial shape will be converted to corresponding + /// shape of results ngraph nodes and will define shape inference when the model is + /// converted to ngraph. + /// \param place Model place + /// \param shape Partial shape for this place + virtual void set_partial_shape(Place::Ptr place, const ngraph::PartialShape& shape); + + /// \brief Returns current partial shape used for this place + /// \param place Model place + /// \return Partial shape for this place + virtual ngraph::PartialShape get_partial_shape(Place::Ptr place) const; + + /// \brief Sets new element type for a place + /// \param place Model place + /// \param type New element type + virtual void set_element_type(Place::Ptr place, const ngraph::element::Type& type); + + /// \brief Freezes a tensor with statically defined value or replace existing value for + /// already constant node or tensor + /// \param place Tensor place + /// \param value Value for tensor place representing a memory buffer + virtual void set_tensor_value(Place::Ptr place, const void* value); + + /// \brief Defines partial value (lower bound and upper bound) for a tensor place + /// TODO: more details for minValue and maxValue format; who defines shape? + /// \param place Tensor place + /// \param minValue Lower bound of partial value for tensor place + /// \param maxValue Upper bound of partial value for tensor place + virtual void set_tensor_partial_value(Place::Ptr place, + const void* minValue, + const void* maxValue); + }; + + } // namespace frontend +} // namespace ngraph diff --git a/ngraph/frontend/frontend_manager/include/frontend_manager/place.hpp b/ngraph/frontend/frontend_manager/include/frontend_manager/place.hpp new file mode 100644 index 00000000000000..5df561fa0d5e4d --- /dev/null +++ b/ngraph/frontend/frontend_manager/include/frontend_manager/place.hpp @@ -0,0 +1,228 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +#include +#include +#include +#include "frontend_manager_defs.hpp" + +namespace ngraph +{ + namespace frontend + { + /// \brief An interface for identifying a place in a graph and iterate over it; can refer to + /// an operation node, tensor, port etc. + /// + /// \note Each front end implementation provides specialization of this interface to + /// represent a place in a model graph. Various methods in the front end classes accept and + /// retrieve instances of Place to point to particular node part which should be modified or + /// satisfies some criteria. For example, this class is used to report model inputs + /// and outputs, for searching operations and tensors by name, for setting shape etc. + /// + /// Place can refer to Tensor, Input Edge, Input Port, Operation, Output Port, Output Edge + /// + /// [Tensor A] + /// | + /// | [Input Edge] + /// | + /// V + /// ------------------- + /// [ [Input Port 0] ] + /// [ ] + /// [ Operation A ] + /// [ ] + /// [ [Output Port 0] ] + /// ------------------- + /// | + /// | [Output Edge] + /// | + /// V + /// [Tensor B] + /// | + /// | [Input Edge] + /// | + /// V + /// ------------------- + /// [ [Input Port 0] ] + /// [ ] + /// [ Operation B ] + /// [ ] + /// [ [Output Port 0] ] + /// ------------------- + /// | + /// | [Output Edge] + /// | + /// V + /// [Tensor C] + /// + class FRONTEND_API Place + { + public: + typedef std::shared_ptr Ptr; + + virtual ~Place() = default; + + /// \brief All associated names (synonyms) that identify this place in the graph in a + /// framework specific way + /// + /// \return A vector of strings each representing a name that identifies this place in + /// the graph. Can be empty if there are no names associated with this place or name + /// cannot be attached. + virtual std::vector get_names() const; + + /// \brief Returns references to all operation nodes that consume data from this place + /// \note It can be called for any kind of graph place searching for the first consuming + /// operations. It is optional if place has only one output port + /// + /// \return A vector with all operation node references that consumes data from this + /// place + virtual std::vector get_consuming_operations() const; + + /// \brief Returns references to all operation nodes that consume data from this place + /// for specified output port + /// + /// \note It can be called for any kind of graph place searching for the first consuming + /// operations. + /// + /// \param outputPortIndex If place is an operational node it specifies which output + /// port should be considered. + /// + /// \return A vector with all operation node references that consumes data from this + /// place + virtual std::vector get_consuming_operations(int outputPortIndex) const; + + /// \brief Returns a tensor place that gets data from this place; applicable for + /// operations, output ports and output edges which have only one output port + /// + /// \return A tensor place which hold the resulting value for this place + virtual Ptr get_target_tensor() const; + + /// \brief Returns a tensor place that gets data from this place; applicable for + /// operations, output ports and output edges + /// + /// \param outputPortIndex Output port index if the current place is an operation node + /// and has multiple output ports + /// + /// \return A tensor place which hold the resulting value for this place + virtual Ptr get_target_tensor(int outputPortIndex) const; + + /// \brief Returns a tensor place that supplies data for this place; applicable for + /// operations, input ports and input edges which have only one input port + /// + /// \return A tensor place which supplies data for this place + virtual Ptr get_source_tensor() const; + + /// \brief Returns a tensor place that supplies data for this place; applicable for + /// operations, input ports and input edges + /// + /// \param inputPortIndex Input port index for operational nodes. + /// + /// \return A tensor place which supplies data for this place + virtual Ptr get_source_tensor(int inputPortIndex) const; + + /// \brief Get an operation node place that immediately produces data for this place; + /// applicable if place has only one input port + /// + /// \return An operation place that produces data for this place + virtual Ptr get_producing_operation() const; + + /// \brief Get an operation node place that immediately produces data for this place + /// + /// \param inputPortIndex If a given place is itself an operation node, this specifies a + /// port index + /// + /// \return An operation place that produces data for this place + virtual Ptr get_producing_operation(int inputPortIndex) const; + + /// Returns a port that produces data for this place + virtual Ptr get_producing_port() const; + + /// \brief For operation node returns reference to an input port; applicable if + /// operation node has only one input port + /// + /// \return Input port place + virtual Ptr get_input_port() const; + + /// \brief For operation node returns reference to an input port with specified index + /// + /// \param inputPortIndex Input port index + /// + /// \return Appropriate input port place + virtual Ptr get_input_port(int inputPortIndex) const; + + /// \brief For operation node returns reference to an input port with specified name; + /// applicable if port group has only one input port + /// + /// \param inputName Name of port group + /// + /// \return Appropriate input port place + virtual Ptr get_input_port(const std::string& inputName) const; + + /// \brief For operation node returns reference to an input port with specified name and + /// index + /// + /// \param inputName Name of port group, each group can have multiple ports + /// + /// \param inputPortIndex Input port index in a group + /// + /// \return Appropriate input port place + virtual Ptr get_input_port(const std::string& inputName, int inputPortIndex) const; + + /// \brief For operation node returns reference to an output port; applicable for + /// operations with only one output port + /// + /// \return Appropriate output port place + virtual Ptr get_output_port() const; + + /// \brief For operation node returns reference to an output port with specified index + /// + /// \param outputPortIndex Output port index + /// + /// \return Appropriate output port place + virtual Ptr get_output_port(int outputPortIndex) const; + + /// \brief For operation node returns reference to an output port with specified name; + /// applicable if port group has only one output port + /// + /// \param outputName Name of output port group + /// + /// \return Appropriate output port place + virtual Ptr get_output_port(const std::string& outputName) const; + + /// \brief For operation node returns reference to an output port with specified name + /// and index + /// + /// \param outputName Name of output port group, each group can have multiple ports + /// + /// \param outputPortIndex Output port index + /// + /// \return Appropriate output port place + virtual Ptr get_output_port(const std::string& outputName, int outputPortIndex) const; + + /// \brief Returns all input ports that consume data flows through this place + virtual std::vector get_consuming_ports() const; + + /// \brief Returns true if this place is input for a model. + virtual bool is_input() const; + + /// \brief Returns true if this place is output for a model. + virtual bool is_output() const; + + /// \brief Returns true if another place is the same as this place. + /// + /// \param another Another place object + virtual bool is_equal(Ptr another) const; + + /// \brief Returns true if another place points to the same data. + /// + /// \note The same data means all places on path: output port -> output edge -> tensor + /// -> input edge -> input port. + /// + /// \param another Another place object + virtual bool is_equal_data(Ptr another) const; + }; + } // namespace frontend +} // namespace ngraph