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

[CPU] Native dynamic shapes support in the Bucketize node #8636

Merged
merged 11 commits into from
Dec 2, 2021
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,6 @@ using namespace InferenceEngine;

bool MKLDNNBucketizeNode::isSupportedOperation(const std::shared_ptr<const ngraph::Node>& op, std::string& errorMessage) noexcept {
try {
if (isDynamicNgraphNode(op)) {
errorMessage = "Doesn't support op with dynamic shapes";
return false;
}
const auto bucketsize = std::dynamic_pointer_cast<const ngraph::opset3::Bucketize>(op);
if (!bucketsize) {
errorMessage = "Only opset3 Bucketize operation is supported";
Expand Down Expand Up @@ -49,22 +45,6 @@ MKLDNNBucketizeNode::MKLDNNBucketizeNode(const std::shared_ptr<ngraph::Node>& op

// check one attribute
with_right = bucketsize->get_with_right_bound();

// check dimensions of input tensors
SizeVector input_tensor_dims = op->get_input_shape(INPUT_TENSOR_PORT);
if (input_tensor_dims.size() < 1) {
IE_THROW() << errorPrefix << " has incorrect dimensions of the input.";
}
SizeVector input_bin_dims = op->get_input_shape(INPUT_BINS_PORT);
if (input_bin_dims.size() != 1) {
IE_THROW() << errorPrefix << " has incorrect dimensions of the boundaries tensor.";
}
if (input_bin_dims[0] != 0) {
with_bins = true;
}
num_bin_values = input_bin_dims[0];

num_values = std::accumulate(input_tensor_dims.begin(), input_tensor_dims.end(), size_t(1), std::multiplies<size_t>());
}

void MKLDNNBucketizeNode::initSupportedPrimitiveDescriptors() {
Expand Down Expand Up @@ -192,6 +172,32 @@ void MKLDNNBucketizeNode::execute(mkldnn::stream strm) {
}
}

void MKLDNNBucketizeNode::prepareParams() {
// update with_bins/num_values/num_bin_values
auto input_tensor_dims = getParentEdgeAt(INPUT_TENSOR_PORT)->getMemoryPtr()->getStaticDims();
if (input_tensor_dims.size() < 1) {
IE_THROW() << errorPrefix << " has incorrect dimensions of the input.";
}
auto input_bin_dims = getParentEdgeAt(INPUT_BINS_PORT)->getMemoryPtr()->getStaticDims();
if (input_bin_dims.size() != 1) {
IE_THROW() << errorPrefix << " has incorrect dimensions of the boundaries tensor.";
}
if (input_bin_dims[0] != 0) {
with_bins = true;
}
num_bin_values = input_bin_dims[0];

num_values =
std::accumulate(input_tensor_dims.begin(), input_tensor_dims.end(), size_t(1), std::multiplies<size_t>());
}

void MKLDNNBucketizeNode::createPrimitive() {
if (inputShapesDefined()) {
prepareParams();
updateLastInputDims();
}
}

template <typename T, typename T_BOUNDARIES, typename T_IND>
void MKLDNNBucketizeNode::bucketize() {
const auto *input_data = reinterpret_cast<const T *>(getParentEdgeAt(0)->getMemoryPtr()->GetPtr());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,13 @@ class MKLDNNBucketizeNode : public MKLDNNNode {

void getSupportedDescriptors() override {};
void initSupportedPrimitiveDescriptors() override;
void createPrimitive() override {};
void createPrimitive() override;
void execute(mkldnn::stream strm) override;
bool created() const override;
void executeDynamicImpl(mkldnn::stream strm) override {
execute(strm);
}
void prepareParams() override;

static bool isSupportedOperation(const std::shared_ptr<const ngraph::Node>& op, std::string& errorMessage) noexcept;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,34 +7,40 @@
#include "single_layer_tests/bucketize.hpp"
#include "common_test_utils/test_constants.hpp"

using namespace LayerTestsDefinitions;
using namespace ov::test::subgraph;

const std::vector<std::vector<size_t>> dataShapes = {
const std::vector<ov::Shape> dataShapes = {
{1, 20, 20},
{2, 3, 50, 50}
};

const std::vector<std::vector<size_t>> bucketsShapes = {
const std::vector<ov::Shape> bucketsShapes = {
{5},
{20},
{100}
};

const std::vector<InferenceEngine::Precision> inPrc = {
InferenceEngine::Precision::FP32,
InferenceEngine::Precision::FP16,
InferenceEngine::Precision::I64,
InferenceEngine::Precision::I32
const std::vector<ov::test::InputShape> dataShapesDynamic = {
{{ngraph::Dimension(1, 10), ngraph::Dimension::dynamic(), ngraph::Dimension::dynamic()},
{{1, 20, 20}, {3, 16, 16}, {10, 16, 16}}},
{{ngraph::Dimension(1, 10), 3, 50, 50}, {{2, 3, 50, 50}, {2, 3, 50, 50}, {2, 3, 50, 50}}}};

const std::vector<ov::test::InputShape> bucketsShapesDynamic = {{{ngraph::Dimension::dynamic()}, {{5}, {20}, {100}}}};

const std::vector<ov::test::ElementType> inPrc = {
ov::element::f32,
ov::element::i64,
ov::element::i32
};

const std::vector<InferenceEngine::Precision> netPrc = {
InferenceEngine::Precision::I64,
InferenceEngine::Precision::I32
const std::vector<ov::test::ElementType> netPrc = {
ov::element::i64,
ov::element::i32
};

const auto test_Bucketize_right_edge = ::testing::Combine(
::testing::ValuesIn(dataShapes),
::testing::ValuesIn(bucketsShapes),
::testing::ValuesIn(ov::test::static_shapes_to_test_representation(dataShapes)),
::testing::ValuesIn(ov::test::static_shapes_to_test_representation(bucketsShapes)),
::testing::Values(true),
::testing::ValuesIn(inPrc),
::testing::ValuesIn(inPrc),
Expand All @@ -43,8 +49,29 @@ const auto test_Bucketize_right_edge = ::testing::Combine(
);

const auto test_Bucketize_left_edge = ::testing::Combine(
::testing::ValuesIn(dataShapes),
::testing::ValuesIn(bucketsShapes),
::testing::ValuesIn(ov::test::static_shapes_to_test_representation(dataShapes)),
::testing::ValuesIn(ov::test::static_shapes_to_test_representation(bucketsShapes)),
::testing::Values(false),
::testing::ValuesIn(inPrc),
::testing::ValuesIn(inPrc),
::testing::ValuesIn(netPrc),
::testing::Values(CommonTestUtils::DEVICE_CPU)
);


const auto test_Bucketize_right_edge_Dynamic = ::testing::Combine(
::testing::ValuesIn(dataShapesDynamic),
::testing::ValuesIn(bucketsShapesDynamic),
::testing::Values(true),
::testing::ValuesIn(inPrc),
::testing::ValuesIn(inPrc),
::testing::ValuesIn(netPrc),
::testing::Values(CommonTestUtils::DEVICE_CPU)
);

const auto test_Bucketize_left_edge_Dynamic = ::testing::Combine(
::testing::ValuesIn(dataShapesDynamic),
::testing::ValuesIn(bucketsShapesDynamic),
::testing::Values(false),
::testing::ValuesIn(inPrc),
::testing::ValuesIn(inPrc),
Expand All @@ -54,3 +81,5 @@ const auto test_Bucketize_left_edge = ::testing::Combine(

INSTANTIATE_TEST_SUITE_P(smoke_TestsBucketize_right, BucketizeLayerTest, test_Bucketize_right_edge, BucketizeLayerTest::getTestCaseName);
INSTANTIATE_TEST_SUITE_P(smoke_TestsBucketize_left, BucketizeLayerTest, test_Bucketize_left_edge, BucketizeLayerTest::getTestCaseName);
INSTANTIATE_TEST_SUITE_P(smoke_TestsBucketize_right_Dynamic, BucketizeLayerTest, test_Bucketize_right_edge_Dynamic, BucketizeLayerTest::getTestCaseName);
INSTANTIATE_TEST_SUITE_P(smoke_TestsBucketize_left_Dynamic, BucketizeLayerTest, test_Bucketize_left_edge_Dynamic, BucketizeLayerTest::getTestCaseName);
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,14 @@

#include "shared_test_classes/single_layer/bucketize.hpp"

namespace LayerTestsDefinitions {
namespace ov {
namespace test {
namespace subgraph {

TEST_P(BucketizeLayerTest, CompareWithRefs) {
Run();
run();
}
} // namespace LayerTestsDefinitions

} // namespace subgraph
} // namespace test
} // namespace ov
Original file line number Diff line number Diff line change
Expand Up @@ -4,32 +4,30 @@

#pragma once

#include <tuple>
#include <string>
#include "shared_test_classes/base/ov_subgraph.hpp"

#include "ngraph_functions/builders.hpp"
#include "ngraph_functions/utils/ngraph_helpers.hpp"
namespace ov {
namespace test {
namespace subgraph {

#include "shared_test_classes/base/layer_test_utils.hpp"

namespace LayerTestsDefinitions {

using bucketizeParamsTuple = std::tuple<
InferenceEngine::SizeVector, // Data shape
InferenceEngine::SizeVector, // Buckets shape
bool, // Right edge of interval
InferenceEngine::Precision, // Data input precision
InferenceEngine::Precision, // Buckets input precision
InferenceEngine::Precision, // Output precision
std::string>; // Device name
using bucketizeParamsTuple = std::tuple<InputShape, // Data shape
InputShape, // Buckets shape
bool, // Right edge of interval
ElementType, // Data input precision
ElementType, // Buckets input precision
ElementType, // Output precision
TargetDevice>; // Device name

class BucketizeLayerTest : public testing::WithParamInterface<bucketizeParamsTuple>,
virtual public LayerTestsUtils::LayerTestsCommon {
virtual public ov::test::SubgraphBaseTest {
public:
static std::string getTestCaseName(const testing::TestParamInfo<bucketizeParamsTuple>& obj);
InferenceEngine::Blob::Ptr GenerateInput(const InferenceEngine::InputInfo &info) const override;
void generate_inputs(const std::vector<ngraph::Shape>& targetInputStaticShapes) override;

protected:
void SetUp() override;
};

} // namespace LayerTestsDefinitions
} // namespace subgraph
} // namespace test
} // namespace ov
Original file line number Diff line number Diff line change
Expand Up @@ -2,66 +2,97 @@
// SPDX-License-Identifier: Apache-2.0
//

// Copyright (C) 2018-2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//

#include "shared_test_classes/single_layer/bucketize.hpp"

namespace LayerTestsDefinitions {

std::string BucketizeLayerTest::getTestCaseName(const testing::TestParamInfo<bucketizeParamsTuple>& obj) {
InferenceEngine::SizeVector dataShape;
InferenceEngine::SizeVector bucketsShape;
bool with_right_bound;
InferenceEngine::Precision inDataPrc;
InferenceEngine::Precision inBucketsPrc;
InferenceEngine::Precision netPrc;
std::string targetDevice;

std::tie(dataShape, bucketsShape, with_right_bound, inDataPrc, inBucketsPrc, netPrc, targetDevice) = obj.param;

std::ostringstream result;
result << "DS=" << CommonTestUtils::vec2str(dataShape) << "_";
result << "BS=" << CommonTestUtils::vec2str(bucketsShape) << "_";
if (with_right_bound)
result << "rightIntervalEdge_";
else
result << "leftIntervalEdge_";
result << "inDataPrc=" << inDataPrc.name() << "_";
result << "inBucketsPrc=" << inBucketsPrc.name() << "_";
result << "netPrc=" << netPrc.name() << "_";
result << "trgDev=" << targetDevice;
return result.str();
}
#include "common_test_utils/common_utils.hpp"
#include "functional_test_utils/ov_tensor_utils.hpp"
#include "ngraph_functions/builders.hpp"

namespace ov {
namespace test {
namespace subgraph {

std::string BucketizeLayerTest::getTestCaseName(const testing::TestParamInfo<bucketizeParamsTuple>& obj) {
InputShape dataShape;
InputShape bucketsShape;
bool with_right_bound;
ElementType inDataPrc;
ElementType inBucketsPrc;
ElementType netPrc;
TargetDevice targetDevice;

std::tie(dataShape, bucketsShape, with_right_bound, inDataPrc, inBucketsPrc, netPrc, targetDevice) = obj.param;

InferenceEngine::Blob::Ptr BucketizeLayerTest::GenerateInput(const InferenceEngine::InputInfo &info) const {
InferenceEngine::Blob::Ptr blobPtr;
const std::string name = info.name();
if (name == "a_data") {
auto data_shape = info.getTensorDesc().getDims();
auto data_size = std::accumulate(begin(data_shape), end(data_shape), 1, std::multiplies<uint64_t>());
blobPtr = FuncTestUtils::createAndFillBlob(info.getTensorDesc(), data_size * 5, 0, 10, 7235346);
} else if (name == "b_buckets") {
blobPtr = FuncTestUtils::createAndFillBlobUniqueSequence(info.getTensorDesc(), 0, 10, 8234231);
}
return blobPtr;
std::ostringstream result;
result << "DS=" << CommonTestUtils::partialShape2str({dataShape.first}) << "_";
for (const auto& item : dataShape.second) {
result << CommonTestUtils::vec2str(item) << "_";
}

void BucketizeLayerTest::SetUp() {
InferenceEngine::SizeVector dataShape;
InferenceEngine::SizeVector bucketsShape;
bool with_right_bound;
InferenceEngine::Precision inDataPrc;
InferenceEngine::Precision inBucketsPrc;
InferenceEngine::Precision netPrc;

std::tie(dataShape, bucketsShape, with_right_bound, inDataPrc, inBucketsPrc, netPrc, targetDevice) = this->GetParam();

auto ngInDataPrc = FuncTestUtils::PrecisionUtils::convertIE2nGraphPrc(inDataPrc);
auto ngInBucketsPrc = FuncTestUtils::PrecisionUtils::convertIE2nGraphPrc(inBucketsPrc);
auto ngNetPrc = FuncTestUtils::PrecisionUtils::convertIE2nGraphPrc(netPrc);
auto data = std::make_shared<ngraph::op::Parameter>(ngInDataPrc, ngraph::Shape(dataShape));
data->set_friendly_name("a_data");
auto buckets = std::make_shared<ngraph::op::Parameter>(ngInBucketsPrc, ngraph::Shape(bucketsShape));
buckets->set_friendly_name("b_buckets");
auto bucketize = std::make_shared<ngraph::op::v3::Bucketize>(data, buckets, ngNetPrc, with_right_bound);
function = std::make_shared<ngraph::Function>(std::make_shared<ngraph::opset1::Result>(bucketize), ngraph::ParameterVector{data, buckets}, "Bucketize");
result << "BS=" << CommonTestUtils::partialShape2str({bucketsShape.first}) << "_";
for (const auto& item : bucketsShape.second) {
result << CommonTestUtils::vec2str(item) << "_";
}
} // namespace LayerTestsDefinitions

if (with_right_bound)
result << "rightIntervalEdge_";
else
result << "leftIntervalEdge_";
result << "inDataPrc=" << inDataPrc << "_";
result << "inBucketsPrc=" << inBucketsPrc << "_";
result << "netPrc=" << netPrc << "_";
result << "trgDev=" << targetDevice;
return result.str();
}

void BucketizeLayerTest::generate_inputs(const std::vector<ngraph::Shape>& targetInputStaticShapes) {
inputs.clear();
const auto& funcInputs = function->inputs();

auto data_size = shape_size(targetInputStaticShapes[0]);
ov::runtime::Tensor tensorData = ov::test::utils::create_and_fill_tensor(funcInputs[0].get_element_type(),
targetInputStaticShapes[0],
data_size * 5,
0,
10,
7235346);

ov::runtime::Tensor tensorBucket =
ov::test::utils::create_and_fill_tensor_unique_sequence(funcInputs[1].get_element_type(),
targetInputStaticShapes[1],
0,
10,
8234231);

inputs.insert({funcInputs[0].get_node_shared_ptr(), tensorData});
inputs.insert({funcInputs[1].get_node_shared_ptr(), tensorBucket});
}

void BucketizeLayerTest::SetUp() {
InputShape dataShape;
InputShape bucketsShape;
bool with_right_bound;
ElementType inDataPrc;
ElementType inBucketsPrc;
ElementType netPrc;

std::tie(dataShape, bucketsShape, with_right_bound, inDataPrc, inBucketsPrc, netPrc, targetDevice) =
this->GetParam();
init_input_shapes({dataShape, bucketsShape});

auto data = std::make_shared<ngraph::op::Parameter>(inDataPrc, inputDynamicShapes[0]);
data->set_friendly_name("a_data");
auto buckets = std::make_shared<ngraph::op::Parameter>(inBucketsPrc, inputDynamicShapes[1]);
buckets->set_friendly_name("b_buckets");
auto bucketize = std::make_shared<ngraph::op::v3::Bucketize>(data, buckets, netPrc, with_right_bound);
function = std::make_shared<ngraph::Function>(std::make_shared<ngraph::opset1::Result>(bucketize),
ngraph::ParameterVector{data, buckets},
"Bucketize");
}
} // namespace subgraph
} // namespace test
} // namespace ov
Loading