Skip to content
This repository has been archived by the owner on Jan 3, 2023. It is now read-only.

Commit

Permalink
Enable Gather with negative indices. (#3701)
Browse files Browse the repository at this point in the history
* Enable Gather with negative indices.

* Address PR feedback.

* Remove GOE from Gather unit tests.
  • Loading branch information
ayzhuang authored and diyessi committed Oct 3, 2019
1 parent b8266ca commit dd8c9ed
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 31 deletions.
13 changes: 11 additions & 2 deletions src/ngraph/runtime/cpu/kernel/gather.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ namespace ngraph
Eigen::array<Eigen::Index, Rank1> in_dims;
Eigen::array<Eigen::Index, Rank2> out_dims;

auto axis_length = inputs_shape[axis];

for (int i = 0; i < Rank1; i++)
{
in_dims[i] = inputs_shape[i];
Expand All @@ -84,6 +86,7 @@ namespace ngraph
static_cast<ElementType*>(inputs), in_dims);

auto indices_ptr = static_cast<IndicesType*>(indices);
IndicesType index_value;
auto indices_rank = indices_shape.size();
auto outer_loop_num = 1;
for (int i = 0; i < axis; i++)
Expand Down Expand Up @@ -123,7 +126,10 @@ namespace ngraph
// at axis
in_extents[axis] = 1;
// at axis, get the value from indices arg
in_offsets[axis] = indices_ptr[0];
index_value = indices_ptr[0];
// take care of negative indices
in_offsets[axis] =
index_value >= 0 ? index_value : index_value + axis_length;

// before axis
for (int r = 0; r < axis; r++)
Expand Down Expand Up @@ -193,7 +199,10 @@ namespace ngraph
}
// at axis, get the value from indices arg
int k = i % num_indices;
in_offsets[axis] = indices_ptr[k];
index_value = indices_ptr[k];
// take care of negative indices
in_offsets[axis] =
index_value >= 0 ? index_value : index_value + axis_length;

// indices_from_indices_arg depends on indices_shape and k.
// suppose the inputs has shape {3, 3, 3}, indices has shape {2, 2}, and
Expand Down
1 change: 1 addition & 0 deletions src/ngraph/runtime/intelgpu/unit_test.manifest
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ gather_2d_indices_axis_1_2d_input
gather_scalar_indices_no_axis_2d_input
gather_1d_indices_no_axis_1d_input
gather_2d_indices_no_axis_2d_input
gather_2d_negative_and_positive_indices_no_axis_2d_input
gather_3d_indices_no_axis_2d_input
gather_4d_indices_no_axis_2d_input
gemm
Expand Down
1 change: 1 addition & 0 deletions src/ngraph/runtime/plaidml/unit_test.manifest
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,7 @@ gather_4d_indices_no_axis_uint8
gather_4d_indices_no_axis_2d_input
gather_3d_indices_no_axis_2d_input
gather_2d_indices_no_axis_2d_input
gather_2d_negative_and_positive_indices_no_axis_2d_input
gather_1d_indices_no_axis_1d_input
gather_scalar_indices_no_axis_2d_input
gather_2d_indices_axis_1_2d_input
Expand Down
2 changes: 2 additions & 0 deletions src/ngraph/runtime/reference/gather_nd.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@ namespace ngraph
for (size_t i = 0; i < slice_rank; i++)
{
U index = indices[indices_index];
// take care of negative indices
index = index >= 0 ? index : index + params_shape[i];
params_start_corner[i] = index;
params_end_corner[i] = index + 1;
indices_index++;
Expand Down
84 changes: 55 additions & 29 deletions test/backend/gather.in.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ NGRAPH_TEST(${BACKEND_NAME}, gather_4d_indices_no_axis_uint8)
auto P = make_shared<op::Parameter>(element::u8, params_shape);
auto I = make_shared<op::Parameter>(element::i32, indices_shape);
auto G = make_shared<op::Gather>(P, I);
auto f = make_shared<Function>(make_shared<op::GetOutputElement>(G, 0), ParameterVector{P, I});
auto f = make_shared<Function>(G, ParameterVector{P, I});

auto backend = runtime::Backend::create("${BACKEND_NAME}");

Expand Down Expand Up @@ -77,7 +77,7 @@ NGRAPH_TEST(${BACKEND_NAME}, gather_4d_indices_no_axis_2d_input)
auto P = make_shared<op::Parameter>(element::f32, params_shape);
auto I = make_shared<op::Parameter>(element::i32, indices_shape);
auto G = make_shared<op::Gather>(P, I);
auto f = make_shared<Function>(make_shared<op::GetOutputElement>(G, 0), ParameterVector{P, I});
auto f = make_shared<Function>(G, ParameterVector{P, I});

auto backend = runtime::Backend::create("${BACKEND_NAME}");

Expand Down Expand Up @@ -113,7 +113,7 @@ NGRAPH_TEST(${BACKEND_NAME}, gather_3d_indices_no_axis_2d_input)
auto P = make_shared<op::Parameter>(element::f32, params_shape);
auto I = make_shared<op::Parameter>(element::i32, indices_shape);
auto G = make_shared<op::Gather>(P, I);
auto f = make_shared<Function>(make_shared<op::GetOutputElement>(G, 0), ParameterVector{P, I});
auto f = make_shared<Function>(G, ParameterVector{P, I});

auto backend = runtime::Backend::create("${BACKEND_NAME}");

Expand Down Expand Up @@ -144,7 +144,7 @@ NGRAPH_TEST(${BACKEND_NAME}, gather_2d_indices_no_axis_2d_input)
auto P = make_shared<op::Parameter>(element::f32, params_shape);
auto I = make_shared<op::Parameter>(element::i32, indices_shape);
auto G = make_shared<op::Gather>(P, I);
auto f = make_shared<Function>(make_shared<op::GetOutputElement>(G, 0), ParameterVector{P, I});
auto f = make_shared<Function>(G, ParameterVector{P, I});

auto backend = runtime::Backend::create("${BACKEND_NAME}");

Expand All @@ -162,6 +162,32 @@ NGRAPH_TEST(${BACKEND_NAME}, gather_2d_indices_no_axis_2d_input)
MIN_FLOAT_TOLERANCE_BITS));
}

NGRAPH_TEST(${BACKEND_NAME}, gather_2d_negative_and_positive_indices_no_axis_2d_input)
{
Shape params_shape{3, 2};
Shape indices_shape{2, 2};
Shape out_shape{2, 2, 2};
auto P = make_shared<op::Parameter>(element::f32, params_shape);
auto I = make_shared<op::Parameter>(element::i32, indices_shape);
auto G = make_shared<op::Gather>(P, I);
auto f = make_shared<Function>(G, ParameterVector{P, I});

auto backend = runtime::Backend::create("${BACKEND_NAME}");

// Create some tensors for input/output
auto p = backend->create_tensor(element::f32, params_shape);
copy_data(p, vector<float>{1.0f, 1.1f, 2.0f, 2.1f, 3.0f, 3.1f});
auto i = backend->create_tensor(element::i32, indices_shape);
copy_data(i, vector<int32_t>{0, -2, 1, 2});
auto result = backend->create_tensor(element::f32, out_shape);

auto c = backend->compile(f);
c->call_with_validate({result}, {p, i});
EXPECT_TRUE(test::all_close_f((vector<float>{1.0f, 1.1f, 2.0f, 2.1f, 2.0f, 2.1f, 3.0f, 3.1f}),
read_vector<float>(result),
MIN_FLOAT_TOLERANCE_BITS));
}

NGRAPH_TEST(${BACKEND_NAME}, gather_1d_indices_no_axis_1d_input)
{
Shape params_shape{3};
Expand All @@ -170,7 +196,7 @@ NGRAPH_TEST(${BACKEND_NAME}, gather_1d_indices_no_axis_1d_input)
auto P = make_shared<op::Parameter>(element::f32, params_shape);
auto I = make_shared<op::Parameter>(element::i32, indices_shape);
auto G = make_shared<op::Gather>(P, I);
auto f = make_shared<Function>(make_shared<op::GetOutputElement>(G, 0), ParameterVector{P, I});
auto f = make_shared<Function>(G, ParameterVector{P, I});

auto backend = runtime::Backend::create("${BACKEND_NAME}");

Expand All @@ -195,7 +221,7 @@ NGRAPH_TEST(${BACKEND_NAME}, gather_scalar_indices_no_axis_2d_input)
auto P = make_shared<op::Parameter>(element::f32, params_shape);
auto I = make_shared<op::Parameter>(element::i32, indices_shape);
auto G = make_shared<op::Gather>(P, I);
auto f = make_shared<Function>(make_shared<op::GetOutputElement>(G, 0), ParameterVector{P, I});
auto f = make_shared<Function>(G, ParameterVector{P, I});

auto backend = runtime::Backend::create("${BACKEND_NAME}");

Expand All @@ -220,7 +246,7 @@ NGRAPH_TEST(${BACKEND_NAME}, gather_2d_indices_axis_1_2d_input)
auto P = make_shared<op::Parameter>(element::f32, params_shape);
auto I = make_shared<op::Parameter>(element::i32, indices_shape);
auto G = make_shared<op::Gather>(P, I, 1);
auto f = make_shared<Function>(make_shared<op::GetOutputElement>(G, 0), ParameterVector{P, I});
auto f = make_shared<Function>(G, ParameterVector{P, I});

auto backend = runtime::Backend::create("${BACKEND_NAME}");

Expand All @@ -246,7 +272,7 @@ NGRAPH_TEST(${BACKEND_NAME}, gather_1d_indices_axis_2_4d_input)
auto P = make_shared<op::Parameter>(element::f32, params_shape);
auto I = make_shared<op::Parameter>(element::i32, indices_shape);
auto G = make_shared<op::Gather>(P, I, 2);
auto f = make_shared<Function>(make_shared<op::GetOutputElement>(G, 0), ParameterVector{P, I});
auto f = make_shared<Function>(G, ParameterVector{P, I});

auto backend = runtime::Backend::create("${BACKEND_NAME}");

Expand Down Expand Up @@ -277,7 +303,7 @@ NGRAPH_TEST(${BACKEND_NAME}, gather_scalar_indices_axis_1_2d_input)
auto P = make_shared<op::Parameter>(element::f32, params_shape);
auto I = make_shared<op::Parameter>(element::i32, indices_shape);
auto G = make_shared<op::Gather>(P, I, 1);
auto f = make_shared<Function>(make_shared<op::GetOutputElement>(G, 0), ParameterVector{P, I});
auto f = make_shared<Function>(G, ParameterVector{P, I});

auto backend = runtime::Backend::create("${BACKEND_NAME}");

Expand All @@ -302,7 +328,7 @@ NGRAPH_TEST(${BACKEND_NAME}, gather_nd_single_indices)
auto P = make_shared<op::Parameter>(element::f32, params_shape);
auto I = make_shared<op::Parameter>(element::i32, indices_shape);
auto G = make_shared<op::GatherND>(P, I);
auto f = make_shared<Function>(make_shared<op::GetOutputElement>(G, 0), ParameterVector{P, I});
auto f = make_shared<Function>(G, ParameterVector{P, I});

auto backend = runtime::Backend::create("${BACKEND_NAME}");

Expand All @@ -327,7 +353,7 @@ NGRAPH_TEST(${BACKEND_NAME}, gather_nd_scalar_from_2d)
auto P = make_shared<op::Parameter>(element::f32, params_shape);
auto I = make_shared<op::Parameter>(element::i32, indices_shape);
auto G = make_shared<op::GatherND>(P, I);
auto f = make_shared<Function>(make_shared<op::GetOutputElement>(G, 0), ParameterVector{P, I});
auto f = make_shared<Function>(G, ParameterVector{P, I});

auto backend = runtime::Backend::create("${BACKEND_NAME}");

Expand All @@ -352,7 +378,7 @@ NGRAPH_TEST(${BACKEND_NAME}, gather_nd_1d_from_2d)
auto P = make_shared<op::Parameter>(element::f32, params_shape);
auto I = make_shared<op::Parameter>(element::i32, indices_shape);
auto G = make_shared<op::GatherND>(P, I);
auto f = make_shared<Function>(make_shared<op::GetOutputElement>(G, 0), ParameterVector{P, I});
auto f = make_shared<Function>(G, ParameterVector{P, I});

auto backend = runtime::Backend::create("${BACKEND_NAME}");

Expand All @@ -378,7 +404,7 @@ NGRAPH_TEST(${BACKEND_NAME}, gather_nd_scalar_from_3d)
auto P = make_shared<op::Parameter>(element::f32, params_shape);
auto I = make_shared<op::Parameter>(element::i32, indices_shape);
auto G = make_shared<op::GatherND>(P, I);
auto f = make_shared<Function>(make_shared<op::GetOutputElement>(G, 0), ParameterVector{P, I});
auto f = make_shared<Function>(G, ParameterVector{P, I});

auto backend = runtime::Backend::create("${BACKEND_NAME}");

Expand All @@ -403,7 +429,7 @@ NGRAPH_TEST(${BACKEND_NAME}, gather_nd_1d_from_3d)
auto P = make_shared<op::Parameter>(element::f32, params_shape);
auto I = make_shared<op::Parameter>(element::i32, indices_shape);
auto G = make_shared<op::GatherND>(P, I);
auto f = make_shared<Function>(make_shared<op::GetOutputElement>(G, 0), ParameterVector{P, I});
auto f = make_shared<Function>(G, ParameterVector{P, I});

auto backend = runtime::Backend::create("${BACKEND_NAME}");

Expand All @@ -429,7 +455,7 @@ NGRAPH_TEST(${BACKEND_NAME}, gather_nd_2d_from_3d)
auto P = make_shared<op::Parameter>(element::f32, params_shape);
auto I = make_shared<op::Parameter>(element::i32, indices_shape);
auto G = make_shared<op::GatherND>(P, I);
auto f = make_shared<Function>(make_shared<op::GetOutputElement>(G, 0), ParameterVector{P, I});
auto f = make_shared<Function>(G, ParameterVector{P, I});

auto backend = runtime::Backend::create("${BACKEND_NAME}");

Expand All @@ -455,7 +481,7 @@ NGRAPH_TEST(${BACKEND_NAME}, gather_nd_batch_scalar_from_2d)
auto P = make_shared<op::Parameter>(element::f32, params_shape);
auto I = make_shared<op::Parameter>(element::i32, indices_shape);
auto G = make_shared<op::GatherND>(P, I);
auto f = make_shared<Function>(make_shared<op::GetOutputElement>(G, 0), ParameterVector{P, I});
auto f = make_shared<Function>(G, ParameterVector{P, I});

auto backend = runtime::Backend::create("${BACKEND_NAME}");

Expand All @@ -480,7 +506,7 @@ NGRAPH_TEST(${BACKEND_NAME}, gather_nd_batch_1d_from_2d)
auto P = make_shared<op::Parameter>(element::f32, params_shape);
auto I = make_shared<op::Parameter>(element::i32, indices_shape);
auto G = make_shared<op::GatherND>(P, I);
auto f = make_shared<Function>(make_shared<op::GetOutputElement>(G, 0), ParameterVector{P, I});
auto f = make_shared<Function>(G, ParameterVector{P, I});

auto backend = runtime::Backend::create("${BACKEND_NAME}");

Expand All @@ -506,7 +532,7 @@ NGRAPH_TEST(${BACKEND_NAME}, gather_nd_batch_scalar_from_3d)
auto P = make_shared<op::Parameter>(element::f32, params_shape);
auto I = make_shared<op::Parameter>(element::i32, indices_shape);
auto G = make_shared<op::GatherND>(P, I);
auto f = make_shared<Function>(make_shared<op::GetOutputElement>(G, 0), ParameterVector{P, I});
auto f = make_shared<Function>(G, ParameterVector{P, I});

auto backend = runtime::Backend::create("${BACKEND_NAME}");

Expand All @@ -532,7 +558,7 @@ NGRAPH_TEST(${BACKEND_NAME}, gather_nd_batch_1d_from_3d)
auto P = make_shared<op::Parameter>(element::f32, params_shape);
auto I = make_shared<op::Parameter>(element::i32, indices_shape);
auto G = make_shared<op::GatherND>(P, I);
auto f = make_shared<Function>(make_shared<op::GetOutputElement>(G, 0), ParameterVector{P, I});
auto f = make_shared<Function>(G, ParameterVector{P, I});

auto backend = runtime::Backend::create("${BACKEND_NAME}");

Expand All @@ -558,7 +584,7 @@ NGRAPH_TEST(${BACKEND_NAME}, gather_nd_batch_2d_from_3d)
auto P = make_shared<op::Parameter>(element::f32, params_shape);
auto I = make_shared<op::Parameter>(element::i32, indices_shape);
auto G = make_shared<op::GatherND>(P, I);
auto f = make_shared<Function>(make_shared<op::GetOutputElement>(G, 0), ParameterVector{P, I});
auto f = make_shared<Function>(G, ParameterVector{P, I});

auto backend = runtime::Backend::create("${BACKEND_NAME}");

Expand All @@ -584,7 +610,7 @@ NGRAPH_TEST(${BACKEND_NAME}, gather_no_axis_int8)
auto P = make_shared<op::Parameter>(element::i8, params_shape);
auto I = make_shared<op::Parameter>(element::i32, indices_shape);
auto G = make_shared<op::Gather>(P, I);
auto f = make_shared<Function>(make_shared<op::GetOutputElement>(G, 0), ParameterVector{P, I});
auto f = make_shared<Function>(G, ParameterVector{P, I});

auto backend = runtime::Backend::create("${BACKEND_NAME}");

Expand All @@ -610,7 +636,7 @@ NGRAPH_TEST(${BACKEND_NAME}, gather_no_axis_int16)
auto P = make_shared<op::Parameter>(element::i16, params_shape);
auto I = make_shared<op::Parameter>(element::i64, indices_shape);
auto G = make_shared<op::Gather>(P, I);
auto f = make_shared<Function>(make_shared<op::GetOutputElement>(G, 0), ParameterVector{P, I});
auto f = make_shared<Function>(G, ParameterVector{P, I});

auto backend = runtime::Backend::create("${BACKEND_NAME}");

Expand All @@ -636,7 +662,7 @@ NGRAPH_TEST(${BACKEND_NAME}, gather_no_axis_int32)
auto P = make_shared<op::Parameter>(element::i32, params_shape);
auto I = make_shared<op::Parameter>(element::i32, indices_shape);
auto G = make_shared<op::Gather>(P, I);
auto f = make_shared<Function>(make_shared<op::GetOutputElement>(G, 0), ParameterVector{P, I});
auto f = make_shared<Function>(G, ParameterVector{P, I});

auto backend = runtime::Backend::create("${BACKEND_NAME}");

Expand All @@ -662,7 +688,7 @@ NGRAPH_TEST(${BACKEND_NAME}, gather_no_axis_int64)
auto P = make_shared<op::Parameter>(element::i64, params_shape);
auto I = make_shared<op::Parameter>(element::i64, indices_shape);
auto G = make_shared<op::Gather>(P, I);
auto f = make_shared<Function>(make_shared<op::GetOutputElement>(G, 0), ParameterVector{P, I});
auto f = make_shared<Function>(G, ParameterVector{P, I});

auto backend = runtime::Backend::create("${BACKEND_NAME}");

Expand All @@ -688,7 +714,7 @@ NGRAPH_TEST(${BACKEND_NAME}, gather_no_axis_uint8)
auto P = make_shared<op::Parameter>(element::u8, params_shape);
auto I = make_shared<op::Parameter>(element::i32, indices_shape);
auto G = make_shared<op::Gather>(P, I);
auto f = make_shared<Function>(make_shared<op::GetOutputElement>(G, 0), ParameterVector{P, I});
auto f = make_shared<Function>(G, ParameterVector{P, I});

auto backend = runtime::Backend::create("${BACKEND_NAME}");

Expand All @@ -714,7 +740,7 @@ NGRAPH_TEST(${BACKEND_NAME}, gather_no_axis_uint16)
auto P = make_shared<op::Parameter>(element::u16, params_shape);
auto I = make_shared<op::Parameter>(element::i64, indices_shape);
auto G = make_shared<op::Gather>(P, I);
auto f = make_shared<Function>(make_shared<op::GetOutputElement>(G, 0), ParameterVector{P, I});
auto f = make_shared<Function>(G, ParameterVector{P, I});

auto backend = runtime::Backend::create("${BACKEND_NAME}");

Expand All @@ -740,7 +766,7 @@ NGRAPH_TEST(${BACKEND_NAME}, gather_no_axis_uint32)
auto P = make_shared<op::Parameter>(element::u32, params_shape);
auto I = make_shared<op::Parameter>(element::i32, indices_shape);
auto G = make_shared<op::Gather>(P, I);
auto f = make_shared<Function>(make_shared<op::GetOutputElement>(G, 0), ParameterVector{P, I});
auto f = make_shared<Function>(G, ParameterVector{P, I});

auto backend = runtime::Backend::create("${BACKEND_NAME}");

Expand All @@ -766,7 +792,7 @@ NGRAPH_TEST(${BACKEND_NAME}, gather_no_axis_uint64)
auto P = make_shared<op::Parameter>(element::u64, params_shape);
auto I = make_shared<op::Parameter>(element::i64, indices_shape);
auto G = make_shared<op::Gather>(P, I);
auto f = make_shared<Function>(make_shared<op::GetOutputElement>(G, 0), ParameterVector{P, I});
auto f = make_shared<Function>(G, ParameterVector{P, I});

auto backend = runtime::Backend::create("${BACKEND_NAME}");

Expand All @@ -792,7 +818,7 @@ NGRAPH_TEST(${BACKEND_NAME}, gather_no_axis_bool)
auto P = make_shared<op::Parameter>(element::boolean, params_shape);
auto I = make_shared<op::Parameter>(element::i64, indices_shape);
auto G = make_shared<op::Gather>(P, I);
auto f = make_shared<Function>(make_shared<op::GetOutputElement>(G, 0), ParameterVector{P, I});
auto f = make_shared<Function>(G, ParameterVector{P, I});

auto backend = runtime::Backend::create("${BACKEND_NAME}");

Expand Down

0 comments on commit dd8c9ed

Please sign in to comment.