[Core] GridSample operator reference implementation (#11841)

This commit is contained in:
Tomasz Jankowski authored and GitHub committed 2022-06-16 08:47:29 +02:00
1 parent 39981bf2b8
commit f8c4e736b4
10 files changed
+897 -36

No files matched your search

@@ -0,0 +1,519 @@
// Copyright (C) 2022 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include "openvino/op/grid_sample.hpp"
#include "base_reference_test.hpp"
#include "gtest/gtest.h"
using namespace ov;
using namespace reference_tests;
namespace {
struct GridSampleParams {
GridSampleParams(const reference_tests::Tensor& data,
const reference_tests::Tensor& grid,
const op::v9::GridSample::Attributes& attrs,
const reference_tests::Tensor& expected,
const std::string& name)
: data_tensor{data},
grid_tensor{grid},
attributes{attrs},
expected_tensor{expected},
test_case_name{name} {}
reference_tests::Tensor data_tensor;
reference_tests::Tensor grid_tensor;
op::v9::GridSample::Attributes attributes;
reference_tests::Tensor expected_tensor;
std::string test_case_name;
};
class ReferenceGridSample : public testing::TestWithParam<GridSampleParams>, public CommonReferenceTest {
public:
void SetUp() override {
const auto& params = GetParam();
function = CreateFunction(params.data_tensor, params.grid_tensor, params.attributes);
inputData = {params.data_tensor.data, params.grid_tensor.data};
refOutData = {params.expected_tensor.data};
}
static std::string getTestCaseName(const testing::TestParamInfo<GridSampleParams>& obj) {
return obj.param.test_case_name;
}
private:
static std::shared_ptr<Model> CreateFunction(const reference_tests::Tensor& data,
const reference_tests::Tensor& grid,
const op::v9::GridSample::Attributes& attributes) {
const auto in1 = std::make_shared<op::v0::Parameter>(data.type, data.shape);
const auto in2 = std::make_shared<op::v0::Parameter>(grid.type, grid.shape);
const auto grid_sample = std::make_shared<op::v9::GridSample>(in1, in2, attributes);
return std::make_shared<Model>(NodeVector{grid_sample}, ParameterVector{in1, in2});
}
};
constexpr auto GS_BICUBIC{op::v9::GridSample::InterpolationMode::BICUBIC};
constexpr auto GS_BILINEAR{op::v9::GridSample::InterpolationMode::BILINEAR};
constexpr auto GS_NEAREST{op::v9::GridSample::InterpolationMode::NEAREST};
constexpr auto GS_BORDER{op::v9::GridSample::PaddingMode::BORDER};
constexpr auto GS_REFLECTION{op::v9::GridSample::PaddingMode::REFLECTION};
constexpr auto GS_ZEROS{op::v9::GridSample::PaddingMode::ZEROS};
constexpr std::array<op::v9::GridSample::PaddingMode, 3> padding_modes{GS_ZEROS, GS_BORDER, GS_REFLECTION};
constexpr std::array<bool, 2> align_corners_modes{false, true};
std::vector<GridSampleParams> generateNearestParamsOddDimensionsInnerGrids() {
std::vector<GridSampleParams> params;
reference_tests::Tensor data_odd_dims{{1, 1, 3, 5},
element::f32,
std::vector<float>{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}};
reference_tests::Tensor grid_inner{
{1, 3, 4, 2},
element::f32,
std::vector<float>{-0.1, -0.1, -0.1, 0.1, 0.1, -0.1, 0.1, 0.1, -0.5, -0.5, -0.5, 0.5,
0.5, -0.5, 0.5, 0.5, -1., -1., -1., 1., 1., -1., 1., 1.}};
reference_tests::Tensor output{{1, 1, 3, 4},
element::f32,
std::vector<float>{8, 8, 8, 8, 2, 12, 4, 14, 1, 11, 5, 15}};
for (const auto& padding : padding_modes) {
for (const auto align : align_corners_modes) {
std::stringstream name;
name << "nearest_" << padding << (align ? "_align" : "_noalign") << "_odd_dims_inner";
params.emplace_back(data_odd_dims,
grid_inner,
op::v9::GridSample::Attributes{align, GS_NEAREST, padding},
output,
name.str());
}
}
return params;
}
std::vector<GridSampleParams> generateNearestParamsOddDimensionsOuterGrids() {
std::vector<GridSampleParams> params;
reference_tests::Tensor data_odd_dims{{1, 1, 3, 5},
element::f32,
std::vector<float>{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}};
reference_tests::Tensor grid_outer{
{1, 1, 7, 2},
element::f32,
std::vector<float>{-10.1, -9.7, -7.55, 0.37, -77., 11.56, 0.5, 2.55, 1.7, 1.1, 3., -0.17, 1.301, -1.001}};
params.emplace_back(data_odd_dims,
grid_outer,
op::v9::GridSample::Attributes{false, GS_NEAREST, GS_ZEROS},
reference_tests::Tensor{{1, 1, 1, 7}, element::f32, std::vector<float>{0, 0, 0, 0, 0, 0, 0}},
"nearest_zeros_noalign_odd_dims_outer");
params.emplace_back(data_odd_dims,
grid_outer,
op::v9::GridSample::Attributes{true, GS_NEAREST, GS_ZEROS},
reference_tests::Tensor{{1, 1, 1, 7}, element::f32, std::vector<float>{0, 0, 0, 0, 0, 0, 0}},
"nearest_zeros_align_odd_dims_outer");
params.emplace_back(
data_odd_dims,
grid_outer,
op::v9::GridSample::Attributes{false, GS_NEAREST, GS_BORDER},
reference_tests::Tensor{{1, 1, 1, 7}, element::f32, std::vector<float>{1, 11, 11, 14, 15, 10, 5}},
"nearest_border_noalign_odd_dims_outer");
params.emplace_back(
data_odd_dims,
grid_outer,
op::v9::GridSample::Attributes{true, GS_NEAREST, GS_BORDER},
reference_tests::Tensor{{1, 1, 1, 7}, element::f32, std::vector<float>{1, 6, 11, 14, 15, 10, 5}},
"nearest_border_align_odd_dims_outer");
params.emplace_back(data_odd_dims,
grid_outer,
op::v9::GridSample::Attributes{false, GS_NEAREST, GS_REFLECTION},
reference_tests::Tensor{{1, 1, 1, 7}, element::f32, std::vector<float>{8, 14, 1, 4, 14, 6, 5}},
"nearest_reflection_noalign_odd_dims_outer");
params.emplace_back(data_odd_dims,
grid_outer,
op::v9::GridSample::Attributes{true, GS_NEAREST, GS_REFLECTION},
reference_tests::Tensor{{1, 1, 1, 7}, element::f32, std::vector<float>{8, 9, 6, 4, 14, 6, 4}},
"nearest_reflection_align_odd_dims_outer");
return params;
}
std::vector<GridSampleParams> generateNearestParamsEvenDimensions() {
std::vector<GridSampleParams> params;
reference_tests::Tensor data_even_dims{
{1, 1, 4, 6},
element::f32,
std::vector<float>{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24}};
reference_tests::Tensor grid_inner{
{1, 1, 8, 2},
element::f32,
std::vector<float>{-0.5, -0.5, -0.5, 0.5, 0.5, -0.5, 0.5, 0.5, -1, 1, 1, -1, -0.1, -0.1, 0.1, 0.1}};
reference_tests::Tensor output_align{{1, 1, 1, 8}, element::f32, std::vector<float>{8, 14, 11, 17, 19, 6, 9, 16}};
reference_tests::Tensor output_noalign{{1, 1, 1, 8}, element::f32, std::vector<float>{2, 14, 5, 17, 19, 6, 9, 16}};
reference_tests::Tensor output_zeros_noalign{{1, 1, 1, 8},
element::f32,
std::vector<float>{2, 14, 5, 17, 0, 0, 9, 16}};
for (const auto& padding : padding_modes) {
std::stringstream name1, name2;
name1 << "nearest_" << padding << "_noalign"
<< "_even_dims_inner";
params.emplace_back(data_even_dims,
grid_inner,
op::v9::GridSample::Attributes{false, GS_NEAREST, padding},
padding == GS_ZEROS ? output_zeros_noalign : output_noalign,
name1.str());
name2 << "nearest_" << padding << "_align"
<< "_even_dims_inner";
params.emplace_back(data_even_dims,
grid_inner,
op::v9::GridSample::Attributes{true, GS_NEAREST, padding},
output_align,
name2.str());
}
return params;
}
std::vector<GridSampleParams> generateBilinearParamsOddDimensionsInnerGrids() {
std::vector<GridSampleParams> params;
reference_tests::Tensor data_odd_dims{{1, 1, 3, 5},
element::f32,
std::vector<float>{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}};
reference_tests::Tensor grid_inner{
{1, 3, 4, 2},
element::f32,
std::vector<float>{-0.1, -0.1, -0.1, 0.1, 0.1, -0.1, 0.1, 0.1, -0.5, -0.5, -0.5, 0.5,
0.5, -0.5, 0.5, 0.5, -1., -1., -1., 1., 1., -1., 1., 1.}};
reference_tests::Tensor output_align{{1, 1, 3, 4},
element::f32,
std::vector<float>{7.3, 8.3, 7.7, 8.7, 4.5, 9.5, 6.5, 11.5, 1, 11, 5, 15}};
reference_tests::Tensor output_noalign{{1, 1, 3, 4},
element::f32,
std::vector<float>{7, 8.5, 7.5, 9, 3, 10.5, 5.5, 13, 1, 11, 5, 15}};
reference_tests::Tensor output_zeros_noalign{
{1, 1, 3, 4},
element::f32,
std::vector<float>{7, 8.5, 7.5, 9, 3, 10.5, 5.5, 13, 0.25, 2.75, 1.25, 3.75}};
params.emplace_back(data_odd_dims,
grid_inner,
op::v9::GridSample::Attributes{false, GS_BILINEAR, GS_ZEROS},
output_zeros_noalign,
"bilinear_zeros_noalign_odd_dims_inner");
params.emplace_back(data_odd_dims,
grid_inner,
op::v9::GridSample::Attributes{true, GS_BILINEAR, GS_ZEROS},
output_align,
"bilinear_zeros_align_odd_dims_inner");
params.emplace_back(data_odd_dims,
grid_inner,
op::v9::GridSample::Attributes{false, GS_BILINEAR, GS_BORDER},
output_noalign,
"bilinear_border_noalign_odd_dims_inner");
params.emplace_back(data_odd_dims,
grid_inner,
op::v9::GridSample::Attributes{true, GS_BILINEAR, GS_BORDER},
output_align,
"bilinear_border_align_odd_dims_inner");
params.emplace_back(data_odd_dims,
grid_inner,
op::v9::GridSample::Attributes{false, GS_BILINEAR, GS_REFLECTION},
output_noalign,
"bilinear_reflection_noalign_odd_dims_inner");
params.emplace_back(data_odd_dims,
grid_inner,
op::v9::GridSample::Attributes{true, GS_BILINEAR, GS_REFLECTION},
output_align,
"bilinear_reflection_align_odd_dims_inner");
return params;
}
std::vector<GridSampleParams> generateBilinearParamsOddDimensionsOuterGrids() {
std::vector<GridSampleParams> params;
reference_tests::Tensor data_odd_dims{{1, 1, 3, 5},
element::f32,
std::vector<float>{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}};
reference_tests::Tensor grid_outer{
{1, 1, 7, 2},
element::f32,
std::vector<float>{-10.1, -9.7, -7.55, 0.37, -77., 11.56, 0.5, 2.55, 1.7, 1.1, 3., -0.17, 1.301, -1.001}};
params.emplace_back(data_odd_dims,
grid_outer,
op::v9::GridSample::Attributes{false, GS_BILINEAR, GS_ZEROS},
reference_tests::Tensor{{1, 1, 1, 7}, element::f32, std::vector<float>{0, 0, 0, 0, 0, 0, 0}},
"bilinear_zeros_noalign_odd_dims_outer");
params.emplace_back(
data_odd_dims,
grid_outer,
op::v9::GridSample::Attributes{true, GS_BILINEAR, GS_ZEROS},
reference_tests::Tensor{{1, 1, 1, 7}, element::f32, std::vector<float>{0, 0, 0, 0, 0, 0, 1.9880099}},
"bilinear_zeros_align_odd_dims_outer");
params.emplace_back(
data_odd_dims,
grid_outer,
op::v9::GridSample::Attributes{false, GS_BILINEAR, GS_BORDER},
reference_tests::Tensor{{1, 1, 1, 7}, element::f32, std::vector<float>{1, 8.775, 11, 14.25, 15, 8.725, 5}},
"bilinear_border_noalign_odd_dims_outer");
params.emplace_back(
data_odd_dims,
grid_outer,
op::v9::GridSample::Attributes{true, GS_BILINEAR, GS_BORDER},
reference_tests::Tensor{{1, 1, 1, 7}, element::f32, std::vector<float>{1, 7.85, 11, 14, 15, 9.15, 5}},
"bilinear_border_align_odd_dims_outer");
params.emplace_back(
data_odd_dims,
grid_outer,
op::v9::GridSample::Attributes{false, GS_BILINEAR, GS_REFLECTION},
reference_tests::Tensor{{1, 1, 1, 7},
element::f32,
std::vector<float>{5.9999995, 11.9, 2.7000031, 5.1250005, 13.75, 4.725, 4.7475}},
"bilinear_reflection_noalign_odd_dims_outer");
params.emplace_back(
data_odd_dims,
grid_outer,
op::v9::GridSample::Attributes{true, GS_BILINEAR, GS_REFLECTION},
reference_tests::Tensor{{1, 1, 1, 7},
element::f32,
std::vector<float>{6.7, 10.75, 3.800002, 6.25, 13.099999, 5.15, 4.4030004}},
"bilinear_reflection_align_odd_dims_outer");
return params;
}
std::vector<GridSampleParams> generateBilinearParamsEvenDimensions() {
std::vector<GridSampleParams> params;
reference_tests::Tensor data_even_dims{
{1, 1, 4, 6},
element::f32,
std::vector<float>{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24}};
reference_tests::Tensor grid_inner{
{1, 1, 8, 2},
element::f32,
std::vector<float>{-0.5, -0.5, -0.5, 0.5, 0.5, -0.5, 0.5, 0.5, -1, 1, 1, -1, -0.1, -0.1, 0.1, 0.1}};
params.emplace_back(
data_even_dims,
grid_inner,
op::v9::GridSample::Attributes{false, GS_BILINEAR, GS_ZEROS},
reference_tests::Tensor{{1, 1, 1, 7}, element::f32, std::vector<float>{5, 17, 8, 20, 4.75, 1.5, 11, 14}},
"bilinear_zeros_noalign_even_dims_inner");
params.emplace_back(data_even_dims,
grid_inner,
op::v9::GridSample::Attributes{true, GS_BILINEAR, GS_ZEROS},
reference_tests::Tensor{{1, 1, 1, 7},
element::f32,
std::vector<float>{6.75, 15.75, 9.25, 18.25, 19, 6, 11.35, 13.65}},
"bilinear_zeros_align_even_dims_inner");
params.emplace_back(
data_even_dims,
grid_inner,
op::v9::GridSample::Attributes{false, GS_BILINEAR, GS_BORDER},
reference_tests::Tensor{{1, 1, 1, 7}, element::f32, std::vector<float>{5, 17, 8, 20, 19, 6, 11, 14}},
"bilinear_border_noalign_even_dims_inner");
params.emplace_back(data_even_dims,
grid_inner,
op::v9::GridSample::Attributes{true, GS_BILINEAR, GS_BORDER},
reference_tests::Tensor{{1, 1, 1, 7},
element::f32,
std::vector<float>{6.75, 15.75, 9.25, 18.25, 19, 6, 11.35, 13.65}},
"bilinear_border_align_even_dims_inner");
params.emplace_back(
data_even_dims,
grid_inner,
op::v9::GridSample::Attributes{false, GS_BILINEAR, GS_REFLECTION},
reference_tests::Tensor{{1, 1, 1, 7}, element::f32, std::vector<float>{5, 17, 8, 20, 19, 6, 11, 14}},
"bilinear_reflection_noalign_even_dims_inner");
params.emplace_back(data_even_dims,
grid_inner,
op::v9::GridSample::Attributes{true, GS_BILINEAR, GS_REFLECTION},
reference_tests::Tensor{{1, 1, 1, 7},
element::f32,
std::vector<float>{6.75, 15.75, 9.25, 18.25, 19, 6, 11.35, 13.65}},
"bilinear_reflection_align_even_dims_inner");
return params;
}
std::vector<GridSampleParams> generateBicubicParams() {
std::vector<GridSampleParams> params;
// clang-format off
reference_tests::Tensor data_even_dims{{1, 1, 4, 7}, element::f32,
std::vector<float>{ 1, 1, 1, 1, 1, 1, 1,
1, 2, 2, 2, 2, 2, 1,
1, 2, 3, 5, 3, 2, 1,
1, 2, 5, 9, 5, 2, 1}};
reference_tests::Tensor grid{
{1, 4, 4, 2},
element::f32,
std::vector<float>{ -0.1, -0.1, -0.1, 0.1, 0.1, -0.1, 0.1, 0.1,
-0.5, -0.5, -0.5, 0.5, 0.5, -0.5, 0.5, 0.5,
-0.9, -0.9, -0.9, 0.9, 0.9, -0.9, 0.9, 0.9,
-1.75, 0.7, 1.33, -1.11, 0.965, 1.007, 21, 37}};
params.emplace_back(data_even_dims,
grid,
op::v9::GridSample::Attributes{false, GS_BICUBIC, GS_ZEROS},
reference_tests::Tensor{{1, 1, 4, 4},
element::f32,
std::vector<float>{2.6663566, 3.527928, 2.6663566, 3.527928,
1.6318359, 2.7156982, 1.6318359, 2.7156982,
0.6378987, 0.57033366, 0.6378987, 0.57033366,
0, -0.01507522, 0.25528803, 0 }},
"bicubic_zeros_noalign");
params.emplace_back(data_even_dims,
grid,
op::v9::GridSample::Attributes{true, GS_BICUBIC, GS_ZEROS},
reference_tests::Tensor{{1, 1, 4, 4},
element::f32,
std::vector<float>{ 2.7887204, 3.4506166, 2.7887204, 3.4506166,
1.8481445, 2.7364502, 1.8481445, 2.7364502,
1.2367951, 1.3602872, 1.2367951, 1.3602872,
0, 0.00650583, 1.1182348, 0 }},
"bicubic_zeros_align");
params.emplace_back(data_even_dims,
grid,
op::v9::GridSample::Attributes{false, GS_BICUBIC, GS_BORDER},
reference_tests::Tensor{{1, 1, 4, 4},
element::f32,
std::vector<float>{ 2.6663566, 3.527928, 2.6663566, 3.527928,
1.5380859, 2.4677734, 1.5380859, 2.4677734,
1.0089612, 0.91871876, 1.0089612, 0.91871876,
1, 1, 0.8902873, 1 }},
"bicubic_border_noalign");
params.emplace_back(data_even_dims,
grid,
op::v9::GridSample::Attributes{true, GS_BICUBIC, GS_BORDER},
reference_tests::Tensor{{1, 1, 4, 4},
element::f32,
std::vector<float>{ 2.7887204, 3.4506166, 2.7887204, 3.4506166,
1.8129883, 2.623291, 1.8129883, 2.623291,
1.0363026, 1.1486388, 1.0363026, 1.1486388,
1, 1.0000064, 1.0641243, 1 }},
"bicubic_border_align");
params.emplace_back(data_even_dims,
grid,
op::v9::GridSample::Attributes{false, GS_BICUBIC, GS_REFLECTION},
reference_tests::Tensor{{1, 1, 4, 4},
element::f32,
std::vector<float>{ 2.6663566, 3.527928, 2.6663566, 3.527928,
1.5380859, 2.4677734, 1.5380859, 2.4677734,
1.0150609, 0.904375, 1.0150609, 0.904375,
5.48851, 0.898316, 0.8237547, 0.8125 }},
"bicubic_reflection_noalign");
params.emplace_back(data_even_dims,
grid,
op::v9::GridSample::Attributes{true, GS_BICUBIC, GS_REFLECTION},
reference_tests::Tensor{{1, 1, 4, 4},
element::f32,
std::vector<float>{ 2.7887204, 3.4506166, 2.7887204, 3.4506166,
1.7745361, 2.6518555, 1.7745361, 2.6518555,
1.0085088, 1.0307077, 1.0085088, 1.0307077,
5.5649586, 1.0553409, 1.0011607, 1 }},
"bicubic_reflection_align");
// clang-format on
return params;
}
std::vector<GridSampleParams> generateBicubicBatchesParams() {
std::vector<GridSampleParams> params;
reference_tests::Tensor data{{2, 2, 4, 3},
element::f32,
std::vector<float>{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48}};
reference_tests::Tensor grid{{2, 2, 4, 2},
element::f32,
std::vector<float>{-0.1, -0.1, -0.1, 0.1, 0.1, -0.1, 0.1, 0.1, -0.5, -0.5, -0.5,
0.5, 0.5, -0.5, 0.5, 0.5, -0.9, -0.9, -0.9, 0.9, 0.9, -0.9,
0.9, 0.9, -1.75, 0.7, 1.33, -1.11, 0.965, 1.007, 21, 37}};
params.emplace_back(
data,
grid,
op::v9::GridSample::Attributes{true, GS_BICUBIC, GS_BORDER},
reference_tests::Tensor{
{2, 2, 2, 4},
element::f32,
std::vector<float>{6.0096254, 6.7048755, 6.2951245, 6.9903746, 3.4101562, 8.402344, 4.5976562, 9.589844,
18.009624, 18.704876, 18.295124, 18.990376, 15.410156, 20.402344, 16.597656, 21.589844,
25.415281, 33.735218, 27.26478, 35.58472, 32.884, 26.852259, 35.996872, 36.,
37.41528, 45.735218, 39.264782, 47.58472, 44.884, 38.852257, 47.996872, 48.}},
"bicubic_border_align_batches");
params.emplace_back(
data,
grid,
op::v9::GridSample::Attributes{false, GS_BICUBIC, GS_REFLECTION},
reference_tests::Tensor{
{2, 2, 2, 4},
element::f32,
std::vector<float>{5.8170314, 6.7650313, 6.2349687, 7.182969, 2.4101562, 8.972656, 4.0273438, 10.589844,
17.81703, 18.765032, 18.234968, 19.18297, 14.410156, 20.972656, 16.027344, 22.589844,
24.356874, 34.301876, 26.698126, 36.643124, 34.304035, 26.55013, 36.74749, 36.75,
36.356876, 46.301876, 38.698124, 48.643124, 46.304035, 38.55013, 48.74749, 48.75}},
"bicubic_reflection_noalign_batches");
return params;
}
std::vector<GridSampleParams> generateGridSampleParams() {
std::vector<std::vector<GridSampleParams>> combo_params{generateNearestParamsOddDimensionsInnerGrids(),
generateNearestParamsOddDimensionsOuterGrids(),
generateNearestParamsEvenDimensions(),
generateBilinearParamsOddDimensionsInnerGrids(),
generateBilinearParamsOddDimensionsOuterGrids(),
generateBilinearParamsEvenDimensions(),
generateBicubicParams(),
generateBicubicBatchesParams()};
std::vector<GridSampleParams> test_params;
for (auto& params : combo_params)
std::move(params.begin(), params.end(), std::back_inserter(test_params));
return test_params;
}
} // namespace
TEST_P(ReferenceGridSample, LayerTest) {
Exec();
}
INSTANTIATE_TEST_SUITE_P(smoke,
ReferenceGridSample,
::testing::ValuesIn(generateGridSampleParams()),
ReferenceGridSample::getTestCaseName);
-4
View File
@@ -127,10 +127,6 @@ xfail_issue_68212 = xfail_test(reason="Unsupported reading model with bytes stre
xfail_issue_78843 = xfail_test(reason="Missing reference output files for ssd mobilenet models")
xfail_issue_81974 = xfail_test(reason="RuntimeError: OpenVINO does not support the following ONNX "
"operations: GridSample, Optional, SequenceConstruct, "
"OptionalHasElement, SequenceInsert")
xfail_issue_81976 = xfail_test(reason="RuntimeError: z node not found in graph cache")
xfail_issue_82038 = xfail_test(reason="ScatterElements, ScatterND, AssertionError: Result mismatch")
xfail_issue_82039 = xfail_test(reason="Unsupported data type Optional, RuntimeError: [ NOT_IMPLEMENTED ] "
@@ -45,7 +45,6 @@ from tests import (
xfail_issue_63137,
xfail_issue_63138,
xfail_issue_69444,
xfail_issue_81974,
xfail_issue_81976,
skip_segfault,
xfail_issue_82038,
@@ -368,17 +367,6 @@ tests_expected_to_fail = [
"OnnxBackendNodeModelTest.test_sce_NCd1d2d3d4d5_mean_weight_cpu", # ticket: 81976
"OnnxBackendNodeModelTest.test_sce_NCd1d2d3d4d5_mean_weight_log_prob_cpu", # ticket: 81976
),
(
xfail_issue_81974,
"OnnxBackendNodeModelTest.test_gridsample_aligncorners_true_cpu",
"OnnxBackendNodeModelTest.test_gridsample_bicubic_cpu",
"OnnxBackendNodeModelTest.test_gridsample_bilinear_cpu",
"OnnxBackendNodeModelTest.test_gridsample_border_padding_cpu",
"OnnxBackendNodeModelTest.test_gridsample_cpu",
"OnnxBackendNodeModelTest.test_gridsample_nearest_cpu",
"OnnxBackendNodeModelTest.test_gridsample_reflection_padding_cpu",
"OnnxBackendNodeModelTest.test_gridsample_zeros_padding_cpu",
),
(
xfail_issue_81976, # SoftmaxCrossEntropyLoss operator
"OnnxBackendNodeModelTest.test_sce_NCd1d2d3_none_no_weight_negative_ii_cpu",
@@ -138,10 +138,6 @@ xfail_issue_78843 = xfail_test(reason="Missing reference output files for ssd mo
xfail_issue_78741 = xfail_test(reason="Cannot get dims for non-static shapes. "
"Requires dynamism support enabled.")
xfail_issue_81974 = xfail_test(reason="RuntimeError: OpenVINO does not support the following ONNX "
"operations: GridSample, Optional, SequenceConstruct, "
"OptionalHasElement, SequenceInsert")
xfail_issue_81976 = xfail_test(reason="RuntimeError: z node not found in graph cache")
xfail_issue_82038 = xfail_test(reason="ScatterElements, ScatterND, AssertionError: Result mismatch")
xfail_issue_82039 = xfail_test(reason="Unsupported data type Optional, RuntimeError: [ NOT_IMPLEMENTED ] "
@@ -45,7 +45,6 @@ from tests_compatibility import (
xfail_issue_63138,
xfail_issue_69444,
xfail_issue_78741,
xfail_issue_81974,
xfail_issue_81976,
skip_segfault,
xfail_issue_82038,
@@ -450,17 +449,6 @@ tests_expected_to_fail = [
"OnnxBackendNodeModelTest.test_sce_NCd1d2d3d4d5_mean_weight_cpu", # ticket: 81976
"OnnxBackendNodeModelTest.test_sce_NCd1d2d3d4d5_mean_weight_log_prob_cpu", # ticket: 81976
),
(
xfail_issue_81974,
"OnnxBackendNodeModelTest.test_gridsample_aligncorners_true_cpu",
"OnnxBackendNodeModelTest.test_gridsample_bicubic_cpu",
"OnnxBackendNodeModelTest.test_gridsample_bilinear_cpu",
"OnnxBackendNodeModelTest.test_gridsample_border_padding_cpu",
"OnnxBackendNodeModelTest.test_gridsample_cpu",
"OnnxBackendNodeModelTest.test_gridsample_nearest_cpu",
"OnnxBackendNodeModelTest.test_gridsample_reflection_padding_cpu",
"OnnxBackendNodeModelTest.test_gridsample_zeros_padding_cpu",
),
(
xfail_issue_81976, # SoftmaxCrossEntropyLoss operator
"OnnxBackendNodeModelTest.test_sce_NCd1d2d3_none_no_weight_negative_ii_cpu",
@@ -30,6 +30,12 @@ public:
InterpolationMode mode = InterpolationMode::BILINEAR;
// Specifies how the out-of-bounds coordinates should be handled: `zeros`, `border`, `reflection`
PaddingMode padding_mode = PaddingMode::ZEROS;
Attributes() = default;
Attributes(bool align_corners, InterpolationMode mode, PaddingMode padding_mode)
: align_corners{align_corners},
mode{mode},
padding_mode{padding_mode} {}
};
GridSample() = default;
@@ -49,6 +55,11 @@ public:
return m_attributes;
}
OPENVINO_SUPPRESS_DEPRECATED_START
bool evaluate(const HostTensorVector& outputs, const HostTensorVector& inputs) const override;
OPENVINO_SUPPRESS_DEPRECATED_END
bool has_evaluate() const override;
private:
Attributes m_attributes = {};
};
@@ -0,0 +1,295 @@
// Copyright (C) 2022 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#pragma once
#include <algorithm>
#include <array>
#include <cassert>
#include <cfenv>
#include <cmath>
#include "ngraph/shape.hpp"
#include "openvino/op/grid_sample.hpp"
namespace ngraph {
namespace runtime {
namespace reference {
namespace {
using index_4D_t = typename std::array<size_t, 4>;
template <typename GRID_ET>
using denormalize_fn_t = typename std::function<GRID_ET(GRID_ET, size_t)>;
template <typename DATA_ET>
using get_padded_fn_t = typename std::function<DATA_ET(const DATA_ET*, const Shape&, size_t, size_t, long, long)>;
template <typename T>
T& get_single_value(T* buffer, const Shape& shape, const index_4D_t& index) {
// In this context below assertion is guaranteed by grid_sample(..) function.
// assert(shape.size() == index.size());
auto sx = shape.back();
auto offset = index.back();
for (auto i = index.size() - 2; i > 0; --i) {
offset += index[i] * sx;
sx *= shape[i];
}
offset += index[0] * sx;
return buffer[offset];
}
template <typename GRID_ET>
GRID_ET rescale_align(GRID_ET value, size_t range) {
return (value + 1) * (static_cast<GRID_ET>(range) - 1) / 2;
}
template <typename GRID_ET>
GRID_ET rescale_noalign(GRID_ET value, size_t range) {
return ((value + 1) * static_cast<GRID_ET>(range) - 1) / 2;
}
template <typename DATA_ET>
DATA_ET zeros_padding(const DATA_ET* data,
const Shape& data_shape,
const size_t n,
const size_t c,
const long y_d,
const long x_d) {
const auto H = static_cast<long>(data_shape[2]);
const auto W = static_cast<long>(data_shape[3]);
if (y_d < 0 || x_d < 0 || y_d >= H || x_d >= W) {
return 0;
} else {
const auto y = static_cast<size_t>(y_d);
const auto x = static_cast<size_t>(x_d);
return get_single_value(data, data_shape, index_4D_t{n, c, y, x});
}
}
template <typename DATA_ET>
DATA_ET border_padding(const DATA_ET* data,
const Shape& data_shape,
const size_t n,
const size_t c,
const long y_d,
const long x_d) {
const auto H = static_cast<long>(data_shape[2]);
const auto W = static_cast<long>(data_shape[3]);
const auto y = static_cast<size_t>(std::min(std::max(y_d, 0l), H - 1));
const auto x = static_cast<size_t>(std::min(std::max(x_d, 0l), W - 1));
return get_single_value(data, data_shape, index_4D_t{n, c, y, x});
}
template <typename DATA_ET>
DATA_ET reflection_data_no_align(const DATA_ET* data,
const Shape& data_shape,
const size_t n,
const size_t c,
long y_d,
long x_d) {
const auto H = static_cast<long>(data_shape[2]);
const auto W = static_cast<long>(data_shape[3]);
const auto H_2 = static_cast<long>(data_shape[2]) * 2l;
const auto W_2 = static_cast<long>(data_shape[3]) * 2l;
y_d = (y_d % H_2 + H_2) % H_2;
x_d = (x_d % W_2 + W_2) % W_2;
const auto y = static_cast<size_t>(y_d >= H ? H_2 - 1 - y_d : y_d);
const auto x = static_cast<size_t>(x_d >= W ? W_2 - 1 - x_d : x_d);
return get_single_value(data, data_shape, index_4D_t{n, c, y, x});
}
template <typename DATA_ET>
DATA_ET reflection_data_with_align(const DATA_ET* data,
const Shape& data_shape,
const size_t n,
const size_t c,
long y_d,
long x_d) {
const auto H = static_cast<long>(data_shape[2]);
const auto W = static_cast<long>(data_shape[3]);
const auto H_2_2 = 2 * (H - 1);
const auto W_2_2 = 2 * (W - 1);
y_d = std::abs(y_d) % H_2_2;
x_d = std::abs(x_d) % W_2_2;
const auto y = static_cast<size_t>(y_d >= H ? H_2_2 - y_d : y_d);
const auto x = static_cast<size_t>(x_d >= W ? W_2_2 - x_d : x_d);
return get_single_value(data, data_shape, index_4D_t{n, c, y, x});
}
template <typename DATA_ET, typename GRID_ET>
DATA_ET bilinear(const DATA_ET* data,
const Shape& data_shape,
const size_t n,
const size_t c,
const GRID_ET y_n,
const GRID_ET x_n,
const get_padded_fn_t<DATA_ET>& get_padded,
const denormalize_fn_t<GRID_ET>& denormalize) {
const auto y_d = denormalize(y_n, data_shape[2]);
const auto x_d = denormalize(x_n, data_shape[3]);
const auto y_topleft = std::floor(y_d);
const auto x_topleft = std::floor(x_d);
const auto dy = y_d - y_topleft;
const auto dx = x_d - x_topleft;
const auto v00 = get_padded(data, data_shape, n, c, y_topleft, x_topleft);
const auto v01 = get_padded(data, data_shape, n, c, y_topleft, x_topleft + 1);
const auto v10 = get_padded(data, data_shape, n, c, y_topleft + 1, x_topleft);
const auto v11 = get_padded(data, data_shape, n, c, y_topleft + 1, x_topleft + 1);
const auto q0 = (1 - dx) * v00 + dx * v01;
const auto q1 = (1 - dx) * v10 + dx * v11;
return dy * q1 + (1 - dy) * q0;
}
template <typename DATA_ET, typename GRID_ET>
DATA_ET nearest(const DATA_ET* data,
const Shape& data_shape,
const size_t n,
const size_t c,
const GRID_ET y_n,
const GRID_ET x_n,
const get_padded_fn_t<DATA_ET>& get_padded,
const denormalize_fn_t<GRID_ET>& denormalize) {
const auto y_nearest = std::lrint(denormalize(y_n, data_shape[2]));
const auto x_nearest = std::lrint(denormalize(x_n, data_shape[3]));
return get_padded(data, data_shape, n, c, y_nearest, x_nearest);
}
template <typename T>
using vector_4_t = typename std::array<T, 4>;
template <typename T>
using matrix_4x4_t = typename std::array<vector_4_t<T>, 4>;
// formula taken from
// https://github.com/onnx/onnx/blob/a92870cdf359297495a118184dca2eaecee4b717/onnx/backend/test/case/node/resize.py#L201-L207
template <typename T>
vector_4_t<T> cubic_coeffs(const T r, const T A = -0.75) {
vector_4_t<T> v;
v[0] = ((A * (r + 1) - 5 * A) * (r + 1) + 8 * A) * (r + 1) - 4 * A;
v[1] = ((A + 2) * r - (A + 3)) * r * r + 1;
v[2] = ((A + 2) * (1 - r) - (A + 3)) * (1 - r) * (1 - r) + 1;
v[3] = ((A * (2 - r) - 5 * A) * (2 - r) + 8 * A) * (2 - r) - 4 * A;
return v;
}
template <typename DATA_ET>
matrix_4x4_t<DATA_ET> gather_4x4(const DATA_ET* data,
const Shape& data_shape,
const size_t n,
const size_t c,
const long y_topleft,
const long x_topleft,
const get_padded_fn_t<DATA_ET>& get_padded) {
matrix_4x4_t<DATA_ET> s;
for (int j = 0; j < 4; ++j)
for (int i = 0; i < 4; ++i)
s[j][i] = get_padded(data, data_shape, n, c, y_topleft + j, x_topleft + i);
return s;
}
template <typename DATA_ET, typename GRID_ET>
DATA_ET bicubic(const DATA_ET* data,
const Shape& data_shape,
const size_t n,
const size_t c,
const GRID_ET y_n,
const GRID_ET x_n,
const get_padded_fn_t<DATA_ET>& get_padded,
const denormalize_fn_t<GRID_ET>& denormalize) {
const auto y_d = denormalize(y_n, data_shape[2]);
const auto x_d = denormalize(x_n, data_shape[3]);
const auto y_topleft = std::floor(y_d);
const auto x_topleft = std::floor(x_d);
const auto dy = y_d - y_topleft;
const auto dx = x_d - x_topleft;
const auto s = gather_4x4(data, data_shape, n, c, y_topleft - 1, x_topleft - 1, get_padded);
const auto cy = cubic_coeffs(dy);
const auto cx = cubic_coeffs(dx);
vector_4_t<DATA_ET> p;
std::transform(s.begin(), s.end(), p.begin(), [&cx](const vector_4_t<DATA_ET>& v) {
return std::inner_product(cx.begin(), cx.end(), v.begin(), static_cast<DATA_ET>(0));
});
return std::inner_product(cy.begin(), cy.end(), p.begin(), static_cast<DATA_ET>(0));
}
} // namespace
template <typename DATA_ET, typename GRID_ET>
void grid_sample(DATA_ET* output,
const DATA_ET* data,
const GRID_ET* grid,
const Shape& data_shape,
const Shape& grid_shape,
const bool align_corners,
const ov::op::v9::GridSample::InterpolationMode interpolation_mode,
const ov::op::v9::GridSample::PaddingMode padding_mode) {
assert(data_shape.size() == 4 && grid_shape.size() == 4);
assert(data_shape[0] == grid_shape[0] and grid_shape[3] == 2);
const auto N = data_shape[0];
const auto C = data_shape[1];
const auto H_out = grid_shape[1];
const auto W_out = grid_shape[2];
const Shape output_shape{N, C, H_out, W_out};
const auto prev_rounding_mode = std::fegetround();
std::fesetround(FE_TONEAREST);
get_padded_fn_t<DATA_ET> get_padded_fn;
switch (padding_mode) {
default:
case ov::op::v9::GridSample::PaddingMode::ZEROS:
get_padded_fn = zeros_padding<DATA_ET>;
break;
case ov::op::v9::GridSample::PaddingMode::BORDER:
get_padded_fn = border_padding<DATA_ET>;
break;
case ov::op::v9::GridSample::PaddingMode::REFLECTION:
if (align_corners)
get_padded_fn = reflection_data_with_align<DATA_ET>;
else
get_padded_fn = reflection_data_no_align<DATA_ET>;
break;
}
denormalize_fn_t<GRID_ET> denormalize_fn;
if (align_corners)
denormalize_fn = rescale_align<GRID_ET>;
else
denormalize_fn = rescale_noalign<GRID_ET>;
for (size_t n = 0; n < N; ++n) {
for (size_t c = 0; c < C; ++c) {
for (size_t y = 0; y < H_out; ++y) {
for (size_t x = 0; x < W_out; ++x) {
const auto y_n = get_single_value(grid, grid_shape, index_4D_t{n, y, x, 1});
const auto x_n = get_single_value(grid, grid_shape, index_4D_t{n, y, x, 0});
auto& out = get_single_value(output, output_shape, index_4D_t{n, c, y, x});
switch (interpolation_mode) {
case ov::op::v9::GridSample::InterpolationMode::BILINEAR:
out =
bilinear<DATA_ET, GRID_ET>(data, data_shape, n, c, y_n, x_n, get_padded_fn, denormalize_fn);
break;
case ov::op::v9::GridSample::InterpolationMode::NEAREST:
out =
nearest<DATA_ET, GRID_ET>(data, data_shape, n, c, y_n, x_n, get_padded_fn, denormalize_fn);
break;
case ov::op::v9::GridSample::InterpolationMode::BICUBIC:
out =
bicubic<DATA_ET, GRID_ET>(data, data_shape, n, c, y_n, x_n, get_padded_fn, denormalize_fn);
break;
}
}
}
}
}
std::fesetround(prev_rounding_mode);
}
} // namespace reference
} // namespace runtime
} // namespace ngraph
+72
View File
@@ -6,6 +6,8 @@
#include "grid_sample_shape_inference.hpp"
#include "itt.hpp"
#include "ngraph/runtime/reference/grid_sample.hpp"
#include "ngraph/validation_util.hpp"
namespace ov {
op::v9::GridSample::GridSample(const Output<Node>& data, const Output<Node>& grid, const Attributes& attributes)
@@ -43,6 +45,10 @@ std::ostream& operator<<(std::ostream& s, const op::v9::GridSample::Interpolatio
return s << as_string(mode);
}
std::ostream& operator<<(std::ostream& s, const op::v9::GridSample::PaddingMode& padding_mode) {
return s << as_string(padding_mode);
}
template <>
NGRAPH_API EnumNames<op::v9::GridSample::InterpolationMode>& EnumNames<op::v9::GridSample::InterpolationMode>::get() {
static auto enum_names =
@@ -62,4 +68,70 @@ NGRAPH_API EnumNames<op::v9::GridSample::PaddingMode>& EnumNames<op::v9::GridSam
{"reflection", op::v9::GridSample::PaddingMode::REFLECTION}});
return enum_names;
}
namespace {
template <element::Type_t DATA_ET, element::Type_t GRID_ET>
bool evaluate_exec(const HostTensorPtr& output,
const HostTensorPtr& data,
const HostTensorPtr& grid,
const op::v9::GridSample::Attributes& attributes) {
ngraph::runtime::reference::grid_sample(output->get_data_ptr<DATA_ET>(),
data->get_data_ptr<DATA_ET>(),
grid->get_data_ptr<GRID_ET>(),
data->get_shape(),
grid->get_shape(),
attributes.align_corners,
attributes.mode,
attributes.padding_mode);
return true;
}
#define GRID_SAMPLE_TYPE_CASE(a, ...) \
case element::Type_t::a: { \
NGRAPH_OP_SCOPE(OV_PP_CAT3(evaluate_exec_grid_sample, _, a)); \
rc = evaluate_exec<DATA_ET, element::Type_t::a>(__VA_ARGS__); \
} break
template <element::Type_t DATA_ET>
bool evaluate(const HostTensorPtr& output,
const HostTensorPtr& data,
const HostTensorPtr& grid,
const op::v9::GridSample::Attributes& attributes) {
auto rc = true;
switch (grid->get_element_type()) {
GRID_SAMPLE_TYPE_CASE(f32, output, data, grid, attributes);
default:
rc = false;
break;
}
return rc;
}
bool evaluate_grid_sample(const HostTensorPtr& output,
const HostTensorPtr& data,
const HostTensorPtr& grid,
const op::v9::GridSample::Attributes& attributes) {
auto rc = true;
switch (output->get_element_type()) {
NGRAPH_TYPE_CASE(evaluate_grid_sample, f32, output, data, grid, attributes);
default:
rc = false;
break;
}
return rc;
}
} // namespace
bool op::v9::GridSample::evaluate(const HostTensorVector& outputs, const HostTensorVector& inputs) const {
NGRAPH_OP_SCOPE(v9_GridSample_evaluate);
OPENVINO_ASSERT(ngraph::validate_host_tensor_vector(inputs, 2), "Invalid GridSample input TensorVector.");
OPENVINO_ASSERT(ngraph::validate_host_tensor_vector(outputs, 1), "Invalid GridSample output TensorVector.");
return evaluate_grid_sample(outputs[0], inputs[0], inputs[1], m_attributes);
}
bool op::v9::GridSample::has_evaluate() const {
return get_input_element_type(0) == element::f32 && get_input_element_type(1) == element::f32;
}
} // namespace ov
@@ -425,5 +425,3 @@ IE_CPU.onnx_softmax_crossentropy_loss_mean
# Cannot find blob with name: Y
IE_CPU.onnx_bool_init_and
onnx_grid_sample
@@ -82,5 +82,3 @@ onnx_clip_no_min_no_max_int64
# z node not found in graph cache - ticket: 81976
INTERPRETER.onnx_expand_context_dependent_function
INTERPRETER.onnx_softmax_crossentropy_loss_mean
onnx_grid_sample