Skip to content

Commit

Permalink
Select operation revision (openvinotoolkit#6483)
Browse files Browse the repository at this point in the history
* Add visitor test.

* Add Serialization SLT.

* Add Select-1 to summarize.py.

* Remove select from evaluates map.

* Remove few Select cases from manifest.

* Fix style.

* Refactor CoordinateTransform usage for NUMPY.

* Refactor CoordinateTransform usage for PDPD.

* Migrate backend tests to template_plugin.

* Revert "Fix style."

This reverts commit 8298c90.

* Add more template plugin tests.

* Fixes for PDPD broadcasting.

* Align Select type prop tests with PDPP broadcasting to new
implementation.

* Remove ngraph:: from types in tests.
  • Loading branch information
jdanieck authored and akuporos committed Sep 29, 2021
1 parent ee9189f commit 9d2acbc
Show file tree
Hide file tree
Showing 11 changed files with 311 additions and 175 deletions.
139 changes: 139 additions & 0 deletions docs/template_plugin/tests/functional/op_reference/select.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
// Copyright (C) 2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//

#include <gtest/gtest.h>

#include <ie_core.hpp>
#include <ie_ngraph_utils.hpp>
#include <ngraph/ngraph.hpp>
#include <shared_test_classes/base/layer_test_utils.hpp>
#include <tuple>

#include "base_reference_test.hpp"

using namespace ngraph;
using namespace InferenceEngine;

struct SelectParams {
template <class IT, class OT>
SelectParams(const element::Type& data_type, const op::AutoBroadcastSpec& broadcast, const PartialShape& select_input_pshape,
const std::vector<char>& select_input, const PartialShape& if_input_pshape, const std::vector<IT>& if_input,
const PartialShape& else_input_pshape, const std::vector<IT>& else_input, const std::vector<OT>& expected_output)
: data_type(data_type),
broadcast(broadcast),
select_input_pshape(select_input_pshape),
select_input(CreateBlob(element::boolean, select_input)),
if_input_pshape(if_input_pshape),
if_input(CreateBlob(data_type, if_input)),
else_input_pshape(else_input_pshape),
else_input(CreateBlob(data_type, else_input)),
expected_output(CreateBlob(data_type, expected_output)) {}

element::Type data_type;
op::AutoBroadcastSpec broadcast;
PartialShape select_input_pshape;
InferenceEngine::Blob::Ptr select_input;
PartialShape if_input_pshape;
InferenceEngine::Blob::Ptr if_input;
PartialShape else_input_pshape;
InferenceEngine::Blob::Ptr else_input;
InferenceEngine::Blob::Ptr expected_output;
};

class ReferenceSelectLayerTest : public testing::TestWithParam<SelectParams>, public CommonReferenceTest {
public:
void SetUp() override {
auto params = GetParam();
function = CreateFunction(params.data_type, params.broadcast, params.select_input_pshape, params.if_input_pshape, params.else_input_pshape);
inputData = {params.select_input, params.if_input, params.else_input};
refOutData = {params.expected_output};
}
static std::string getTestCaseName(const testing::TestParamInfo<SelectParams>& obj) {
auto param = obj.param;
std::ostringstream result;
result << "data_type=" << param.data_type << "_";
result << "broadcast=" << param.broadcast.m_type << "_";
result << "select_shape=" << param.select_input_pshape << "_";
result << "if_shape=" << param.if_input_pshape << "_";
result << "else_shape=" << param.else_input_pshape;
return result.str();
}

private:
static std::shared_ptr<Function> CreateFunction(const element::Type& data_type, const op::AutoBroadcastSpec& broadcast,
const PartialShape& select_pshape, const PartialShape& if_pshape, const PartialShape& else_pshape) {
auto A = std::make_shared<op::Parameter>(element::boolean, select_pshape);
auto B = std::make_shared<op::Parameter>(data_type, if_pshape);
auto C = std::make_shared<op::Parameter>(data_type, else_pshape);
return std::make_shared<Function>(std::make_shared<op::v1::Select>(A, B, C, broadcast), ParameterVector {A, B, C});
}
};

TEST_P(ReferenceSelectLayerTest, CompareWithHardcodedRefs) {
Exec();
}

INSTANTIATE_TEST_SUITE_P(smoke_Select_With_Hardcoded_Refs, ReferenceSelectLayerTest,
::testing::Values(
// fp32, no brodcasting
SelectParams(element::f32, // if/else/output data type
op::AutoBroadcastType::NONE, // broadcasting type
PartialShape {2, 2, 2}, // select shape
std::vector<char> {0, 1, 1, 0, 0, 1, 0, 1}, // select data
PartialShape {2, 2, 2}, // if shape
std::vector<float> {1, 2, 3, 4, 5, 6, 7, 8}, // if data
PartialShape {2, 2, 2}, // else shape
std::vector<float> {11, 12, 13, 14, 15, 16, 17, 18}, // else data
std::vector<float> {11, 2, 3, 14, 15, 6, 17, 8}), // expected output data
// i32, no brodcasting
SelectParams(element::i32, // if/else/output data type
op::AutoBroadcastType::NONE, // broadcasting type
PartialShape {2, 2, 2}, // select shape
std::vector<char> {0, 1, 1, 0, 0, 1, 0, 1}, // select data
PartialShape {2, 2, 2}, // if shape
std::vector<float> {1, 2, 3, 4, 5, 6, 7, 8}, // if data
PartialShape {2, 2, 2}, // else shape
std::vector<float> {11, 12, 13, 14, 15, 16, 17, 18}, // else data
std::vector<float> {11, 2, 3, 14, 15, 6, 17, 8}), // expected output data
// fp32, numpy brodcasting
SelectParams(element::f32, // if/else/output data type
op::AutoBroadcastType::NUMPY, // broadcasting type
PartialShape {4}, // select shape
std::vector<char> {0, 1, 1, 0}, // select data
PartialShape {4}, // if shape
std::vector<float> {1, 2, 3, 4}, // if data
PartialShape {2, 4}, // else shape
std::vector<float> {11, 12, 13, 14, 15, 16, 17, 18}, // else data
std::vector<float> {11, 2, 3, 14, 15, 2, 3, 18}), // expected output data
// i32, numpy brodcasting
SelectParams(element::i32, // if/else/output data type
op::AutoBroadcastType::NUMPY, // broadcasting type
PartialShape {4}, // select shape
std::vector<char> {0, 1, 1, 0}, // select data
PartialShape {4}, // if shape
std::vector<float> {1, 2, 3, 4}, // if data
PartialShape {2, 4}, // else shape
std::vector<float> {11, 12, 13, 14, 15, 16, 17, 18}, // else data
std::vector<float> {11, 2, 3, 14, 15, 2, 3, 18}), // expected output data
// fp32, pdpd brodcasting
SelectParams(element::f32, // if/else/output data type
{op::AutoBroadcastType::PDPD, -1}, // broadcasting type
PartialShape {2, 4}, // select shape
std::vector<char> {0, 0, 0, 0, 0, 1, 1, 1}, // select data
PartialShape {2, 4}, // if shape
std::vector<float> {1, 2, 3, 4, 5, 6, 7, 8}, // if data
PartialShape {4}, // else shape
std::vector<float> {11, 12, 13, 14}, // else data
std::vector<float> {11, 12, 13, 14, 11, 6, 7, 8}), // expected output data
// i32, pdpd brodcasting
SelectParams(element::i32, // if/else/output data type
{op::AutoBroadcastType::PDPD, -1}, // broadcasting type
PartialShape {2, 4}, // select shape
std::vector<char> {0, 0, 0, 0, 0, 1, 1, 1}, // select data
PartialShape {2, 4}, // if shape
std::vector<float> {1, 2, 3, 4, 5, 6, 7, 8}, // if data
PartialShape {4}, // else shape
std::vector<float> {11, 12, 13, 14}, // else data
std::vector<float> {11, 12, 13, 14, 11, 6, 7, 8})), // expected output data
ReferenceSelectLayerTest::getTestCaseName);
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// Copyright (C) 2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//

#include "shared_test_classes/single_layer/select.hpp"

#include <vector>
using namespace LayerTestsDefinitions;

const std::vector<InferenceEngine::Precision> inputPrecision = {
InferenceEngine::Precision::I8, InferenceEngine::Precision::I16,
InferenceEngine::Precision::I32, InferenceEngine::Precision::FP16,
InferenceEngine::Precision::FP32};

const std::vector<std::vector<std::vector<size_t>>> noneShapes = {
{{2, 3, 4, 5, 6}, {2, 3, 4, 5, 6}, {2, 3, 4, 5, 6}}};

const auto noneCases = ::testing::Combine(
::testing::ValuesIn(noneShapes), ::testing::ValuesIn(inputPrecision),
::testing::Values(ngraph::op::AutoBroadcastSpec::NONE),
::testing::Values(CommonTestUtils::DEVICE_CPU));

const std::vector<std::vector<std::vector<size_t>>> numpyShapes = {
{{5, 1, 2, 1}, {8, 1, 9, 1, 1}, {5, 1, 2, 1}}};

const auto numpyCases = ::testing::Combine(
::testing::ValuesIn(numpyShapes), ::testing::ValuesIn(inputPrecision),
::testing::Values(ngraph::op::AutoBroadcastSpec::NUMPY),
::testing::Values(CommonTestUtils::DEVICE_CPU));

TEST_P(SelectLayerTest, Serialize) {
Serialize();
}

INSTANTIATE_TEST_SUITE_P(smoke_Serialization_SelectLayerTest_none,
SelectLayerTest, noneCases,
SelectLayerTest::getTestCaseName);

INSTANTIATE_TEST_SUITE_P(smoke_Serialization_SelectLayerTest_numpy,
SelectLayerTest, numpyCases,
SelectLayerTest::getTestCaseName);
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@
'Round-5',
'SpaceToDepth-1',
'ScatterNDUpdate-4',
'Select-1',
'ShapeOf-1',
'ShapeOf-3',
'ShuffleChannels-1',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#pragma once

#include <cstddef>
#include <numeric>

#include <utility>
#include "ngraph/coordinate_transform.hpp"
Expand Down Expand Up @@ -439,23 +440,38 @@ namespace ngraph
arg1_padded_shape[i]}));
}

NGRAPH_SUPPRESS_DEPRECATED_START
CoordinateTransform arg0_transform(arg0_squeezed_shape);
CoordinateTransform arg1_transform(arg1_squeezed_shape);
CoordinateTransform arg2_transform(arg2_squeezed_shape);
CoordinateTransform output_transform(output_shape);
CoordinateTransformBasic arg0_transform(arg0_squeezed_shape);
CoordinateTransformBasic arg1_transform(arg1_squeezed_shape);
CoordinateTransformBasic arg2_transform(arg2_squeezed_shape);
CoordinateTransformBasic output_transform(output_shape);

const auto arg0_strides = row_major_strides(arg0_squeezed_shape);
const auto arg1_strides = row_major_strides(arg1_squeezed_shape);
const auto arg2_strides = row_major_strides(arg2_squeezed_shape);
const auto output_strides = row_major_strides(output_shape);

for (const Coordinate& output_coord : output_transform)
{
Coordinate arg0_coord = reduce(output_coord, arg0_squeezed_axes, false);
Coordinate arg1_coord = reduce(output_coord, arg1_squeezed_axes, false);
Coordinate arg2_coord = reduce(output_coord, arg2_squeezed_axes, false);
out[output_transform.index(output_coord)] =
elementwise_functor(arg0[arg0_transform.index(arg0_coord)],
arg1[arg1_transform.index(arg1_coord)],
arg2[arg2_transform.index(arg2_coord)]);
const Coordinate arg0_coord =
reduce(output_coord, arg0_squeezed_axes, false);
const Coordinate arg1_coord =
reduce(output_coord, arg1_squeezed_axes, false);
const Coordinate arg2_coord =
reduce(output_coord, arg2_squeezed_axes, false);

const size_t arg0_idx = std::inner_product(
arg0_coord.begin(), arg0_coord.end(), arg0_strides.begin(), 0);
const size_t arg1_idx = std::inner_product(
arg1_coord.begin(), arg1_coord.end(), arg1_strides.begin(), 0);
const size_t arg2_idx = std::inner_product(
arg2_coord.begin(), arg2_coord.end(), arg2_strides.begin(), 0);
const size_t output_idx = std::inner_product(output_coord.begin(),
output_coord.end(),
output_strides.begin(),
0);
out[output_idx] =
elementwise_functor(arg0[arg0_idx], arg1[arg1_idx], arg2[arg2_idx]);
}
NGRAPH_SUPPRESS_DEPRECATED_END
}
break;
case op::AutoBroadcastType::PDPD:
Expand All @@ -475,7 +491,9 @@ namespace ngraph
arg0_padded_shape.pop_back();
}

for (int64_t i = 0; i < axis; ++i)
for (int64_t i = 0;
(i < axis) && (arg0_padded_shape.size() < arg1_shape.size());
++i)
{
arg0_padded_shape.insert(arg0_padded_shape.begin(), 1);
}
Expand All @@ -489,8 +507,9 @@ namespace ngraph
{
arg2_padded_shape.pop_back();
}

for (int64_t i = 0; i < axis; ++i)
for (int64_t i = 0;
(i < axis) && (arg2_padded_shape.size() < arg1_shape.size());
++i)
{
arg2_padded_shape.insert(arg2_padded_shape.begin(), 1);
}
Expand Down Expand Up @@ -525,22 +544,34 @@ namespace ngraph
}
}

NGRAPH_SUPPRESS_DEPRECATED_START
CoordinateTransform arg0_transform(arg0_squeezed_shape);
CoordinateTransform arg1_transform(arg1_shape);
CoordinateTransform arg2_transform(arg2_squeezed_shape);
CoordinateTransform output_transform(arg1_shape);
CoordinateTransformBasic arg0_transform(arg0_squeezed_shape);
CoordinateTransformBasic arg1_transform(arg1_shape);
CoordinateTransformBasic arg2_transform(arg2_squeezed_shape);
CoordinateTransformBasic output_transform(arg1_shape);

const auto arg0_strides = row_major_strides(arg0_squeezed_shape);
const auto arg2_strides = row_major_strides(arg2_squeezed_shape);
const auto output_strides = row_major_strides(arg1_shape);

for (const Coordinate& output_coord : output_transform)
{
Coordinate arg0_coord = reduce(output_coord, arg0_squeezed_axes, false);
Coordinate arg2_coord = reduce(output_coord, arg2_squeezed_axes, false);
out[output_transform.index(output_coord)] =
elementwise_functor(arg0[arg0_transform.index(arg0_coord)],
arg1[arg1_transform.index(output_coord)],
arg2[arg2_transform.index(arg2_coord)]);
const Coordinate arg0_coord =
reduce(output_coord, arg0_squeezed_axes, false);
const Coordinate arg2_coord =
reduce(output_coord, arg2_squeezed_axes, false);

const size_t arg0_idx = std::inner_product(
arg0_coord.begin(), arg0_coord.end(), arg0_strides.begin(), 0);
const size_t arg1_idx = std::inner_product(
output_coord.begin(), output_coord.end(), output_strides.begin(), 0);
const size_t arg2_idx = std::inner_product(
arg2_coord.begin(), arg2_coord.end(), arg2_strides.begin(), 0);
const size_t output_idx = std::inner_product(
output_coord.begin(), output_coord.end(), output_strides.begin(), 0);

out[output_idx] =
elementwise_functor(arg0[arg0_idx], arg1[arg1_idx], arg2[arg2_idx]);
}
NGRAPH_SUPPRESS_DEPRECATED_END
}
}
}
Expand Down
Loading

0 comments on commit 9d2acbc

Please sign in to comment.