diff --git a/src/plugins/intel_cpu/src/nodes/grn.cpp b/src/plugins/intel_cpu/src/nodes/grn.cpp index a4ac8bc214e..faabdbc9b8c 100644 --- a/src/plugins/intel_cpu/src/nodes/grn.cpp +++ b/src/plugins/intel_cpu/src/nodes/grn.cpp @@ -16,10 +16,6 @@ namespace node { bool GRN::isSupportedOperation(const std::shared_ptr& op, std::string& errorMessage) noexcept { try { - if (isDynamicNgraphNode(op)) { - errorMessage = "Doesn't support op with dynamic shapes"; - return false; - } const auto grn = std::dynamic_pointer_cast(op); if (!grn) { errorMessage = "Only opset1 GRN operation is supported"; @@ -44,9 +40,14 @@ GRN::GRN(const std::shared_ptr& op, const dnnl::engine& eng, IE_THROW() << "Operation with name '" << op->get_friendly_name() << "' is not an instance of GRN from opset1."; - if (getOriginalInputsNumber() != 1 || getOriginalOutputsNumber() != 1) + if (inputShapes.size() != 1 || outputShapes.size() != 1) IE_THROW() << errorPrefix << " has incorrect number of input/output edges!"; + const auto dataRank = getInputShapeAtPort(0).getRank(); + + if (dataRank != getOutputShapeAtPort(0).getRank()) + IE_THROW() << errorPrefix << " has input/output rank mismatch"; + bias = grn->get_bias(); } @@ -59,17 +60,43 @@ void GRN::initSupportedPrimitiveDescriptors() { impl_desc_type::ref_any); } +void GRN::prepareParams() { + const auto& dataMemPtr = getParentEdgeAt(0)->getMemoryPtr(); + const auto& dstMemPtr = getChildEdgeAt(0)->getMemoryPtr(); + + if (!dataMemPtr || !dataMemPtr->isAllocated()) + IE_THROW() << errorPrefix << " has not allocated input memory"; + if (!dstMemPtr || !dstMemPtr->isAllocated()) + IE_THROW() << errorPrefix << " has not allocated output memory"; + if (getSelectedPrimitiveDescriptor() == nullptr) + IE_THROW() << errorPrefix << " has unidentified preferable primitive descriptor"; + + const VectorDims& dataDims = dataMemPtr->getStaticDims(); + const VectorDims& dstDims = dstMemPtr->getStaticDims(); + + for (size_t i = 0; i < dataDims.size(); ++i) { + if (dataDims[i] != dstDims[i]) + IE_THROW() << errorPrefix << " hsd input/output tensors dimensions mismatch"; + } + + if (dataDims.size() > 0) + N = static_cast(dataDims[0]); + if (dataDims.size() > 1) + C = static_cast(dataDims[1]); + if (dataDims.size() > 2) + H = static_cast(dataDims[2]); + if (dataDims.size() > 3) + W = static_cast(dataDims[3]); +} + +void GRN::executeDynamicImpl(dnnl::stream strm) { + execute(std::move(strm)); +} + void GRN::execute(dnnl::stream strm) { const float* src_data = reinterpret_cast(getParentEdgeAt(0)->getMemoryPtr()->GetPtr()); float* dst_data = reinterpret_cast(getChildEdgesAtPort(0)[0]->getMemoryPtr()->GetPtr()); - const auto &dims = getParentEdgeAt(0)->getMemory().getStaticDims(); - - int N = static_cast((dims.size() > 0) ? dims[0] : 1); - int C = static_cast((dims.size() > 1) ? dims[1] : 1); - int H = static_cast((dims.size() > 2) ? dims[2] : 1); - int W = static_cast((dims.size() > 3) ? dims[3] : 1); - parallel_for3d(N, H, W, [&](int b, int h, int w) { double variance = 0; for (int c = 0; c < C; c++) { diff --git a/src/plugins/intel_cpu/src/nodes/grn.h b/src/plugins/intel_cpu/src/nodes/grn.h index 603152369a0..1f15423889a 100644 --- a/src/plugins/intel_cpu/src/nodes/grn.h +++ b/src/plugins/intel_cpu/src/nodes/grn.h @@ -17,14 +17,20 @@ public: void getSupportedDescriptors() override {}; void initSupportedPrimitiveDescriptors() override; - void createPrimitive() override {}; void execute(dnnl::stream strm) override; bool created() const override; + void prepareParams() override; + void executeDynamicImpl(dnnl::stream strm) override; + static bool isSupportedOperation(const std::shared_ptr& op, std::string& errorMessage) noexcept; private: float bias = 1.0f; + int N = 1; + int C = 1; + int H = 1; + int W = 1; std::string errorPrefix; }; diff --git a/src/tests/functional/plugin/cpu/single_layer_tests/grn.cpp b/src/tests/functional/plugin/cpu/single_layer_tests/grn.cpp new file mode 100644 index 00000000000..9a558547da2 --- /dev/null +++ b/src/tests/functional/plugin/cpu/single_layer_tests/grn.cpp @@ -0,0 +1,124 @@ +// Copyright (C) 2018-2022 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "shared_test_classes/base/ov_subgraph.hpp" +#include "ngraph_functions/builders.hpp" +#include "test_utils/cpu_test_utils.hpp" + +using namespace CPUTestUtils; +using namespace ov::test; + +namespace CPULayerTestsDefinitions { + +using GRNCPUTestParams = typename std::tuple< + ov::element::Type, // Network precision + InferenceEngine::Precision, // Input precision + InferenceEngine::Precision, // Output precision + InferenceEngine::Layout, // Input layout + InferenceEngine::Layout, // Output layout + InputShape, // Input shape + float, // Bias + std::string>; // Device name + +class GRNLayerCPUTest : public testing::WithParamInterface, + virtual public SubgraphBaseTest, public CPUTestsBase { +public: + static std::string getTestCaseName(testing::TestParamInfo obj) { + ov::element::Type netPrecision; + InferenceEngine::Precision inPrc, outPrc; + InferenceEngine::Layout inLayout, outLayout; + InputShape inputShape; + float bias; + std::string targetDevice; + + std::tie(netPrecision, inPrc, outPrc, + inLayout, outLayout, + inputShape, + bias, + targetDevice) = obj.param; + + std::ostringstream result; + result << "IS=" << CommonTestUtils::partialShape2str({inputShape.first}) << "_"; + result << "TS="; + for (const auto& item : inputShape.second) { + result << CommonTestUtils::vec2str(item) << "_"; + } + result << "netPRC=" << netPrecision.get_type_name() << "_"; + result << "inPRC=" << inPrc.name() << "_"; + result << "outPRC=" << outPrc.name() << "_"; + result << "inL=" << inLayout << "_"; + result << "outL=" << outLayout << "_"; + result << "bias=" << bias << "_"; + result << "trgDev=" << targetDevice; + + return result.str(); + } + +protected: + void SetUp() override { + ov::element::Type netPrecision; + InferenceEngine::Precision inPrc, outPrc; + InferenceEngine::Layout inLayout, outLayout; + InputShape inputShape; + float bias; + + std::tie(netPrecision, inPrc, outPrc, inLayout, outLayout, inputShape, bias, targetDevice) = GetParam(); + + init_input_shapes({inputShape}); + + const auto paramsIn = ngraph::builder::makeDynamicParams(netPrecision, inputDynamicShapes); + + const auto paramsOut = ngraph::helpers::convert2OutputVector(ngraph::helpers::castOps2Nodes(paramsIn)); + const auto grn = std::make_shared(paramsOut[0], bias); + const ngraph::ResultVector results{std::make_shared(grn)}; + function = std::make_shared(results, paramsIn, "Grn"); + } +}; + +TEST_P(GRNLayerCPUTest, CompareWithRefs) { + run(); +} + +namespace { + +const std::vector netPrecisions = { + ov::element::bf16, + ov::element::f16, + ov::element::f32 +}; + +const std::vector biases = {1e-6f, 0.33f, 1.1f, 2.25f, 100.25f}; + +const std::vector dataInputStaticShapes = {{{}, {{16, 24}}}, {{}, {{3, 16, 24}}}, {{}, {{1, 3, 30, 30}}}}; + +const std::vector dataInputDynamicShapes = + {{{-1, -1}, {{5, 17}, {10, 3}}}, {{3, {10, 12}, -1}, {{3, 12, 25}, {3, 10, 10}}}, + {{2, -1, -1, {5, 10}}, {{2, 17, 20, 7}, {2, 10, 12, 5}}}}; + +INSTANTIATE_TEST_SUITE_P(smoke_GRNCPUStatic, GRNLayerCPUTest, + ::testing::Combine( + ::testing::ValuesIn(netPrecisions), + ::testing::Values(InferenceEngine::Precision::UNSPECIFIED), + ::testing::Values(InferenceEngine::Precision::UNSPECIFIED), + ::testing::Values(InferenceEngine::Layout::ANY), + ::testing::Values(InferenceEngine::Layout::ANY), + ::testing::ValuesIn(dataInputStaticShapes), + ::testing::ValuesIn(biases), + ::testing::Values(CommonTestUtils::DEVICE_CPU)), + GRNLayerCPUTest::getTestCaseName); + +INSTANTIATE_TEST_SUITE_P(smoke_GRNCPUDynamic, GRNLayerCPUTest, + ::testing::Combine( + ::testing::ValuesIn(netPrecisions), + ::testing::Values(InferenceEngine::Precision::UNSPECIFIED), + ::testing::Values(InferenceEngine::Precision::UNSPECIFIED), + ::testing::Values(InferenceEngine::Layout::ANY), + ::testing::Values(InferenceEngine::Layout::ANY), + ::testing::ValuesIn(dataInputDynamicShapes), + ::testing::ValuesIn(biases), + ::testing::Values(CommonTestUtils::DEVICE_CPU)), + GRNLayerCPUTest::getTestCaseName); + +} // namespace +} // namespace CPULayerTestsDefinitions \ No newline at end of file