Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Select operation revision #6483

Merged
merged 18 commits into from
Jul 21, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
jdanieck marked this conversation as resolved.
Show resolved Hide resolved
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 @@ -90,6 +90,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