Skip to content

Commit 55c4e53

Browse files
committed
.
1 parent f7a1b82 commit 55c4e53

1 file changed

Lines changed: 84 additions & 71 deletions

File tree

src/plugins/intel_gpu/src/plugin/ops/constant.cpp

Lines changed: 84 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -229,14 +229,62 @@ static void CreateConstantOp(ProgramBuilder& p, const std::shared_ptr<ov::op::v0
229229

230230
return false;
231231
};
232-
// WA to inconsistency between input and const 1d tensors
233-
// For Concat along batch we go with batch interpretation
234-
// For Gather input we go with batch interpretation
235-
// Also check if constant users is a backprop convolution - in that case O and I need to be swapped.
236-
for (auto& node : constUsers) {
237-
auto outOp = node.get_node();
238-
bool apply_rank2_matmul_wa = false;
232+
233+
auto apply_common_consumer_adaptation = [&](const ov::Input<ov::Node>& node, ov::Node* outOp) -> bool {
234+
if (auto castedOp = ov::as_type<ov::op::v0::Concat>(outOp)) {
235+
if (castedOp->get_axis() == 0) {
236+
consts[op].needsBatchInterpretation = constDims.size() == 1;
237+
}
238+
return true;
239+
}
240+
241+
if (((is_binary_eltwise(outOp) || ov::is_type<ov::op::v0::SquaredDifference>(outOp)) && is_all_inputs_1d(outOp)) ||
242+
is_convert_into_binary_eltwise(outOp)) {
243+
consts[op].needsBatchInterpretation = constDims.size() == 1;
244+
return true;
245+
}
246+
247+
if (ov::is_type<ov::op::v1::Gather>(outOp) ||
248+
ov::is_type<ov::op::v7::Gather>(outOp) ||
249+
ov::is_type<ov::op::v8::Gather>(outOp) ||
250+
ov::is_type<ov::op::v5::GatherND>(outOp) ||
251+
ov::is_type<ov::op::v8::GatherND>(outOp) ||
252+
ov::is_type<ov::op::v1::Split>(outOp) ||
253+
ov::is_type<ov::op::v1::VariadicSplit>(outOp)) {
254+
consts[op].needsBatchInterpretation = constDims.size() == 1;
255+
return true;
256+
}
257+
258+
if (ov::is_type<ov::op::v0::PRelu>(outOp) && node.get_index() == 1) {
259+
auto input_shape = outOp->get_input_partial_shape(0);
260+
if ((constDims.size() != 1 && constDims.size() < input_shape.size()) ||
261+
(constDims.size() == 1 && input_shape.is_static() && input_shape.size() > 1 &&
262+
static_cast<int64_t>(constDims[0]) != input_shape[1].get_length())) {
263+
ov::Shape slope_shape(input_shape.size(), 1);
264+
for (size_t j = 1; j <= constDims.size(); j++)
265+
slope_shape[slope_shape.size() - j] = constDims[constDims.size() - j];
266+
constDims = slope_shape;
267+
}
268+
return true;
269+
}
270+
271+
if (ov::is_type<ov::op::v3::ROIAlign>(outOp) || ov::is_type<ov::op::v9::ROIAlign>(outOp) ||
272+
ov::is_type<ov::op::v15::ROIAlignRotated>(outOp)) {
273+
consts[op].needsBatchInterpretation = constDims.size() == 1;
274+
return true;
275+
}
276+
277+
if (ov::is_type<ov::op::v5::Loop>(outOp) || ov::is_type<ov::op::v0::TensorIterator>(outOp)) {
278+
consts[op].needsBatchInterpretation = constDims.size() == 1;
279+
return true;
280+
}
281+
282+
return false;
283+
};
284+
285+
auto apply_legacy_shape_layout_wa = [&](const ov::Input<ov::Node>& node, ov::Node* outOp) -> bool {
239286
size_t user_index = node.get_index();
287+
bool apply_rank2_matmul_wa = false;
240288
auto is_convert_matmul_pattern = [&](ov::Node* convert_node, size_t& matmul_input_index_ref) -> bool {
241289
if (ov::is_type<ov::op::v0::Convert>(convert_node) && !p.use_new_shape_infer()) {
242290
auto convert_consumers = convert_node->get_output_target_inputs(0);
@@ -253,89 +301,54 @@ static void CreateConstantOp(ProgramBuilder& p, const std::shared_ptr<ov::op::v0
253301
}
254302
return false;
255303
};
256-
if (auto castedOp = ov::as_type<ov::op::v0::Concat>(outOp)) {
257-
if (castedOp->get_axis() == 0) {
258-
consts[op].needsBatchInterpretation = constDims.size() == 1;
259-
}
260-
} else if (((is_binary_eltwise(outOp) || ov::is_type<ov::op::v0::SquaredDifference>(outOp)) && is_all_inputs_1d(outOp)) ||
261-
is_convert_into_binary_eltwise(outOp)) {
262-
consts[op].needsBatchInterpretation = constDims.size() == 1;
263-
} else if (ov::is_type<ov::op::v1::Gather>(outOp) ||
264-
ov::is_type<ov::op::v7::Gather>(outOp) ||
265-
ov::is_type<ov::op::v8::Gather>(outOp) ||
266-
ov::is_type<ov::op::v5::GatherND>(outOp) ||
267-
ov::is_type<ov::op::v8::GatherND>(outOp) ||
268-
ov::is_type<ov::op::v1::Split>(outOp) ||
269-
ov::is_type<ov::op::v1::VariadicSplit>(outOp)) {
270-
consts[op].needsBatchInterpretation = constDims.size() == 1;
271-
} else if (ov::is_type<ov::op::v0::PRelu>(outOp) && node.get_index() == 1) {
272-
// PReLU slope tensor reshape policy
273-
//
274-
// 1. 1-dim slope is handled by 'getConstTensor' (if slope dimension is equal to the feature dimension of input).
275-
// ex) [1] --> [1, 1, 1, 1]
276-
// [N] --> [1, N, 1, 1]
277-
//
278-
// 2. Multi-dims slope tensor is handled by the numpy broadcasting rule that is defined at
279-
// 'https://docs.openvino.ai/2023.0/openvino_docs_ops_broadcast_rules.html'.
280-
// ex) [N, 1, 1] --> [1, N, 1, 1]
281-
// [N, M, 1] --> [1, N, M, 1]
282-
auto input_shape = outOp->get_input_partial_shape(0);
283-
if ((constDims.size() != 1 && constDims.size() < input_shape.size()) ||
284-
(constDims.size() == 1 && input_shape.is_static() && input_shape.size() > 1 &&
285-
static_cast<int64_t>(constDims[0]) != input_shape[1].get_length())) {
286-
// Reshape 'constDims' according to the numpy broadcasting rule.
287-
ov::Shape slope_shape(input_shape.size(), 1);
288-
for (size_t j = 1; j <= constDims.size(); j++)
289-
slope_shape[slope_shape.size() - j] = constDims[constDims.size() - j];
290-
constDims = slope_shape;
291-
}
292-
} else if (is_grouped_conv(outOp) && node.get_index() == 1 && !p.use_new_shape_infer()) {
304+
305+
if (is_grouped_conv(outOp) && node.get_index() == 1 && !p.use_new_shape_infer()) {
293306
auto input_shape = outOp->get_input_partial_shape(0);
294-
if (constDims.size() == 4 && input_shape.size() == 3) { // In case of weight dim 4 and input dim 3,
295-
constDims.push_back(1); // The weight cldnn tensor adds 1d to the end as the input cldnn tensor does
307+
if (constDims.size() == 4 && input_shape.size() == 3) {
308+
constDims.push_back(1);
296309
}
297-
} else if (ov::is_type<ov::op::v3::ROIAlign>(outOp) || ov::is_type<ov::op::v9::ROIAlign>(outOp) ||
298-
ov::is_type<ov::op::v15::ROIAlignRotated>(outOp)) { //< Hacks...
299-
consts[op].needsBatchInterpretation = constDims.size() == 1;
300-
} else if ((ov::is_type<ov::op::v5::Loop>(outOp) || ov::is_type<ov::op::v0::TensorIterator>(outOp))) {
301-
// when inner network has 1d parameter which is connected to outer loop's constant 1d data,
302-
// outer constant 1d data and inner 1d parameter has same bytes_count but layout is different
303-
// (outer constant is [1, N, 1, 1] but inner parameter is [N, 1, 1, 1]).
304-
// To pass check_memory_to_set in input_layout::set_data for this case, Set constDims to [N, 1, 1, 1]
305-
// when constDims is one dim and user op is Loop or TensorIterator.
306-
consts[op].needsBatchInterpretation = constDims.size() == 1;
307-
} else if (ov::is_type<ov::op::v0::Result>(outOp) && !p.use_new_shape_infer() && p.is_inner_program()) {
308-
// When IF-operation generates branch-true and branch-false,
309-
// simple nodes for both can be created such as Parameter->Result, Constant->Result
310-
// And each layout will be like Parameter->Result [N, 1, 1, 1], Constant->Result [1, N, 1, 1], that produces layout mismatch error.
311-
// For that case, Constant->Result needs to be [N, 1, 1, 1]
310+
return true;
311+
}
312+
313+
if (ov::is_type<ov::op::v0::Result>(outOp) && !p.use_new_shape_infer() && p.is_inner_program()) {
312314
consts[op].needsBatchInterpretation = constDims.size() == 1;
313-
} else if (is_convert_matmul_pattern(outOp, user_index)) {
315+
return true;
316+
}
317+
318+
if (is_convert_matmul_pattern(outOp, user_index)) {
314319
const size_t const_static_max_dims = 4;
315-
// MatMul constant reshape WA (legacy shape infer path):
316-
// Only reshape 1D and 2D constants to fix getConstTensor batch/feature
317-
// mis-mapping. For rank >= 3, getConstTensor already produces layouts
318-
// compatible with gemm_inst::transform_input_layouts (trailing 1s align
319-
// with weight_rank extraction). Reshaping rank >= 3 would prepend 1s,
320-
// breaking the first-N-dims extraction in transform_input_layouts.
321320
if (constDims.size() == 1) {
322321
ov::Shape reshaped_const_dims(const_static_max_dims, 1);
323-
const size_t const_idx = (user_index == 0)?
322+
const size_t const_idx = (user_index == 0) ?
324323
(const_static_max_dims - 1)
325324
: (const_static_max_dims - 2);
326325
reshaped_const_dims[const_idx] = constDims[0];
327326
constDims = std::move(reshaped_const_dims);
328327
} else if (constDims.size() == 2 && user_index == 0 && apply_rank2_matmul_wa) {
329328
ov::Shape reshaped_const_dims(const_static_max_dims, 1);
330-
// For MatMul input0, gemm::transform_input_layouts takes the first input_rank dims.
331-
// Keep [M, K] in leading positions and append trailing 1s.
332329
const size_t offset = 0;
333330
for (size_t i = 0; i < constDims.size(); ++i) {
334331
reshaped_const_dims[offset + i] = constDims[i];
335332
}
336333
constDims = std::move(reshaped_const_dims);
337334
}
335+
return true;
336+
}
337+
338+
return false;
339+
};
340+
341+
// WA to inconsistency between input and const 1d tensors
342+
// For Concat along batch we go with batch interpretation
343+
// For Gather input we go with batch interpretation
344+
// Also check if constant users is a backprop convolution - in that case O and I need to be swapped.
345+
for (auto& node : constUsers) {
346+
auto outOp = node.get_node();
347+
if (apply_common_consumer_adaptation(node, outOp)) {
348+
continue;
338349
}
350+
351+
apply_legacy_shape_layout_wa(node, outOp);
339352
}
340353

341354
for (auto& it : consts) {

0 commit comments

Comments
 (0)