Skip to content

Commit

Permalink
[GPU] Fix fused op macro for dynamic shape eltwise fusing into convol…
Browse files Browse the repository at this point in the history
…ution, fix deconvolution attribute kernel param when 1d (openvinotoolkit#27010)

### Details:
- fix fused op input load macro for convolution with dynamic shape
eltwise fusing
 - fix deconvolution kernel  stride, pad, dilation axis extension for 1d

### Tickets:
 - 152406
  • Loading branch information
wilson-seok authored Oct 21, 2024
1 parent 9a02e54 commit 2be7e5f
Show file tree
Hide file tree
Showing 5 changed files with 358 additions and 12 deletions.
16 changes: 7 additions & 9 deletions src/plugins/intel_gpu/src/graph/impls/ocl/deconvolution.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "primitive_base.hpp"

#include "deconvolution_inst.h"
#include "intel_gpu/plugin/common_utils.hpp"
#include "deconvolution/deconvolution_kernel_selector.h"
#include "deconvolution/deconvolution_kernel_base.h"

Expand Down Expand Up @@ -54,19 +55,16 @@ struct deconvolution_impl : typed_primitive_impl_ocl<deconvolution> {

params.filterSize = { kx, ky, kz };

uint32_t pad_z = std::max<std::ptrdiff_t>(pad.size() >= 3 ? pad[pad.size() - 3] : 0, 0);
uint32_t pad_y = std::max<std::ptrdiff_t>(pad.size() >= 2 ? pad[pad.size() - 2] : 0, 0);
uint32_t pad_x = std::max<std::ptrdiff_t>(pad.size() >= 1 ? pad[pad.size() - 1] : 0, 0);
uint32_t pad_x, pad_y, pad_z;
std::tie(pad_x, pad_y, pad_z) = ov::intel_gpu::get_xyz<ov::CoordinateDiff, uint32_t>(pad, 0);
params.padding = {pad_x, pad_y, pad_z};

uint32_t stride_z = stride.size() >= 3 ? static_cast<uint32_t>(stride[stride.size() - 3]) : 1;
uint32_t stride_y = stride.size() >= 2 ? static_cast<uint32_t>(stride[stride.size() - 2]) : 1;
uint32_t stride_x = stride.size() >= 1 ? static_cast<uint32_t>(stride[stride.size() - 1]) : 1;
uint32_t stride_x, stride_y, stride_z;
std::tie(stride_x, stride_y, stride_z) = ov::intel_gpu::get_xyz<ov::Strides, uint32_t>(stride, 1);
params.stride = {stride_x, stride_y, stride_z};

uint32_t dilation_z = dilation.size() >= 3 ? static_cast<uint32_t>(dilation[dilation.size() - 3]) : 1;
uint32_t dilation_y = dilation.size() >= 2 ? static_cast<uint32_t>(dilation[dilation.size() - 2]) : 1;
uint32_t dilation_x = dilation.size() >= 1 ? static_cast<uint32_t>(dilation[dilation.size() - 1]) : 1;
uint32_t dilation_x, dilation_y, dilation_z;
std::tie(dilation_x, dilation_y, dilation_z) = ov::intel_gpu::get_xyz<ov::Strides, uint32_t>(dilation, 1);
params.dilation = {dilation_x, dilation_y, dilation_z};

return params;
Expand Down
16 changes: 15 additions & 1 deletion src/plugins/intel_gpu/src/kernel_selector/jitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2197,7 +2197,21 @@ std::string FusedOpsCodeGenerator::GetJitLoad(const FusedOpsConfiguration& conf,

if (vec_size > 1) {
return block_read;
} else if (input_tensor.LogicalSize() > 1) {
}

bool multiple_elements = false;
// For dynamic shape input tensor, check any one of static dimension has more than one element.
if (input_tensor.is_dynamic()) {
for (auto dim : input_tensor.GetDims()) {
auto v = dim.v;
if (v > 1) {
multiple_elements = true;
break;
}
}
}

if (input_tensor.LogicalSize() > 1 || multiple_elements) {
// Currently we assume that in such scenario we can safely load sub_group_size elements from the pointer
return Broadcast(block_read, input_dt, vec_size);
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -211,4 +211,40 @@ INSTANTIATE_TEST_SUITE_P(smoke_ConvolutionBackpropData3D_AutoPadding_OutputPaddi
::testing::Values(ov::test::utils::DEVICE_GPU)),
ConvolutionBackpropDataLayerTest::getTestCaseName);

const std::vector<size_t> numOutChannels1d = {256};

/* ============= 1D ConvolutionBackpropData ============= */
const std::vector<ov::element::Type> netPrecisions1D = {
ov::element::f32
};

const std::vector<std::vector<ov::Shape>> inputShapes1D = {{{1, 512, 577}}};
const std::vector<std::vector<size_t >> kernels1D = {{16}};
const std::vector<std::vector<size_t >> strides1D = {{8}};
const std::vector<std::vector<ptrdiff_t>> padBegins1D = {{4}};
const std::vector<std::vector<ptrdiff_t>> padEnds1D = {{4}};
const std::vector<std::vector<size_t >> dilations1D = {{1}};


const std::vector<std::vector<ptrdiff_t>> outputPadding1D = {{0}};

const auto conv1DParams_ExplicitPadding_output_padding = ::testing::Combine(
::testing::ValuesIn(kernels1D),
::testing::ValuesIn(strides1D),
::testing::ValuesIn(padBegins1D),
::testing::ValuesIn(padEnds1D),
::testing::ValuesIn(dilations1D),
::testing::ValuesIn(numOutChannels1d),
::testing::Values(ov::op::PadType::EXPLICIT),
::testing::ValuesIn(outputPadding1D)
);

INSTANTIATE_TEST_SUITE_P(smoke_ConvolutionBackpropData1D_ExplicitPadding, ConvolutionBackpropDataLayerTest,
::testing::Combine(
conv1DParams_ExplicitPadding_output_padding,
::testing::ValuesIn(netPrecisions1D),
::testing::ValuesIn(ov::test::static_shapes_to_test_representation(inputShapes1D)),
::testing::ValuesIn(emptyOutputShape),
::testing::Values(ov::test::utils::DEVICE_GPU)),
ConvolutionBackpropDataLayerTest::getTestCaseName);
} // namespace
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include "common_test_utils/ov_tensor_utils.hpp"
#include "common_test_utils/node_builders/activation.hpp"
#include "common_test_utils/node_builders/convolution.hpp"
#include "common_test_utils/node_builders/eltwise.hpp"
#include "shared_test_classes/base/ov_subgraph.hpp"
#include "shared_test_classes/single_op/convolution.hpp"

Expand Down Expand Up @@ -317,4 +318,256 @@ INSTANTIATE_TEST_SUITE_P(smoke_ConvolutionLayerGPUTest_dynamic3DAsymPad, Convolu
::testing::Values(false)),
ConvolutionLayerGPUTestDynamic::getTestCaseName);

typedef std::tuple<
convSpecificParams,
ov::element::Type, // Model type
std::vector<InputShape>, // Input shapes
std::string, // Device name
bool // activation fusing
> convLayerFusingTestParamsSet;


class ConvolutionLayerGPUTestDynamicEltwiseFusing : public testing::WithParamInterface<convLayerFusingTestParamsSet>,
virtual public ov::test::SubgraphBaseTest {
public:
static std::string getTestCaseName(const testing::TestParamInfo<convLayerFusingTestParamsSet>& obj) {
convSpecificParams convParams;
ov::element::Type model_type;
std::vector<InputShape> inputShapes;
std::string targetDevice;
bool activationFusing;
std::tie(convParams, model_type, inputShapes, targetDevice, activationFusing) = obj.param;

ov::op::PadType padType;
std::vector<size_t> kernel, stride, dilation;
std::vector<ptrdiff_t> padBegin, padEnd;
size_t convOutChannels;
std::tie(kernel, stride, padBegin, padEnd, dilation, convOutChannels, padType) = convParams;

std::ostringstream result;
for (const auto& inputShape : inputShapes) {
result << "IS=";
result << ov::test::utils::partialShape2str({inputShape.first}) << "_";
result << "TS=(";
for (const auto& shape : inputShape.second) {
result << ov::test::utils::vec2str(shape) << "_";
}
}
result << ")_";
result << "K" << ov::test::utils::vec2str(kernel) << "_";
result << "S" << ov::test::utils::vec2str(stride) << "_";
result << "PB" << ov::test::utils::vec2str(padBegin) << "_";
result << "PE" << ov::test::utils::vec2str(padEnd) << "_";
result << "D=" << ov::test::utils::vec2str(dilation) << "_";
result << "O=" << convOutChannels << "_";
result << "AP=" << padType << "_";
result << "netPRC=" << model_type << "_";
result << "trgDev=" << targetDevice << "_";
result << "activationFusing=" << activationFusing;

return result.str();
}

protected:
void SetUp() override {
convSpecificParams convParams;
std::vector<InputShape> inputShapes;
auto model_type = ov::element::undefined;
bool activationFusing;
std::tie(convParams, model_type, inputShapes, targetDevice, activationFusing) = this->GetParam();

init_input_shapes({inputShapes});

ov::op::PadType padType;
std::vector<size_t> kernel, stride, dilation;
std::vector<ptrdiff_t> padBegin, padEnd;
size_t convOutChannels;
std::tie(kernel, stride, padBegin, padEnd, dilation, convOutChannels, padType) = convParams;

ov::ParameterVector inputParams;
for (auto&& shape : inputDynamicShapes)
inputParams.push_back(std::make_shared<ov::op::v0::Parameter>(model_type, shape));

auto convolutionNode = ov::test::utils::make_convolution(inputParams.front(), model_type, kernel, stride, padBegin,
padEnd, dilation, padType, convOutChannels);
if (activationFusing) {
auto activationNode = ov::test::utils::make_activation(convolutionNode, model_type, ov::test::utils::ActivationTypes::Relu);
auto eltwiseNode = ov::test::utils::make_eltwise(inputParams.back(), activationNode, ov::test::utils::EltwiseTypes::ADD);

ov::ResultVector results;
for (size_t i = 0; i < eltwiseNode->get_output_size(); i++)
results.push_back(std::make_shared<ov::op::v0::Result>(eltwiseNode->output(i)));

function = std::make_shared<ov::Model>(results, inputParams, "Convolution");
} else {
auto eltwiseNode = ov::test::utils::make_eltwise(inputParams.back(), convolutionNode, ov::test::utils::EltwiseTypes::ADD);

ov::ResultVector results;
for (size_t i = 0; i < eltwiseNode->get_output_size(); i++)
results.push_back(std::make_shared<ov::op::v0::Result>(eltwiseNode->output(i)));

function = std::make_shared<ov::Model>(results, inputParams, "Convolution");
}
}
};

TEST_P(ConvolutionLayerGPUTestDynamicEltwiseFusing, Inference) {
run();
}
const std::vector<std::vector<ov::test::InputShape>> dynInputShapes1D_test = {
{
{
{1, 192, ov::Dimension::dynamic()},
{{1, 192, 191}}
},
{
{1, 192, ov::Dimension::dynamic()},
{{1, 192, 1}}
}
},
{
{
{ov::Dimension::dynamic(), 192, ov::Dimension::dynamic()},
{{1, 192, 257}}
},
{
{1, 1, ov::Dimension::dynamic()},
{{1, 1, 257}}
}
},
{
{
{ov::Dimension::dynamic(), 192, ov::Dimension::dynamic()},
{{1, 192, 257}}
},
{
{1, ov::Dimension::dynamic(), ov::Dimension::dynamic()},
{{1, 1, 1}}
}
},
{
{
{ov::Dimension::dynamic(), 192, ov::Dimension::dynamic()},
{{1, 192, 1}}
},
{
{1, ov::Dimension::dynamic(), ov::Dimension::dynamic()},
{{1, 1, 1}}
}
},
};

INSTANTIATE_TEST_SUITE_P(smoke_ConvolutionLayerGPUTest_dynamic1D_test_0, ConvolutionLayerGPUTestDynamicEltwiseFusing,
::testing::Combine(
::testing::Combine(
::testing::Values(std::vector<size_t>{1}),
::testing::Values(std::vector<size_t>{1}),
::testing::Values(std::vector<ptrdiff_t>{0}),
::testing::Values(std::vector<ptrdiff_t>{0}),
::testing::Values(std::vector<size_t>{1}),
::testing::Values(192),
::testing::Values(ov::op::PadType::EXPLICIT)),
::testing::Values(ov::element::f32),
::testing::ValuesIn(dynInputShapes1D_test),
::testing::Values<std::string>(ov::test::utils::DEVICE_GPU),
::testing::Values(false)),
ConvolutionLayerGPUTestDynamicEltwiseFusing::getTestCaseName);

const std::vector<std::vector<ov::test::InputShape>> dynInputShapes1D_test1 = {
{
{
{1, 512, ov::Dimension::dynamic()},
{{1, 512, 191}}
},
{
{1, 512, ov::Dimension::dynamic()},
{{1, 512, 1}}
}
},
{
{
{ov::Dimension::dynamic(), 512, ov::Dimension::dynamic()},
{{1, 512, 191}}
},
{
{1, 1, ov::Dimension::dynamic()},
{{1, 1, 191}}
}
},
{
{
{ov::Dimension::dynamic(), 512, ov::Dimension::dynamic()},
{{1, 512, 191}}
},
{
{1, 1, ov::Dimension::dynamic()},
{{1, 1, 1}}
}
},
};

INSTANTIATE_TEST_SUITE_P(smoke_ConvolutionLayerGPUTest_dynamic1D_test_1, ConvolutionLayerGPUTestDynamicEltwiseFusing,
::testing::Combine(
::testing::Combine(
::testing::Values(std::vector<size_t>{1}),
::testing::Values(std::vector<size_t>{1}),
::testing::Values(std::vector<ptrdiff_t>{0}),
::testing::Values(std::vector<ptrdiff_t>{0}),
::testing::Values(std::vector<size_t>{1}),
::testing::Values(512),
::testing::Values(ov::op::PadType::EXPLICIT)),
::testing::Values(ov::element::f32),
::testing::ValuesIn(dynInputShapes1D_test1),
::testing::Values<std::string>(ov::test::utils::DEVICE_GPU),
::testing::Values(false)),
ConvolutionLayerGPUTestDynamicEltwiseFusing::getTestCaseName);

const std::vector<std::vector<ov::test::InputShape>> dynInputShapes1D_test2 = {
{
{
{1, 2048, ov::Dimension::dynamic()},
{{1, 2048, 191}}
},
{
{1, 2048, ov::Dimension::dynamic()},
{{1, 2048, 1}}
}
},
{
{
{1, 2048, ov::Dimension::dynamic()},
{{1, 2048, 191}}
},
{
{ov::Dimension::dynamic(), 1, ov::Dimension::dynamic()},
{{1, 1, 191}}
}
},
{
{
{1, 2048, ov::Dimension::dynamic()},
{{1, 2048, 191}}
},
{
{ov::Dimension::dynamic(), 1, ov::Dimension::dynamic()},
{{1, 1, 1}}
}
},
};

INSTANTIATE_TEST_SUITE_P(smoke_ConvolutionLayerGPUTest_dynamic1D_test_2, ConvolutionLayerGPUTestDynamicEltwiseFusing,
::testing::Combine(
::testing::Combine(
::testing::Values(std::vector<size_t>{1}),
::testing::Values(std::vector<size_t>{1}),
::testing::Values(std::vector<ptrdiff_t>{0}),
::testing::Values(std::vector<ptrdiff_t>{0}),
::testing::Values(std::vector<size_t>{1}),
::testing::Values(2048),
::testing::Values(ov::op::PadType::EXPLICIT)),
::testing::Values(ov::element::f32),
::testing::ValuesIn(dynInputShapes1D_test2),
::testing::Values<std::string>(ov::test::utils::DEVICE_GPU),
::testing::Values(false)),
ConvolutionLayerGPUTestDynamicEltwiseFusing::getTestCaseName);
} // namespace
Loading

0 comments on commit 2be7e5f

Please sign in to comment.