[GPU] gather nd shape agnostic kernel implementation (#17940)
* gather nd shape agnostic kernel implementation * add func test * fix minor bugs * minor bug fixes * fix win build error
This commit is contained in:
1 parent
c413825845
commit
cff083f83d
7 files changed
+426
-24
No files matched your search
@@ -100,6 +100,8 @@ std::vector<layout> gather_nd_inst::calc_output_layouts(gather_nd_node const& /*
|
||||
ov::op::v8::shape_infer(&op, input_shapes, output_shapes);
|
||||
}
|
||||
|
||||
OPENVINO_ASSERT(!output_shapes[0].rank().is_dynamic(),
|
||||
"[GPU] Doesn't support output dynamic rank in gather_nd");
|
||||
format output_format = format::adjust_to_rank(input_layout.format, output_shapes[0].size());
|
||||
|
||||
return { layout{output_shapes[0], output_type, output_format} };
|
||||
|
||||
@@ -35,22 +35,45 @@ struct gather_nd_impl : typed_primitive_impl_ocl<gather_nd> {
|
||||
params.inputs.push_back(convert_data_tensor(impl_param.get_input_layout(1)));
|
||||
return {params, optional_params};
|
||||
}
|
||||
|
||||
void update_dispatch_data(const kernel_impl_params& impl_param) override {
|
||||
auto kernel_params = get_kernel_params(impl_param);
|
||||
(_kernel_data.update_dispatch_data_func)(kernel_params.first, _kernel_data);
|
||||
}
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
|
||||
attach_gather_nd_impl::attach_gather_nd_impl() {
|
||||
implementation_map<gather_nd>::add(impl_types::ocl, typed_primitive_impl_ocl<gather_nd>::create<gather_nd_impl>, {
|
||||
std::make_tuple(data_types::f32, format::bfyx),
|
||||
std::make_tuple(data_types::f16, format::bfyx),
|
||||
std::make_tuple(data_types::i32, format::bfyx),
|
||||
std::make_tuple(data_types::f32, format::bfzyx),
|
||||
std::make_tuple(data_types::f16, format::bfzyx),
|
||||
std::make_tuple(data_types::i32, format::bfzyx),
|
||||
std::make_tuple(data_types::f32, format::bfwzyx),
|
||||
std::make_tuple(data_types::f16, format::bfwzyx),
|
||||
std::make_tuple(data_types::i32, format::bfwzyx),
|
||||
});
|
||||
auto types = {
|
||||
data_types::f32,
|
||||
data_types::f16,
|
||||
data_types::i32
|
||||
};
|
||||
|
||||
auto static_formats = {
|
||||
format::bfyx,
|
||||
format::bfzyx,
|
||||
format::bfwzyx
|
||||
};
|
||||
|
||||
implementation_map<gather_nd>::add(impl_types::ocl,
|
||||
shape_types::static_shape,
|
||||
typed_primitive_impl_ocl<gather_nd>::create<gather_nd_impl>,
|
||||
types,
|
||||
static_formats);
|
||||
|
||||
auto dyn_formats = {
|
||||
format::bfyx,
|
||||
format::bfzyx,
|
||||
format::bfwzyx
|
||||
};
|
||||
|
||||
implementation_map<gather_nd>::add(impl_types::ocl,
|
||||
shape_types::dynamic_shape,
|
||||
typed_primitive_impl_ocl<gather_nd>::create<gather_nd_impl>,
|
||||
types,
|
||||
dyn_formats);
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
@@ -33,15 +33,31 @@
|
||||
|
||||
#define INDICES_MAX_DIM 6
|
||||
|
||||
KERNEL(gather_nd_ref)(const __global INPUT0_TYPE* data,
|
||||
const __global INPUT1_TYPE* indices,
|
||||
__global OUTPUT_TYPE* output
|
||||
KERNEL(gather_nd_ref)(
|
||||
OPTIONAL_SHAPE_INFO_ARG
|
||||
const __global INPUT0_TYPE* data,
|
||||
const __global INPUT1_TYPE* indices,
|
||||
__global OUTPUT_TYPE* output
|
||||
#if HAS_FUSED_OPS_DECLS
|
||||
, FUSED_OPS_DECLS
|
||||
, FUSED_OPS_DECLS
|
||||
#endif
|
||||
)
|
||||
{
|
||||
|
||||
#if IS_DYNAMIC
|
||||
uint wi_slice = 1;
|
||||
#if INPUT0_DIMS == 4
|
||||
uint input_dim[4] = {INPUT0_BATCH_NUM, INPUT0_FEATURE_NUM, INPUT0_SIZE_Y, INPUT0_SIZE_X};
|
||||
#elif INPUT0_DIMS == 5
|
||||
uint input_dim[5] = {INPUT0_BATCH_NUM, INPUT0_FEATURE_NUM, INPUT0_SIZE_Z, INPUT0_SIZE_Y, INPUT0_SIZE_X};
|
||||
#else
|
||||
uint input_dim[6] = {INPUT0_BATCH_NUM, INPUT0_FEATURE_NUM, INPUT0_SIZE_W, INPUT0_SIZE_Z, INPUT0_SIZE_Y, INPUT0_SIZE_X};
|
||||
#endif
|
||||
for (uint i = BATCH_DIMS + INPUT1_SIZE_X; i < INPUT0_DIMS; i++)
|
||||
wi_slice *= input_dim[i];
|
||||
#define WI_SLICE_SIZE wi_slice
|
||||
#else
|
||||
#define WI_SLICE_SIZE WI_SLICE_SIZE_STATIC
|
||||
#endif
|
||||
const uint dim0 = get_global_id(0);
|
||||
const uint dim1 = get_global_id(1);
|
||||
const uint dim2 = get_global_id(2);
|
||||
|
||||
@@ -29,6 +29,7 @@ ParamsKey GatherNDKernelRef::GetSupportedKey() const {
|
||||
k.EnableTensorPitches();
|
||||
k.EnableBatching();
|
||||
k.EnableDifferentTypes();
|
||||
k.EnableDynamicShapesSupport();
|
||||
return k;
|
||||
}
|
||||
|
||||
@@ -45,7 +46,7 @@ static inline std::vector<std::string> GetDefaultOrder(size_t size) {
|
||||
return default_order;
|
||||
}
|
||||
|
||||
CommonDispatchData GatherNDKernelRef::SetDefault(const gather_nd_params& params, const optional_params&) const {
|
||||
CommonDispatchData GatherNDKernelRef::SetDefault(const gather_nd_params& params) const {
|
||||
CommonDispatchData dispatchData;
|
||||
|
||||
auto indices_dims = params.inputs[1].LogicalDims();
|
||||
@@ -118,7 +119,7 @@ JitConstants GatherNDKernelRef::GetJitConstants(const gather_nd_params& params)
|
||||
jit.AddConstant(MakeJitConstant("INDICES_RANK", params.indices_rank));
|
||||
jit.AddConstant(MakeJitConstant("BATCH_DIMS", params.batch_dims));
|
||||
jit.AddConstant(MakeJitConstant("BATCH_MERGED_OUTPUT", params.batch_merged_output));
|
||||
jit.AddConstant(MakeJitConstant("WI_SLICE_SIZE", GetSliceSize(params)));
|
||||
jit.AddConstant(MakeJitConstant("WI_SLICE_SIZE_STATIC", GetSliceSize(params)));
|
||||
jit.AddConstant(MakeJitConstant("INDICES_LAST_DIM", GetIndicesLastDim(params)));
|
||||
|
||||
if (!params.fused_ops.empty()) {
|
||||
@@ -155,9 +156,11 @@ bool GatherNDKernelRef::Validate(const Params& p, const optional_params& o) cons
|
||||
return false;
|
||||
}
|
||||
|
||||
for (uint8_t i = 0; i < batch_dims; i++) {
|
||||
if (input_dims[i] != indices_dims[i]) {
|
||||
return false;
|
||||
if (!params.inputs[0].is_dynamic()) {
|
||||
for (uint8_t i = 0; i < batch_dims; i++) {
|
||||
if (input_dims[i] != indices_dims[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -177,13 +180,35 @@ KernelsData GatherNDKernelRef::GetKernelsData(const Params& params, const option
|
||||
KernelData kd = KernelData::Default<gather_nd_params>(params);
|
||||
gather_nd_params& newParams = *static_cast<gather_nd_params*>(kd.params.get());
|
||||
|
||||
auto dispatchData = SetDefault(newParams, options);
|
||||
auto dispatchData = SetDefault(newParams);
|
||||
auto cldnn_jit = GetJitConstants(newParams);
|
||||
|
||||
auto entry_point = GetEntryPoint(kernelName, newParams.layerID, params, options);
|
||||
auto jit = CreateJit(kernelName, cldnn_jit, entry_point);
|
||||
auto& kernel = kd.kernels[0];
|
||||
FillCLKernelData(kernel, dispatchData, params.engineInfo, kernelName, jit, entry_point, "", false, false, 2, GetFusedPrimitiveInputsCount(params));
|
||||
|
||||
kd.update_dispatch_data_func = [this](const Params& params, KernelData& kd) {
|
||||
const auto& prim_params = static_cast<const gather_nd_params&>(params);
|
||||
auto dispatchData = SetDefault(prim_params);
|
||||
OPENVINO_ASSERT(kd.kernels.size() == 1, "[GPU] Invalid kernels size for update dispatch data func");
|
||||
kd.kernels[0].params.workGroups.global = dispatchData.gws;
|
||||
kd.kernels[0].params.workGroups.local = dispatchData.lws;
|
||||
kd.kernels[0].skip_execution = KernelData::SkipKernelExecution(prim_params);
|
||||
};
|
||||
|
||||
FillCLKernelData(kernel,
|
||||
dispatchData,
|
||||
params.engineInfo,
|
||||
kernelName,
|
||||
jit,
|
||||
entry_point,
|
||||
"",
|
||||
false,
|
||||
false,
|
||||
2,
|
||||
GetFusedPrimitiveInputsCount(params),
|
||||
1,
|
||||
newParams.has_dynamic_tensors());
|
||||
|
||||
return { kd };
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ public:
|
||||
GatherNDKernelRef() : KernelBaseOpenCL("gather_nd_ref") {}
|
||||
virtual ~GatherNDKernelRef() {}
|
||||
virtual JitConstants GetJitConstants(const gather_nd_params& params) const;
|
||||
virtual CommonDispatchData SetDefault(const gather_nd_params& params, const optional_params&) const;
|
||||
virtual CommonDispatchData SetDefault(const gather_nd_params& params) const;
|
||||
KernelsData GetKernelsData(const Params& params, const optional_params& options) const override;
|
||||
ParamsKey GetSupportedKey() const override;
|
||||
std::vector<FusedOpType> GetSupportedFusedOps() const override {
|
||||
|
||||
@@ -0,0 +1,163 @@
|
||||
// Copyright (C) 2023 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#include "shared_test_classes/single_layer/gather_nd.hpp"
|
||||
#include "shared_test_classes/base/ov_subgraph.hpp"
|
||||
#include "ie_precision.hpp"
|
||||
#include "ngraph_functions/builders.hpp"
|
||||
#include "common_test_utils/ov_tensor_utils.hpp"
|
||||
#include <string>
|
||||
|
||||
using namespace ngraph;
|
||||
using namespace InferenceEngine;
|
||||
using namespace ov::test;
|
||||
|
||||
namespace GPULayerTestsDefinitions {
|
||||
struct GatherNDShapeParams {
|
||||
InputShape inputShapes;
|
||||
InputShape targetShapes;
|
||||
int batch_dims;
|
||||
};
|
||||
|
||||
typedef std::tuple<
|
||||
GatherNDShapeParams,
|
||||
ElementType, // Network precision
|
||||
bool // Is const Indices
|
||||
> GatherNDGPUTestParams;
|
||||
|
||||
|
||||
class GatherNDGPUTest : public testing::WithParamInterface<GatherNDGPUTestParams>,
|
||||
virtual public ov::test::SubgraphBaseTest {
|
||||
public:
|
||||
static std::string getTestCaseName(testing::TestParamInfo<GatherNDGPUTestParams> obj) {
|
||||
GatherNDShapeParams Shapes;
|
||||
ElementType netPrecision;
|
||||
bool isIndicesConstant;
|
||||
|
||||
std::tie(Shapes, netPrecision, isIndicesConstant) = obj.param;
|
||||
|
||||
std::ostringstream result;
|
||||
result << "IS=(";
|
||||
result << CommonTestUtils::partialShape2str({Shapes.inputShapes.first}) << "_";
|
||||
for (size_t i = 0lu; i < Shapes.inputShapes.second.size(); i++) {
|
||||
result << "{";
|
||||
result << CommonTestUtils::vec2str(Shapes.inputShapes.second[i]) << "_";
|
||||
result << "}_";
|
||||
}
|
||||
result << "TS=(";
|
||||
result << CommonTestUtils::partialShape2str({Shapes.targetShapes.first}) << "_";
|
||||
for (size_t i = 0lu; i < Shapes.targetShapes.second.size(); i++) {
|
||||
result << "{";
|
||||
result << CommonTestUtils::vec2str(Shapes.targetShapes.second[i]) << "_";
|
||||
result << "}_";
|
||||
}
|
||||
result << "batchDims=" << Shapes.batch_dims << "_";
|
||||
result << "netPrc=" << netPrecision << "_";
|
||||
result << "constIdx=" << (isIndicesConstant ? "True" : "False") << "_";
|
||||
|
||||
return result.str();
|
||||
}
|
||||
|
||||
protected:
|
||||
void SetUp() override {
|
||||
GatherNDShapeParams Shapes;
|
||||
ElementType netPrecision;
|
||||
bool isIndicesConstant;
|
||||
const ElementType intInputsPrecision = ElementType::i32;
|
||||
|
||||
std::tie(Shapes, netPrecision, isIndicesConstant) = this->GetParam();
|
||||
const int batchDims = Shapes.batch_dims;
|
||||
targetDevice = CommonTestUtils::DEVICE_GPU;
|
||||
std::shared_ptr<ov::Node> indicesNode;
|
||||
std::shared_ptr<ov::Node> gather_ndNode;
|
||||
|
||||
if (isIndicesConstant) {
|
||||
init_input_shapes({Shapes.inputShapes});
|
||||
} else { // Not being tested because currently parameter targetshape is not supported
|
||||
init_input_shapes({Shapes.inputShapes, Shapes.targetShapes});
|
||||
}
|
||||
|
||||
ngraph::ParameterVector params{std::make_shared<ov::op::v0::Parameter>(netPrecision, inputDynamicShapes[0])};
|
||||
params.back()->set_friendly_name("data");
|
||||
|
||||
if (isIndicesConstant) {
|
||||
int64_t idx_range = INT64_MAX;
|
||||
for (size_t i = 0; i < Shapes.inputShapes.second.size(); ++i) {
|
||||
for (size_t j = 0; j < Shapes.inputShapes.second[i].size(); ++j) {
|
||||
idx_range = std::min(static_cast<int64_t>(Shapes.inputShapes.second[i][j]), idx_range);
|
||||
}
|
||||
}
|
||||
indicesNode = ngraph::builder::makeConstant<int64_t>(
|
||||
ngraph::element::i64,
|
||||
Shapes.targetShapes.second[0],
|
||||
{},
|
||||
true,
|
||||
idx_range - 1,
|
||||
0);
|
||||
} else {
|
||||
params.push_back(std::make_shared<ov::op::v0::Parameter>(intInputsPrecision, inputDynamicShapes[1]));
|
||||
params.back()->set_friendly_name("indices");
|
||||
}
|
||||
|
||||
auto paramOuts =
|
||||
ngraph::helpers::convert2OutputVector(ngraph::helpers::castOps2Nodes<ov::op::v0::Parameter>(params));
|
||||
|
||||
gather_ndNode = std::make_shared<ov::op::v8::GatherND>(paramOuts[0],
|
||||
isIndicesConstant ? indicesNode : paramOuts[1],
|
||||
batchDims);
|
||||
ngraph::ResultVector results{std::make_shared<ngraph::opset4::Result>(gather_ndNode)};
|
||||
function = std::make_shared<ngraph::Function>(results, params, "GatherND");
|
||||
}
|
||||
};
|
||||
|
||||
TEST_P(GatherNDGPUTest, CompareWithRefs) {
|
||||
SKIP_IF_CURRENT_TEST_IS_DISABLED()
|
||||
|
||||
run();
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
const std::vector<ov::element::Type_t> netPrecisions = {
|
||||
ov::element::f32,
|
||||
ov::element::f16,
|
||||
ov::element::i32
|
||||
};
|
||||
|
||||
const std::vector<GatherNDShapeParams> dynamicInputShapeConstTargetShape = {
|
||||
{
|
||||
ov::test::InputShape(ov::PartialShape({-1, -1}), {{2, 2}}),
|
||||
ov::test::InputShape(ov::PartialShape({}), {{2, 1}}),
|
||||
1
|
||||
},
|
||||
{
|
||||
ov::test::InputShape(ov::PartialShape({-1, -1, -1}), {{2, 3, 4}, {3, 4, 5}}),
|
||||
ov::test::InputShape(ov::PartialShape({}), {{2, 1}}),
|
||||
0
|
||||
},
|
||||
{
|
||||
ov::test::InputShape(ov::PartialShape({-1, -1, -1, -1}), {{2, 7, 8, 9}, {2, 7, 4, 8}}),
|
||||
ov::test::InputShape(ov::PartialShape({}), {{2, 1}}),
|
||||
1
|
||||
},
|
||||
{
|
||||
ov::test::InputShape(ov::PartialShape({-1, -1, -1, -1, -1}), {{15, 12, 20, 15, 2}, {15, 12, 18, 7, 17}}),
|
||||
ov::test::InputShape(ov::PartialShape({}), {{15, 12, 5, 9, 1, 3}}),
|
||||
2
|
||||
},
|
||||
{
|
||||
ov::test::InputShape(ov::PartialShape({-1, -1, -1, -1, -1, -1}), {{4, 3, 2, 5, 5, 2}, {4, 3, 2, 5, 7, 2}}),
|
||||
ov::test::InputShape(ov::PartialShape({}), {{4, 3, 2, 5, 6, 2}}),
|
||||
4
|
||||
}
|
||||
};
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(smoke_dynamic_input_shapes_const_target_shapes, GatherNDGPUTest,
|
||||
::testing::Combine(
|
||||
::testing::ValuesIn(dynamicInputShapeConstTargetShape), // input shapes
|
||||
::testing::ValuesIn(netPrecisions), // network precision
|
||||
::testing::Values(true)), // is const indices
|
||||
GatherNDGPUTest::getTestCaseName);
|
||||
} // namespace
|
||||
} // namespace GPULayerTestsDefinitions
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <intel_gpu/primitives/input_layout.hpp>
|
||||
#include <intel_gpu/primitives/gather_nd.hpp>
|
||||
|
||||
#include "gather_nd_inst.h"
|
||||
|
||||
using namespace cldnn;
|
||||
using namespace ::tests;
|
||||
@@ -780,3 +781,175 @@ TEST(gather_nd_gpu_fp16, export_import) {
|
||||
DoTestV5(engine,input0, input1, expected_results, indices_rank, batch_dims, format::bfyx, { 3, 1, 1, 1 }, true);
|
||||
DoTestV8(engine, input0, input1, expected_results, indices_rank, batch_dims, format::bfyx, { 3, 1, 1, 1 }, true);
|
||||
}
|
||||
|
||||
TEST(gather_nd_gpu_fp16, dynamic_r4) {
|
||||
auto& engine = get_test_engine();
|
||||
|
||||
ov::Shape in1_shape = {3, 3, 2, 3};
|
||||
ov::Shape in2_shape = {3, 2, 2, 3};
|
||||
const int batch_dims = 0;
|
||||
auto in1_layout = layout{ov::PartialShape::dynamic(in1_shape.size()), data_types::f16, format::bfyx};
|
||||
auto in2_layout = layout{ov::PartialShape(in2_shape), data_types::f16, format::bfyx};
|
||||
auto input1 = engine.allocate_memory(layout{ov::PartialShape(in1_shape), data_types::f16, format::bfyx}); // data
|
||||
auto input2 = engine.allocate_memory(layout{ov::PartialShape(in2_shape), data_types::f16, format::bfyx}); // Indexes
|
||||
|
||||
set_values(input1, {
|
||||
FLOAT16(1), FLOAT16(2), FLOAT16(3), FLOAT16(4), FLOAT16(5), FLOAT16(6),
|
||||
FLOAT16(7), FLOAT16(8), FLOAT16(9), FLOAT16(10), FLOAT16(11), FLOAT16(12),
|
||||
FLOAT16(13), FLOAT16(14), FLOAT16(15), FLOAT16(16), FLOAT16(17), FLOAT16(18),
|
||||
|
||||
FLOAT16(19), FLOAT16(20), FLOAT16(21), FLOAT16(22), FLOAT16(23), FLOAT16(24),
|
||||
FLOAT16(25), FLOAT16(26), FLOAT16(27), FLOAT16(28), FLOAT16(29), FLOAT16(30),
|
||||
FLOAT16(31), FLOAT16(32), FLOAT16(33), FLOAT16(34), FLOAT16(35), FLOAT16(36),
|
||||
|
||||
FLOAT16(41), FLOAT16(42), FLOAT16(43), FLOAT16(44), FLOAT16(45), FLOAT16(46),
|
||||
FLOAT16(51), FLOAT16(52), FLOAT16(53), FLOAT16(54), FLOAT16(55), FLOAT16(56),
|
||||
FLOAT16(61), FLOAT16(62), FLOAT16(63), FLOAT16(64), FLOAT16(65), FLOAT16(66),
|
||||
});
|
||||
|
||||
set_values(input2, {
|
||||
FLOAT16(2), FLOAT16(0), FLOAT16(0), FLOAT16(2), FLOAT16(2), FLOAT16(0),
|
||||
FLOAT16(1), FLOAT16(0), FLOAT16(0), FLOAT16(1), FLOAT16(1), FLOAT16(0),
|
||||
|
||||
FLOAT16(1), FLOAT16(0), FLOAT16(1), FLOAT16(1), FLOAT16(1), FLOAT16(1),
|
||||
FLOAT16(2), FLOAT16(0), FLOAT16(0), FLOAT16(2), FLOAT16(1), FLOAT16(0),
|
||||
|
||||
FLOAT16(1), FLOAT16(1), FLOAT16(1), FLOAT16(0), FLOAT16(1), FLOAT16(1),
|
||||
FLOAT16(1), FLOAT16(2), FLOAT16(1), FLOAT16(0), FLOAT16(2), FLOAT16(1),
|
||||
});
|
||||
|
||||
std::vector<float> expected_results = {
|
||||
FLOAT16(41), FLOAT16(42), FLOAT16(43), FLOAT16(61), FLOAT16(62), FLOAT16(63),
|
||||
FLOAT16(19), FLOAT16(20), FLOAT16(21), FLOAT16(25), FLOAT16(26), FLOAT16(27),
|
||||
|
||||
FLOAT16(22), FLOAT16(23), FLOAT16(24), FLOAT16(28), FLOAT16(29), FLOAT16(30),
|
||||
FLOAT16(41), FLOAT16(42), FLOAT16(43), FLOAT16(51), FLOAT16(52), FLOAT16(53),
|
||||
|
||||
FLOAT16(28), FLOAT16(29), FLOAT16(30), FLOAT16(10), FLOAT16(11), FLOAT16(12),
|
||||
FLOAT16(34), FLOAT16(35), FLOAT16(36), FLOAT16(16), FLOAT16(17), FLOAT16(18),
|
||||
};
|
||||
|
||||
auto expected_fmt = format::bfyx;
|
||||
const tensor expected_ts = { 3, 2, 3, 2 };
|
||||
uint8_t dim_size = 4;
|
||||
|
||||
topology topology;
|
||||
topology.add(input_layout("input1", in1_layout));
|
||||
topology.add(input_layout("input2", in2_layout));
|
||||
topology.add(gather_nd("gather_nd", input_info("input1"), input_info("input2"), static_cast<uint8_t>(in1_shape.size()), static_cast<uint8_t>(in2_shape.size()), batch_dims, true));
|
||||
|
||||
ExecutionConfig config = get_test_default_config(engine);
|
||||
config.set_property(ov::intel_gpu::allow_new_shape_infer(true));
|
||||
network network(engine, topology, config);
|
||||
network.set_input_data("input1", input1);
|
||||
network.set_input_data("input2", input2);
|
||||
|
||||
auto inst = network.get_primitive("gather_nd");
|
||||
auto impl = inst->get_impl();
|
||||
ASSERT_TRUE(impl != nullptr);
|
||||
ASSERT_TRUE(impl->is_dynamic());
|
||||
|
||||
auto outputs = network.execute();
|
||||
|
||||
auto output = outputs.at("gather_nd").get_memory();
|
||||
// Compare output shape
|
||||
auto output_format = output->get_layout().format;
|
||||
auto output_shape = output->get_layout().get_tensor();
|
||||
|
||||
ASSERT_EQ(expected_fmt, output_format);
|
||||
|
||||
for (int32_t i = 0; i < dim_size; i++)
|
||||
{
|
||||
ASSERT_EQ(expected_ts.sizes()[i], output_shape.sizes()[i]);
|
||||
}
|
||||
cldnn::mem_lock<uint16_t> output_ptr(output, get_test_stream());
|
||||
|
||||
ASSERT_EQ(expected_results.size(), output_ptr.size());
|
||||
for (size_t i = 0; i < expected_results.size(); ++i) {
|
||||
EXPECT_EQ(expected_results[i], half_to_float(output_ptr[i])) << i;
|
||||
}
|
||||
}
|
||||
|
||||
TEST(gather_nd_gpu_fp16, dynamic_r5) {
|
||||
auto& engine = get_test_engine();
|
||||
|
||||
ov::Shape in1_shape = {2, 3, 3, 2, 2};
|
||||
ov::Shape in2_shape = {2, 3, 3, 2, 1};
|
||||
const int batch_dims = 4;
|
||||
auto in1_layout = layout{ov::PartialShape::dynamic(in1_shape.size()), data_types::f16, format::bfzyx};
|
||||
auto in2_layout = layout{ov::PartialShape(in2_shape), data_types::f16, format::bfzyx};
|
||||
auto input1 = engine.allocate_memory(layout{ov::PartialShape(in1_shape), data_types::f16, format::bfzyx}); // data
|
||||
auto input2 = engine.allocate_memory(layout{ov::PartialShape(in2_shape), data_types::f16, format::bfzyx}); // Indexes
|
||||
|
||||
set_values(input1, {
|
||||
FLOAT16(11), FLOAT16(12), FLOAT16(13), FLOAT16(14), FLOAT16(15), FLOAT16(16), FLOAT16(17), FLOAT16(18), FLOAT16(19), FLOAT16(10), FLOAT16(21), FLOAT16(18),
|
||||
FLOAT16(21), FLOAT16(22), FLOAT16(23), FLOAT16(24), FLOAT16(25), FLOAT16(26), FLOAT16(27), FLOAT16(28), FLOAT16(29), FLOAT16(20), FLOAT16(27), FLOAT16(28),
|
||||
FLOAT16(31), FLOAT16(32), FLOAT16(33), FLOAT16(34), FLOAT16(35), FLOAT16(36), FLOAT16(37), FLOAT16(38), FLOAT16(39), FLOAT16(30), FLOAT16(31), FLOAT16(30),
|
||||
|
||||
FLOAT16(11), FLOAT16(12), FLOAT16(13), FLOAT16(14), FLOAT16(15), FLOAT16(16), FLOAT16(17), FLOAT16(18), FLOAT16(19), FLOAT16(10), FLOAT16(17), FLOAT16(18),
|
||||
FLOAT16(21), FLOAT16(22), FLOAT16(23), FLOAT16(24), FLOAT16(25), FLOAT16(26), FLOAT16(27), FLOAT16(28), FLOAT16(29), FLOAT16(20), FLOAT16(27), FLOAT16(28),
|
||||
FLOAT16(31), FLOAT16(32), FLOAT16(33), FLOAT16(34), FLOAT16(35), FLOAT16(36), FLOAT16(37), FLOAT16(38), FLOAT16(39), FLOAT16(30), FLOAT16(29), FLOAT16(30),
|
||||
});
|
||||
|
||||
set_values(input2, {
|
||||
FLOAT16(1), FLOAT16(1), FLOAT16(1), FLOAT16(1), FLOAT16(1), FLOAT16(1),
|
||||
FLOAT16(0), FLOAT16(0), FLOAT16(0), FLOAT16(0), FLOAT16(0), FLOAT16(0),
|
||||
FLOAT16(1), FLOAT16(0), FLOAT16(0), FLOAT16(1), FLOAT16(1), FLOAT16(0),
|
||||
|
||||
FLOAT16(1), FLOAT16(1), FLOAT16(1), FLOAT16(1), FLOAT16(1), FLOAT16(1),
|
||||
FLOAT16(0), FLOAT16(0), FLOAT16(0), FLOAT16(0), FLOAT16(0), FLOAT16(0),
|
||||
FLOAT16(1), FLOAT16(0), FLOAT16(0), FLOAT16(1), FLOAT16(1), FLOAT16(0),
|
||||
});
|
||||
|
||||
std::vector<float> expected_results = {
|
||||
FLOAT16(12), FLOAT16(14), FLOAT16(16), FLOAT16(18), FLOAT16(10), FLOAT16(18),
|
||||
FLOAT16(21), FLOAT16(23), FLOAT16(25), FLOAT16(27), FLOAT16(29), FLOAT16(27),
|
||||
FLOAT16(32), FLOAT16(33), FLOAT16(35), FLOAT16(38), FLOAT16(30), FLOAT16(31),
|
||||
|
||||
FLOAT16(12), FLOAT16(14), FLOAT16(16), FLOAT16(18), FLOAT16(10), FLOAT16(18),
|
||||
FLOAT16(21), FLOAT16(23), FLOAT16(25), FLOAT16(27), FLOAT16(29), FLOAT16(27),
|
||||
FLOAT16(32), FLOAT16(33), FLOAT16(35), FLOAT16(38), FLOAT16(30), FLOAT16(29),
|
||||
};
|
||||
|
||||
auto expected_fmt = format::bfyx;
|
||||
const tensor expected_ts = { 2, 3, 2, 3 };
|
||||
uint8_t dim_size = 4;
|
||||
|
||||
topology topology;
|
||||
topology.add(input_layout("input1", in1_layout));
|
||||
topology.add(input_layout("input2", in2_layout));
|
||||
topology.add(gather_nd("gather_nd", input_info("input1"), input_info("input2"), static_cast<uint8_t>(in1_shape.size()), static_cast<uint8_t>(in2_shape.size()), batch_dims, false));
|
||||
|
||||
ExecutionConfig config = get_test_default_config(engine);
|
||||
config.set_property(ov::intel_gpu::allow_new_shape_infer(true));
|
||||
network network(engine, topology, config);
|
||||
network.set_input_data("input1", input1);
|
||||
network.set_input_data("input2", input2);
|
||||
|
||||
auto inst = network.get_primitive("gather_nd");
|
||||
auto impl = inst->get_impl();
|
||||
ASSERT_TRUE(impl != nullptr);
|
||||
ASSERT_TRUE(impl->is_dynamic());
|
||||
|
||||
auto outputs = network.execute();
|
||||
|
||||
auto output = outputs.at("gather_nd").get_memory();
|
||||
|
||||
// Compare output shape
|
||||
auto output_format = output->get_layout().format;
|
||||
auto output_shape = output->get_layout().get_tensor();
|
||||
|
||||
ASSERT_EQ(expected_fmt, output_format);
|
||||
|
||||
for (int32_t i = 0; i < dim_size; i++)
|
||||
{
|
||||
ASSERT_EQ(expected_ts.sizes()[i], output_shape.sizes()[i]);
|
||||
}
|
||||
|
||||
cldnn::mem_lock<uint16_t> output_ptr(output, get_test_stream());
|
||||
|
||||
ASSERT_EQ(expected_results.size(), output_ptr.size());
|
||||
for (size_t i = 0; i < expected_results.size(); ++i) {
|
||||
EXPECT_EQ(expected_results[i], half_to_float(output_ptr[i])) << i;
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user