[GNA] Precision convert support (#9282)

* Rebase master

* [gna] Fixed export/import precision

* Revert "[gna] Fixed export/import precision"

This reverts commit d381a2e216.

* Rebase master

* [gna] Fixed export/import precision

* Revert "[gna] Fixed export/import precision"

* Removed convert nodes

* Added convert transformations

* Output casting

* Fixed convert function

* Added functional tests

* Update inference-engine/tests/functional/plugin/gna/preprocess_tests/precision_convert.cpp

Co-authored-by: Nadezhda Ageeva <nkogteva@gmail.com>
This commit is contained in:
Mikhail RyzhovandNadezhda Ageeva authored and GitHub committed 2021-12-22 20:01:06 +03:00
1 parent 7e85ada7e4
commit 7e0bf0dad5
9 files changed
+772 -112

No files matched your search

@@ -2075,11 +2075,13 @@ void convertFunctionToICNNNetwork(const std::shared_ptr<const ::ngraph::Function
InputsDataMap resultInputDataMap;
cnnNetworkImpl->getInputsInfo(resultInputDataMap);
IE_ASSERT(resultInputDataMap.size() == thisInputDataMap.size());
for (auto i : resultInputDataMap) {
auto &thisInputData = *thisInputDataMap[i.first];
i.second->setPrecision(thisInputData.getPrecision());
i.second->setLayout(thisInputData.getLayout());
i.second->getPreProcess() = thisInputData.getPreProcess();
auto params = graph->get_parameters();
for ( const auto &param : params ) {
const std::string input_name = param->get_friendly_name();
auto &thisInputData = *thisInputDataMap[input_name];
resultInputDataMap[input_name]->setPrecision(thisInputData.getPrecision());
resultInputDataMap[input_name]->setLayout(thisInputData.getLayout());
resultInputDataMap[input_name]->getPreProcess() = thisInputData.getPreProcess();
}
}
@@ -344,6 +344,7 @@ bool ValidateConvConcatAxis(const InferenceEngine::ConcatLayer* concat_layer) {
}
bool AreLayersSupported(InferenceEngine::CNNNetwork& network, std::string& errMessage, bool userWarning) {
IE_SUPPRESS_DEPRECATED_START
InferenceEngine::InputsDataMap inputs = network.getInputsInfo();
std::unordered_set<InferenceEngine::CNNLayer *> allLayers;
InferenceEngine::CNNLayerPtr startLayer;
+76 -84
View File
@@ -70,10 +70,12 @@
#include "transformations/convert_dwsc_to_scaleshifts.hpp"
#include "transformations/op_conversions/lstm_cell_decomposition.hpp"
#include "transformations/remove_single_input_concat.hpp"
#include "transformations/remove_converts.hpp"
#include "transformations/broadcast_const.hpp"
#include "transformations/op_conversions/convert_mvn1_to_mvn6.hpp"
#include "transformations/decompose_mvn.hpp"
#include "transformations/substitute_softsign.hpp"
#include "transformations/convert_precision.hpp"
#include <ngraph/opsets/opset7.hpp>
@@ -270,20 +272,49 @@ void GNAPlugin::ExportScores(void *ptr_dst,
}
}
void GNAPlugin::ImportFrames(
void *ptr_dst,
const void *ptr_src,
Precision input_precision,
float scaleFactor,
intel_dnn_orientation_t orientation,
uint32_t num_frames,
uint32_t num_group,
uint32_t num_vector_elements,
uint32_t num_vector_stride) {
if (orientation == kDnnInterleavedOrientation) {
// TODO : fix that as well
if (input_precision == Precision::U8) {
auto src = reinterpret_cast<const uint8_t *>(ptr_src);
void GNAPlugin::ImportFrames(void *ptr_dst,
const void *ptr_src,
Precision input_precision,
float scaleFactor,
intel_dnn_orientation_t orientation,
uint32_t num_frames,
uint32_t num_group,
uint32_t num_vector_elements,
uint32_t num_vector_stride) {
switch (input_precision) {
case Precision::U8:
case Precision::I8:
{
auto src = reinterpret_cast<const uint8_t *>(ptr_src);
if (!gnaFlags->input_low_precision) {
auto dst = reinterpret_cast<int16_t*>(ptr_dst);
copyInputData(dst, src, num_frames, num_group, num_vector_elements, num_vector_stride, orientation, scaleFactor);
} else {
auto dst = reinterpret_cast<int8_t*>(ptr_dst);
copyInputData(dst, src, num_frames, num_group, num_vector_elements, num_vector_stride, orientation, scaleFactor);
}
break;
}
case Precision::I16:
{
auto src = reinterpret_cast<const int16_t *>(ptr_src);
if (!gnaFlags->input_low_precision) {
auto dst = reinterpret_cast<int16_t*>(ptr_dst);
copyInputData(dst, src, num_frames, num_group, num_vector_elements, num_vector_stride, orientation, scaleFactor);
} else {
auto dst = reinterpret_cast<int8_t*>(ptr_dst);
copyInputData(dst, src, num_frames, num_group, num_vector_elements, num_vector_stride, orientation, scaleFactor);
}
break;
}
case Precision::FP32:
case Precision::I32:
{
auto src = reinterpret_cast<const float *>(ptr_src);
if (!gnadevice) {
auto dst = reinterpret_cast<float *>(ptr_dst);
copyInputData(dst, src, num_frames, num_group, num_vector_elements, num_vector_stride, orientation, scaleFactor);
} else {
if (!gnaFlags->input_low_precision) {
auto dst = reinterpret_cast<int16_t*>(ptr_dst);
copyInputData(dst, src, num_frames, num_group, num_vector_elements, num_vector_stride, orientation, scaleFactor);
@@ -291,69 +322,11 @@ void GNAPlugin::ImportFrames(
auto dst = reinterpret_cast<int8_t*>(ptr_dst);
copyInputData(dst, src, num_frames, num_group, num_vector_elements, num_vector_stride, orientation, scaleFactor);
}
} else if (input_precision.size() == 2) {
auto src = reinterpret_cast<const int16_t *>(ptr_src);
if (!gnaFlags->input_low_precision) {
auto dst = reinterpret_cast<int16_t*>(ptr_dst);
copyInputData(dst, src, num_frames, num_group, num_vector_elements, num_vector_stride, orientation, scaleFactor);
} else {
auto dst = reinterpret_cast<int8_t*>(ptr_dst);
copyInputData(dst, src, num_frames, num_group, num_vector_elements, num_vector_stride, orientation, scaleFactor);
}
} else if (input_precision.size() == 4) {
if (!gnadevice) {
auto dst = reinterpret_cast<float *>(ptr_dst);
auto src = reinterpret_cast<const float *>(ptr_src);
copyInputData(dst, src, num_frames, num_group, num_vector_elements, num_vector_stride, orientation, scaleFactor);
} else {
auto src = reinterpret_cast<const float *>(ptr_src);
if (!gnaFlags->input_low_precision) {
auto dst = reinterpret_cast<int16_t*>(ptr_dst);
copyInputData(dst, src, num_frames, num_group, num_vector_elements, num_vector_stride, orientation, scaleFactor);
} else {
auto dst = reinterpret_cast<int8_t*>(ptr_dst);
copyInputData(dst, src, num_frames, num_group, num_vector_elements, num_vector_stride, orientation, scaleFactor);
}
}
}
} else {
if (input_precision == Precision::U8) {
auto src = reinterpret_cast<const uint8_t *>(ptr_src);
if (!gnadevice) {
auto dst = reinterpret_cast<float *>(ptr_dst);
copyInputData(dst, src, num_frames, num_group, num_vector_elements, num_vector_stride, orientation, scaleFactor);
} else if (!gnaFlags->input_low_precision) {
auto dst = reinterpret_cast<int16_t*>(ptr_dst);
copyInputData(dst, src, num_frames, num_group, num_vector_elements, num_vector_stride, orientation, scaleFactor);
} else {
auto dst = reinterpret_cast<int8_t*>(ptr_dst);
copyInputData(dst, src, num_frames, num_group, num_vector_elements, num_vector_stride, orientation, scaleFactor);
}
} else if (input_precision.size()== 2) {
auto src = reinterpret_cast<const int16_t *>(ptr_src);
if (!gnaFlags->input_low_precision) {
auto dst = reinterpret_cast<int16_t*>(ptr_dst);
copyInputData(dst, src, num_frames, num_group, num_vector_elements, num_vector_stride, orientation, scaleFactor);
} else {
auto dst = reinterpret_cast<int8_t*>(ptr_dst);
copyInputData(dst, src, num_frames, num_group, num_vector_elements, num_vector_stride, orientation, scaleFactor);
}
} else if (input_precision.size() == 4) {
if (!gnadevice) {
auto dst = reinterpret_cast<float *>(ptr_dst);
auto src = reinterpret_cast<const float *>(ptr_src);
copyInputData(dst, src, num_frames, num_group, num_vector_elements, num_vector_stride, orientation, scaleFactor);
} else {
auto src = reinterpret_cast<const float *>(ptr_src);
if (!gnaFlags->input_low_precision) {
auto dst = reinterpret_cast<int16_t*>(ptr_dst);
copyInputData(dst, src, num_frames, num_group, num_vector_elements, num_vector_stride, orientation, scaleFactor);
} else {
auto dst = reinterpret_cast<int8_t*>(ptr_dst);
copyInputData(dst, src, num_frames, num_group, num_vector_elements, num_vector_stride, orientation, scaleFactor);
}
}
}
break;
}
default:
break;
}
}
@@ -690,15 +663,21 @@ void GNAPlugin::LoadNetwork(CNNNetwork & _network) {
bool isNgraphPassesUsed = false;
bool fake_quantized = false;
if (_network.getFunction()) {
CNNNetwork clonedNetwork = InferenceEngine::cloneNetwork(_network);
const auto& graph = clonedNetwork.getFunction();
ngraph::pass::Manager manager;
manager.register_pass<ngraph::pass::InitNodeInfo>();
fake_quantized = ngraph::op::util::has_op_with_type<ngraph::opset7::FakeQuantize>(graph);
// In OV API 2.0(IRv10) default convertion to fp32 (inputs, outputs and weights) is disabled
// and we need to run the ConvertPrecision transformation to support old networks.
manager.register_pass<ngraph::pass::ConvertPrecision>(precisions_array{{ngraph::element::f16, ngraph::element::f32}});
manager.register_pass<ngraph::pass::ConvertMVN1ToMVN6>();
manager.register_pass<DecomposeMVN>();
manager.register_pass<ngraph::pass::CommonOptimizations>();
manager.register_pass<RemoveInputConvert>();
manager.register_pass<RemoveOutputConvert>();
manager.register_pass<ngraph::pass::LSTMCellDecomposition>();
manager.register_pass<ConvertDWSCToScaleShifts>();
manager.register_pass<ConvertPaddedToValidConv>();
@@ -754,7 +733,6 @@ void GNAPlugin::LoadNetwork(CNNNetwork & _network) {
pass_config->disable<ngraph::pass::TransposeReduction>();
manager.run_passes(graph);
convertedNetwork = InferenceEngine::details::convertFunctionToICNNNetwork(graph, clonedNetwork);
isNgraphPassesUsed = true;
}
IE_SUPPRESS_DEPRECATED_START
@@ -765,7 +743,8 @@ void GNAPlugin::LoadNetwork(CNNNetwork & _network) {
NetPass::ConvertPrecision(network, Precision::U64, Precision::I32);
NetPass::ConvertPrecision(network, Precision::U32, Precision::I32);
// Check the input network
// Check the network
std::string error;
if (!GNAPluginNS::GNALimitations::AreLayersSupported(network, error, gnaFlags->log_level == PluginConfigParams::LOG_WARNING)) {
THROW_GNA_EXCEPTION << error.c_str();
@@ -1293,7 +1272,7 @@ uint32_t GNAPlugin::QueueInference(const InferenceEngine::BlobMap &inputs, Infer
ImportFrames(inputs_ptr_->at(input.first).ptrs[idx],
input.second->cbuffer().as<float *>(),
input.second->getTensorDesc().getPrecision(),
gnaFlags->sw_fp32 ? 1.0f : inputs_ptr_->at(input.first).scale_factor,
gnaFlags->sw_fp32 ? GNAPluginNS::kScaleFactorDefault : inputs_ptr_->at(input.first).scale_factor,
inputOrientation,
importedFrames,
targetGroups,
@@ -1455,11 +1434,24 @@ GnaWaitStatus GNAPlugin::WaitFor(uint32_t request_idx, int64_t millisTimeout) {
fprintf(f, "\n\n");
}
#endif
ConvertToFloat(outputBlob->buffer(),
outputBlob->buffer(),
elementsPerBatch,
batchSize,
outputDesc.scale_factor);
switch (outputBlob->getTensorDesc().getPrecision()) {
case InferenceEngine::Precision::FP32 :
UnscaleAndCast(outputBlob->buffer().as<float*>(),
outputBlob->buffer().as<int32_t*>(),
elementsPerBatch, batchSize, outputDesc.scale_factor);
break;
case InferenceEngine::Precision::I32 :
UnscaleAndCast(outputBlob->buffer().as<int32_t*>(),
outputBlob->buffer().as<int32_t*>(),
elementsPerBatch, batchSize, outputDesc.scale_factor);
break;
default:
THROW_GNA_EXCEPTION << "Unsupported target precision: " << outputBlob->getTensorDesc().getPrecision() << std::endl;
break;
}
#ifdef PLOT
if (f) {
if (isScalar) {
-17
View File
@@ -38,20 +38,3 @@ void GNAPluginNS::ConvertToInt16(int16_t *ptr_dst,
ptr_dst[i] = GNAPluginNS::ConvertFloatToInt16(ptr_src[i]*scale_factor);
}
}
void GNAPluginNS::ConvertToFloat(float *ptr_dst,
int32_t *ptr_src,
const uint32_t num_rows,
const uint32_t num_columns,
const float scale_factor) {
if (!ptr_dst || !ptr_src) {
return;
}
for (uint32_t i = 0; i < num_rows; i++) {
int32_t *ptr_int_row = ptr_src + i * num_columns;
float *ptr_float_row = ptr_dst + i * num_columns;
for (uint32_t j = 0; j < num_columns; j++) {
ptr_float_row[j] = static_cast<float>(ptr_int_row[j]) / scale_factor;
}
}
}
+16 -6
View File
@@ -14,12 +14,22 @@ void ConvertToInt16(int16_t *ptr_dst,
const uint32_t num_columns,
const float scale_factor);
void ConvertToFloat(float *ptr_dst,
int32_t *ptr_src,
const uint32_t num_rows,
const uint32_t num_columns,
const float scale_factor);
int16_t ConvertFloatToInt16(float src);
int8_t ConvertFloatToInt8(float src);
template<typename T1, typename T2>
inline void UnscaleAndCast(T2 *ptr_dst, T1 *ptr_src, const uint32_t num_rows, const uint32_t num_columns,
const float scale_factor) {
if (!ptr_dst || !ptr_src) {
return;
}
for (uint32_t i = 0; i < num_rows; i++) {
T1 *ptr_int_row = ptr_src + i * num_columns;
T2 *ptr_float_row = ptr_dst + i * num_columns;
for (uint32_t j = 0; j < num_columns; j++) {
ptr_float_row[j] = static_cast<T2>(ptr_int_row[j]) / scale_factor;
}
}
}
} // namespace GNAPluginNS
@@ -0,0 +1,84 @@
// Copyright (C) 2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include <openvino/cc/ngraph/itt.hpp>
#include "transformations/remove_converts.hpp"
#include <memory>
#include <vector>
#include <ngraph/opsets/opset4.hpp>
#include <ngraph/opsets/opset8.hpp>
#include <ngraph/pattern/op/wrap_type.hpp>
#include <ngraph/pass/manager.hpp>
namespace GNAPluginNS {
NGRAPH_RTTI_DEFINITION(RemoveInputConvert, "RemoveInputConvert", 0);
RemoveInputConvert::RemoveInputConvert() {
MATCHER_SCOPE(RemoveInputConvert);
const auto input = ngraph::pattern::wrap_type<ngraph::opset8::Parameter>(ngraph::pattern::type_matches_any(kSupportedInputTypesFrom));
const auto convert = ngraph::pattern::wrap_type<ngraph::opset8::Convert>({input},
ngraph::pattern::type_matches_any(kSupportedInputTypesTo));
ngraph::matcher_pass_callback callback = [=](ngraph::pattern::Matcher& m) {
const auto& pattern_map = m.get_pattern_value_map();
auto convert_node = pattern_map.at(convert).get_node_shared_ptr();
auto input_node = pattern_map.at(input).get_node_shared_ptr();
// check the supported combinations
auto from_type = input_node->get_element_type();
auto to_type = convert_node->get_element_type();
if (std::count(kSupportedInputConverts.begin(), kSupportedInputConverts.end(), std::make_pair(from_type, to_type)) == 0)
return false;
// replace input precision with convert's one
if (auto param = ov::as_type_ptr<ngraph::opset8::Parameter>(input_node)) {
param->set_element_type(to_type);
}
ngraph::replace_output_update_name(convert_node->output(0), convert_node->input_value(0));
return true;
};
auto m = std::make_shared<ngraph::pattern::Matcher>(convert, matcher_name);
this->register_matcher(m, callback);
}
NGRAPH_RTTI_DEFINITION(RemoveOutputConvert, "RemoveOutputConvert", 0);
RemoveOutputConvert::RemoveOutputConvert() {
MATCHER_SCOPE(RemoveOutputConvert);
auto output = ngraph::pattern::any_input(ngraph::pattern::type_matches_any(kSupportedOutputTypesFrom));
const auto convert = ngraph::pattern::wrap_type<ngraph::opset8::Convert>({output},
ngraph::pattern::type_matches_any(kSupportedOutputTypesTo));
const auto result = ngraph::pattern::wrap_type<ngraph::opset8::Result>({convert},
ngraph::pattern::type_matches_any(kSupportedOutputTypesTo));
ngraph::matcher_pass_callback callback = [=](ngraph::pattern::Matcher& m) {
const auto& pattern_map = m.get_pattern_value_map();
auto output_node = pattern_map.at(output).get_node_shared_ptr();
auto convert_node = pattern_map.at(convert).get_node_shared_ptr();
// check the supported combinations
auto from_type = output_node->get_element_type();
auto to_type = convert_node->get_element_type();
if (std::count(kSupportedOutputConverts.begin(), kSupportedOutputConverts.end(), std::make_pair(from_type, to_type)) == 0) {
return false;
}
// the result presicion will be changed automaically
ngraph::replace_output_update_name(convert_node->output(0), convert_node->input_value(0));
return true;
};
auto m = std::make_shared<ngraph::pattern::Matcher>(result, matcher_name);
this->register_matcher(m, callback);
}
} // namespace GNAPluginNS
@@ -0,0 +1,98 @@
// Copyright (C) 2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#pragma once
#include <ngraph/pass/graph_rewrite.hpp>
namespace GNAPluginNS {
/**
* @brief remove convert layers after inputs and changing it's precision
* to support preprocessing conversions from user's precision to network presicion
*
* Searches for next pattern
* Any input layer
* |
* Convert
* |
* Any layer
*
* And transforms to
* Any input layer
* |
* Any layer
*/
const std::vector<ov::element::Type> kSupportedInputTypesFrom = {
ov::element::u8,
ov::element::i16,
ov::element::f32
};
const std::vector<ov::element::Type> kSupportedInputTypesTo = {
ov::element::u8,
ov::element::i8,
ov::element::i16,
ov::element::i32,
ov::element::f32
};
const std::vector<std::pair<ov::element::Type, ov::element::Type>> kSupportedInputConverts {
// FROM -> TO
{ov::element::u8, ov::element::u8},
{ov::element::u8, ov::element::i8},
{ov::element::u8, ov::element::i16},
{ov::element::i16, ov::element::i8},
{ov::element::i16, ov::element::i16},
{ov::element::f32, ov::element::i8},
{ov::element::f32, ov::element::i16},
{ov::element::f32, ov::element::i32},
{ov::element::f32, ov::element::f32}
};
class RemoveInputConvert : public ngraph::pass::MatcherPass {
public:
NGRAPH_RTTI_DECLARATION;
RemoveInputConvert();
};
/**
* @brief remove convert layers after before outputs changing it's precision
* to support postprocessing conversions from network to user's precision
*
* Searches for next pattern
* Any layer
* |
* Convert
* |
* Any output layer
*
* And transforms to
* Any layer
* |
* Any output layer
*/
const std::vector<ov::element::Type> kSupportedOutputTypesFrom = {
ov::element::f32
};
const std::vector<ov::element::Type> kSupportedOutputTypesTo = {
ov::element::i32,
ov::element::f32
};
const std::vector<std::pair<ov::element::Type, ov::element::Type>> kSupportedOutputConverts {
// FROM -> TO
{ov::element::f32, ov::element::f32},
{ov::element::f32, ov::element::i32}
};
class RemoveOutputConvert : public ngraph::pass::MatcherPass {
public:
NGRAPH_RTTI_DECLARATION;
RemoveOutputConvert();
};
} // namespace GNAPluginNS
@@ -0,0 +1,164 @@
// Copyright (C) 2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include "shared_test_classes/base/ov_subgraph.hpp"
#include "ngraph_functions/utils/ngraph_helpers.hpp"
#include "ngraph_functions/builders.hpp"
#include "common_test_utils/common_utils.hpp"
using namespace InferenceEngine;
using namespace ov::test;
namespace LayerTestsDefinitions {
typedef std::tuple<
ov::element::Type, // Net precision
ov::element::Type, // Input precision
ov::element::Type, // Output precision
std::string, // Device name
std::map<std::string, std::string> // Configuration
> preprocessTestParamsSet;
class PreprocessGNATest : public testing::WithParamInterface<preprocessTestParamsSet>,
virtual public SubgraphBaseTest {
public:
static std::string getTestCaseName(const testing::TestParamInfo<preprocessTestParamsSet>& obj) {
ov::element::Type net_type, in_type, out_type;
std::string target_device;
std::map<std::string, std::string> conf;
std::tie(net_type, in_type, out_type, target_device, conf) = obj.param;
std::ostringstream result;
result << "netPRC=" << net_type << "_";
result << "inPRC=" << in_type << "_";
result << "outPRC=" << out_type << "_";
result << "trgDev=" << target_device;
for (auto const &conf_i : conf) {
result << "_configItem=" << conf_i.first.c_str() << "_" << conf_i.second.c_str();
}
return result.str();
}
protected:
void SetUp() override {
ov::element::Type net_type;
std::vector<InputShape> input_shapes = static_shapes_to_test_representation({{8, 2}, {8, 2}});
std::map<std::string, std::string> conf;
abs_threshold = std::numeric_limits<int32_t>::max();
rel_threshold = std::numeric_limits<int32_t>::max();
std::tie(net_type, inType, outType, targetDevice, conf) = this->GetParam();
configuration.insert(conf.begin(), conf.end());
init_input_shapes({input_shapes});
auto params = ngraph::builder::makeDynamicParams(net_type, inputDynamicShapes);
auto paramOuts = ngraph::helpers::convert2OutputVector(
ngraph::helpers::castOps2Nodes<ngraph::op::Parameter>(params));
auto concat = std::make_shared<ngraph::opset8::Concat>(paramOuts, 1);
ngraph::ResultVector results{std::make_shared<ngraph::opset8::Result>(concat)};
function = std::make_shared<ngraph::Function>(results, params, "concat");
}
};
class PreprocessGNAUnsupportedTest : public PreprocessGNATest {
public:
PreprocessGNAUnsupportedTest(std::string error_str) : exp_error_str_(error_str) {}
void run() override {
try {
PreprocessGNATest::compile_model();
FAIL() << "GNA's unsupported layers were not detected during LoadNetwork()";
}
catch (std::runtime_error& e) {
const std::string errorMsg = e.what();
const auto expectedMsg = exp_error_str_;
ASSERT_STR_CONTAINS(errorMsg, expectedMsg);
EXPECT_TRUE(errorMsg.find(expectedMsg) != std::string::npos)
<< "Wrong error message, actual error message: " << errorMsg
<< ", expected: " << expectedMsg;
}
}
private:
std::string exp_error_str_;
};
class PreprocessGNAUnsupportedInputsTest : public PreprocessGNAUnsupportedTest {
public:
PreprocessGNAUnsupportedInputsTest() : PreprocessGNAUnsupportedTest("The plugin does not support input precision") {}
};
class PreprocessGNAUnsupportedOutputsTest : public PreprocessGNAUnsupportedTest {
public:
PreprocessGNAUnsupportedOutputsTest() : PreprocessGNAUnsupportedTest("The plugin does not support layer") {}
};
TEST_P(PreprocessGNATest, CompareWithRefs) {
run();
}
TEST_P(PreprocessGNAUnsupportedInputsTest, CompareWithRefs) {
run();
}
TEST_P(PreprocessGNAUnsupportedOutputsTest, CompareWithRefs) {
run();
}
std::map<std::string, std::string> config = {
{
{"GNA_DEVICE_MODE", "GNA_SW_EXACT"},
{"GNA_SCALE_FACTOR_0", "1"},
{"GNA_SCALE_FACTOR_1", "1"}
}
};
ov::element::TypeVector inputTypesUnsupported = {
ov::element::i32
};
ov::element::TypeVector outputTypesUnsupported = {
ov::element::u8,
ov::element::i16,
};
ov::element::TypeVector outputTypesSupported = {
ov::element::i32,
ov::element::f32
};
ov::element::TypeVector netTypes = {
ov::element::f16,
ov::element::f32
};
INSTANTIATE_TEST_SUITE_P(smoke_Preprocess, PreprocessGNATest,
::testing::Combine(
::testing::ValuesIn(netTypes),
::testing::Values(ov::element::f32),
::testing::ValuesIn(outputTypesSupported),
::testing::Values(CommonTestUtils::DEVICE_GNA),
::testing::Values(config)),
PreprocessGNATest::getTestCaseName);
INSTANTIATE_TEST_SUITE_P(smoke_Preprocess, PreprocessGNAUnsupportedInputsTest,
::testing::Combine(
::testing::ValuesIn(netTypes),
::testing::ValuesIn(inputTypesUnsupported),
::testing::Values(ov::element::f32),
::testing::Values(CommonTestUtils::DEVICE_GNA),
::testing::Values(config)),
PreprocessGNATest::getTestCaseName);
INSTANTIATE_TEST_SUITE_P(smoke_Preprocess, PreprocessGNAUnsupportedOutputsTest,
::testing::Combine(
::testing::ValuesIn(netTypes),
::testing::Values(ov::element::f32),
::testing::ValuesIn(outputTypesUnsupported),
::testing::Values(CommonTestUtils::DEVICE_GNA),
::testing::Values(config)),
PreprocessGNATest::getTestCaseName);
} // namespace LayerTestsDefinitions
@@ -0,0 +1,326 @@
// Copyright (C) 2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include <gtest/gtest.h>
#include <ngraph/function.hpp>
#include <ngraph/opsets/opset8.hpp>
#include <ngraph/pass/manager.hpp>
#include "ngraph_functions/builders.hpp"
#include <transformations/init_node_info.hpp>
#include "transformations/remove_converts.hpp"
#include "common_test_utils/ngraph_test_utils.hpp"
namespace testing {
typedef std::tuple<
ov::element::Type, // Net precision
ov::element::Type // Convert precision
> removeConvertTestParams;
class RemoveInputConvertTest: public CommonTestUtils::TestsCommon,
public ::testing::WithParamInterface<removeConvertTestParams> {
public:
static std::string getTestCaseName(const testing::TestParamInfo<removeConvertTestParams>& obj) {
ov::element::Type net_precision, target_precision;
std::tie(net_precision, target_precision) = obj.param;
std::ostringstream result;
result << "netPRC=" << net_precision << "_";
result << "trgPRC=" << target_precision << "_";
return result.str();
}
void SetUp() override;
virtual void Validate();
virtual void Run();
public:
std::shared_ptr<ngraph::Function> func_, ref_func_no_convert_, ref_func_convert_;
ov::element::Type net_precision_, target_precision_;
};
void RemoveInputConvertTest::Run() {
SetUp();
Validate();
}
void RemoveInputConvertTest::SetUp() {
const ngraph::Shape input_shape{10};
std::tie(net_precision_, target_precision_) = this->GetParam();
// test function
{
auto params = std::make_shared<ngraph::opset8::Parameter>(target_precision_, input_shape);
auto conversion = ngraph::builder::makeConversion(params, net_precision_, ngraph::helpers::ConversionTypes::CONVERT);
auto add_const = ngraph::opset8::Constant::create(net_precision_, input_shape, {10});
auto add = std::make_shared<ngraph::opset8::Add>(conversion, add_const);
auto result = std::make_shared<ngraph::opset8::Result>(add);
func_ = std::make_shared<ngraph::Function>(ngraph::ResultVector{result},
ngraph::ParameterVector{params},
"Conversion");
}
// ref function convert should be removed
{
auto params = std::make_shared<ngraph::opset8::Parameter>(net_precision_, input_shape);
auto add_const = ngraph::opset8::Constant::create(net_precision_, input_shape, {10});
auto add = std::make_shared<ngraph::opset8::Add>(params, add_const);
auto result = std::make_shared<ngraph::opset8::Result>(add);
ref_func_no_convert_ = std::make_shared<ngraph::Function>(ngraph::ResultVector{result},
ngraph::ParameterVector{params},
"Conversion");
}
// ref function convert should not be removed
ref_func_convert_ = ngraph::clone_function(*func_);
}
void RemoveInputConvertTest::Validate() {
ngraph::pass::Manager m;
m.register_pass<ngraph::pass::InitNodeInfo>();
m.register_pass<GNAPluginNS::RemoveInputConvert>();
m.run_passes(func_);
ASSERT_NO_THROW(check_rt_info(func_));
const FunctionsComparator func_comparator = FunctionsComparator::with_default().enable(FunctionsComparator::ATTRIBUTES);
FunctionsComparator::Result result;
if (std::count(GNAPluginNS::kSupportedInputConverts.begin(),
GNAPluginNS::kSupportedInputConverts.end(),
std::make_pair(target_precision_, net_precision_)) == 0) {
result = func_comparator(func_, ref_func_convert_);
} else {
result = func_comparator(func_, ref_func_no_convert_);
}
ASSERT_TRUE(result.valid);
}
class RemoveOutputConvertTest: public RemoveInputConvertTest {
public:
void SetUp() override {
const ngraph::Shape input_shape{10};
std::tie(net_precision_, target_precision_) = this->GetParam();
// test function
{
auto params = std::make_shared<ngraph::opset8::Parameter>(net_precision_, input_shape);
auto add_const = ngraph::opset8::Constant::create(net_precision_, input_shape, {10});
auto add = std::make_shared<ngraph::opset8::Add>(params, add_const);
auto conversion = ngraph::builder::makeConversion(add, target_precision_, ngraph::helpers::ConversionTypes::CONVERT);
auto result = std::make_shared<ngraph::opset8::Result>(conversion);
func_ = std::make_shared<ngraph::Function>(ngraph::ResultVector{result}, ngraph::ParameterVector{params},
"Conversion");
}
// ref function
{
auto params = std::make_shared<ngraph::opset8::Parameter>(net_precision_, input_shape);
auto add_const = ngraph::opset8::Constant::create(net_precision_, input_shape, {10});
auto add = std::make_shared<ngraph::opset8::Add>(params, add_const);
auto result = std::make_shared<ngraph::opset8::Result>(add);
ref_func_no_convert_ = std::make_shared<ngraph::Function>(ngraph::ResultVector{result}, ngraph::ParameterVector{params},
"Conversion");
}
// ref function convert should not be removed
ref_func_convert_ = ngraph::clone_function(*func_);
}
void Validate() override {
ngraph::pass::Manager m;
m.register_pass<ngraph::pass::InitNodeInfo>();
m.register_pass<GNAPluginNS::RemoveOutputConvert>();
m.run_passes(func_);
ASSERT_NO_THROW(check_rt_info(func_));
const FunctionsComparator func_comparator = FunctionsComparator::with_default().enable(FunctionsComparator::ATTRIBUTES);
FunctionsComparator::Result result;
if (std::count(GNAPluginNS::kSupportedOutputConverts.begin(),
GNAPluginNS::kSupportedOutputConverts.end(),
std::make_pair(net_precision_, target_precision_)) == 0) {
result = func_comparator(func_, ref_func_convert_);
} else {
result = func_comparator(func_, ref_func_no_convert_);
}
ASSERT_TRUE(result.valid);
}
};
class LeaveConvertTest: public RemoveInputConvertTest {
public:
void SetUp() override {
const ngraph::Shape input_shape{10};
std::tie(net_precision_, target_precision_) = this->GetParam();
// test function
{
auto params = std::make_shared<ngraph::opset8::Parameter>(net_precision_, input_shape);
auto add_const = ngraph::opset8::Constant::create(net_precision_, input_shape, {10});
auto add1 = std::make_shared<ngraph::opset8::Add>(params, add_const);
auto conversion = ngraph::builder::makeConversion(add1, net_precision_, ngraph::helpers::ConversionTypes::CONVERT);
auto add2 = std::make_shared<ngraph::opset8::Add>(conversion, add_const);
auto result = std::make_shared<ngraph::opset8::Result>(add2);
func_ = std::make_shared<ngraph::Function>(ngraph::ResultVector{result}, ngraph::ParameterVector{params}, "Conversion");
}
// ref function
ref_func_convert_ = ngraph::clone_function(*func_);
}
void Validate() override {
ngraph::pass::Manager m;
m.register_pass<ngraph::pass::InitNodeInfo>();
m.register_pass<GNAPluginNS::RemoveInputConvert>();
m.register_pass<GNAPluginNS::RemoveOutputConvert>();
m.run_passes(func_);
ASSERT_NO_THROW(check_rt_info(func_));
const FunctionsComparator func_comparator = FunctionsComparator::with_default().enable(FunctionsComparator::ATTRIBUTES);
const FunctionsComparator::Result result = func_comparator(func_, ref_func_convert_);
ASSERT_TRUE(result.valid);
}
};
class RemoveMultiInputsConvertTest: public RemoveInputConvertTest {
public:
void SetUp() override {
std::tie(net_precision_, target_precision_) = this->GetParam();
const ngraph::Shape input_shape{1, 10};
// test function
{
auto input = ngraph::builder::makeParams(target_precision_, {input_shape, input_shape, input_shape});
auto convert1 = ngraph::builder::makeConversion(input[0], net_precision_, ngraph::helpers::ConversionTypes::CONVERT);
auto convert2 = ngraph::builder::makeConversion(input[1], net_precision_, ngraph::helpers::ConversionTypes::CONVERT);
auto convert3 = ngraph::builder::makeConversion(input[2], net_precision_, ngraph::helpers::ConversionTypes::CONVERT);
auto mul1 = ngraph::builder::makeEltwise(convert1, convert2, ngraph::helpers::EltwiseTypes::ADD);
auto mul2 = ngraph::builder::makeEltwise(convert3, mul1, ngraph::helpers::EltwiseTypes::ADD);
auto result = std::make_shared<ngraph::opset8::Result>(mul2);
func_ = std::make_shared<ngraph::Function>(ngraph::ResultVector{result}, input, "multiple_input");
}
// ref function
{
auto input = ngraph::builder::makeParams(net_precision_, {input_shape, input_shape, input_shape});
auto mul1 = ngraph::builder::makeEltwise(input[0], input[1], ngraph::helpers::EltwiseTypes::ADD);
auto mul2 = ngraph::builder::makeEltwise(input[2], mul1, ngraph::helpers::EltwiseTypes::ADD);
auto result = std::make_shared<ngraph::opset8::Result>(mul2);
ref_func_no_convert_ = std::make_shared<ngraph::Function>(ngraph::ResultVector{result}, input, "multiple_input");
}
// ref function convert should not be removed
ref_func_convert_ = ngraph::clone_function(*func_);
}
};
class RemoveMultiOutputsConvertTest: public RemoveOutputConvertTest {
public:
void SetUp() override {
std::tie(net_precision_, target_precision_) = this->GetParam();
const ngraph::Shape input_shape{1, 10};
// test function
{
auto input = ngraph::builder::makeParams(net_precision_, {input_shape, input_shape, input_shape, input_shape});
auto mul1 = ngraph::builder::makeEltwise(input[0], input[1], ngraph::helpers::EltwiseTypes::ADD);
auto mul2 = ngraph::builder::makeEltwise(input[2], input[3], ngraph::helpers::EltwiseTypes::ADD);
auto convert1 = ngraph::builder::makeConversion(mul1, target_precision_, ngraph::helpers::ConversionTypes::CONVERT);
auto convert2 = ngraph::builder::makeConversion(mul2, target_precision_, ngraph::helpers::ConversionTypes::CONVERT);
auto result1 = std::make_shared<ngraph::opset8::Result>(convert1);
auto result2 = std::make_shared<ngraph::opset8::Result>(convert2);
func_ = std::make_shared<ngraph::Function>(ngraph::ResultVector{result1, result2}, input, "multiple_output");
}
// ref function
{
auto input = ngraph::builder::makeParams(net_precision_, {input_shape, input_shape, input_shape, input_shape});
auto mul1 = ngraph::builder::makeEltwise(input[0], input[1], ngraph::helpers::EltwiseTypes::ADD);
auto mul2 = ngraph::builder::makeEltwise(input[2], input[3], ngraph::helpers::EltwiseTypes::ADD);
auto result1 = std::make_shared<ngraph::opset8::Result>(mul1);
auto result2 = std::make_shared<ngraph::opset8::Result>(mul2);
ref_func_no_convert_ = std::make_shared<ngraph::Function>(ngraph::ResultVector{result1, result2}, input, "multiple_output");
}
// ref function convert should not be removed
ref_func_convert_ = ngraph::clone_function(*func_);
}
};
ov::element::TypeVector netTypes = {
ov::element::f16,
ov::element::f32,
ov::element::i8,
ov::element::u8,
ov::element::i16,
ov::element::i32,
ov::element::i64
};
ov::element::TypeVector targetTypes = {
ov::element::f16,
ov::element::f32,
ov::element::i8,
ov::element::u8,
ov::element::i16,
ov::element::i32,
ov::element::i64
};
TEST_P(RemoveInputConvertTest, CompareWithRefs) {
Run();
}
TEST_P(RemoveOutputConvertTest, CompareWithRefs) {
Run();
}
TEST_P(LeaveConvertTest, CompareWithRefs) {
Run();
}
TEST_P(RemoveMultiInputsConvertTest, CompareWithRefs) {
Run();
}
TEST_P(RemoveMultiOutputsConvertTest, CompareWithRefs) {
Run();
}
INSTANTIATE_TEST_SUITE_P(TransformationTests, RemoveInputConvertTest,
::testing::Combine(
::testing::ValuesIn(netTypes),
::testing::ValuesIn(targetTypes)),
RemoveInputConvertTest::getTestCaseName);
INSTANTIATE_TEST_SUITE_P(TransformationTests, RemoveOutputConvertTest,
::testing::Combine(
::testing::ValuesIn(netTypes),
::testing::ValuesIn(targetTypes)),
RemoveOutputConvertTest::getTestCaseName);
INSTANTIATE_TEST_SUITE_P(TransformationTests, LeaveConvertTest,
::testing::Combine(
::testing::ValuesIn(netTypes),
::testing::ValuesIn(targetTypes)),
LeaveConvertTest::getTestCaseName);
INSTANTIATE_TEST_SUITE_P(TransformationTests, RemoveMultiInputsConvertTest,
::testing::Combine(
::testing::ValuesIn(netTypes),
::testing::ValuesIn(targetTypes)),
RemoveMultiInputsConvertTest::getTestCaseName);
INSTANTIATE_TEST_SUITE_P(TransformationTests, RemoveMultiOutputsConvertTest,
::testing::Combine(
::testing::ValuesIn(netTypes),
::testing::ValuesIn(targetTypes)),
RemoveMultiOutputsConvertTest::getTestCaseName);
} // namespace testing