Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions src/plugins/intel_gpu/src/graph/select.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,29 @@ select_inst::typed_primitive_inst(network& network, select_node const& node) : p
"Invalid input shapes");
}
}
} else if (node.get_primitive()->broadcast_spec.m_type == ov::op::AutoBroadcastType::PDPD) {
auto output_pshape = deps[1].first->get_output_layout().get_partial_shape();
auto broadcast_spec = node.get_primitive()->broadcast_spec;

auto check_broadcast = [&](const ov::PartialShape& input_pshape, const char* input_name) {
auto spec = broadcast_spec;
if (spec.m_axis > 0 &&
input_pshape.rank().is_static() &&
output_pshape.rank().is_static() &&
input_pshape.rank().get_length() == output_pshape.rank().get_length()) {
// Inputs may be pre-aligned to output rank for PDPD; ignore explicit axis in the check.
spec.m_axis = 0;
}
auto merged = output_pshape;
bool ok = ov::PartialShape::broadcast_merge_into(merged, input_pshape, spec);
CLDNN_ERROR_BOOL(node.id(),
std::string(input_name) + " broadcastable to output shape",
!ok,
"Invalid input shapes");
};

check_broadcast(deps[2].first->get_output_layout().get_partial_shape(), "Else");
check_broadcast(deps[0].first->get_output_layout().get_partial_shape(), "Cond");
} else {
CLDNN_ERROR_MESSAGE(node.id(), "Unsupported broadcast_type: " + std::to_string(static_cast<int>(node.get_primitive()->broadcast_spec.m_type)));
}
Expand Down
58 changes: 50 additions & 8 deletions src/plugins/intel_gpu/src/plugin/ops/select.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,28 @@

namespace ov::intel_gpu {

namespace {

ov::Shape get_pdpd_aligned_shape(const ov::Shape& input_shape, size_t output_rank, int64_t axis) {
ov::Shape padded_shape = input_shape;

while (!padded_shape.empty() && padded_shape.back() == 1) {
padded_shape.pop_back();
}

for (int64_t i = 0; i < axis && padded_shape.size() < output_rank; ++i) {
padded_shape.insert(padded_shape.begin(), 1ul);
}

while (padded_shape.size() < output_rank) {
padded_shape.push_back(1ul);
}

return padded_shape;
}

} // namespace

static void CreateSelectOp(ProgramBuilder& p, const std::shared_ptr<ov::op::v1::Select>& op) {
validate_inputs_count(op, {3});
auto inputs = p.GetInputInfo(op);
Expand All @@ -24,18 +46,27 @@ static void CreateSelectOp(ProgramBuilder& p, const std::shared_ptr<ov::op::v1::
auto broadcast_type = op->get_auto_broadcast();

if (broadcast_type.m_type != ov::op::AutoBroadcastType::NONE &&
broadcast_type.m_type != ov::op::AutoBroadcastType::NUMPY) {
broadcast_type.m_type != ov::op::AutoBroadcastType::NUMPY &&
broadcast_type.m_type != ov::op::AutoBroadcastType::PDPD) {
OPENVINO_THROW("[GPU] Unsupported broadcast type (", broadcast_type.m_type, ") in layer " + op->get_friendly_name());
}

if (broadcast_type.m_type == ov::op::AutoBroadcastType::NUMPY) {
if (broadcast_type.m_type == ov::op::AutoBroadcastType::NUMPY ||
broadcast_type.m_type == ov::op::AutoBroadcastType::PDPD) {
// Preprocess inputs
int64_t pdpd_axis = broadcast_type.m_axis;
if (broadcast_type.m_type == ov::op::AutoBroadcastType::PDPD && pdpd_axis == -1) {
auto input2_pshape = op->get_input_partial_shape(2);
pdpd_axis = static_cast<int64_t>(output_rank) - static_cast<int64_t>(input2_pshape.size());
}

for (size_t i = 0; i < inputs.size(); ++i) {
auto input_pshape = op->get_input_partial_shape(i);

if (input_pshape.is_static() && !p.use_new_shape_infer()) {
auto input_shape = input_pshape.to_shape();
auto input_rank = input_shape.size();
ov::Shape target_shape = input_shape;

// Add reorder if changing number of dimensions requires changing format
auto targetFormat = cldnn::format::get_default_format(output_rank);
Expand All @@ -53,14 +84,25 @@ static void CreateSelectOp(ProgramBuilder& p, const std::shared_ptr<ov::op::v1::
inputs[i] = cldnn::input_info(reorderName);
}

// Reshape input if they differ or select specific shape matches default one
if (input_rank != output_rank || input_rank < 4) {
auto reshapeName = layerName + "_cldnn_in" + std::to_string(i) + "_reshape";

if (broadcast_type.m_type == ov::op::AutoBroadcastType::NUMPY) {
// Extend input dimensions to the same size as output dimensions by prepending ones
input_shape.insert(input_shape.begin(), output_rank - input_rank, 1ul);
target_shape.insert(target_shape.begin(), output_rank - input_rank, 1ul);
} else if (broadcast_type.m_type == ov::op::AutoBroadcastType::PDPD && i != 1) {
if (input_rank > output_rank || static_cast<size_t>(pdpd_axis) + input_rank > output_rank) {
OPENVINO_THROW("[GPU] Invalid PDPD broadcast axis (", pdpd_axis, ") for input ", i,
" in layer " + op->get_friendly_name());
}
target_shape = get_pdpd_aligned_shape(input_shape, output_rank, pdpd_axis);
}

const bool pdpd_adjusts_shape =
(broadcast_type.m_type == ov::op::AutoBroadcastType::PDPD) && (target_shape != input_shape);
const bool need_reshape = (input_rank != output_rank) || (input_rank < 4) || pdpd_adjusts_shape;

auto targetShape = tensor_from_dims(input_shape);
// Reshape input if they differ or select specific shape matches default one
if (need_reshape) {
auto reshapeName = layerName + "_cldnn_in" + std::to_string(i) + "_reshape";
auto targetShape = tensor_from_dims(target_shape);

auto reshapePrim = cldnn::reshape(reshapeName, inputs[i], targetShape);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,24 @@ const std::vector<std::vector<ov::Shape>> numpyShapes = {
{{2, 2, 2, 2, 2}, {2, 2, 2, 2, 2}, {2, 2, 2, 2}}
};

const std::vector<std::vector<ov::Shape>> pdpdShapes = {
{{4, 5}, {2, 3, 4, 5}, {4, 5}},
{{1}, {2, 3, 4}, {1}},
{{3, 4}, {2, 3, 4}, {3, 4}},
{{1, 4}, {2, 3, 4}, {1, 4}},
{{1, 4, 1}, {2, 3, 4, 5}, {3, 4, 1}},
{{1, 1}, {2, 3, 4, 5}, {4, 1}},
{{4, 1, 1}, {2, 3, 4, 5, 6}, {4, 1, 1}},
};

const std::vector<std::vector<ov::Shape>> pdpdAxis1Shapes = {
{{1, 3, 4, 1}, {1, 2, 3, 4, 1}, {1, 3, 4, 1}},
{{3, 4}, {2, 3, 4, 5}, {3, 4}},
{{1, 3, 4, 1}, {1, 2, 3, 4, 5}, {1, 3, 4, 1}},
{{2, 3, 4}, {1, 2, 3, 4, 5}, {2, 3, 4}},
{{3, 4, 1}, {2, 3, 4, 5}, {3, 4, 1}},
};

INSTANTIATE_TEST_SUITE_P(smoke_CLDNN_TestsSelect_none,
SelectLayerTest,
::testing::Combine(::testing::ValuesIn(ov::test::static_shapes_to_test_representation(noneShapes)),
Expand All @@ -65,3 +83,19 @@ INSTANTIATE_TEST_SUITE_P(smoke_CLDNN_TestsSelect_numpy,
::testing::Values(ov::op::AutoBroadcastType::NUMPY),
::testing::Values(ov::test::utils::DEVICE_GPU)),
SelectLayerTest::getTestCaseName);

INSTANTIATE_TEST_SUITE_P(smoke_CLDNN_TestsSelect_pdpd,
SelectLayerTest,
::testing::Combine(::testing::ValuesIn(ov::test::static_shapes_to_test_representation(pdpdShapes)),
::testing::ValuesIn(inputPrecision),
::testing::Values(ov::op::AutoBroadcastType::PDPD),
::testing::Values(ov::test::utils::DEVICE_GPU)),
SelectLayerTest::getTestCaseName);

INSTANTIATE_TEST_SUITE_P(smoke_CLDNN_TestsSelect_pdpd_axis1,
SelectLayerTest,
::testing::Combine(::testing::ValuesIn(ov::test::static_shapes_to_test_representation(pdpdAxis1Shapes)),
::testing::ValuesIn(inputPrecision),
::testing::Values(ov::op::AutoBroadcastSpec(ov::op::AutoBroadcastType::PDPD, 1)),
::testing::Values(ov::test::utils::DEVICE_GPU)),
SelectLayerTest::getTestCaseName);
Loading