From ab749ce60a1254bc078956da0f1c5e2600d9386f Mon Sep 17 00:00:00 2001 From: Przemyslaw Wysocki Date: Mon, 13 Jan 2025 18:57:20 +0100 Subject: [PATCH] Override the default `isExecutable()` method in `StringTensorPack-15` (#28376) ### Details: - Override the default `isExecutable()` method in `StringTensorPack-15` - This fixes incorrect packing of empty strings (see reproducer in the ticket) ### Tickets: - CVS-159636 --------- Signed-off-by: p-wysocki --- .../src/nodes/string_tensor_pack.cpp | 4 ++ .../intel_cpu/src/nodes/string_tensor_pack.h | 1 + .../classes/string_tensor_pack.cpp | 43 +++++++++++++------ .../op_reference/string_tensor_pack.cpp | 5 +++ 4 files changed, 41 insertions(+), 12 deletions(-) diff --git a/src/plugins/intel_cpu/src/nodes/string_tensor_pack.cpp b/src/plugins/intel_cpu/src/nodes/string_tensor_pack.cpp index fa1c7e11dbe754..c3634b67399e8b 100644 --- a/src/plugins/intel_cpu/src/nodes/string_tensor_pack.cpp +++ b/src/plugins/intel_cpu/src/nodes/string_tensor_pack.cpp @@ -81,6 +81,10 @@ struct StringTensorPack::StringTensorPackExecute { } }; +bool StringTensorPack::isExecutable() const { + return !(isInputTensorAtPortEmpty(0) || isInputTensorAtPortEmpty(1)); +} + void StringTensorPack::execute(dnnl::stream strm) { auto indicesPrecision = getParentEdgeAt(0)->getMemory().getDesc().getPrecision(); StringTensorPackContext ctx = {*this}; diff --git a/src/plugins/intel_cpu/src/nodes/string_tensor_pack.h b/src/plugins/intel_cpu/src/nodes/string_tensor_pack.h index 57eed3084d3f2e..952093eab53e21 100644 --- a/src/plugins/intel_cpu/src/nodes/string_tensor_pack.h +++ b/src/plugins/intel_cpu/src/nodes/string_tensor_pack.h @@ -17,6 +17,7 @@ class StringTensorPack : public Node { static bool isSupportedOperation(const std::shared_ptr& op, std::string& errorMessage) noexcept; void getSupportedDescriptors() override; void initSupportedPrimitiveDescriptors() override; + bool isExecutable() const override; void execute(dnnl::stream strm) override; bool created() const override; bool needPrepareParams() const override; diff --git a/src/plugins/intel_cpu/tests/functional/custom/single_layer_tests/classes/string_tensor_pack.cpp b/src/plugins/intel_cpu/tests/functional/custom/single_layer_tests/classes/string_tensor_pack.cpp index 0784745615a4d8..72726eb683d2d9 100644 --- a/src/plugins/intel_cpu/tests/functional/custom/single_layer_tests/classes/string_tensor_pack.cpp +++ b/src/plugins/intel_cpu/tests/functional/custom/single_layer_tests/classes/string_tensor_pack.cpp @@ -52,19 +52,30 @@ void StringTensorPackLayerCPUTest::generate_inputs(const std::vector& const auto indicesType = funcInputs[0].get_element_type(); const auto& indicesShape = targetInputStaticShapes[0]; const auto& symbolsShape = targetInputStaticShapes[2]; - - const ov::Tensor beginsTensor = ov::test::utils::create_and_fill_tensor_consistently(indicesType, indicesShape, symbolsShape[0], 0, 3); - const ov::Tensor endsTensor = ov::test::utils::create_and_fill_tensor_consistently(indicesType, indicesShape, symbolsShape[0], 3, 3); - inputs.insert({ funcInputs[0].get_node_shared_ptr(), beginsTensor }); - inputs.insert({ funcInputs[1].get_node_shared_ptr(), endsTensor }); - + ov::Tensor beginsTensor; + ov::Tensor endsTensor; ov::Tensor symbolsTensor; - ov::test::utils::InputGenerateData in_symbol_data; - in_symbol_data.start_from = 0; - in_symbol_data.range = 10; - symbolsTensor = ov::test::utils::create_and_fill_tensor(ov::element::u8, symbolsShape, in_symbol_data); - inputs.insert({ funcInputs[2].get_node_shared_ptr(), symbolsTensor }); - } + if (shape_size(symbolsShape) == 0) { + symbolsTensor = ov::Tensor(ov::element::u8, symbolsShape); + beginsTensor = ov::Tensor(indicesType, indicesShape); + endsTensor = ov::Tensor(indicesType, indicesShape); + beginsTensor = ov::test::utils::create_and_fill_tensor_consistently(indicesType, indicesShape, 0, 0, 0); + endsTensor = ov::test::utils::create_and_fill_tensor_consistently(indicesType, indicesShape, 0, 0, 0); + } else { + ov::test::utils::InputGenerateData in_symbol_data; + in_symbol_data.start_from = 0; + in_symbol_data.range = 10; + symbolsTensor = ov::test::utils::create_and_fill_tensor(ov::element::u8, symbolsShape, in_symbol_data); + beginsTensor = + ov::test::utils::create_and_fill_tensor_consistently(indicesType, indicesShape, symbolsShape[0], 0, 3); + endsTensor = + ov::test::utils::create_and_fill_tensor_consistently(indicesType, indicesShape, symbolsShape[0], 3, 3); + } + + inputs.insert({funcInputs[0].get_node_shared_ptr(), beginsTensor}); + inputs.insert({funcInputs[1].get_node_shared_ptr(), endsTensor}); + inputs.insert({funcInputs[2].get_node_shared_ptr(), symbolsTensor}); +} void StringTensorPackLayerCPUTest::SetUp() { StringTensorPackLayerTestParams basicParamsSet; @@ -120,6 +131,14 @@ const std::vector StringTensorPackParamsVector = InputShape{{-1, {1, 4}, {1, 4}}, {{1, 1, 4}, {1, 4, 1}}}, // begins/ends shape InputShape{{{50, 100}}, {{50}, {75}, {100}}}, // utf-8 encoded symbols shape }, + StringTensorPackSpecificParams{ + InputShape{{}, {{1, 1, 4}}}, // begins/ends shape + InputShape{{}, {{0}}}, // utf-8 encoded symbols shape + }, + StringTensorPackSpecificParams{ + InputShape{{-1, -1, -1}, {{1, 1, 3}, {1, 1, 4}, {1, 3, 4}, {1, 3, 4}}}, // begins/ends shape + InputShape{{-1}, {{9}, {0}, {108}, {0}}}, // utf-8 encoded symbols shape + }, }; } // namespace StringTensorPack diff --git a/src/plugins/template/tests/functional/op_reference/string_tensor_pack.cpp b/src/plugins/template/tests/functional/op_reference/string_tensor_pack.cpp index ef0e32bdd79dfb..09170b24e061b3 100644 --- a/src/plugins/template/tests/functional/op_reference/string_tensor_pack.cpp +++ b/src/plugins/template/tests/functional/op_reference/string_tensor_pack.cpp @@ -155,6 +155,11 @@ std::vector generateStringTensorPackParams() { ov::element::u8, std::vector{0x49, 0x6e, 0x74, 0x65, 0x6c, 0x4f, 0x70, 0x65, 0x6e, 0x56, 0x49, 0x4e, 0x4f}), Tensor({1, 3}, ov::element::string, std::vector{"Intel", "OpenVINO", ""})), + // empty bytes input + StringTensorPackParams(Tensor({1, 3}, T_idx, std::vector{0, 0, 0}), + Tensor({1, 3}, T_idx, std::vector{0, 0, 0}), + Tensor({0}, ov::element::u8, std::vector{}), + Tensor({1, 3}, ov::element::string, std::vector{"", "", ""})), }; return StringTensorPackParamsList; }