CVS-44774: Fixed preprocessing for template plugin (#4118)

* Fixed preprocessing for template plugin

* Added more tests instances

* Split common transformation to smaller ones which can be used by plugins

* Moved preprocessing transformation to Plugin API

* Added PreprocessConversionTest tests

* Disabled tests on GPU: CVS-51764

* Disabled some tests on VPU and TEMPLATE

* Support for input layout conversions in TEMPLATE plugin

* Improvements in Template Plugin

* Fixed compilation

* Fixes

* Disables some tests

* Fixed compilation on Windows

* Fixed docs
This commit is contained in:
Ilya Lavrenov 2021-04-30 10:47:29 +03:00 committed by GitHub
parent ff9e67e732
commit 8b1b900591
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 589 additions and 52 deletions

View File

@ -61,9 +61,9 @@ nGraph has three main transformation types:
Template for FunctionPass transformation class Template for FunctionPass transformation class
@snippet src/template_function_transformation.hpp function_pass:template_transformation_hpp @snippet src/transformations/template_function_transformation.hpp function_pass:template_transformation_hpp
@snippet src/template_function_transformation.cpp function_pass:template_transformation_cpp @snippet src/transformations/template_function_transformation.cpp function_pass:template_transformation_cpp
Using `ngraph::FunctionPass`, you need to override the `run_on_function` method where you will write the transformation code. Using `ngraph::FunctionPass`, you need to override the `run_on_function` method where you will write the transformation code.
Return value is `true` if the original function has changed during transformation (new operation was added, or operations replacement was made, or node attributes were changed); otherwise, it is `false`. Return value is `true` if the original function has changed during transformation (new operation was added, or operations replacement was made, or node attributes were changed); otherwise, it is `false`.
@ -75,9 +75,9 @@ Also `ngraph::FunctionPass` based transformations can be executed via `pass::Man
`ngraph::pass::MatcherPass` is used for pattern-based transformations. `ngraph::pass::MatcherPass` is used for pattern-based transformations.
Template for MatcherPass transformation class Template for MatcherPass transformation class
@snippet src/template_pattern_transformation.hpp graph_rewrite:template_transformation_hpp @snippet src/transformations/template_pattern_transformation.hpp graph_rewrite:template_transformation_hpp
@snippet src/template_pattern_transformation.cpp graph_rewrite:template_transformation_cpp @snippet src/transformations/template_pattern_transformation.cpp graph_rewrite:template_transformation_cpp
To use `ngraph::pass::MatcherPass`, you need to complete these steps: To use `ngraph::pass::MatcherPass`, you need to complete these steps:
1. Create a pattern 1. Create a pattern
@ -113,7 +113,7 @@ That means that matcher passes registered in `pass::GraphRewrite` will be applie
The example below shows how single MatcherPass can fuse sequence of operations using the `register_new_node` method. The example below shows how single MatcherPass can fuse sequence of operations using the `register_new_node` method.
@snippet src/template_pattern_transformation.cpp matcher_pass:relu_fusion @snippet src/transformations/template_pattern_transformation.cpp matcher_pass:relu_fusion
> **NOTE**: If you register multiple nodes, please add them in topological order. We do not topologically sort these nodes as it is a time-consuming operation. > **NOTE**: If you register multiple nodes, please add them in topological order. We do not topologically sort these nodes as it is a time-consuming operation.
@ -128,11 +128,11 @@ register_matcher(m, callback);
### Execute MatcherPass ### Execute MatcherPass
MatcherPass has multiple ways to be executed: MatcherPass has multiple ways to be executed:
* Run on a single node - it can be useful if you want to run MatcherPass inside another transformation. * Run on a single node - it can be useful if you want to run MatcherPass inside another transformation.
@snippet src/template_pattern_transformation.cpp matcher_pass:run_on_node @snippet src/transformations/template_pattern_transformation.cpp matcher_pass:run_on_node
* Run on `ngraph::Function` using GraphRewrite - this approach gives ability to run MatcherPass on whole `ngraph::Function`. Moreover, multiple MatcherPass transformation can be registered in a single GraphRewite to be executed in a single graph traversal. * Run on `ngraph::Function` using GraphRewrite - this approach gives ability to run MatcherPass on whole `ngraph::Function`. Moreover, multiple MatcherPass transformation can be registered in a single GraphRewite to be executed in a single graph traversal.
@snippet src/template_pattern_transformation.cpp matcher_pass:graph_rewrite @snippet src/transformations/template_pattern_transformation.cpp matcher_pass:graph_rewrite
* Run on `ngraph::Function` using `pass::Manager` - this approach helps you to register MatcherPass for execution on `ngraph::Function` as another transformation types. * Run on `ngraph::Function` using `pass::Manager` - this approach helps you to register MatcherPass for execution on `ngraph::Function` as another transformation types.
@snippet src/template_pattern_transformation.cpp matcher_pass:manager @snippet src/transformations/template_pattern_transformation.cpp matcher_pass:manager
### ngraph::pass::GraphRewrite <a name="graph_rewrite_pass"></a> ### ngraph::pass::GraphRewrite <a name="graph_rewrite_pass"></a>
@ -140,7 +140,7 @@ MatcherPass has multiple ways to be executed:
GraphRewrite pass serves for running multiple matcher passes on `ngraph::Function` in a single graph traversal. GraphRewrite pass serves for running multiple matcher passes on `ngraph::Function` in a single graph traversal.
Example: Example:
@snippet src/template_pattern_transformation.cpp matcher_pass:graph_rewrite @snippet src/transformations/template_pattern_transformation.cpp matcher_pass:graph_rewrite
In addition, GraphRewrite handles nodes that were registered by MatcherPasses during their execution. This nodes will be added to the beginning of the sequence with nodes for pattern matching. In addition, GraphRewrite handles nodes that were registered by MatcherPasses during their execution. This nodes will be added to the beginning of the sequence with nodes for pattern matching.
@ -352,7 +352,7 @@ Manual constant folding is more preferable than `ngraph::pass::ConstantFolding()
Below you can find an example of manual constant folding: Below you can find an example of manual constant folding:
@snippet src/template_pattern_transformation.cpp manual_constant_folding @snippet src/transformations/template_pattern_transformation.cpp manual_constant_folding
## Common mistakes in transformations <a name="common_mistakes"></a> ## Common mistakes in transformations <a name="common_mistakes"></a>
@ -373,11 +373,11 @@ In addition, `ngraph::pass::Manager` has extended debug capabilities (find more
The example below shows basic usage of `ngraph::pass::Manager` The example below shows basic usage of `ngraph::pass::Manager`
@snippet src/template_pattern_transformation.cpp matcher_pass:manager3 @snippet src/transformations/template_pattern_transformation.cpp matcher_pass:manager3
Another example shows how multiple matcher passes can be united into single GraphRewrite. Another example shows how multiple matcher passes can be united into single GraphRewrite.
@snippet src/template_pattern_transformation.cpp matcher_pass:manager2 @snippet src/transformations/template_pattern_transformation.cpp matcher_pass:manager2
> **Note:** nGraph used to have the `pass::PassConfig` class for transformation pipeline manipulation. > **Note:** nGraph used to have the `pass::PassConfig` class for transformation pipeline manipulation.
This mechanism is now obsolete and the `pass::PassConfig` class will be removed in future release. This mechanism is now obsolete and the `pass::PassConfig` class will be removed in future release.

View File

@ -5,7 +5,7 @@
# [cmake:plugin] # [cmake:plugin]
set(TARGET_NAME "templatePlugin") set(TARGET_NAME "templatePlugin")
file(GLOB SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp) file(GLOB_RECURSE SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp)
file(GLOB_RECURSE HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/*.hpp) file(GLOB_RECURSE HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/*.hpp)
# adds a shared library with plugin # adds a shared library with plugin

View File

@ -28,7 +28,7 @@ Configuration::Configuration(const ConfigMap& config, const Configuration & defa
} else if (CONFIG_KEY(DEVICE_ID) == key) { } else if (CONFIG_KEY(DEVICE_ID) == key) {
deviceId = std::stoi(value); deviceId = std::stoi(value);
if (deviceId > 0) { if (deviceId > 0) {
IE_THROW() << "Device ID " << deviceId << " is not supported"; IE_THROW(NotImplemented) << "Device ID " << deviceId << " is not supported";
} }
} else if (CONFIG_KEY(PERF_COUNT) == key) { } else if (CONFIG_KEY(PERF_COUNT) == key) {
perfCount = (CONFIG_VALUE(YES) == value); perfCount = (CONFIG_VALUE(YES) == value);

View File

@ -16,6 +16,8 @@ using namespace TemplatePlugin;
// ! [executable_network:ctor_cnnnetwork] // ! [executable_network:ctor_cnnnetwork]
TemplatePlugin::ExecutableNetwork::ExecutableNetwork(const std::shared_ptr<const ngraph::Function>& function, TemplatePlugin::ExecutableNetwork::ExecutableNetwork(const std::shared_ptr<const ngraph::Function>& function,
const InferenceEngine::InputsDataMap& inputInfoMap,
const InferenceEngine::OutputsDataMap& outputsInfoMap,
const Configuration& cfg, const Configuration& cfg,
const Plugin::Ptr& plugin) : const Plugin::Ptr& plugin) :
InferenceEngine::ExecutableNetworkThreadSafeDefault(nullptr, nullptr), // Disable default threads creation InferenceEngine::ExecutableNetworkThreadSafeDefault(nullptr, nullptr), // Disable default threads creation
@ -25,14 +27,14 @@ TemplatePlugin::ExecutableNetwork::ExecutableNetwork(const std::shared_ptr<const
// you should select proper device based on KEY_DEVICE_ID or automatic behavior // you should select proper device based on KEY_DEVICE_ID or automatic behavior
// In this case, _waitExecutor should also be created per device. // In this case, _waitExecutor should also be created per device.
try { try {
CompileNetwork(function); CompileNetwork(function, inputInfoMap, outputsInfoMap);
InitExecutor(); // creates thread-based executor using for async requests InitExecutor(); // creates thread-based executor using for async requests
} catch (const InferenceEngine::Exception&) { } catch (const InferenceEngine::Exception&) {
throw; throw;
} catch (const std::exception & e) { } catch (const std::exception & e) {
IE_THROW() << "Standard exception from compilation library: " << e.what(); IE_THROW(Unexpected) << "Standard exception from compilation library: " << e.what();
} catch (...) { } catch (...) {
IE_THROW() << "Generic exception is thrown"; IE_THROW(Unexpected) << "Generic exception is thrown";
} }
} }
// ! [executable_network:ctor_cnnnetwork] // ! [executable_network:ctor_cnnnetwork]
@ -64,6 +66,8 @@ TemplatePlugin::ExecutableNetwork::ExecutableNetwork(std::istream & model,
// TODO: implement Import / Export of configuration options and merge with `cfg` // TODO: implement Import / Export of configuration options and merge with `cfg`
// TODO: implement Import / Export of network precisions, layouts, preprocessing info // TODO: implement Import / Export of network precisions, layouts, preprocessing info
InferenceEngine::InputsDataMap inputInfoMap;
InferenceEngine::OutputsDataMap outputInfoMap;
auto cnnnetwork = _plugin->GetCore()->ReadNetwork(xmlString, std::move(dataBlob)); auto cnnnetwork = _plugin->GetCore()->ReadNetwork(xmlString, std::move(dataBlob));
@ -72,27 +76,31 @@ TemplatePlugin::ExecutableNetwork::ExecutableNetwork(std::istream & model,
SetPointerToPlugin(_plugin->shared_from_this()); SetPointerToPlugin(_plugin->shared_from_this());
try { try {
CompileNetwork(cnnnetwork.getFunction()); CompileNetwork(cnnnetwork.getFunction(), inputInfoMap, outputInfoMap);
InitExecutor(); // creates thread-based executor using for async requests InitExecutor(); // creates thread-based executor using for async requests
} catch (const InferenceEngine::Exception&) { } catch (const InferenceEngine::Exception&) {
throw; throw;
} catch (const std::exception & e) { } catch (const std::exception & e) {
IE_THROW() << "Standard exception from compilation library: " << e.what(); IE_THROW(Unexpected) << "Standard exception from compilation library: " << e.what();
} catch (...) { } catch (...) {
IE_THROW() << "Generic exception is thrown"; IE_THROW(Unexpected) << "Generic exception is thrown";
} }
} }
// ! [executable_network:ctor_import_stream] // ! [executable_network:ctor_import_stream]
// ! [executable_network:map_graph] // ! [executable_network:map_graph]
// forward declaration // forward declaration
std::shared_ptr<ngraph::Function> TransformNetwork(const std::shared_ptr<const ngraph::Function>& function); std::shared_ptr<ngraph::Function> TransformNetwork(const std::shared_ptr<const ngraph::Function>& function,
const InferenceEngine::InputsDataMap & inputInfoMap,
const InferenceEngine::OutputsDataMap& outputsInfoMap);
void TemplatePlugin::ExecutableNetwork::CompileNetwork(const std::shared_ptr<const ngraph::Function>& function) { void TemplatePlugin::ExecutableNetwork::CompileNetwork(const std::shared_ptr<const ngraph::Function>& function,
const InferenceEngine::InputsDataMap & inputInfoMap,
const InferenceEngine::OutputsDataMap& outputsInfoMap) {
// TODO: perform actual graph compilation / mapping to backend graph representation / kernels // TODO: perform actual graph compilation / mapping to backend graph representation / kernels
// apply plugins transformations // apply plugins transformations
_function = TransformNetwork(function); _function = TransformNetwork(function, inputInfoMap, outputsInfoMap);
// Generate backend specific blob mappings. For example Inference Engine uses not ngraph::Result nodes friendly name // Generate backend specific blob mappings. For example Inference Engine uses not ngraph::Result nodes friendly name
// as inference request output names but the name of the layer before. // as inference request output names but the name of the layer before.

View File

@ -25,6 +25,8 @@ class Plugin;
class ExecutableNetwork : public InferenceEngine::ExecutableNetworkThreadSafeDefault { class ExecutableNetwork : public InferenceEngine::ExecutableNetworkThreadSafeDefault {
public: public:
ExecutableNetwork(const std::shared_ptr<const ngraph::Function>& function, ExecutableNetwork(const std::shared_ptr<const ngraph::Function>& function,
const InferenceEngine::InputsDataMap& inputInfoMap,
const InferenceEngine::OutputsDataMap& outputsInfoMap,
const Configuration& cfg, const Configuration& cfg,
const std::shared_ptr<Plugin>& plugin); const std::shared_ptr<Plugin>& plugin);
@ -46,7 +48,9 @@ public:
private: private:
friend class TemplateInferRequest; friend class TemplateInferRequest;
void CompileNetwork(const std::shared_ptr<const ngraph::Function>& function); void CompileNetwork(const std::shared_ptr<const ngraph::Function>& function,
const InferenceEngine::InputsDataMap& inputInfoMap,
const InferenceEngine::OutputsDataMap& outputsInfoMap);
void InitExecutor(); void InitExecutor();
std::atomic<std::size_t> _requestId = {0}; std::atomic<std::size_t> _requestId = {0};

View File

@ -61,7 +61,8 @@ template<typename BlobDataMap, typename GetNetworkPrecisionF>
static void AllocateImpl(const BlobDataMap& userDataMap, static void AllocateImpl(const BlobDataMap& userDataMap,
BlobMap& userBlobMap, BlobMap& userBlobMap,
BlobMap& deviceBlobMap, BlobMap& deviceBlobMap,
GetNetworkPrecisionF&& GetNetworkPrecision) { GetNetworkPrecisionF&& GetNetworkPrecision,
bool isInputBlob = true) {
for (auto&& userData : userDataMap) { for (auto&& userData : userDataMap) {
auto& dims = userData.second->getTensorDesc().getDims(); auto& dims = userData.second->getTensorDesc().getDims();
const auto devicePrecision = Precision::FP32; const auto devicePrecision = Precision::FP32;
@ -77,7 +78,7 @@ static void AllocateImpl(const BlobDataMap& userDataMap,
case Precision::FP32 : { case Precision::FP32 : {
userBlob = InferenceEngine::make_shared_blob<float>({userPrecision, dims, userLayout}); userBlob = InferenceEngine::make_shared_blob<float>({userPrecision, dims, userLayout});
} break; } break;
default: IE_THROW() << "Template Plugin: Unsupported Input/Output Precision"; default: IE_THROW(NotImplemented) << "Template Plugin: Unsupported Input/Output Precision";
} }
userBlob->allocate(); userBlob->allocate();
userBlobMap[userData.first] = userBlob; userBlobMap[userData.first] = userBlob;
@ -92,12 +93,16 @@ static void AllocateImpl(const BlobDataMap& userDataMap,
deviceBlob = InferenceEngine::make_shared_blob<float>({devicePrecision, dims, deviceLayout}); deviceBlob = InferenceEngine::make_shared_blob<float>({devicePrecision, dims, deviceLayout});
} }
} break; } break;
default: IE_THROW() << "Template Plugin: Unsupported network Input/Output Presision"; default: IE_THROW(NotImplemented) << "Template Plugin: Unsupported network Input/Output Presision";
} }
// preprocessing converts user input blob to desired device input blob automatically
// NOTE: this is not supported for output user blobs yet
if (userBlob != deviceBlob) { if (userBlob != deviceBlob) {
if (isInputBlob) {
// preprocessing converts user input blob to desired device input blob automatically
deviceBlob->allocate(); deviceBlob->allocate();
} else {
// NOTE: this is not supported for output user blobs yet
IE_THROW(NotImplemented) << "Template Plugin: does not support setPrecision, setLayout for outputs";
}
} }
deviceBlobMap[userData.first] = deviceBlob; deviceBlobMap[userData.first] = deviceBlob;
} }
@ -111,7 +116,7 @@ void TemplateInferRequest::allocateBlobs() {
auto&& results = _executableNetwork->_function->get_results(); auto&& results = _executableNetwork->_function->get_results();
AllocateImpl(_networkOutputs, _outputs, _networkOutputBlobs, [&] (const std::string& blobName) { AllocateImpl(_networkOutputs, _outputs, _networkOutputBlobs, [&] (const std::string& blobName) {
return results.at(_executableNetwork->_outputIndex.at(blobName))->get_element_type(); return results.at(_executableNetwork->_outputIndex.at(blobName))->get_element_type();
}); }, false);
} }
// ! [infer_request:infer_impl] // ! [infer_request:infer_impl]
@ -140,7 +145,7 @@ static void blobCopy(const Blob::Ptr& src, const Blob::Ptr& dst) {
blobCopy<std::uint8_t, float>(src, dst); blobCopy<std::uint8_t, float>(src, dst);
} break; } break;
default : { default : {
IE_THROW() << "Unsupported precision conversion from " IE_THROW(NotImplemented) << "Unsupported precision conversion from "
<< src->getTensorDesc().getPrecision() <<" to " << dst->getTensorDesc().getPrecision(); << src->getTensorDesc().getPrecision() <<" to " << dst->getTensorDesc().getPrecision();
} }
} }
@ -152,13 +157,13 @@ static void blobCopy(const Blob::Ptr& src, const Blob::Ptr& dst) {
blobCopy<float, std::uint8_t>(src, dst); blobCopy<float, std::uint8_t>(src, dst);
} break; } break;
default : { default : {
IE_THROW() << "Unsupported precision conversion from " IE_THROW(NotImplemented) << "Unsupported precision conversion from "
<< src->getTensorDesc().getPrecision() <<" to " << dst->getTensorDesc().getPrecision(); << src->getTensorDesc().getPrecision() <<" to " << dst->getTensorDesc().getPrecision();
} }
} }
} break; } break;
default : { default : {
IE_THROW() << "Unsupported precision conversion from " << src->getTensorDesc().getPrecision(); IE_THROW(NotImplemented) << "Unsupported precision conversion from " << src->getTensorDesc().getPrecision();
} }
} }
} }

View File

@ -22,7 +22,8 @@
#include "template_plugin.hpp" #include "template_plugin.hpp"
#include "template_executable_network.hpp" #include "template_executable_network.hpp"
#include "template_infer_request.hpp" #include "template_infer_request.hpp"
#include "template_pattern_transformation.hpp" #include "transformations/template_pattern_transformation.hpp"
#include "transformations/preprocessing/preprocessing.hpp"
using namespace TemplatePlugin; using namespace TemplatePlugin;
@ -52,12 +53,17 @@ Plugin::~Plugin() {
// ! [plugin:transform_network] // ! [plugin:transform_network]
std::shared_ptr<ngraph::Function> TransformNetwork(const std::shared_ptr<const ngraph::Function>& function) { std::shared_ptr<ngraph::Function> TransformNetwork(const std::shared_ptr<const ngraph::Function>& function,
const InferenceEngine::InputsDataMap & inputInfoMap,
const InferenceEngine::OutputsDataMap& outputsInfoMap) {
// 1. Copy ngraph::Function first to apply some transformations which modify original ngraph::Function // 1. Copy ngraph::Function first to apply some transformations which modify original ngraph::Function
auto transformedNetwork = ngraph::clone_function(*function); auto transformedNetwork = ngraph::clone_function(*function);
// 2. Perform common optimizations and device-specific transformations // 2. Perform common optimizations and device-specific transformations
ngraph::pass::Manager passManager; ngraph::pass::Manager passManager;
// Example: register transformation to convert preprocessing information to graph nodes
passManager.register_pass<ngraph::pass::AddPreprocessing>(inputInfoMap);
// TODO: add post-processing based on outputsInfoMap
// Example: register CommonOptimizations transformation from transformations library // Example: register CommonOptimizations transformation from transformations library
passManager.register_pass<ngraph::pass::CommonOptimizations>(); passManager.register_pass<ngraph::pass::CommonOptimizations>();
// Template plugin handles only FP32 networks // Template plugin handles only FP32 networks
@ -81,8 +87,12 @@ InferenceEngine::ExecutableNetworkInternal::Ptr Plugin::LoadExeNetworkImpl(const
const ConfigMap &config) { const ConfigMap &config) {
OV_ITT_SCOPED_TASK(itt::domains::TemplatePlugin, "Plugin::LoadExeNetworkImpl"); OV_ITT_SCOPED_TASK(itt::domains::TemplatePlugin, "Plugin::LoadExeNetworkImpl");
InferenceEngine::InputsDataMap networkInputs = network.getInputsInfo();
InferenceEngine::OutputsDataMap networkOutputs = network.getOutputsInfo();
auto fullConfig = Configuration{ config, _cfg }; auto fullConfig = Configuration{ config, _cfg };
return std::make_shared<ExecutableNetwork>(network.getFunction(), fullConfig, return std::make_shared<ExecutableNetwork>(network.getFunction(),
networkInputs, networkOutputs, fullConfig,
std::static_pointer_cast<Plugin>(shared_from_this())); std::static_pointer_cast<Plugin>(shared_from_this()));
} }
// ! [plugin:load_exe_network_impl] // ! [plugin:load_exe_network_impl]
@ -114,7 +124,7 @@ InferenceEngine::QueryNetworkResult Plugin::QueryNetwork(const InferenceEngine::
} }
// 2. It is needed to apply all transformations as it is done in LoadExeNetworkImpl // 2. It is needed to apply all transformations as it is done in LoadExeNetworkImpl
auto transformedFunction = TransformNetwork(function); auto transformedFunction = TransformNetwork(function, network.getInputsInfo(), network.getOutputsInfo());
// 3. The same input node can be transformed into supported and unsupported backend node // 3. The same input node can be transformed into supported and unsupported backend node
// So we need store as supported either unsupported node sets // So we need store as supported either unsupported node sets
@ -246,7 +256,7 @@ InferenceEngine::Parameter Plugin::GetMetric(const std::string& name, const std:
using uint = unsigned int; using uint = unsigned int;
IE_SET_METRIC_RETURN(RANGE_FOR_ASYNC_INFER_REQUESTS, std::make_tuple(uint{1}, uint{1}, uint{1})); IE_SET_METRIC_RETURN(RANGE_FOR_ASYNC_INFER_REQUESTS, std::make_tuple(uint{1}, uint{1}, uint{1}));
} else { } else {
IE_THROW() << "Unsupported device metric: " << name; IE_THROW(NotFound) << "Unsupported device metric: " << name;
} }
} }
// ! [plugin:get_metric] // ! [plugin:get_metric]

View File

@ -0,0 +1,48 @@
// Copyright (C) 2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include <ngraph/opsets/opset3.hpp>
#include <ngraph/pass/manager.hpp>
#include <ngraph/pattern/op/wrap_type.hpp>
#include "transformations/preprocessing/mean_image_or_value.hpp"
using namespace ngraph;
NGRAPH_RTTI_DEFINITION(ngraph::pass::AddMeanSubtract, "AddMeanSubtract", 0);
ngraph::pass::AddMeanSubtract::AddMeanSubtract(const MeanMap & inputInfoMap) {
// RUN_ON_FUNCTION_SCOPE(AddMeanSubtract);
auto param = ngraph::pattern::wrap_type<ngraph::opset3::Parameter>();
ngraph::matcher_pass_callback callback = [=] (pattern::Matcher& m) {
auto param = std::dynamic_pointer_cast<ngraph::opset3::Parameter>(m.get_match_root());
if (!param) {
return false;
}
auto it = inputInfoMap.find(param->get_friendly_name());
if (it == inputInfoMap.end()) {
return false;
}
auto mean_const = it->second;
NGRAPH_CHECK(mean_const->get_element_type() == ngraph::element::f32,
"Mean for ", param->get_friendly_name(), " must have f32 type");
auto copy_param = param->clone_with_new_inputs({});
auto sub = std::make_shared<ngraph::opset3::Subtract>(copy_param, mean_const);
ngraph::replace_node(param, sub);
sub->set_argument(0, param);
// Return true as the root node was changed
return true;
};
// Register pattern with Parameter operation as a pattern root node
auto m = std::make_shared<ngraph::pattern::Matcher>(param, "AddMeanSubtract");
// Register Matcher
register_matcher(m, callback);
}

View File

@ -0,0 +1,33 @@
// Copyright (C) 2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#pragma once
#include <map>
#include <string>
#include <ngraph/op/constant.hpp>
#include <ngraph/pass/graph_rewrite.hpp>
#include "transformations_visibility.hpp"
namespace ngraph {
namespace pass {
class AddMeanSubtract;
} // namespace pass
} // namespace ngraph
/**
* @ingroup ie_transformation_common_api
* @brief Add `meanValue` or `meanImage` preprocessing to input nodes
*/
class ngraph::pass::AddMeanSubtract : public ngraph::pass::MatcherPass {
public:
using MeanMap = std::map<std::string, std::shared_ptr<ngraph::op::v0::Constant>>;
NGRAPH_RTTI_DECLARATION;
explicit AddMeanSubtract(const MeanMap & inputInfoMap);
};

View File

@ -0,0 +1,101 @@
// Copyright (C) 2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include <ngraph/pass/manager.hpp>
#include <ngraph/opsets/opset3.hpp>
#include "transformations/preprocessing/mean_image_or_value.hpp"
#include "transformations/preprocessing/std_scale.hpp"
#include "transformations/preprocessing/preprocessing.hpp"
NGRAPH_RTTI_DEFINITION(ngraph::pass::AddPreprocessing, "AddPreprocessing", 0);
ngraph::pass::AddPreprocessing::AddPreprocessing(const InferenceEngine::InputsDataMap & inputInfoMap)
: m_inputInfoMap(inputInfoMap) { }
bool ngraph::pass::AddPreprocessing::run_on_function(std::shared_ptr<ngraph::Function> f) {
ngraph::pass::AddMeanSubtract::MeanMap meanMap;
ngraph::pass::AddStdScale::ScaleMap scaleMap;
for (const auto & it : m_inputInfoMap) {
bool has_scales = false, has_mean_values = false, has_mean_image = false;
const InferenceEngine::PreProcessInfo & pInfo = it.second->getPreProcess();
const auto & inputDims = it.second->getTensorDesc().getDims();
const size_t cn = pInfo.getNumberOfChannels();
std::vector<float> meanValues(cn), stdScales(cn);
InferenceEngine::Blob::Ptr meanImage = nullptr;
for (size_t c = 0; c < cn; ++c) {
if ((stdScales[c] = pInfo[c]->stdScale) != 1.0f) {
has_scales = true;
}
if ((meanValues[c] = pInfo[c]->meanValue) != 0.0f) {
has_mean_values = true;
}
if (pInfo[c]->meanData != nullptr) {
has_mean_image = true;
if (c == 0) {
meanImage = pInfo[c]->meanData;
NGRAPH_CHECK(meanImage->getTensorDesc().getPrecision() == InferenceEngine::Precision::FP32,
"Only InferenceEngine::Precision::FP32 precision is supported for PreProcessChannel::meanData");
} else {
NGRAPH_CHECK(meanImage->getTensorDesc() == pInfo[c]->meanData->getTensorDesc(),
"TensorDesc for PreProcessChannel::meanData must be equal");
}
}
}
// no preprocessing for current input
if (!has_mean_values && !has_scales && !has_mean_image) {
continue;
}
NGRAPH_CHECK(!(has_mean_image && has_scales),
"Only PreProcessChannel::meanData or PreProcessChannel::meanValue can be set.");
if (has_scales) {
ngraph::Shape shape(inputDims.size(), 1);
shape[1] = stdScales.size(); // C
scaleMap[it.first] = ngraph::opset3::Constant::create(ngraph::element::f32, shape, stdScales);
}
if (has_mean_values) {
ngraph::Shape shape(inputDims.size(), 1);
shape[1] = meanValues.size(); // C
meanMap[it.first] = ngraph::opset3::Constant::create(ngraph::element::f32, shape, meanValues);
} else if (has_mean_image) {
ngraph::Shape shape = { cn };
auto dims = meanImage->getTensorDesc().getDims();
std::copy(dims.begin(), dims.end(), std::back_inserter(shape));
std::vector<float> meanImageData(ngraph::shape_size(shape));
for (size_t c = 0, i = 0; c < cn; ++c) {
auto lm = pInfo[c]->meanData->buffer();
const float *data = lm.as<const float *>();
std::memcpy(&meanImageData[i], data, meanImage->byteSize());
i += meanImage->size();
}
meanMap[it.first] = ngraph::opset3::Constant::create(ngraph::element::f32,
shape, meanImageData);
}
}
ngraph::pass::Manager manager(get_pass_config());
auto preproc = manager.register_pass<ngraph::pass::GraphRewrite>();
if (!scaleMap.empty()) {
preproc->add_matcher<ngraph::pass::AddStdScale>(scaleMap);
}
if (!meanMap.empty()) {
preproc->add_matcher<ngraph::pass::AddMeanSubtract>(meanMap);
}
manager.run_passes(f);
return false;
}

View File

@ -0,0 +1,35 @@
// Copyright (C) 2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#pragma once
#include <ngraph/pass/pass.hpp>
#include "ie_input_info.hpp"
namespace ngraph {
namespace pass {
class AddPreprocessing;
} // namespace pass
} // namespace ngraph
/**
* @brief Converts the following preprocessing information to ngraph operations:
* - InferenceEngine::PreProcessInfo->PreProcessChannel::meanData -> Subtract
* - InferenceEngine::PreProcessInfo->PreProcessChannel::meanValue -> Subtract
* - InferenceEngine::PreProcessInfo->PreProcessChannel::stdScale -> Multiply
*
* The order of operations is the following:
* (x - mean) * stdScale
*/
class ngraph::pass::AddPreprocessing : public ngraph::pass::FunctionPass {
const InferenceEngine::InputsDataMap & m_inputInfoMap;
public:
NGRAPH_RTTI_DECLARATION;
explicit AddPreprocessing(const InferenceEngine::InputsDataMap & inputInfoMap);
bool run_on_function(std::shared_ptr<ngraph::Function> f) override;
};

View File

@ -0,0 +1,48 @@
// Copyright (C) 2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include <ngraph/opsets/opset3.hpp>
#include <ngraph/pass/manager.hpp>
#include <ngraph/pattern/op/wrap_type.hpp>
#include "transformations/preprocessing/std_scale.hpp"
using namespace ngraph;
NGRAPH_RTTI_DEFINITION(ngraph::pass::AddStdScale, "AddStdScale", 0);
ngraph::pass::AddStdScale::AddStdScale(const ScaleMap& inputInfoMap) {
// RUN_ON_FUNCTION_SCOPE(AddStdScale);
auto param = ngraph::pattern::wrap_type<ngraph::opset3::Parameter>();
ngraph::matcher_pass_callback callback = [=] (pattern::Matcher& m) {
auto param = std::dynamic_pointer_cast<ngraph::opset3::Parameter>(m.get_match_root());
if (!param) {
return false;
}
auto it = inputInfoMap.find(param->get_friendly_name());
if (it == inputInfoMap.end()) {
return false;
}
auto scale_const = it->second;
NGRAPH_CHECK(scale_const->get_element_type() == ngraph::element::f32,
"Scale for ", param->get_friendly_name(), " must have f32 type");
auto copy_param = param->clone_with_new_inputs({});
auto mul = std::make_shared<ngraph::opset3::Multiply>(copy_param, it->second);
ngraph::replace_node(param, mul);
mul->set_argument(0, param);
// Return true as the root node was changed
return true;
};
// Register pattern with Parameter operation as a pattern root node
auto m = std::make_shared<ngraph::pattern::Matcher>(param, "AddStdScale");
// Register Matcher
register_matcher(m, callback);
}

View File

@ -0,0 +1,33 @@
// Copyright (C) 2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#pragma once
#include <map>
#include <string>
#include <ngraph/op/constant.hpp>
#include <ngraph/pass/graph_rewrite.hpp>
#include "transformations_visibility.hpp"
namespace ngraph {
namespace pass {
class AddStdScale;
} // namespace pass
} // namespace ngraph
/**
* @ingroup ie_transformation_common_api
* @brief Add `stdScale` preprocessing to input nodes
*/
class ngraph::pass::AddStdScale : public ngraph::pass::MatcherPass {
public:
using ScaleMap = std::map<std::string, std::shared_ptr<ngraph::op::v0::Constant>>;
NGRAPH_RTTI_DECLARATION;
explicit AddStdScale(const ScaleMap& inputInfoMap);
};

View File

@ -2,8 +2,8 @@
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
// //
#include "template_pattern_transformation.hpp" #include "transformations/template_pattern_transformation.hpp"
#include "template_function_transformation.hpp" #include "transformations/template_function_transformation.hpp"
#include <ngraph/opsets/opset3.hpp> #include <ngraph/opsets/opset3.hpp>
#include <ngraph/pass/manager.hpp> #include <ngraph/pass/manager.hpp>

View File

@ -16,7 +16,7 @@ class ReluReluFusionMatcher;
} // namespace ngraph } // namespace ngraph
// ! [graph_rewrite:template_transformation_hpp] // ! [graph_rewrite:template_transformation_hpp]
// template_pattern_transformation.hpp // transformations/template_pattern_transformation.hpp
/** /**
* @ingroup ie_transformation_common_api * @ingroup ie_transformation_common_api
* @brief Add transformation description. * @brief Add transformation description.

View File

@ -19,7 +19,7 @@ const std::vector<std::map<std::string, std::string>> configs = {
{} {}
}; };
INSTANTIATE_TEST_CASE_P(PreprocessingPrecisionConvertTestsViaSetInput, PreprocessingPrecisionConvertTest, INSTANTIATE_TEST_CASE_P(smoke_PreprocessingPrecisionConvertTestsViaSetInput, PreprocessingPrecisionConvertTest,
::testing::Combine( ::testing::Combine(
::testing::ValuesIn(inputPrecisions), ::testing::ValuesIn(inputPrecisions),
::testing::Values(4), // Number of input tensor channels ::testing::Values(4), // Number of input tensor channels
@ -28,7 +28,7 @@ INSTANTIATE_TEST_CASE_P(PreprocessingPrecisionConvertTestsViaSetInput, Preproces
::testing::ValuesIn(configs)), ::testing::ValuesIn(configs)),
PreprocessingPrecisionConvertTest::getTestCaseName); PreprocessingPrecisionConvertTest::getTestCaseName);
INSTANTIATE_TEST_CASE_P(PreprocessingPrecisionConvertTestsViaGetBlob, PreprocessingPrecisionConvertTest, INSTANTIATE_TEST_CASE_P(smoke_PreprocessingPrecisionConvertTestsViaGetBlob, PreprocessingPrecisionConvertTest,
::testing::Combine( ::testing::Combine(
::testing::ValuesIn(inputPrecisions), ::testing::ValuesIn(inputPrecisions),
::testing::Values(4), // Number of input tensor channels (blob_copy only supports 4d and 5d tensors) ::testing::Values(4), // Number of input tensor channels (blob_copy only supports 4d and 5d tensors)

View File

@ -19,6 +19,15 @@ const std::vector<std::map<std::string, std::string>> configs = {
{} {}
}; };
const std::vector<std::map<std::string, std::string>> multiConfigs = {
{{ InferenceEngine::MultiDeviceConfigParams::KEY_MULTI_DEVICE_PRIORITIES,
CommonTestUtils::DEVICE_TEMPLATE }}
};
const std::vector<std::map<std::string, std::string>> heteroConfigs = {
{{ "TARGET_FALLBACK", CommonTestUtils::DEVICE_TEMPLATE }}
};
INSTANTIATE_TEST_CASE_P(smoke_BehaviorTests, PreprocessTest, INSTANTIATE_TEST_CASE_P(smoke_BehaviorTests, PreprocessTest,
::testing::Combine( ::testing::Combine(
::testing::ValuesIn(netPrecisions), ::testing::ValuesIn(netPrecisions),
@ -26,6 +35,20 @@ INSTANTIATE_TEST_CASE_P(smoke_BehaviorTests, PreprocessTest,
::testing::ValuesIn(configs)), ::testing::ValuesIn(configs)),
PreprocessTest::getTestCaseName); PreprocessTest::getTestCaseName);
INSTANTIATE_TEST_CASE_P(smoke_Multi_BehaviorTests, PreprocessTest,
::testing::Combine(
::testing::ValuesIn(netPrecisions),
::testing::Values(CommonTestUtils::DEVICE_MULTI),
::testing::ValuesIn(multiConfigs)),
PreprocessTest::getTestCaseName);
INSTANTIATE_TEST_CASE_P(smoke_Hetero_BehaviorTests, PreprocessTest,
::testing::Combine(
::testing::ValuesIn(netPrecisions),
::testing::Values(CommonTestUtils::DEVICE_HETERO),
::testing::ValuesIn(heteroConfigs)),
PreprocessTest::getTestCaseName);
const std::vector<InferenceEngine::Precision> ioPrecisions = { const std::vector<InferenceEngine::Precision> ioPrecisions = {
InferenceEngine::Precision::FP32, InferenceEngine::Precision::FP32,
InferenceEngine::Precision::U8 InferenceEngine::Precision::U8

View File

@ -12,10 +12,10 @@ std::vector<std::string> disabledTestPatterns() {
".*ExclusiveAsyncRequests.*", ".*ExclusiveAsyncRequests.*",
".*reusableCPUStreamsExecutor.*", ".*reusableCPUStreamsExecutor.*",
R"(.*SplitLayerTest.*numSplits\=30.*)", R"(.*SplitLayerTest.*numSplits\=30.*)",
// CVS-44774
".*PreprocessTest.*",
// CVS-51758 // CVS-51758
".*PreprocessConversionTest.*oPRC=U8.*", ".*PreprocessConversionTest.*oPRC=U8.*",
".*PreprocessConversionTest.*oLT=NHWC.*" ".*PreprocessConversionTest.*oLT=NHWC.*",
".*PreprocessingPrecisionConvertTestsViaSetInput.*SetInput.*",
".*PreprocessingPrecisionConvertTestsViaGetBlob.*GetBlob.*",
}; };
} }

View File

@ -0,0 +1,183 @@
// // Copyright (C) 2021 Intel Corporation
// // SPDX-License-Identifier: Apache-2.0
// //
// #include <gtest/gtest.h>
// #include <string>
// #include <memory>
// #include <map>
// #include <ngraph/function.hpp>
// #include <ngraph/opsets/opset5.hpp>
// #include <ngraph/pass/manager.hpp>
// #include <transformations/init_node_info.hpp>
// #include <transformations/preprocessing/std_scale.hpp>
// #include <transformations/preprocessing/mean_image_or_value.hpp>
// #include "common_test_utils/ngraph_test_utils.hpp"
// using namespace testing;
// using namespace ngraph;
// TEST(TransformationTests, Preprocessing_AddStdScale) {
// std::shared_ptr<Function> f(nullptr), f_ref(nullptr);
// const Shape data_shape{1, 3, 14, 14};
// const Shape scale_shape{3, 1, 1};
// {
// auto data = std::make_shared<opset5::Parameter>(element::f32, data_shape);
// auto relu = std::make_shared<opset5::Relu>(data);
// f = std::make_shared<Function>(NodeVector{relu}, ParameterVector{data});
// auto scales = opset5::Constant::create(element::f32, scale_shape,
// std::vector<float>(shape_size(scale_shape), 2.0f));
// pass::Manager m;
// m.register_pass<pass::InitNodeInfo>();
// m.register_pass<pass::AddStdScale>(pass::AddStdScale::ScaleMap{ { data->get_friendly_name(), scales } });
// m.run_passes(f);
// }
// {
// auto data = std::make_shared<opset5::Parameter>(element::f32, data_shape);
// auto scales = opset5::Constant::create(element::f32, scale_shape,
// std::vector<float>(shape_size(scale_shape), 2.0f));
// auto mul = std::make_shared<opset5::Multiply>(data, scales);
// auto relu = std::make_shared<opset5::Relu>(mul);
// f_ref = std::make_shared<Function>(NodeVector{relu}, ParameterVector{data});
// }
// auto res = compare_functions(f, f_ref);
// ASSERT_TRUE(res.first) << res.second;
// }
// TEST(TransformationTests, Preprocessing_AddMeanValue) {
// std::shared_ptr<Function> f(nullptr), f_ref(nullptr);
// const Shape data_shape{1, 3, 14, 14};
// const Shape mean_shape{3, 1, 1};
// {
// auto data = std::make_shared<opset5::Parameter>(element::f32, data_shape);
// auto relu = std::make_shared<opset5::Relu>(data);
// f = std::make_shared<Function>(NodeVector{relu}, ParameterVector{data});
// auto meanValues = opset5::Constant::create(element::f32, mean_shape,
// std::vector<float>(shape_size(mean_shape), 2.0f));
// pass::Manager m;
// m.register_pass<pass::InitNodeInfo>();
// m.register_pass<pass::AddMeanSubtract>(pass::AddMeanSubtract::MeanMap{ { data->get_friendly_name(), meanValues } });
// m.run_passes(f);
// }
// {
// auto data = std::make_shared<opset5::Parameter>(element::f32, data_shape);
// auto meanValues = opset5::Constant::create(element::f32, mean_shape,
// std::vector<float>(shape_size(mean_shape), 2.0f));
// auto sub = std::make_shared<opset5::Subtract>(data, meanValues);
// auto relu = std::make_shared<opset5::Relu>(sub);
// f_ref = std::make_shared<Function>(NodeVector{relu}, ParameterVector{data});
// }
// auto res = compare_functions(f, f_ref);
// ASSERT_TRUE(res.first) << res.second;
// }
// TEST(TransformationTests, Preprocessing_AddMeanImage) {
// std::shared_ptr<Function> f(nullptr), f_ref(nullptr);
// const Shape data_shape{1, 3, 14, 14};
// const Shape mean_shape{3, 14, 14};
// {
// auto data = std::make_shared<opset5::Parameter>(element::f32, data_shape);
// auto relu = std::make_shared<opset5::Relu>(data);
// f = std::make_shared<Function>(NodeVector{relu}, ParameterVector{data});
// auto meanValues = opset5::Constant::create(element::f32, mean_shape,
// std::vector<float>(shape_size(mean_shape), 2.0f));
// pass::Manager m;
// m.register_pass<pass::InitNodeInfo>();
// m.register_pass<pass::AddMeanSubtract>(pass::AddMeanSubtract::MeanMap{ { data->get_friendly_name(), meanValues } });
// m.run_passes(f);
// }
// {
// auto data = std::make_shared<opset5::Parameter>(element::f32, data_shape);
// auto meanValues = opset5::Constant::create(element::f32, mean_shape,
// std::vector<float>(shape_size(mean_shape), 2.0f));
// auto sub = std::make_shared<opset5::Subtract>(data, meanValues);
// auto relu = std::make_shared<opset5::Relu>(sub);
// f_ref = std::make_shared<Function>(NodeVector{relu}, ParameterVector{data});
// }
// auto res = compare_functions(f, f_ref);
// ASSERT_TRUE(res.first) << res.second;
// }
// TEST(TransformationTests, Preprocessing_AddMeanImageAndScale) {
// std::shared_ptr<Function> f(nullptr), f_ref(nullptr);
// const Shape data_shape{1, 3, 14, 14};
// const Shape mean_shape{3, 14, 14};
// const Shape scale_shape{3, 1, 1};
// {
// auto data = std::make_shared<opset5::Parameter>(element::f32, data_shape);
// auto relu = std::make_shared<opset5::Relu>(data);
// f = std::make_shared<Function>(NodeVector{relu}, ParameterVector{data});
// auto meanValues = opset5::Constant::create(element::f32, mean_shape,
// std::vector<float>(shape_size(mean_shape), 2.0f));
// auto scaleValues = opset5::Constant::create(element::f32, scale_shape,
// std::vector<float>(shape_size(scale_shape), 2.0f));
// pass::Manager m;
// m.register_pass<pass::InitNodeInfo>();
// m.register_pass<pass::AddStdScale>(pass::AddStdScale::ScaleMap{ { data->get_friendly_name(), scaleValues } });
// m.register_pass<pass::AddMeanSubtract>(pass::AddMeanSubtract::MeanMap{ { data->get_friendly_name(), meanValues } });
// m.run_passes(f);
// }
// {
// auto data = std::make_shared<opset5::Parameter>(element::f32, data_shape);
// auto meanValues = opset5::Constant::create(element::f32, mean_shape,
// std::vector<float>(shape_size(mean_shape), 2.0f));
// auto scaleValues = opset5::Constant::create(element::f32, scale_shape,
// std::vector<float>(shape_size(scale_shape), 2.0f));
// auto sub = std::make_shared<opset5::Subtract>(data, meanValues);
// auto mul = std::make_shared<opset5::Multiply>(sub, scaleValues);
// auto relu = std::make_shared<opset5::Relu>(mul);
// f_ref = std::make_shared<Function>(NodeVector{relu}, ParameterVector{data});
// }
// auto res = compare_functions(f, f_ref);
// ASSERT_TRUE(res.first) << res.second;
// }
// TEST(TransformationTests, Preprocessing_AddMeanValueAndScale) {
// std::shared_ptr<Function> f(nullptr), f_ref(nullptr);
// const Shape data_shape{1, 3, 14, 14};
// const Shape mean_shape{3, 1, 1};
// const Shape scale_shape{3, 1, 1};
// {
// auto data = std::make_shared<opset5::Parameter>(element::f32, data_shape);
// auto relu = std::make_shared<opset5::Relu>(data);
// f = std::make_shared<Function>(NodeVector{relu}, ParameterVector{data});
// auto meanValues = opset5::Constant::create(element::f32, mean_shape,
// std::vector<float>(shape_size(mean_shape), 2.0f));
// auto scaleValues = opset5::Constant::create(element::f32, scale_shape,
// std::vector<float>(shape_size(scale_shape), 2.0f));
// pass::Manager m;
// m.register_pass<pass::InitNodeInfo>();
// m.register_pass<pass::AddStdScale>(pass::AddStdScale::ScaleMap{ { data->get_friendly_name(), scaleValues } });
// m.register_pass<pass::AddMeanSubtract>(pass::AddMeanSubtract::MeanMap{ { data->get_friendly_name(), meanValues } });
// m.run_passes(f);
// }
// {
// auto data = std::make_shared<opset5::Parameter>(element::f32, data_shape);
// auto meanValues = opset5::Constant::create(element::f32, mean_shape,
// std::vector<float>(shape_size(mean_shape), 2.0f));
// auto scaleValues = opset5::Constant::create(element::f32, scale_shape,
// std::vector<float>(shape_size(scale_shape), 2.0f));
// auto sub = std::make_shared<opset5::Subtract>(data, meanValues);
// auto mul = std::make_shared<opset5::Multiply>(sub, meanValues);
// auto relu = std::make_shared<opset5::Relu>(mul);
// f_ref = std::make_shared<Function>(NodeVector{relu}, ParameterVector{data});
// }
// auto res = compare_functions(f, f_ref);
// ASSERT_TRUE(res.first) << res.second;
// }

View File

@ -29,6 +29,9 @@ namespace InferenceEngine {
* @defgroup ie_dev_api_plugin_api Plugin base classes * @defgroup ie_dev_api_plugin_api Plugin base classes
* @brief A set of base and helper classes to implement a plugin class * @brief A set of base and helper classes to implement a plugin class
* *
* @defgroup ie_dev_api_preproc_api Preprocessing API
* @brief A set transformations to convert InferenceEngine::PreProcessInfo to ngraph operations
*
* @defgroup ie_dev_api_exec_network_api Executable Network base classes * @defgroup ie_dev_api_exec_network_api Executable Network base classes
* @brief A set of base and helper classes to implement an executable network class * @brief A set of base and helper classes to implement an executable network class
* *

View File

@ -124,10 +124,11 @@ TEST_P(PreprocessTest, SetMeanImagePreProcessGetBlob) {
auto outMem = outBlob->cbuffer(); auto outMem = outBlob->cbuffer();
const auto* outData = outMem.as<const float*>(); const auto* outData = outMem.as<const float*>();
ASSERT_EQ(inBlob->size(), outBlob->size()); ASSERT_EQ(inBlob->size(), outBlob->size());
for (size_t i = 0; i < inBlob->size(); i++) for (size_t i = 0; i < inBlob->size(); i++) {
ASSERT_EQ(inData[i] + inData[i], outData[i]); ASSERT_EQ(inData[i] + inData[i], outData[i]);
} }
} }
}
TEST_P(PreprocessTest, SetMeanImagePreProcessSetBlob) { TEST_P(PreprocessTest, SetMeanImagePreProcessSetBlob) {
// Skip test according to plugin specific disabledTestPatterns() (if any) // Skip test according to plugin specific disabledTestPatterns() (if any)
@ -255,10 +256,11 @@ TEST_P(PreprocessTest, SetMeanValuePreProcessGetBlob) {
auto outMem = outBlob->cbuffer(); auto outMem = outBlob->cbuffer();
const auto* outData = outMem.as<const float*>(); const auto* outData = outMem.as<const float*>();
ASSERT_EQ(inBlob->size(), outBlob->size()); ASSERT_EQ(inBlob->size(), outBlob->size());
for (size_t i = 0; i < inBlob->size(); i++) for (size_t i = 0; i < inBlob->size(); i++) {
ASSERT_EQ(inData[i] + 5, outData[i]); ASSERT_EQ(inData[i] + 5, outData[i]);
} }
} }
}
TEST_P(PreprocessTest, SetMeanValuePreProcessSetBlob) { TEST_P(PreprocessTest, SetMeanValuePreProcessSetBlob) {
// Skip test according to plugin specific disabledTestPatterns() (if any) // Skip test according to plugin specific disabledTestPatterns() (if any)
@ -511,10 +513,11 @@ TEST_P(PreprocessTest, SetScalePreProcessGetBlob) {
auto outMem = outBlob->cbuffer(); auto outMem = outBlob->cbuffer();
const auto* outData = outMem.as<const float*>(); const auto* outData = outMem.as<const float*>();
ASSERT_EQ(inBlob->size(), outBlob->size()); ASSERT_EQ(inBlob->size(), outBlob->size());
for (size_t i = 0; i < inBlob->size(); i++) for (size_t i = 0; i < inBlob->size(); i++) {
ASSERT_EQ(inData[i]*2, outData[i]); ASSERT_EQ(inData[i]*2, outData[i]);
} }
} }
}
TEST_P(PreprocessTest, SetScalePreProcessSetBlob) { TEST_P(PreprocessTest, SetScalePreProcessSetBlob) {