From 55bf88473aea039f1a2035fe6894cb7564b9ef8b Mon Sep 17 00:00:00 2001 From: Vladislav Golubev Date: Mon, 23 Aug 2021 08:59:54 +0300 Subject: [PATCH 01/76] [CPU][TESTS][LPT] MatMulTransformations test-cases removed from skip config (#7181) --- .../plugin/cpu/shared_tests_instances/skip_tests_config.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/skip_tests_config.cpp b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/skip_tests_config.cpp index f46f975f979..984250795b5 100644 --- a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/skip_tests_config.cpp +++ b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/skip_tests_config.cpp @@ -52,8 +52,6 @@ std::vector disabledTestPatterns() { R"(.*ConvolutionLayerCPUTest.*BF16.*_inFmts=(ndhwc|nhwc).*)", // TODO: 56827. Sporadic test failures R"(.*smoke_Conv.+_FP32.ConvolutionLayerCPUTest\.CompareWithRefs.IS=\(1\.67.+\).*inFmts=n.+c.*_primitive=jit_avx2.*)", - // lpt transformation produce the same names for MatMul and Multiply - R"(.*MatMulTransformation.*)", // incorrect jit_uni_planar_convolution with dilation = {1, 2, 1} and output channel 1 R"(.*smoke_Convolution3D.*D=\(1.2.1\)_O=1.*)", From 5da224abc44c910148b01ec5211e160f658d8566 Mon Sep 17 00:00:00 2001 From: Maksim Shabunin Date: Mon, 23 Aug 2021 09:46:11 +0300 Subject: [PATCH 02/76] Fixed ngraph_onnx_importer compatibility target creation for older cmake (3.10) (#7176) --- cmake/templates/ngraphConfig.cmake.in | 29 ++++++++++++--------------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/cmake/templates/ngraphConfig.cmake.in b/cmake/templates/ngraphConfig.cmake.in index b945d0148aa..543c14daba6 100644 --- a/cmake/templates/ngraphConfig.cmake.in +++ b/cmake/templates/ngraphConfig.cmake.in @@ -37,30 +37,27 @@ @PACKAGE_INIT@ -function(set_imported_global target) - get_target_property(IS_IMPORTED_GLOBAL ${target} IMPORTED_GLOBAL) - if (NOT IS_IMPORTED_GLOBAL) - set_target_properties(${target} PROPERTIES IMPORTED_GLOBAL TRUE) - endif() -endfunction() - if(NOT TARGET ngraph) include("${CMAKE_CURRENT_LIST_DIR}/ngraphTargets.cmake") - set_imported_global(ngraph::ngraph) - set_imported_global(ngraph::frontend_manager) endif() set(ngraph_ngraph_FOUND ON) set(NGRAPH_LIBRARIES ngraph::ngraph) set(ngraph_onnx_ngraph_frontend_FOUND @NGRAPH_ONNX_FRONTEND_ENABLE@) -if (ngraph_onnx_ngraph_frontend_FOUND AND NOT TARGET onnx_ngraph_frontend AND NOT TARGET ngraph::onnx_importer) - set_imported_global(ngraph::onnx_ngraph_frontend) - add_library(ngraph::onnx_importer ALIAS ngraph::onnx_ngraph_frontend) -endif() -set(ngraph_paddlepaddle_frontend_FOUND @NGRAPH_PDPD_FRONTEND_ENABLE@) -if(ngraph_paddlepaddle_frontend_FOUND AND NOT TARGET paddlepaddle_ngraph_frontend) - set_imported_global(ngraph::paddlepaddle_ngraph_frontend) + +# ngraph::onnx_importer target and variables are deprecated +set(ngraph_onnx_importer_FOUND @NGRAPH_ONNX_FRONTEND_ENABLE@) +if(ngraph_onnx_importer_FOUND) + set(ONNX_IMPORTER_LIBRARIES ngraph::onnx_ngraph_frontend) + if(NOT TARGET ngraph::onnx_importer) + add_library(ngraph::onnx_importer INTERFACE IMPORTED) + set_target_properties(ngraph::onnx_importer PROPERTIES + INTERFACE_LINK_LIBRARIES ngraph::onnx_ngraph_frontend + ) + endif() endif() +set(ngraph_paddlepaddle_frontend_FOUND @NGRAPH_PDPD_FRONTEND_ENABLE@) + check_required_components(ngraph) From 5a564197a70e5077b2a96e045e82c887b3615bc1 Mon Sep 17 00:00:00 2001 From: Andrew Kwangwoong Park Date: Mon, 23 Aug 2021 16:08:03 +0900 Subject: [PATCH 03/76] [GPU] Fix clBuildProgram failure with ssd_mobilnet_v1_coco and batch=256 (#7121) --- .../detection_output/detection_output_kernel_ref.cpp | 2 +- .../core/cl_kernels/detection_output_gpu_ref.cl | 11 +++++------ 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/inference-engine/thirdparty/clDNN/kernel_selector/core/actual_kernels/detection_output/detection_output_kernel_ref.cpp b/inference-engine/thirdparty/clDNN/kernel_selector/core/actual_kernels/detection_output/detection_output_kernel_ref.cpp index 8917ecffd7e..aaa51eeccf1 100644 --- a/inference-engine/thirdparty/clDNN/kernel_selector/core/actual_kernels/detection_output/detection_output_kernel_ref.cpp +++ b/inference-engine/thirdparty/clDNN/kernel_selector/core/actual_kernels/detection_output/detection_output_kernel_ref.cpp @@ -123,7 +123,7 @@ DetectionOutputKernelRef::DispatchData SetDefault(const detection_output_params& dispatchData.lws = {1, 1, 1}; } else { dispatchData.gws = {input.Batch().v, 1, 1}; - dispatchData.lws = {input.Batch().v, 1, 1}; + dispatchData.lws = {1, 1, 1}; } } else { dispatchData.gws = {1, 1, 1}; diff --git a/inference-engine/thirdparty/clDNN/kernel_selector/core/cl_kernels/detection_output_gpu_ref.cl b/inference-engine/thirdparty/clDNN/kernel_selector/core/cl_kernels/detection_output_gpu_ref.cl index 6f19536ed68..5d9ae37def8 100644 --- a/inference-engine/thirdparty/clDNN/kernel_selector/core/cl_kernels/detection_output_gpu_ref.cl +++ b/inference-engine/thirdparty/clDNN/kernel_selector/core/cl_kernels/detection_output_gpu_ref.cl @@ -658,7 +658,7 @@ KERNEL (detection_output_stage_final_caffe)(__global INPUT0_TYPE* input_location __global int *buffer1) { const int batchId = get_global_id(0); - __local int class_offset[LOCAL_BATCHES_NUM * NUM_CLASSES_ACC]; + __local int class_offset[NUM_CLASSES_ACC]; const int total_det = FUNC_CALL(get_accumulated_detections)(buffer1, batchId); buffer1[batchId * NUM_CLASSES_ACC + NUM_CLASSES] = total_det; @@ -689,9 +689,9 @@ KERNEL (detection_output_stage_final_caffe)(__global INPUT0_TYPE* input_location } // calculate starting point of each class - class_offset[scores_size_offset] = 0; + class_offset[0] = 0; for (int i = 1; i < NUM_CLASSES_ACC; ++i) { - class_offset[scores_size_offset + i] = class_offset[scores_size_offset + i - 1] + buffer1[scores_size_offset + i - 1]; + class_offset[i] = class_offset[i - 1] + buffer1[scores_size_offset + i - 1]; } barrier(CLK_LOCAL_MEM_FENCE); @@ -700,7 +700,7 @@ KERNEL (detection_output_stage_final_caffe)(__global INPUT0_TYPE* input_location for (uint idx_num_det = 0; idx_num_det < KEEP_TOP_K; idx_num_det++) { SCORES_INFO score_info; score_info = scoresList[scores_offset + idx_num_det]; - const int idx = startIdx + class_offset[batchId * NUM_CLASSES_ACC + score_info.classId]; + const int idx = startIdx + class_offset[score_info.classId]; output[idx * OUTPUT_ROW_SIZE] = TO_OUTPUT_TYPE(batchId); output[idx * OUTPUT_ROW_SIZE + 1] = TO_OUTPUT_TYPE((DECREASE_LABEL_ID) ? score_info.classId - 1 : score_info.classId); output[idx * OUTPUT_ROW_SIZE + 2] = TO_OUTPUT_TYPE(score_info.score); @@ -719,7 +719,7 @@ KERNEL (detection_output_stage_final_caffe)(__global INPUT0_TYPE* input_location ymax = max(TO_INPUT0_TYPE(0.0), min(TO_INPUT0_TYPE(1.0), ymax)); } vstore4((OUTPUT_TYPE4)(xmin, ymin, xmax, ymax), 0, output + idx * OUTPUT_ROW_SIZE + 3); - class_offset[batchId * NUM_CLASSES_ACC + score_info.classId]++; + class_offset[score_info.classId]++; } } else { const int startIdx = FUNC_CALL(get_start_idx)(buffer1, batchId); @@ -753,7 +753,6 @@ KERNEL (detection_output_stage_final_caffe)(__global INPUT0_TYPE* input_location } } - barrier(CLK_GLOBAL_MEM_FENCE); if(batchId == 0) { const int final_detections = FUNC_CALL(get_final_detections)(buffer1); unroll_for (uint i = final_detections; i < NUM_OF_IMAGES * KEEP_TOP_K; i++) { From 745c8933bc67f0eaf7996848f5188521fdf50d14 Mon Sep 17 00:00:00 2001 From: Katarzyna Mitrus Date: Mon, 23 Aug 2021 10:00:35 +0200 Subject: [PATCH 04/76] Fix v0::MVN default constructor (#7175) --- ngraph/core/include/ngraph/op/mvn.hpp | 2 +- ngraph/core/src/op/mvn.cpp | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/ngraph/core/include/ngraph/op/mvn.hpp b/ngraph/core/include/ngraph/op/mvn.hpp index 406e2893963..4b6cd70c63a 100644 --- a/ngraph/core/include/ngraph/op/mvn.hpp +++ b/ngraph/core/include/ngraph/op/mvn.hpp @@ -17,7 +17,7 @@ class NGRAPH_API MVN : public Op { public: NGRAPH_RTTI_DECLARATION; - MVN(); + MVN() = default; /// \brief Constructs an MVN operation. /// /// \param data Input tensor with data diff --git a/ngraph/core/src/op/mvn.cpp b/ngraph/core/src/op/mvn.cpp index b70c944a692..6ab313d1583 100644 --- a/ngraph/core/src/op/mvn.cpp +++ b/ngraph/core/src/op/mvn.cpp @@ -15,8 +15,6 @@ using namespace ngraph; NGRAPH_RTTI_DEFINITION(op::v0::MVN, "MVN", 0); -op::v0::MVN::MVN() : Op(), m_across_channels(), m_normalize_variance(), m_reduction_axes() {} - op::v0::MVN::MVN(const Output& data, bool across_channels, bool normalize_variance, double eps) : Op({data}), m_eps{eps}, From f00a1f3141033c65e11e6b76637413ebdbbfb991 Mon Sep 17 00:00:00 2001 From: Mikhail Letavin Date: Mon, 23 Aug 2021 11:44:51 +0300 Subject: [PATCH 05/76] [GPU] Fixes for correct MultiDevice plugin and inference request behavior (#7161) --- inference-engine/src/cldnn_engine/cldnn_remote_context.cpp | 7 +++++-- inference-engine/thirdparty/clDNN/src/network.cpp | 2 ++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/inference-engine/src/cldnn_engine/cldnn_remote_context.cpp b/inference-engine/src/cldnn_engine/cldnn_remote_context.cpp index 34c3ae30d29..1ee476390d6 100644 --- a/inference-engine/src/cldnn_engine/cldnn_remote_context.cpp +++ b/inference-engine/src/cldnn_engine/cldnn_remote_context.cpp @@ -131,7 +131,7 @@ const std::shared_ptr& CLDNNRemoteBlobImpl::getAllocator() const noe }; std::string CLDNNRemoteBlobImpl::getDeviceName() const noexcept { - return getContextImpl(m_context.lock())->GetPlugin().lock()->GetName(); + return getContextImpl(m_context.lock())->getDeviceName(); }; std::shared_ptr CLDNNRemoteBlobImpl::getContext() const noexcept { @@ -266,7 +266,10 @@ ParamMap CLDNNExecutionContextImpl::getParams() const { } std::string CLDNNExecutionContextImpl::getDeviceName() const noexcept { - return m_plugin.lock()->GetName(); + auto devName = m_plugin.lock()->GetName(); + if (!m_config.device_id.empty()) + devName += "." + m_config.device_id; + return devName; } }; // namespace CLDNNPlugin diff --git a/inference-engine/thirdparty/clDNN/src/network.cpp b/inference-engine/thirdparty/clDNN/src/network.cpp index 1aef6da691c..9692bd7ee73 100644 --- a/inference-engine/thirdparty/clDNN/src/network.cpp +++ b/inference-engine/thirdparty/clDNN/src/network.cpp @@ -418,6 +418,8 @@ void network::set_output_memory(const primitive_id& id, memory::ptr mem_new) { for (auto& prim : o_iter->second) { prim->set_output_memory(eng.reinterpret_buffer(*mem_new, prim->output_memory().get_layout()), false); + if (!_reset_arguments) + prim->set_arguments(); } } From 8d4e850356d8229c820bb25fedf0f0a224b707c4 Mon Sep 17 00:00:00 2001 From: Gabriele Galiero Casay Date: Mon, 23 Aug 2021 12:12:46 +0200 Subject: [PATCH 06/76] Fix op category section in operations spec (#7130) --- docs/ops/activation/HSwish_4.md | 2 +- docs/ops/activation/LogSoftmax_5.md | 2 +- docs/ops/arithmetic/Abs_1.md | 2 +- docs/ops/arithmetic/Acos_1.md | 2 +- docs/ops/arithmetic/Acosh_3.md | 2 +- docs/ops/arithmetic/Add_1.md | 2 +- docs/ops/arithmetic/Asin_1.md | 2 +- docs/ops/arithmetic/Asinh_3.md | 2 +- docs/ops/arithmetic/Atan_1.md | 2 +- docs/ops/arithmetic/Atanh_3.md | 2 +- docs/ops/arithmetic/Ceiling_1.md | 2 +- docs/ops/arithmetic/Cos_1.md | 2 +- docs/ops/arithmetic/Cosh_1.md | 2 +- docs/ops/arithmetic/CumSum_3.md | 2 +- docs/ops/arithmetic/Divide_1.md | 2 +- docs/ops/arithmetic/Erf_1.md | 2 +- docs/ops/arithmetic/FloorMod_1.md | 2 +- docs/ops/arithmetic/Floor_1.md | 2 +- docs/ops/arithmetic/Log_1.md | 2 +- docs/ops/arithmetic/Maximum_1.md | 2 +- docs/ops/arithmetic/Minimum_1.md | 2 +- docs/ops/arithmetic/Mod_1.md | 2 +- docs/ops/arithmetic/Multiply_1.md | 2 +- docs/ops/arithmetic/Negative_1.md | 2 +- docs/ops/arithmetic/Power_1.md | 2 +- docs/ops/arithmetic/Round_5.md | 2 +- docs/ops/arithmetic/Sign_1.md | 2 +- docs/ops/arithmetic/Sin_1.md | 2 +- docs/ops/arithmetic/Sinh_1.md | 2 +- docs/ops/arithmetic/Sqrt_1.md | 2 +- docs/ops/arithmetic/SquaredDifference_1.md | 2 +- docs/ops/arithmetic/Subtract_1.md | 2 +- docs/ops/arithmetic/Tan_1.md | 2 +- docs/ops/arithmetic/Tanh_1.md | 2 +- docs/ops/comparison/Equal_1.md | 2 +- docs/ops/comparison/GreaterEqual_1.md | 2 +- docs/ops/comparison/Greater_1.md | 2 +- docs/ops/comparison/LessEqual_1.md | 2 +- docs/ops/comparison/Less_1.md | 2 +- docs/ops/comparison/NotEqual_1.md | 2 +- docs/ops/condition/Bucketize_3.md | 2 +- docs/ops/condition/If_8.md | 2 +- docs/ops/condition/NonZero_3.md | 2 +- docs/ops/condition/Select_1.md | 2 +- docs/ops/convolution/ConvolutionBackpropData_1.md | 2 +- docs/ops/convolution/Convolution_1.md | 2 +- docs/ops/convolution/DeformableConvolution_1.md | 2 +- docs/ops/convolution/DeformableConvolution_8.md | 2 +- docs/ops/convolution/GroupConvolutionBackpropData_1.md | 2 +- docs/ops/convolution/GroupConvolution_1.md | 2 +- docs/ops/detection/DeformablePSROIPooling_1.md | 2 +- docs/ops/detection/ExperimentalDetectronDetectionOutput_6.md | 2 +- .../ExperimentalDetectronGenerateProposalsSingleImage_6.md | 2 +- docs/ops/detection/ExperimentalDetectronPriorGridGenerator_6.md | 2 +- .../ops/detection/ExperimentalDetectronROIFeatureExtractor_6.md | 2 +- docs/ops/detection/PSROIPooling_1.md | 2 +- docs/ops/detection/PriorBoxClustered_1.md | 2 +- docs/ops/detection/PriorBox_1.md | 2 +- docs/ops/detection/ROIAlign_3.md | 2 +- docs/ops/detection/ROIPooling_1.md | 2 +- docs/ops/generation/RandomUniform_8.md | 2 +- docs/ops/generation/Range_1.md | 2 +- docs/ops/generation/Range_4.md | 2 +- docs/ops/image/Interpolate_1.md | 2 +- docs/ops/image/Interpolate_4.md | 2 +- docs/ops/infrastructure/Loop_5.md | 2 +- docs/ops/infrastructure/TensorIterator_1.md | 2 +- docs/ops/logical/LogicalAnd_1.md | 2 +- docs/ops/logical/LogicalNot_1.md | 2 +- docs/ops/logical/LogicalOr_1.md | 2 +- docs/ops/logical/LogicalXor_1.md | 2 +- docs/ops/matrix/Einsum_7.md | 2 +- docs/ops/matrix/MatMul_1.md | 2 +- docs/ops/movement/Broadcast_1.md | 2 +- docs/ops/movement/Broadcast_3.md | 2 +- docs/ops/movement/Concat_1.md | 2 +- docs/ops/movement/GatherElements_6.md | 2 +- docs/ops/movement/GatherND_5.md | 2 +- docs/ops/movement/Gather_1.md | 2 +- docs/ops/movement/Gather_7.md | 2 +- docs/ops/movement/Gather_8.md | 2 +- docs/ops/movement/Pad_1.md | 2 +- docs/ops/movement/Reverse_1.md | 2 +- docs/ops/movement/Roll_7.md | 2 +- docs/ops/movement/ScatterElementsUpdate_3.md | 2 +- docs/ops/movement/ScatterNDUpdate_3.md | 2 +- docs/ops/movement/ScatterUpdate_3.md | 2 +- docs/ops/movement/ShuffleChannels_1.md | 2 +- docs/ops/movement/Split_1.md | 2 +- docs/ops/movement/StridedSlice_1.md | 2 +- docs/ops/movement/Tile_1.md | 2 +- docs/ops/movement/Transpose_1.md | 2 +- docs/ops/movement/VariadicSplit_1.md | 2 +- docs/ops/quantization/FakeQuantize_1.md | 2 +- docs/ops/sequence/CTCGreedyDecoderSeqLen_6.md | 2 +- docs/ops/sequence/CTCGreedyDecoder_1.md | 2 +- docs/ops/sequence/CTCLoss_4.md | 2 +- docs/ops/sequence/GRUCell_3.md | 2 +- docs/ops/sequence/OneHot_1.md | 2 +- docs/ops/sequence/RNNCell_3.md | 2 +- docs/ops/shape/Reshape_1.md | 2 +- docs/ops/shape/ShapeOf_1.md | 2 +- docs/ops/shape/ShapeOf_3.md | 2 +- docs/ops/shape/Squeeze_1.md | 2 +- docs/ops/shape/Unsqueeze_1.md | 2 +- docs/ops/signals/DFT_7.md | 2 +- docs/ops/signals/IDFT_7.md | 2 +- docs/ops/sort/ExperimentalDetectronTopKROIs_6.md | 2 +- 108 files changed, 108 insertions(+), 108 deletions(-) diff --git a/docs/ops/activation/HSwish_4.md b/docs/ops/activation/HSwish_4.md index 3f27517a44b..b5870983af3 100644 --- a/docs/ops/activation/HSwish_4.md +++ b/docs/ops/activation/HSwish_4.md @@ -2,7 +2,7 @@ **Versioned name**: *HSwish-4* -**Category**: *Activation* +**Category**: *Activation function* **Short description**: HSwish takes one input tensor and produces output tensor where the hard version of swish function is applied to the tensor elementwise. diff --git a/docs/ops/activation/LogSoftmax_5.md b/docs/ops/activation/LogSoftmax_5.md index d26488fa968..25296571319 100644 --- a/docs/ops/activation/LogSoftmax_5.md +++ b/docs/ops/activation/LogSoftmax_5.md @@ -2,7 +2,7 @@ **Versioned name**: *LogSoftmax-5* -**Category**: *Activation* +**Category**: *Activation function* **Short description**: LogSoftmax computes the natural logarithm of softmax values for the given input. diff --git a/docs/ops/arithmetic/Abs_1.md b/docs/ops/arithmetic/Abs_1.md index 1dc73dee933..457085a36f9 100644 --- a/docs/ops/arithmetic/Abs_1.md +++ b/docs/ops/arithmetic/Abs_1.md @@ -2,7 +2,7 @@ **Versioned name**: *Abs-1* -**Category**: Arithmetic unary operation +**Category**: *Arithmetic unary* **Short description**: *Abs* performs element-wise the absolute value with given tensor. diff --git a/docs/ops/arithmetic/Acos_1.md b/docs/ops/arithmetic/Acos_1.md index 2c274b01c8a..5b866047551 100644 --- a/docs/ops/arithmetic/Acos_1.md +++ b/docs/ops/arithmetic/Acos_1.md @@ -2,7 +2,7 @@ **Versioned name**: *Acos-1* -**Category**: Arithmetic unary operation +**Category**: *Arithmetic unary* **Short description**: *Acos* performs element-wise inverse cosine (arccos) operation with given tensor. diff --git a/docs/ops/arithmetic/Acosh_3.md b/docs/ops/arithmetic/Acosh_3.md index 9f858924d4e..20f8dee4969 100644 --- a/docs/ops/arithmetic/Acosh_3.md +++ b/docs/ops/arithmetic/Acosh_3.md @@ -2,7 +2,7 @@ **Versioned name**: *Acosh-3* -**Category**: Arithmetic unary operation +**Category**: *Arithmetic unary* **Short description**: *Acosh* performs element-wise hyperbolic inverse cosine (arccosh) operation with given tensor. diff --git a/docs/ops/arithmetic/Add_1.md b/docs/ops/arithmetic/Add_1.md index d73bdaaea85..c71d182cc9f 100644 --- a/docs/ops/arithmetic/Add_1.md +++ b/docs/ops/arithmetic/Add_1.md @@ -2,7 +2,7 @@ **Versioned name**: *Add-1* -**Category**: Arithmetic binary operation +**Category**: *Arithmetic binary* **Short description**: *Add* performs element-wise addition operation with two given tensors applying broadcasting rule specified in the *auto_broacast* attribute. diff --git a/docs/ops/arithmetic/Asin_1.md b/docs/ops/arithmetic/Asin_1.md index 5e7fe068ba7..69be38d84ab 100644 --- a/docs/ops/arithmetic/Asin_1.md +++ b/docs/ops/arithmetic/Asin_1.md @@ -2,7 +2,7 @@ **Versioned name**: *Asin-1* -**Category**: Arithmetic unary operation +**Category**: *Arithmetic unary* **Short description**: *Asin* performs element-wise inverse sine (arcsin) operation with given tensor. diff --git a/docs/ops/arithmetic/Asinh_3.md b/docs/ops/arithmetic/Asinh_3.md index 6fae01555d0..093161399f0 100644 --- a/docs/ops/arithmetic/Asinh_3.md +++ b/docs/ops/arithmetic/Asinh_3.md @@ -2,7 +2,7 @@ **Versioned name**: *Asinh-3* -**Category**: Arithmetic unary operation +**Category**: *Arithmetic unary* **Short description**: *Asinh* performs element-wise inverse hyperbolic sine operation (arcsinh) on a given input tensor. diff --git a/docs/ops/arithmetic/Atan_1.md b/docs/ops/arithmetic/Atan_1.md index 7fc9525bf66..4439477f2a9 100644 --- a/docs/ops/arithmetic/Atan_1.md +++ b/docs/ops/arithmetic/Atan_1.md @@ -2,7 +2,7 @@ **Versioned name**: *Atan-1* -**Category**: Arithmetic unary operation +**Category**: *Arithmetic unary* **Short description**: *Atan* performs element-wise inverse tangent (arctangent) operation with given tensor. diff --git a/docs/ops/arithmetic/Atanh_3.md b/docs/ops/arithmetic/Atanh_3.md index d08486c4205..57deafc4130 100644 --- a/docs/ops/arithmetic/Atanh_3.md +++ b/docs/ops/arithmetic/Atanh_3.md @@ -2,7 +2,7 @@ **Versioned name**: *Atanh-3* -**Category**: Arithmetic unary operation +**Category**: *Arithmetic unary* **Short description**: *Atanh* performs element-wise hyperbolic inverse tangent (arctangenth) operation with a given tensor. diff --git a/docs/ops/arithmetic/Ceiling_1.md b/docs/ops/arithmetic/Ceiling_1.md index e091824c96d..4f8a5e983d4 100644 --- a/docs/ops/arithmetic/Ceiling_1.md +++ b/docs/ops/arithmetic/Ceiling_1.md @@ -2,7 +2,7 @@ **Versioned name**: *Ceiling-1* -**Category**: Arithmetic unary operation +**Category**: *Arithmetic unary* **Short description**: *Ceiling* performs element-wise ceiling operation with given tensor. diff --git a/docs/ops/arithmetic/Cos_1.md b/docs/ops/arithmetic/Cos_1.md index 462b98fde2c..6b134d17f9b 100644 --- a/docs/ops/arithmetic/Cos_1.md +++ b/docs/ops/arithmetic/Cos_1.md @@ -2,7 +2,7 @@ **Versioned name**: *Cos-1* -**Category**: Arithmetic unary operation +**Category**: *Arithmetic unary* **Short description**: *Cos* performs element-wise cosine operation on a given input tensor. diff --git a/docs/ops/arithmetic/Cosh_1.md b/docs/ops/arithmetic/Cosh_1.md index 7f1e3055dd3..e736b2fb11f 100644 --- a/docs/ops/arithmetic/Cosh_1.md +++ b/docs/ops/arithmetic/Cosh_1.md @@ -2,7 +2,7 @@ **Versioned name**: *Cosh-1* -**Category**: Arithmetic unary operation +**Category**: *Arithmetic unary* **Short description**: *Cosh* performs element-wise hyperbolic cosine operation on a given input tensor. diff --git a/docs/ops/arithmetic/CumSum_3.md b/docs/ops/arithmetic/CumSum_3.md index 4ae6f8bde56..c33524a39f2 100644 --- a/docs/ops/arithmetic/CumSum_3.md +++ b/docs/ops/arithmetic/CumSum_3.md @@ -2,7 +2,7 @@ **Versioned name**: *CumSum-3* -**Category**: Arithmetic unary operation +**Category**: *Arithmetic unary* **Short description**: *CumSum* performs cumulative summation of the input elements along the given axis. diff --git a/docs/ops/arithmetic/Divide_1.md b/docs/ops/arithmetic/Divide_1.md index b69a07454a1..ef07ea3e1fa 100644 --- a/docs/ops/arithmetic/Divide_1.md +++ b/docs/ops/arithmetic/Divide_1.md @@ -2,7 +2,7 @@ **Versioned name**: *Divide-1* -**Category**: Arithmetic binary operation +**Category**: *Arithmetic binary* **Short description**: *Divide* performs element-wise division operation with two given tensors applying broadcasting rule specified in the *auto_broacast* attribute. diff --git a/docs/ops/arithmetic/Erf_1.md b/docs/ops/arithmetic/Erf_1.md index 52d2d0301cb..ff137416254 100644 --- a/docs/ops/arithmetic/Erf_1.md +++ b/docs/ops/arithmetic/Erf_1.md @@ -2,7 +2,7 @@ **Versioned name**: *Erf-1* -**Category**: Arithmetic unary operation +**Category**: *Arithmetic unary* **Short description**: *Erf* performs element-wise Gauss error function (erf) on a given input tensor. diff --git a/docs/ops/arithmetic/FloorMod_1.md b/docs/ops/arithmetic/FloorMod_1.md index c573dee8304..eccad4177ef 100644 --- a/docs/ops/arithmetic/FloorMod_1.md +++ b/docs/ops/arithmetic/FloorMod_1.md @@ -2,7 +2,7 @@ **Versioned name**: *FloorMod-1* -**Category**: Arithmetic binary operation +**Category**: *Arithmetic binary* **Short description**: *FloorMod* performs an element-wise floor modulo operation with two given tensors applying broadcasting rule specified in the *auto_broadcast* attribute. diff --git a/docs/ops/arithmetic/Floor_1.md b/docs/ops/arithmetic/Floor_1.md index 06690f06df8..d62c604e32b 100644 --- a/docs/ops/arithmetic/Floor_1.md +++ b/docs/ops/arithmetic/Floor_1.md @@ -2,7 +2,7 @@ **Versioned name**: *Floor-1* -**Category**: Arithmetic unary operation +**Category**: *Arithmetic unary* **Short description**: *Floor* performs element-wise floor operation with given tensor. diff --git a/docs/ops/arithmetic/Log_1.md b/docs/ops/arithmetic/Log_1.md index b8074316e79..f24e3d21542 100644 --- a/docs/ops/arithmetic/Log_1.md +++ b/docs/ops/arithmetic/Log_1.md @@ -2,7 +2,7 @@ **Versioned name**: *Log-1* -**Category**: Arithmetic unary operation +**Category**: *Arithmetic unary* **Short description**: *Log* performs element-wise natural logarithm operation with given tensor. diff --git a/docs/ops/arithmetic/Maximum_1.md b/docs/ops/arithmetic/Maximum_1.md index 18eb0e757b9..8ef87a94552 100644 --- a/docs/ops/arithmetic/Maximum_1.md +++ b/docs/ops/arithmetic/Maximum_1.md @@ -2,7 +2,7 @@ **Versioned name**: *Maximum-1* -**Category**: Arithmetic binary operation +**Category**: *Arithmetic binary* **Short description**: *Maximum* performs element-wise maximum operation with two given tensors applying broadcasting rule specified in the *auto_broadcast* attribute. diff --git a/docs/ops/arithmetic/Minimum_1.md b/docs/ops/arithmetic/Minimum_1.md index 30204e136dc..8131ffa6bc9 100644 --- a/docs/ops/arithmetic/Minimum_1.md +++ b/docs/ops/arithmetic/Minimum_1.md @@ -2,7 +2,7 @@ **Versioned name**: *Minimum-1* -**Category**: Arithmetic binary operation +**Category**: *Arithmetic binary* **Short description**: *Minimum* performs element-wise minimum operation with two given tensors applying broadcasting rule specified in the *auto_broadcast* attribute. diff --git a/docs/ops/arithmetic/Mod_1.md b/docs/ops/arithmetic/Mod_1.md index df414c0f4fe..febac678ed6 100644 --- a/docs/ops/arithmetic/Mod_1.md +++ b/docs/ops/arithmetic/Mod_1.md @@ -2,7 +2,7 @@ **Versioned name**: *Mod-1* -**Category**: Arithmetic binary operation +**Category**: *Arithmetic binary* **Short description**: *Mod* performs an element-wise modulo operation with two given tensors applying broadcasting rule specified in the *auto_broadcast* attribute. diff --git a/docs/ops/arithmetic/Multiply_1.md b/docs/ops/arithmetic/Multiply_1.md index a713c9c0eac..c6fd0b11ea2 100644 --- a/docs/ops/arithmetic/Multiply_1.md +++ b/docs/ops/arithmetic/Multiply_1.md @@ -2,7 +2,7 @@ **Versioned name**: *Multiply-1* -**Category**: Arithmetic binary operation +**Category**: *Arithmetic binary* **Short description**: *Multiply* performs element-wise multiplication operation with two given tensors applying broadcasting rule specified in the *auto_broacast* attribute. diff --git a/docs/ops/arithmetic/Negative_1.md b/docs/ops/arithmetic/Negative_1.md index 997342c2d05..5fa0e630dda 100644 --- a/docs/ops/arithmetic/Negative_1.md +++ b/docs/ops/arithmetic/Negative_1.md @@ -2,7 +2,7 @@ **Versioned name**: *Negative-1* -**Category**: Arithmetic unary operation +**Category**: *Arithmetic unary* **Short description**: *Negative* performs element-wise negative operation on a given input tensor. diff --git a/docs/ops/arithmetic/Power_1.md b/docs/ops/arithmetic/Power_1.md index 571b4445e3d..f4de24bf038 100644 --- a/docs/ops/arithmetic/Power_1.md +++ b/docs/ops/arithmetic/Power_1.md @@ -2,7 +2,7 @@ **Versioned name**: *Power-1* -**Category**: Arithmetic binary operation +**Category**: *Arithmetic binary* **Short description**: *Power* performs element-wise power operation with two given tensors applying broadcasting rule specified in the *auto_broadcast* attribute. diff --git a/docs/ops/arithmetic/Round_5.md b/docs/ops/arithmetic/Round_5.md index 85cb480cadd..ae423dcd091 100644 --- a/docs/ops/arithmetic/Round_5.md +++ b/docs/ops/arithmetic/Round_5.md @@ -2,7 +2,7 @@ **Versioned name**: *Round-5* -**Category**: Arithmetic unary operation +**Category**: *Arithmetic unary* **Short description**: *Round* performs element-wise round operation with given tensor. diff --git a/docs/ops/arithmetic/Sign_1.md b/docs/ops/arithmetic/Sign_1.md index 1aa87097e62..f9691bf5488 100644 --- a/docs/ops/arithmetic/Sign_1.md +++ b/docs/ops/arithmetic/Sign_1.md @@ -2,7 +2,7 @@ **Versioned name**: *Sign-1* -**Category**: Arithmetic unary operation +**Category**: *Arithmetic unary* **Short description**: *Sign* performs element-wise sign operation on a given input tensor. diff --git a/docs/ops/arithmetic/Sin_1.md b/docs/ops/arithmetic/Sin_1.md index 24b43d2e39d..36bef086315 100644 --- a/docs/ops/arithmetic/Sin_1.md +++ b/docs/ops/arithmetic/Sin_1.md @@ -2,7 +2,7 @@ **Versioned name**: *Sin-1* -**Category**: Arithmetic unary operation +**Category**: *Arithmetic unary* **Short description**: *Sin* performs element-wise sine operation with given tensor. diff --git a/docs/ops/arithmetic/Sinh_1.md b/docs/ops/arithmetic/Sinh_1.md index 0f0c83b63e1..aeb99c7918d 100644 --- a/docs/ops/arithmetic/Sinh_1.md +++ b/docs/ops/arithmetic/Sinh_1.md @@ -2,7 +2,7 @@ **Versioned name**: *Sinh-1* -**Category**: Arithmetic unary operation +**Category**: *Arithmetic unary* **Short description**: *Sinh* performs element-wise hyperbolic sine (sinh) operation on a given input tensor diff --git a/docs/ops/arithmetic/Sqrt_1.md b/docs/ops/arithmetic/Sqrt_1.md index 9f2d1f665d7..a69dfd6458a 100644 --- a/docs/ops/arithmetic/Sqrt_1.md +++ b/docs/ops/arithmetic/Sqrt_1.md @@ -2,7 +2,7 @@ **Versioned name**: *Sqrt-1* -**Category**: Arithmetic unary operation +**Category**: *Arithmetic unary* **Short description**: Square root element-wise operation. diff --git a/docs/ops/arithmetic/SquaredDifference_1.md b/docs/ops/arithmetic/SquaredDifference_1.md index 509b70c2e14..b20ec7aa1ce 100644 --- a/docs/ops/arithmetic/SquaredDifference_1.md +++ b/docs/ops/arithmetic/SquaredDifference_1.md @@ -2,7 +2,7 @@ **Versioned name**: *SquaredDifference-1* -**Category**: Arithmetic binary operation +**Category**: *Arithmetic binary* **Short description**: *SquaredDifference* performs element-wise subtract and square the result operation with two given tensors applying broadcasting rule specified in the *auto_broadcast* attribute. diff --git a/docs/ops/arithmetic/Subtract_1.md b/docs/ops/arithmetic/Subtract_1.md index 0720bd3415c..6a35d32ac35 100644 --- a/docs/ops/arithmetic/Subtract_1.md +++ b/docs/ops/arithmetic/Subtract_1.md @@ -2,7 +2,7 @@ **Versioned name**: *Subtract-1* -**Category**: Arithmetic binary operation +**Category**: *Arithmetic binary* **Short description**: *Subtract* performs element-wise subtraction operation with two given tensors applying broadcasting rule specified in the *auto_broacast* attribute. diff --git a/docs/ops/arithmetic/Tan_1.md b/docs/ops/arithmetic/Tan_1.md index d9086f7ad5f..07491c3c9d1 100644 --- a/docs/ops/arithmetic/Tan_1.md +++ b/docs/ops/arithmetic/Tan_1.md @@ -2,7 +2,7 @@ **Versioned name**: *Tan-1* -**Category**: Arithmetic unary operation +**Category**: *Arithmetic unary* **Short description**: *Tan* performs element-wise tangent operation with given tensor. diff --git a/docs/ops/arithmetic/Tanh_1.md b/docs/ops/arithmetic/Tanh_1.md index c5c77dbe0ab..0c90d4b496d 100644 --- a/docs/ops/arithmetic/Tanh_1.md +++ b/docs/ops/arithmetic/Tanh_1.md @@ -2,7 +2,7 @@ **Versioned name**: *Tanh-1* -**Category**: *Arithmetic function* +**Category**: *Arithmetic unary* **Short description**: *Tanh* performs element-wise hyperbolic tangent (tanh) operation with given tensor. diff --git a/docs/ops/comparison/Equal_1.md b/docs/ops/comparison/Equal_1.md index 9bdd3361c26..bf813ca6c8c 100644 --- a/docs/ops/comparison/Equal_1.md +++ b/docs/ops/comparison/Equal_1.md @@ -2,7 +2,7 @@ **Versioned name**: *Equal-1* -**Category**: Comparison binary operation +**Category**: *Comparison binary* **Short description**: *Equal* performs element-wise comparison operation with two given input tensors applying multi-directional broadcast rules specified in the *auto_broadcast* attribute. diff --git a/docs/ops/comparison/GreaterEqual_1.md b/docs/ops/comparison/GreaterEqual_1.md index f4a29c667fe..c072a9c5923 100644 --- a/docs/ops/comparison/GreaterEqual_1.md +++ b/docs/ops/comparison/GreaterEqual_1.md @@ -2,7 +2,7 @@ **Versioned name**: *GreaterEqual-1* -**Category**: Comparison binary operation +**Category**: *Comparison binary* **Short description**: *GreaterEqual* performs element-wise comparison operation with two given tensors applying multi-directional broadcast rules. diff --git a/docs/ops/comparison/Greater_1.md b/docs/ops/comparison/Greater_1.md index a1fe52e0364..2beb0ce3fd0 100644 --- a/docs/ops/comparison/Greater_1.md +++ b/docs/ops/comparison/Greater_1.md @@ -2,7 +2,7 @@ **Versioned name**: *Greater-1* -**Category**: Comparison binary operation +**Category**: *Comparison binary* **Short description**: *Greater* performs element-wise comparison operation with two given tensors applying broadcast rules specified in the `auto_broadcast` attribute. diff --git a/docs/ops/comparison/LessEqual_1.md b/docs/ops/comparison/LessEqual_1.md index bb7eed13793..dbdf80c3716 100644 --- a/docs/ops/comparison/LessEqual_1.md +++ b/docs/ops/comparison/LessEqual_1.md @@ -2,7 +2,7 @@ **Versioned name**: *LessEqual-1* -**Category**: Comparison binary operation +**Category**: *Comparison binary* **Short description**: *LessEqual* performs element-wise comparison operation with two given tensors applying broadcast rules specified in the *auto_broadcast* attribute. diff --git a/docs/ops/comparison/Less_1.md b/docs/ops/comparison/Less_1.md index dcf210d6579..ca24f17cd16 100644 --- a/docs/ops/comparison/Less_1.md +++ b/docs/ops/comparison/Less_1.md @@ -2,7 +2,7 @@ **Versioned name**: *Less-1* -**Category**: Comparison binary operation +**Category**: *Comparison binary* **Short description**: *Less* performs element-wise comparison operation with two given tensors applying multi-directional broadcast rules. diff --git a/docs/ops/comparison/NotEqual_1.md b/docs/ops/comparison/NotEqual_1.md index 691da41c175..dd077b9d2fc 100644 --- a/docs/ops/comparison/NotEqual_1.md +++ b/docs/ops/comparison/NotEqual_1.md @@ -2,7 +2,7 @@ **Versioned name**: *NotEqual-1* -**Category**: Comparison binary operation +**Category**: *Comparison binary* **Short description**: *NotEqual* performs element-wise comparison operation with two given tensors applying multi-directional broadcast rules specified in the `auto_broadcast` attribute. diff --git a/docs/ops/condition/Bucketize_3.md b/docs/ops/condition/Bucketize_3.md index 40b9369f191..2de9a166aea 100644 --- a/docs/ops/condition/Bucketize_3.md +++ b/docs/ops/condition/Bucketize_3.md @@ -2,7 +2,7 @@ **Versioned name**: *Bucketize-3* -**Category**: Condition operation +**Category**: *Condition* **Short description**: *Bucketize* bucketizes the input based on boundaries. This is similar to [Reference](https://www.tensorflow.org/api_docs/cc/class/tensorflow/ops/bucketize). diff --git a/docs/ops/condition/If_8.md b/docs/ops/condition/If_8.md index 7de2449b1ea..3d2e9268901 100644 --- a/docs/ops/condition/If_8.md +++ b/docs/ops/condition/If_8.md @@ -2,7 +2,7 @@ **Versioned name**: *If-8* -**Category**: Infrastructure +**Category**: *Condition* **Short description**: *If* operation contains two internal networks(subgraphs) such as `then_body` and `else_body`, and performs one of them depending on `cond` value. If `cond` is `True`, `then_body` is executed. If `cond` is `False`, diff --git a/docs/ops/condition/NonZero_3.md b/docs/ops/condition/NonZero_3.md index 3034936721c..6d71ea808f3 100644 --- a/docs/ops/condition/NonZero_3.md +++ b/docs/ops/condition/NonZero_3.md @@ -2,7 +2,7 @@ **Versioned name**: *NonZero-3* -**Category**: Condition operation +**Category**: *Condition* **Short description**: *NonZero* returns the indices of the non-zero elements of the input tensor. diff --git a/docs/ops/condition/Select_1.md b/docs/ops/condition/Select_1.md index 56e5fde8eab..78ec5d5a5d2 100644 --- a/docs/ops/condition/Select_1.md +++ b/docs/ops/condition/Select_1.md @@ -2,7 +2,7 @@ **Versioned name**: *Select-1* -**Category**: *Conditions* +**Category**: *Condition* **Short description**: *Select* returns a tensor filled with the elements from the second or the third inputs, depending on the condition (the first input) value. diff --git a/docs/ops/convolution/ConvolutionBackpropData_1.md b/docs/ops/convolution/ConvolutionBackpropData_1.md index a69f5e300ad..a630a113cf7 100644 --- a/docs/ops/convolution/ConvolutionBackpropData_1.md +++ b/docs/ops/convolution/ConvolutionBackpropData_1.md @@ -2,7 +2,7 @@ **Versioned name**: *ConvolutionBackpropData-1* -**Category**: Convolution +**Category**: *Convolution* **Short description**: Computes 1D, 2D or 3D *ConvolutionBackpropData* operation with respect to the input and kernel tensors. Also known as a Transposed Convolution. diff --git a/docs/ops/convolution/Convolution_1.md b/docs/ops/convolution/Convolution_1.md index 431575b99c3..068bad8b210 100644 --- a/docs/ops/convolution/Convolution_1.md +++ b/docs/ops/convolution/Convolution_1.md @@ -2,7 +2,7 @@ **Versioned name**: *Convolution-1* -**Category**: Convolution +**Category**: *Convolution* **Short description**: Computes 1D, 2D or 3D convolution (cross-correlation to be precise) of input and kernel tensors. diff --git a/docs/ops/convolution/DeformableConvolution_1.md b/docs/ops/convolution/DeformableConvolution_1.md index 6c73e202be5..ed64bb0e71c 100644 --- a/docs/ops/convolution/DeformableConvolution_1.md +++ b/docs/ops/convolution/DeformableConvolution_1.md @@ -2,7 +2,7 @@ **Versioned name**: *DeformableConvolution-1* -**Category**: Convolution +**Category**: *Convolution* **Short description**: Computes 2D deformable convolution of input and kernel tensors. diff --git a/docs/ops/convolution/DeformableConvolution_8.md b/docs/ops/convolution/DeformableConvolution_8.md index fc7c05a235c..9ae40f87a9e 100644 --- a/docs/ops/convolution/DeformableConvolution_8.md +++ b/docs/ops/convolution/DeformableConvolution_8.md @@ -2,7 +2,7 @@ **Versioned name**: *DeformableConvolution-8* -**Category**: Convolution +**Category**: *Convolution* **Short description**: Computes 2D deformable convolution of input and kernel tensors. diff --git a/docs/ops/convolution/GroupConvolutionBackpropData_1.md b/docs/ops/convolution/GroupConvolutionBackpropData_1.md index 6739d5dfcb0..94f7bdf267c 100644 --- a/docs/ops/convolution/GroupConvolutionBackpropData_1.md +++ b/docs/ops/convolution/GroupConvolutionBackpropData_1.md @@ -2,7 +2,7 @@ **Versioned name**: *GroupConvolutionBackpropData-1* -**Category**: Convolution +**Category**: *Convolution* **Short description**: Computes 1D, 2D or 3D *GroupConvolutionBackpropData* of input and kernel tensors. diff --git a/docs/ops/convolution/GroupConvolution_1.md b/docs/ops/convolution/GroupConvolution_1.md index 619d5f6151d..9739274147c 100644 --- a/docs/ops/convolution/GroupConvolution_1.md +++ b/docs/ops/convolution/GroupConvolution_1.md @@ -2,7 +2,7 @@ **Versioned name**: *GroupConvolution-1* -**Category**: Convolution +**Category**: *Convolution* **Short description**: Computes 1D, 2D or 3D GroupConvolution of input and kernel tensors. diff --git a/docs/ops/detection/DeformablePSROIPooling_1.md b/docs/ops/detection/DeformablePSROIPooling_1.md index 856b273da8d..1d4fbfb8abe 100644 --- a/docs/ops/detection/DeformablePSROIPooling_1.md +++ b/docs/ops/detection/DeformablePSROIPooling_1.md @@ -2,7 +2,7 @@ **Versioned name**: *DeformablePSROIPooling-1* -**Category**: Object detection +**Category**: *Object detection* **Short description**: *DeformablePSROIPooling* computes deformable position-sensitive pooling of regions of interest specified by input. diff --git a/docs/ops/detection/ExperimentalDetectronDetectionOutput_6.md b/docs/ops/detection/ExperimentalDetectronDetectionOutput_6.md index 56e3222e973..a1008ec14be 100644 --- a/docs/ops/detection/ExperimentalDetectronDetectionOutput_6.md +++ b/docs/ops/detection/ExperimentalDetectronDetectionOutput_6.md @@ -2,7 +2,7 @@ **Versioned name**: *ExperimentalDetectronDetectionOutput-6* -**Category**: Object detection +**Category**: *Object detection* **Short description**: The *ExperimentalDetectronDetectionOutput* operation performs non-maximum suppression to generate the detection output using information on location and score predictions. diff --git a/docs/ops/detection/ExperimentalDetectronGenerateProposalsSingleImage_6.md b/docs/ops/detection/ExperimentalDetectronGenerateProposalsSingleImage_6.md index c822f74de8d..915a269d10f 100644 --- a/docs/ops/detection/ExperimentalDetectronGenerateProposalsSingleImage_6.md +++ b/docs/ops/detection/ExperimentalDetectronGenerateProposalsSingleImage_6.md @@ -2,7 +2,7 @@ **Versioned name**: *ExperimentalDetectronGenerateProposalsSingleImage-6* -**Category**: Object detection +**Category**: *Object detection* **Short description**: The *ExperimentalDetectronGenerateProposalsSingleImage* operation computes ROIs and their scores based on input data. diff --git a/docs/ops/detection/ExperimentalDetectronPriorGridGenerator_6.md b/docs/ops/detection/ExperimentalDetectronPriorGridGenerator_6.md index d3e1caa5155..31078c09516 100644 --- a/docs/ops/detection/ExperimentalDetectronPriorGridGenerator_6.md +++ b/docs/ops/detection/ExperimentalDetectronPriorGridGenerator_6.md @@ -2,7 +2,7 @@ **Versioned name**: *ExperimentalDetectronPriorGridGenerator-6* -**Category**: Object detection +**Category**: *Object detection* **Short description**: The *ExperimentalDetectronPriorGridGenerator* operation generates prior grids of specified sizes. diff --git a/docs/ops/detection/ExperimentalDetectronROIFeatureExtractor_6.md b/docs/ops/detection/ExperimentalDetectronROIFeatureExtractor_6.md index effa9472ff3..b6536e71a12 100644 --- a/docs/ops/detection/ExperimentalDetectronROIFeatureExtractor_6.md +++ b/docs/ops/detection/ExperimentalDetectronROIFeatureExtractor_6.md @@ -2,7 +2,7 @@ **Versioned name**: *ExperimentalDetectronROIFeatureExtractor-6* -**Category**: Object detection +**Category**: *Object detection* **Short description**: *ExperimentalDetectronROIFeatureExtractor* is the [ROIAlign](ROIAlign_3.md) operation applied over a feature pyramid. diff --git a/docs/ops/detection/PSROIPooling_1.md b/docs/ops/detection/PSROIPooling_1.md index 44d4bca2c8e..4b4546f7efb 100644 --- a/docs/ops/detection/PSROIPooling_1.md +++ b/docs/ops/detection/PSROIPooling_1.md @@ -2,7 +2,7 @@ **Versioned name**: *PSROIPooling-1* -**Category**: Object detection +**Category**: *Object detection* **Short description**: *PSROIPooling* computes position-sensitive pooling on regions of interest specified by input. diff --git a/docs/ops/detection/PriorBoxClustered_1.md b/docs/ops/detection/PriorBoxClustered_1.md index 3049f851949..1815e5a72b3 100644 --- a/docs/ops/detection/PriorBoxClustered_1.md +++ b/docs/ops/detection/PriorBoxClustered_1.md @@ -2,7 +2,7 @@ **Versioned name**: *PriorBoxClustered-1* -**Category**: Object detection +**Category**: *Object detection* **Short description**: *PriorBoxClustered* operation generates prior boxes of specified sizes normalized to the input image size. diff --git a/docs/ops/detection/PriorBox_1.md b/docs/ops/detection/PriorBox_1.md index 57cd936a8f9..39ea4afecb2 100644 --- a/docs/ops/detection/PriorBox_1.md +++ b/docs/ops/detection/PriorBox_1.md @@ -2,7 +2,7 @@ **Versioned name**: *PriorBox-1* -**Category**: Object detection +**Category**: *Object detection* **Short description**: *PriorBox* operation generates prior boxes of specified sizes and aspect ratios across all dimensions. diff --git a/docs/ops/detection/ROIAlign_3.md b/docs/ops/detection/ROIAlign_3.md index 13c049f2f7e..23ad2911039 100644 --- a/docs/ops/detection/ROIAlign_3.md +++ b/docs/ops/detection/ROIAlign_3.md @@ -2,7 +2,7 @@ **Versioned name**: *ROIAlign-3* -**Category**: Object detection +**Category**: *Object detection* **Short description**: *ROIAlign* is a *pooling layer* used over feature maps of non-uniform input sizes and outputs a feature map of a fixed size. diff --git a/docs/ops/detection/ROIPooling_1.md b/docs/ops/detection/ROIPooling_1.md index 65da4d44e6d..2597fa3d20b 100644 --- a/docs/ops/detection/ROIPooling_1.md +++ b/docs/ops/detection/ROIPooling_1.md @@ -2,7 +2,7 @@ **Versioned name**: *ROIPooling-1* -**Category**: Object detection +**Category**: *Object detection* **Short description**: *ROIPooling* is a *pooling layer* used over feature maps of non-uniform input sizes and outputs a feature map of a fixed size. diff --git a/docs/ops/generation/RandomUniform_8.md b/docs/ops/generation/RandomUniform_8.md index 4fff2684d6c..8f461bdf045 100644 --- a/docs/ops/generation/RandomUniform_8.md +++ b/docs/ops/generation/RandomUniform_8.md @@ -2,7 +2,7 @@ **Versioned name**: *RandomUniform-8* -**Category**: Generation +**Category**: *Generation* **Short description**: *RandomUniform* operation generates a sequence of random values from a uniform distribution. diff --git a/docs/ops/generation/Range_1.md b/docs/ops/generation/Range_1.md index 3e2f1d37eef..3852f021594 100644 --- a/docs/ops/generation/Range_1.md +++ b/docs/ops/generation/Range_1.md @@ -2,7 +2,7 @@ **Versioned name**: *Range-1* -**Category**: Generation +**Category**: *Generation* **Short description**: *Range* operation generates a sequence of numbers according input values [start, stop) with a step. diff --git a/docs/ops/generation/Range_4.md b/docs/ops/generation/Range_4.md index 0c36bac7cfd..bf57e13412f 100644 --- a/docs/ops/generation/Range_4.md +++ b/docs/ops/generation/Range_4.md @@ -2,7 +2,7 @@ **Versioned name**: *Range-4* -**Category**: Generation +**Category**: *Generation* **Short description**: *Range* operation generates a sequence of numbers according input values [start, stop) with a step. diff --git a/docs/ops/image/Interpolate_1.md b/docs/ops/image/Interpolate_1.md index e4f998faf4e..4cb3ad21030 100644 --- a/docs/ops/image/Interpolate_1.md +++ b/docs/ops/image/Interpolate_1.md @@ -2,7 +2,7 @@ **Versioned name**: *Interpolate-1* -**Category**: Image processing +**Category**: *Image processing* **Short description**: *Interpolate* layer performs interpolation of independent slices in input tensor by specified dimensions and attributes. diff --git a/docs/ops/image/Interpolate_4.md b/docs/ops/image/Interpolate_4.md index 6e5b6e8f818..ef159ab2b82 100644 --- a/docs/ops/image/Interpolate_4.md +++ b/docs/ops/image/Interpolate_4.md @@ -2,7 +2,7 @@ **Versioned name**: *Interpolate-4* -**Category**: Image processing +**Category**: *Image processing* **Short description**: *Interpolate* layer performs interpolation of independent slices in input tensor by specified dimensions and attributes. diff --git a/docs/ops/infrastructure/Loop_5.md b/docs/ops/infrastructure/Loop_5.md index 784dc4ca294..3774c1dc68d 100644 --- a/docs/ops/infrastructure/Loop_5.md +++ b/docs/ops/infrastructure/Loop_5.md @@ -2,7 +2,7 @@ **Versioned name**: *Loop-5* -**Category**: Infrastructure +**Category**: *Infrastructure* **Short description**: *Loop* operation performs recurrent execution of the network, which is described in the `body`, iterating through the data. The operation has similar semantic to the ONNX* Loop [operation](https://github.com/onnx/onnx/blob/master/docs/Changelog.md#Loop-13). diff --git a/docs/ops/infrastructure/TensorIterator_1.md b/docs/ops/infrastructure/TensorIterator_1.md index 6edffef5dae..996b0b1d321 100644 --- a/docs/ops/infrastructure/TensorIterator_1.md +++ b/docs/ops/infrastructure/TensorIterator_1.md @@ -2,7 +2,7 @@ **Versioned name**: *TensorIterator-1* -**Category**: Infrastructure +**Category**: *Infrastructure* **Short description**: *TensorIterator* layer performs recurrent execution of the network, which is described in the `body`, iterating through the data. diff --git a/docs/ops/logical/LogicalAnd_1.md b/docs/ops/logical/LogicalAnd_1.md index 385dd89a3a3..b8c935a7769 100644 --- a/docs/ops/logical/LogicalAnd_1.md +++ b/docs/ops/logical/LogicalAnd_1.md @@ -2,7 +2,7 @@ **Versioned name**: *LogicalAnd-1* -**Category**: Logical binary operation +**Category**: *Logical binary* **Short description**: *LogicalAnd* performs element-wise logical AND operation with two given tensors applying multi-directional broadcast rules. diff --git a/docs/ops/logical/LogicalNot_1.md b/docs/ops/logical/LogicalNot_1.md index 97c41ddb14c..0552da02c7b 100644 --- a/docs/ops/logical/LogicalNot_1.md +++ b/docs/ops/logical/LogicalNot_1.md @@ -2,7 +2,7 @@ **Versioned name**: *LogicalNot-1* -**Category**: Logical unary operation +**Category**: *Logical unary* **Short description**: *LogicalNot* performs element-wise logical negation operation with given tensor. diff --git a/docs/ops/logical/LogicalOr_1.md b/docs/ops/logical/LogicalOr_1.md index 0e88a6c82fa..54c6344b0c5 100644 --- a/docs/ops/logical/LogicalOr_1.md +++ b/docs/ops/logical/LogicalOr_1.md @@ -2,7 +2,7 @@ **Versioned name**: *LogicalOr-1* -**Category**: Logical binary operation +**Category**: *Logical binary* **Short description**: *LogicalOr* performs element-wise logical OR operation with two given tensors applying multi-directional broadcast rules. diff --git a/docs/ops/logical/LogicalXor_1.md b/docs/ops/logical/LogicalXor_1.md index a6a832308ae..52f25caae67 100644 --- a/docs/ops/logical/LogicalXor_1.md +++ b/docs/ops/logical/LogicalXor_1.md @@ -2,7 +2,7 @@ **Versioned name**: *LogicalXor-1* -**Category**: Logical binary operation +**Category**: *Logical binary* **Short description**: *LogicalXor* performs element-wise logical XOR operation with two given tensors applying multi-directional broadcast rules. diff --git a/docs/ops/matrix/Einsum_7.md b/docs/ops/matrix/Einsum_7.md index ab8057dfcee..94cb1387282 100644 --- a/docs/ops/matrix/Einsum_7.md +++ b/docs/ops/matrix/Einsum_7.md @@ -2,7 +2,7 @@ **Versioned name**: *Einsum-7* -**Category**: Matrix multiplication +**Category**: *Matrix multiplication* **Short description**: *Einsum* performs the Einstein summation convention on the operands. diff --git a/docs/ops/matrix/MatMul_1.md b/docs/ops/matrix/MatMul_1.md index 2299ea01f96..33ed6695324 100644 --- a/docs/ops/matrix/MatMul_1.md +++ b/docs/ops/matrix/MatMul_1.md @@ -2,7 +2,7 @@ **Versioned name**: *MatMul-1* -**Category**: Matrix multiplication +**Category**: *Matrix multiplication* **Short description**: Generalized matrix multiplication diff --git a/docs/ops/movement/Broadcast_1.md b/docs/ops/movement/Broadcast_1.md index b224f6dfc53..be1db9cc658 100644 --- a/docs/ops/movement/Broadcast_1.md +++ b/docs/ops/movement/Broadcast_1.md @@ -2,7 +2,7 @@ **Versioned name**: *Broadcast-1* -**Category**: Data movement +**Category**: *Data movement* **Short description**: *Broadcast* replicates data on the first input to fit a given shape on the second input. diff --git a/docs/ops/movement/Broadcast_3.md b/docs/ops/movement/Broadcast_3.md index 51b91e7aee6..cd24431324a 100644 --- a/docs/ops/movement/Broadcast_3.md +++ b/docs/ops/movement/Broadcast_3.md @@ -2,7 +2,7 @@ **Versioned name**: *Broadcast-3* -**Category**: Data movement +**Category**: *Data movement* **Short description**: *Broadcast* replicates data on the first input to fit a given shape on the second input. diff --git a/docs/ops/movement/Concat_1.md b/docs/ops/movement/Concat_1.md index 36f2ba620c7..371ae8bd9a8 100644 --- a/docs/ops/movement/Concat_1.md +++ b/docs/ops/movement/Concat_1.md @@ -2,7 +2,7 @@ **Versioned name**: *Concat-1* -**Category**: data movement operation. +**Category**: *Data movement* **Short description**: Concatenates arbitrary number of input tensors to a single output tensor along one axis. diff --git a/docs/ops/movement/GatherElements_6.md b/docs/ops/movement/GatherElements_6.md index 57b67a697cf..153b52e89c1 100644 --- a/docs/ops/movement/GatherElements_6.md +++ b/docs/ops/movement/GatherElements_6.md @@ -2,7 +2,7 @@ **Versioned name**: *GatherElements-6* -**Category**: Data movement operations +**Category**: *Data movement* **Short description**: *GatherElements* takes elements from the input `data` tensor at positions specified in the `indices` tensor. diff --git a/docs/ops/movement/GatherND_5.md b/docs/ops/movement/GatherND_5.md index 85270d0c463..322c0e8f2ba 100644 --- a/docs/ops/movement/GatherND_5.md +++ b/docs/ops/movement/GatherND_5.md @@ -2,7 +2,7 @@ **Versioned name**: *GatherND-5* -**Category**: Data movement operations +**Category**: *Data movement* **Short description**: *GatherND* gathers slices from input tensor into a tensor of a shape specified by indices. diff --git a/docs/ops/movement/Gather_1.md b/docs/ops/movement/Gather_1.md index f10724c0a56..d105a1dfd9b 100644 --- a/docs/ops/movement/Gather_1.md +++ b/docs/ops/movement/Gather_1.md @@ -2,7 +2,7 @@ **Versioned name**: *Gather-1* -**Category**: Data movement operations +**Category**: *Data movement* **Short description**: *Gather* operation takes slices of data in the first input tensor according to the indices specified in the second input tensor and axis from the third input. diff --git a/docs/ops/movement/Gather_7.md b/docs/ops/movement/Gather_7.md index 63f30c9faaa..19e5854f0ca 100644 --- a/docs/ops/movement/Gather_7.md +++ b/docs/ops/movement/Gather_7.md @@ -2,7 +2,7 @@ **Versioned name**: *Gather-7* -**Category**: Data movement operations +**Category**: *Data movement* **Short description**: *Gather* operation takes slices of data of the first input tensor according to the indices specified with the second input tensor and axis from the third input. Semantics of this operation is identical to diff --git a/docs/ops/movement/Gather_8.md b/docs/ops/movement/Gather_8.md index 9c07397288c..064023af773 100644 --- a/docs/ops/movement/Gather_8.md +++ b/docs/ops/movement/Gather_8.md @@ -2,7 +2,7 @@ **Versioned name**: *Gather-8* -**Category**: Data movement operations +**Category**: *Data movement* **Short description**: *Gather* operation takes slices of data of the first input tensor according to the indices specified with the second input tensor and axis from the third input. Semantics of this operation is identical to diff --git a/docs/ops/movement/Pad_1.md b/docs/ops/movement/Pad_1.md index 4b9d3a3f642..5aa1fc6fdb2 100644 --- a/docs/ops/movement/Pad_1.md +++ b/docs/ops/movement/Pad_1.md @@ -2,7 +2,7 @@ **Versioned name**: *Pad-1* -**Category**: *Data movement operations* +**Category**: *Data movement* **Short description**: *Pad* operation extends an input tensor on edges. The amount and value of padded elements are defined by inputs and attributes. diff --git a/docs/ops/movement/Reverse_1.md b/docs/ops/movement/Reverse_1.md index a75bf520bcc..31f04969953 100644 --- a/docs/ops/movement/Reverse_1.md +++ b/docs/ops/movement/Reverse_1.md @@ -2,7 +2,7 @@ **Versioned name**: *Reverse-1* -**Category**: data movement operation +**Category**: *Data movement* **Short description**: *Reverse* operations reverse specified axis in an input tensor. diff --git a/docs/ops/movement/Roll_7.md b/docs/ops/movement/Roll_7.md index 8633d7bc963..fc58a033926 100644 --- a/docs/ops/movement/Roll_7.md +++ b/docs/ops/movement/Roll_7.md @@ -2,7 +2,7 @@ **Versioned name**: *Roll-7* -**Category**: data movement operation +**Category**: *Data movement* **Short description**: The *Roll* operation shifts elements of a tensor along specified axes. diff --git a/docs/ops/movement/ScatterElementsUpdate_3.md b/docs/ops/movement/ScatterElementsUpdate_3.md index 5a7a81f76b5..271e98a0b08 100644 --- a/docs/ops/movement/ScatterElementsUpdate_3.md +++ b/docs/ops/movement/ScatterElementsUpdate_3.md @@ -2,7 +2,7 @@ **Versioned name**: *ScatterElementsUpdate-3* -**Category**: Data movement operations +**Category**: *Data movement* **Short description**: Creates a copy of the first input tensor with updated elements specified with second and third input tensors. diff --git a/docs/ops/movement/ScatterNDUpdate_3.md b/docs/ops/movement/ScatterNDUpdate_3.md index 42376bcb12e..242d4d9b37d 100644 --- a/docs/ops/movement/ScatterNDUpdate_3.md +++ b/docs/ops/movement/ScatterNDUpdate_3.md @@ -2,7 +2,7 @@ **Versioned name**: *ScatterNDUpdate-3* -**Category**: Data movement operations +**Category**: *Data movement* **Short description**: Creates a copy of the first input tensor with updated elements specified with second and third input tensors. diff --git a/docs/ops/movement/ScatterUpdate_3.md b/docs/ops/movement/ScatterUpdate_3.md index 74903e21117..b004ad1b663 100644 --- a/docs/ops/movement/ScatterUpdate_3.md +++ b/docs/ops/movement/ScatterUpdate_3.md @@ -2,7 +2,7 @@ **Versioned name**: *ScatterUpdate-3* -**Category**: Data movement operations +**Category**: *Data movement* **Short description**: *ScatterUpdate* creates a copy of the first input tensor with updated elements specified with second and third input tensors. diff --git a/docs/ops/movement/ShuffleChannels_1.md b/docs/ops/movement/ShuffleChannels_1.md index 9970fed7c6a..47f3518746c 100644 --- a/docs/ops/movement/ShuffleChannels_1.md +++ b/docs/ops/movement/ShuffleChannels_1.md @@ -4,7 +4,7 @@ **Name**: *ShuffleChannels* -**Category**: Data movement +**Category**: *Data movement* **Short description**: *ShuffleChannels* permutes data in the channel dimension of the input tensor. diff --git a/docs/ops/movement/Split_1.md b/docs/ops/movement/Split_1.md index 7dd0ed6f102..0f78b20e0e0 100644 --- a/docs/ops/movement/Split_1.md +++ b/docs/ops/movement/Split_1.md @@ -2,7 +2,7 @@ **Versioned name**: *Split-1* -**Category**: *Data movement operations* +**Category**: *Data movement* **Short description**: *Split* operation splits an input tensor into pieces of the same length along some axis. diff --git a/docs/ops/movement/StridedSlice_1.md b/docs/ops/movement/StridedSlice_1.md index da3a580e0ec..238bd4c0c36 100644 --- a/docs/ops/movement/StridedSlice_1.md +++ b/docs/ops/movement/StridedSlice_1.md @@ -2,7 +2,7 @@ **Versioned name**: *StridedSlice-1* -**Category**: Data movement operation +**Category**: *Data movement* **Short description**: *StridedSlice* extracts a strided slice of a tensor. diff --git a/docs/ops/movement/Tile_1.md b/docs/ops/movement/Tile_1.md index b0d17a3fb47..76ba4f58490 100644 --- a/docs/ops/movement/Tile_1.md +++ b/docs/ops/movement/Tile_1.md @@ -2,7 +2,7 @@ **Versioned name**: *Tile-1* -**Category**: Data movement +**Category**: *Data movement* **Short description**: *Tile* operation repeats an input tensor *"data"* the number of times given by *"repeats"* input tensor along each dimension. * If number of elements in *"repeats"* is more than shape of *"data"*, then *"data"* will be promoted to "*repeats*" by prepending new axes, e.g. let's shape of *"data"* is equal to (2, 3) and *"repeats"* is equal to [2, 2, 2], then shape of *"data"* will be promoted to (1, 2, 3) and result shape will be (2, 4, 6). diff --git a/docs/ops/movement/Transpose_1.md b/docs/ops/movement/Transpose_1.md index 5c38171035e..d60387dd8b3 100644 --- a/docs/ops/movement/Transpose_1.md +++ b/docs/ops/movement/Transpose_1.md @@ -2,7 +2,7 @@ **Versioned name**: *Transpose-1* -**Category**: Data movement +**Category**: *Data movement* **Short description**: *Transpose* operation reorders the input tensor dimensions. diff --git a/docs/ops/movement/VariadicSplit_1.md b/docs/ops/movement/VariadicSplit_1.md index d14bce1324f..da15f9fc809 100644 --- a/docs/ops/movement/VariadicSplit_1.md +++ b/docs/ops/movement/VariadicSplit_1.md @@ -2,7 +2,7 @@ **Versioned name**: *VariadicSplit-1* -**Category**: *Data movement operations* +**Category**: *Data movement* **Short description**: *VariadicSplit* operation splits an input tensor into chunks along some axis. The chunks may have variadic lengths depending on `split_lengths` input tensor. diff --git a/docs/ops/quantization/FakeQuantize_1.md b/docs/ops/quantization/FakeQuantize_1.md index 099cdecc9c5..6598de09d48 100644 --- a/docs/ops/quantization/FakeQuantize_1.md +++ b/docs/ops/quantization/FakeQuantize_1.md @@ -2,7 +2,7 @@ **Versioned name**: *FakeQuantize-1* -**Category**: Quantization +**Category**: *Quantization* **Short description**: *FakeQuantize* is element-wise linear quantization of floating-point input values into a discrete set of floating-point values. diff --git a/docs/ops/sequence/CTCGreedyDecoderSeqLen_6.md b/docs/ops/sequence/CTCGreedyDecoderSeqLen_6.md index 1ff17376926..c4122cb50fb 100644 --- a/docs/ops/sequence/CTCGreedyDecoderSeqLen_6.md +++ b/docs/ops/sequence/CTCGreedyDecoderSeqLen_6.md @@ -2,7 +2,7 @@ **Versioned name**: *CTCGreedyDecoderSeqLen-6* -**Category**: Sequence processing +**Category**: *Sequence processing* **Short description**: *CTCGreedyDecoderSeqLen* performs greedy decoding of the logits provided as the first input. The sequence lengths are provided as the second input. diff --git a/docs/ops/sequence/CTCGreedyDecoder_1.md b/docs/ops/sequence/CTCGreedyDecoder_1.md index ca90cdcae6c..cfaced502a4 100644 --- a/docs/ops/sequence/CTCGreedyDecoder_1.md +++ b/docs/ops/sequence/CTCGreedyDecoder_1.md @@ -2,7 +2,7 @@ **Versioned name**: *CTCGreedyDecoder-1* -**Category**: Sequence processing +**Category**: *Sequence processing* **Short description**: *CTCGreedyDecoder* performs greedy decoding on the logits given in input (best path). diff --git a/docs/ops/sequence/CTCLoss_4.md b/docs/ops/sequence/CTCLoss_4.md index 66a2b30167f..cb092511077 100644 --- a/docs/ops/sequence/CTCLoss_4.md +++ b/docs/ops/sequence/CTCLoss_4.md @@ -2,7 +2,7 @@ **Versioned name**: *CTCLoss-4* -**Category**: Sequence processing +**Category**: *Sequence processing* **Short description**: *CTCLoss* computes the CTC (Connectionist Temporal Classification) Loss. diff --git a/docs/ops/sequence/GRUCell_3.md b/docs/ops/sequence/GRUCell_3.md index 0c5f40a6916..df5b14046d9 100644 --- a/docs/ops/sequence/GRUCell_3.md +++ b/docs/ops/sequence/GRUCell_3.md @@ -2,7 +2,7 @@ **Versioned name**: *GRUCell-3* -**Category**: Sequence processing +**Category**: *Sequence processing* **Short description**: *GRUCell* represents a single GRU Cell that computes the output using the formula described in the [paper](https://arxiv.org/abs/1406.1078). diff --git a/docs/ops/sequence/OneHot_1.md b/docs/ops/sequence/OneHot_1.md index 8554779efc0..bc1e37a446f 100644 --- a/docs/ops/sequence/OneHot_1.md +++ b/docs/ops/sequence/OneHot_1.md @@ -2,7 +2,7 @@ **Versioned name**: *OneHot-1* -**Category**: Sequence processing +**Category**: *Sequence processing* **Short description**: *OneHot* sets the elements in the output tensor with specified indices to `on_value` and fills all other locations with `off_value`. diff --git a/docs/ops/sequence/RNNCell_3.md b/docs/ops/sequence/RNNCell_3.md index ea678fd4854..dc7418ec1f2 100644 --- a/docs/ops/sequence/RNNCell_3.md +++ b/docs/ops/sequence/RNNCell_3.md @@ -2,7 +2,7 @@ **Versioned name**: *RNNCell-3* -**Category**: Sequence processing +**Category**: *Sequence processing* **Short description**: *RNNCell* represents a single RNN cell that computes the output using the formula described in the [article](https://hackernoon.com/understanding-architecture-of-lstm-cell-from-scratch-with-code-8da40f0b71f4). diff --git a/docs/ops/shape/Reshape_1.md b/docs/ops/shape/Reshape_1.md index ac3cbbb0707..324a2dab9ec 100644 --- a/docs/ops/shape/Reshape_1.md +++ b/docs/ops/shape/Reshape_1.md @@ -2,7 +2,7 @@ **Versioned name**: *Reshape-1* -**Category**: Shape manipulation +**Category**: *Shape manipulation* **Short description**: *Reshape* operation changes dimensions of the input tensor according to the specified order. Input tensor volume is equal to output tensor volume, where volume is the product of dimensions. diff --git a/docs/ops/shape/ShapeOf_1.md b/docs/ops/shape/ShapeOf_1.md index 7711b7424c3..cda4bd74c61 100644 --- a/docs/ops/shape/ShapeOf_1.md +++ b/docs/ops/shape/ShapeOf_1.md @@ -2,7 +2,7 @@ **Versioned name**: *ShapeOf-1* -**Category**: Shape manipulation +**Category**: *Shape manipulation* **Short description**: *ShapeOf* produces 1D tensor with the input tensor shape. diff --git a/docs/ops/shape/ShapeOf_3.md b/docs/ops/shape/ShapeOf_3.md index 8952753ef82..3ca8013d627 100644 --- a/docs/ops/shape/ShapeOf_3.md +++ b/docs/ops/shape/ShapeOf_3.md @@ -2,7 +2,7 @@ **Versioned name**: *ShapeOf-3* -**Category**: Shape manipulation +**Category**: *Shape manipulation* **Short description**: *ShapeOf* produces 1D tensor with the input tensor shape. diff --git a/docs/ops/shape/Squeeze_1.md b/docs/ops/shape/Squeeze_1.md index 7a8b9733be1..535e60c4ac9 100644 --- a/docs/ops/shape/Squeeze_1.md +++ b/docs/ops/shape/Squeeze_1.md @@ -2,7 +2,7 @@ **Versioned name**: *Squeeze-1* -**Category**: Shape manipulation +**Category**: *Shape manipulation* **Short description**: *Squeeze* removes dimensions equal to 1 from the first input tensor. diff --git a/docs/ops/shape/Unsqueeze_1.md b/docs/ops/shape/Unsqueeze_1.md index 062a933403b..f98616c0ba6 100644 --- a/docs/ops/shape/Unsqueeze_1.md +++ b/docs/ops/shape/Unsqueeze_1.md @@ -2,7 +2,7 @@ **Versioned name**: *Unsqueeze-1* -**Category**: Shape manipulation +**Category**: *Shape manipulation* **Short description**: *Unsqueeze* adds dimensions of size 1 to the first input tensor. The second input value specifies a list of dimensions that will be inserted. Indices specify dimensions in the output tensor. diff --git a/docs/ops/signals/DFT_7.md b/docs/ops/signals/DFT_7.md index c9a841446a9..aea3f68337e 100644 --- a/docs/ops/signals/DFT_7.md +++ b/docs/ops/signals/DFT_7.md @@ -2,7 +2,7 @@ **Versioned name**: *DFT-7* -**Category**: Signal processing +**Category**: *Signal processing* **Short description**: *DFT* operation performs the discrete complex-to-complex Fourier transformation of input tensor by specified dimensions. diff --git a/docs/ops/signals/IDFT_7.md b/docs/ops/signals/IDFT_7.md index 78f94466267..272480d751d 100644 --- a/docs/ops/signals/IDFT_7.md +++ b/docs/ops/signals/IDFT_7.md @@ -2,7 +2,7 @@ **Versioned name**: *IDFT-7* -**Category**: Signal processing +**Category**: *Signal processing* **Short description**: *IDFT* operation performs the inverse discrete Fourier transformation of input tensor by specified dimensions. diff --git a/docs/ops/sort/ExperimentalDetectronTopKROIs_6.md b/docs/ops/sort/ExperimentalDetectronTopKROIs_6.md index 87a56127861..389974558c7 100644 --- a/docs/ops/sort/ExperimentalDetectronTopKROIs_6.md +++ b/docs/ops/sort/ExperimentalDetectronTopKROIs_6.md @@ -2,7 +2,7 @@ **Versioned name**: *ExperimentalDetectronTopKROIs-6* -**Category**: Sort +**Category**: *Sorting and maximization* **Short description**: The *ExperimentalDetectronTopKROIs* operation is TopK operation applied to probabilities of input ROIs. From b18d0105a11820ac4033ff24f2307b4308a95d21 Mon Sep 17 00:00:00 2001 From: Evgeny Kotov Date: Mon, 23 Aug 2021 17:07:04 +0300 Subject: [PATCH 07/76] add ngraph::pass::LSTMCellDecomposition as mandatory (#7028) * add ngraph::pass::LSTMCellDecomposition as mandatory * move LSTMCellDecomposition just after CommonOptimizations before all convert opset transformations * code review fixes: add flag that prevents some legacy transformations if their ngraph-based analogues were executed * remove isNgraphPassesUsed from ModelQuantizer * cleanups --- inference-engine/src/gna_plugin/gna_plugin.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/inference-engine/src/gna_plugin/gna_plugin.cpp b/inference-engine/src/gna_plugin/gna_plugin.cpp index e51914c3cc6..651bf075b6d 100644 --- a/inference-engine/src/gna_plugin/gna_plugin.cpp +++ b/inference-engine/src/gna_plugin/gna_plugin.cpp @@ -66,6 +66,7 @@ #include "transformations/handle_transposes_around_matmul.hpp" #include "transformations/decompose_2d_conv.hpp" #include "transformations/convert_padded2valid_conv.hpp" +#include "transformations/op_conversions/lstm_cell_decomposition.hpp" #include @@ -680,6 +681,8 @@ void GNAPlugin::LoadNetwork(CNNNetwork & _network) { InitGNADevice(); } + bool isNgraphPassesUsed = false; + if (_network.getFunction()) { CNNNetwork clonedNetwork = InferenceEngine::cloneNetwork(_network); const auto& graph = clonedNetwork.getFunction(); @@ -688,6 +691,7 @@ void GNAPlugin::LoadNetwork(CNNNetwork & _network) { // WA: ConvertPriorBox must be executed before the 1st ConstantFolding pass manager.register_pass(); manager.register_pass(); + manager.register_pass(); manager.register_pass(); if (config.gnaCompileTarget == InferenceEngine::GNAConfigParams::GNA_TARGET_2_0) { manager.register_pass(); @@ -732,6 +736,8 @@ void GNAPlugin::LoadNetwork(CNNNetwork & _network) { pass_config->disable(); manager.run_passes(graph); convertedNetwork = InferenceEngine::details::convertFunctionToICNNNetwork(graph, clonedNetwork); + + isNgraphPassesUsed = true; } IE_SUPPRESS_DEPRECATED_START InferenceEngine::CNNNetwork network = convertedNetwork ? InferenceEngine::CNNNetwork{convertedNetwork} : _network; @@ -762,7 +768,8 @@ void GNAPlugin::LoadNetwork(CNNNetwork & _network) { passes->registerPass(); passes->registerPass(); passes->registerPass(); - passes->registerPass(); + if (!isNgraphPassesUsed) + passes->registerPass(); passes->registerPass(); // fake quantisation aware passes From 29193982d4eab928bd147bd346f95115327bb292 Mon Sep 17 00:00:00 2001 From: Pavel Esir Date: Mon, 23 Aug 2021 18:35:37 +0300 Subject: [PATCH 08/76] [IE] Convert to unsigned NMS:0 ->Gather path (#6474) * inserted Convert to unsigned * moved declarations from hpp into cpp, specification corrected * added static const modifier * updated convert specification * minor corrections * split into 3 passes(Init, Propogate, Update), renamed final pass to ConvertNmsGatherPathToUnsigned * added description why transformation is needed * added matcher for several NMS versions, removed TRANSFORMATIONS_API macros from cpp * applied comments: - used GraphRewrite instead of FunctionPass - simplified some expressions - corrected case when Converts output goes to multiple nodes - added to MOC transformations - other minor corrections * removed redundant namespace prefixes * fixed #include * removed matcher_scope, debug code, and redundant dynamic_cast --- docs/ops/movement/Gather_8.md | 19 ++- docs/ops/type/Convert_1.md | 11 +- .../src/moc_transformations.cpp | 3 + .../convert_nms_gather_path_to_unsigned.hpp | 32 ++++ .../common_optimizations.cpp | 3 +- .../convert_nms_gather_path_to_unsigned.cpp | 128 ++++++++++++++++ ...nvert_nms_gather_path_to_unsigned_test.cpp | 138 ++++++++++++++++++ 7 files changed, 328 insertions(+), 6 deletions(-) create mode 100644 inference-engine/src/transformations/include/transformations/common_optimizations/convert_nms_gather_path_to_unsigned.hpp create mode 100644 inference-engine/src/transformations/src/transformations/common_optimizations/convert_nms_gather_path_to_unsigned.cpp create mode 100644 inference-engine/tests/functional/inference_engine/transformations/convert_nms_gather_path_to_unsigned_test.cpp diff --git a/docs/ops/movement/Gather_8.md b/docs/ops/movement/Gather_8.md index 064023af773..4120d3f3eaf 100644 --- a/docs/ops/movement/Gather_8.md +++ b/docs/ops/movement/Gather_8.md @@ -6,7 +6,8 @@ **Short description**: *Gather* operation takes slices of data of the first input tensor according to the indices specified with the second input tensor and axis from the third input. Semantics of this operation is identical to -TensorFlow\* [Gather](https://www.tensorflow.org/api_docs/python/tf/gather) operation. +TensorFlow\* [Gather](https://www.tensorflow.org/api_docs/python/tf/gather) operation but also includes +support of negative indices. **Detailed description** @@ -15,6 +16,8 @@ TensorFlow\* [Gather](https://www.tensorflow.org/api_docs/python/tf/gather) oper Where `data`, `indices` and `axis` are tensors from first, second and third inputs correspondingly, `b` is the number of batch dimensions. `N` and `M` are numbers of dimensions of `data` and `indices` tensors, respectively. +Allowed values for indices are in the range `[-data.shape[axis], data.shape[axis] - 1]`. If index value exceed allowed +range output data for corresponding index will be filled with zeros (Example 7). **Attributes**: * *batch_dims* @@ -142,13 +145,23 @@ data = [1, 2, 3, 4, 5] output = [1, 4, 5] ``` +Example 7 with indices out of the range: +``` +batch_dims = 0 +axis = 0 + +indices = [3, 10, -20] +data = [1, 2, 3, 4, 5] +output = [4, 0, 0] +``` + **Inputs** * **1**: `data` tensor of type *T* with arbitrary data. **Required.** * **2**: `indices` tensor of type *T_IND* with indices to gather. 0D tensor (scalar) for indices is also allowed. - The values for indices are in the range `[-data[axis], data[axis] - 1]`. - Negative values of indices indicate reverse indexing from `data[axis]`. + The values for indices are in the range `[-data.shape[axis], data.shape[axis] - 1]`. + Negative values of indices indicate reverse indexing from `data.shape[axis]`. **Required.** * **3**: Scalar or 1D tensor `axis` of *T_AXIS* type is a dimension index to gather data from. For example, diff --git a/docs/ops/type/Convert_1.md b/docs/ops/type/Convert_1.md index e26575c70ba..4ee9dfdda43 100644 --- a/docs/ops/type/Convert_1.md +++ b/docs/ops/type/Convert_1.md @@ -8,9 +8,16 @@ **Detailed description** -Conversion from one supported type to another supported type is always allowed. User must be aware of precision loss and value change caused by range difference between two types. For example, a 32-bit float `3.141592` may be round to a 32-bit int `3`. The result of unsupported conversions is undefined, e.g. conversion of negative signed integer value to any unsigned integer type. +Conversion from one supported type to another supported type is always allowed. User must be aware of precision loss +and value change caused by range difference between two types. For example, a 32-bit float `3.141592` may be round +to a 32-bit int `3`. -Output elements are represented as follows: +Conversion of negative signed integer to unsigned integer value happens in accordance with c++ standard. Notably, +result is the unique value of the destination unsigned type that is congruent to the source integer modulo 2^N (where +N is the bit width of the destination type). For example, when an int32 value `-1` is converted to uint32 the result +will be `uint32 max` which is `4,294,967,295`. + +The result of unsupported conversions is undefined. Output elements are represented as follows: \f[ o_{i} = Convert(a_{i}) diff --git a/inference-engine/src/offline_transformations/src/moc_transformations.cpp b/inference-engine/src/offline_transformations/src/moc_transformations.cpp index 9852c5e4b99..95aae8c819a 100644 --- a/inference-engine/src/offline_transformations/src/moc_transformations.cpp +++ b/inference-engine/src/offline_transformations/src/moc_transformations.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -60,6 +61,8 @@ bool ngraph::pass::MOCTransformations::run_on_function(std::shared_ptr(); manager.register_pass(); manager.register_pass(); + // workaround until dynamism in NMS is not supported + manager.register_pass(); auto transpose_sinking = manager.register_pass(); transpose_sinking->add_matcher(); diff --git a/inference-engine/src/transformations/include/transformations/common_optimizations/convert_nms_gather_path_to_unsigned.hpp b/inference-engine/src/transformations/include/transformations/common_optimizations/convert_nms_gather_path_to_unsigned.hpp new file mode 100644 index 00000000000..06c0dca450c --- /dev/null +++ b/inference-engine/src/transformations/include/transformations/common_optimizations/convert_nms_gather_path_to_unsigned.hpp @@ -0,0 +1,32 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +#include +#include + +namespace ngraph { +namespace pass { + +class TRANSFORMATIONS_API ConvertNmsGatherPathToUnsigned; + +} // namespace pass +} // namespace ngraph + +/** + * @ingroup ie_transformation_common_api + * @brief Converts Gather indices to unsigned if indices are from NMS selected indices output. + * NMS returns -1 for not selected boxes, old version of Gather fill corresponding + * output for such indices with zero. + * But new Gather-8 has support of negative indices indicating counting from the end. + * In order to keep such behaviour (until dynamism is not supported) instead of -1 new + * Gather-8 will accept UINT32_MAX which is always outside of the bounds + * and corresponding output for such indices in gather always will be filled with zeros. + */ +class ngraph::pass::ConvertNmsGatherPathToUnsigned: public ngraph::pass::GraphRewrite { +public: + NGRAPH_RTTI_DECLARATION; + ConvertNmsGatherPathToUnsigned(); +}; diff --git a/inference-engine/src/transformations/src/transformations/common_optimizations/common_optimizations.cpp b/inference-engine/src/transformations/src/transformations/common_optimizations/common_optimizations.cpp index 373e34f9a01..253c4f113ab 100644 --- a/inference-engine/src/transformations/src/transformations/common_optimizations/common_optimizations.cpp +++ b/inference-engine/src/transformations/src/transformations/common_optimizations/common_optimizations.cpp @@ -44,6 +44,7 @@ #include "transformations/common_optimizations/split_squeeze_concat_fusion.hpp" #include "transformations/common_optimizations/transpose_to_reshape.hpp" #include "transformations/common_optimizations/strides_optimization.hpp" +#include "transformations/common_optimizations/convert_nms_gather_path_to_unsigned.hpp" #include "transformations/op_conversions/bidirectional_sequences_decomposition.hpp" #include "transformations/op_conversions/convert_pad_to_group_conv.hpp" #include "transformations/op_conversions/convert_divide.hpp" @@ -66,7 +67,6 @@ #include "transformations/op_conversions/reduce_l1_decomposition.hpp" #include "transformations/op_conversions/reduce_l2_decomposition.hpp" #include "transformations/op_conversions/hswish_decomposition.hpp" -#include "transformations/op_conversions/convert_previous_nms_to_nms_5.hpp" #include "transformations/op_conversions/hsigmoid_decomposition.hpp" #include "transformations/op_conversions/log_softmax_decomposition.hpp" #include "transformations/op_conversions/mvn6_decomposition.hpp" @@ -91,6 +91,7 @@ bool ngraph::pass::CommonOptimizations::run_on_function(std::shared_ptr(); manager.register_pass(); manager.register_pass(); // Resolves dynamism (replaces NonZero), CF needed + manager.register_pass(); // workaround until dynamism in NMS is not supported // TODO: move to KMB manager.register_pass(); diff --git a/inference-engine/src/transformations/src/transformations/common_optimizations/convert_nms_gather_path_to_unsigned.cpp b/inference-engine/src/transformations/src/transformations/common_optimizations/convert_nms_gather_path_to_unsigned.cpp new file mode 100644 index 00000000000..22cc9f3df28 --- /dev/null +++ b/inference-engine/src/transformations/src/transformations/common_optimizations/convert_nms_gather_path_to_unsigned.cpp @@ -0,0 +1,128 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "transformations/common_optimizations/convert_nms_gather_path_to_unsigned.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "itt.hpp" +#include "ngraph/node.hpp" + +using namespace ngraph; +using namespace std; + +class InitNMSPath: public pass::MatcherPass { +public: + NGRAPH_RTTI_DECLARATION; + + InitNMSPath() { + MATCHER_SCOPE(InitNMSPath); + + auto nms_pattern = pattern::wrap_type(); + + matcher_pass_callback callback = [=](pattern::Matcher &m) { + const auto& out_nodes = m.get_match_root()->output(0).get_target_inputs(); + for (const auto& out_node : out_nodes) { + auto& out_rt_info = out_node.get_node()->get_rt_info(); + out_rt_info["NMS_SELECTED_INDICES"] = make_shared>(""); + } + return true; + }; + + auto m = make_shared(nms_pattern, matcher_name); + register_matcher(m, callback); + } +}; + +NGRAPH_RTTI_DEFINITION(InitNMSPath, "InitNMSPath", 0); + + +class PropagateNMSPath: public pass::MatcherPass { +public: + NGRAPH_RTTI_DECLARATION; + + PropagateNMSPath(){ + MATCHER_SCOPE(PropagateNMSPath); + + auto node_pattern = pattern::wrap_type< + opset8::Squeeze, + opset8::Unsqueeze, + opset8::Reshape, + op::util::BroadcastBase, + opset8::StridedSlice, + opset8::VariadicSplit, + opset8::Concat, + opset8::Convert>(); + + matcher_pass_callback callback = [=](pattern::Matcher &m) { + auto node = m.get_match_root(); + const auto & inputs = node->input_values(); + if (any_of(inputs.begin(), inputs.end(), [](const Output & output) { + return output.get_node()->get_rt_info().count("NMS_SELECTED_INDICES"); + })) { + auto & rt_info = node->get_rt_info(); + rt_info["NMS_SELECTED_INDICES"] = make_shared>(""); + } + return true; + }; + + auto m = make_shared(node_pattern, matcher_name); + register_matcher(m, callback); + } +}; + +NGRAPH_RTTI_DEFINITION(PropagateNMSPath, "PropagateNMSPath", 0); + +class UpdateConvertGather: public pass::MatcherPass { +public: + NGRAPH_RTTI_DECLARATION; + + UpdateConvertGather(){ + MATCHER_SCOPE(UpdateConvertGather); + + auto node_pattern = pattern::wrap_type(); + + matcher_pass_callback callback = [=](pattern::Matcher &m) { + auto gather = m.get_match_root(); + auto indices = gather->input_value(1); + + const auto& rt_info = indices.get_node()->get_rt_info(); + if (!rt_info.count("NMS_SELECTED_INDICES")) + return false; + + auto out_type = (indices.get_element_type() == element::i64 ? element::u64 : element::u32); + auto existing_convert = dynamic_pointer_cast(indices.get_node_shared_ptr()); + if (existing_convert && indices.get_target_inputs().size() == 1) { + existing_convert->set_convert_element_type(out_type); + existing_convert->validate_and_infer_types(); + } else { + auto new_convert_to_unsigned = make_shared(indices, out_type); + gather->input(1).replace_source_output(new_convert_to_unsigned); + copy_runtime_info(gather, new_convert_to_unsigned); + } + return true; + }; + + auto m = make_shared(node_pattern, matcher_name); + register_matcher(m, callback); + } +}; + +NGRAPH_RTTI_DEFINITION(UpdateConvertGather, "UpdateConvertGather", 0); + +pass::ConvertNmsGatherPathToUnsigned::ConvertNmsGatherPathToUnsigned() { + add_matcher(); + add_matcher(); + add_matcher(); +} + +NGRAPH_RTTI_DEFINITION(pass::ConvertNmsGatherPathToUnsigned, "ConvertNmsGatherPathToUnsigned", 0); diff --git a/inference-engine/tests/functional/inference_engine/transformations/convert_nms_gather_path_to_unsigned_test.cpp b/inference-engine/tests/functional/inference_engine/transformations/convert_nms_gather_path_to_unsigned_test.cpp new file mode 100644 index 00000000000..47ba365ea94 --- /dev/null +++ b/inference-engine/tests/functional/inference_engine/transformations/convert_nms_gather_path_to_unsigned_test.cpp @@ -0,0 +1,138 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include +#include "common_test_utils/ngraph_test_utils.hpp" +#include "ngraph/pass/visualize_tree.hpp" +#include +#include +#include +#include +#include + +using namespace testing; +using namespace ngraph; +using namespace std; + +TEST(TransformationTests, test_convert_to_unsigned_nms_gather_1) { + // if Convert doesn't exist + shared_ptr f(nullptr), f_ref(nullptr); + { + auto boxes = make_shared(element::f32, Shape{1, 1000, 4}); + auto scores = make_shared(element::f32, Shape{1, 1, 1000}); + auto nms = make_shared(boxes, scores); + + auto begin = opset8::Constant::create(element::i32, Shape{1}, {3}); + auto end = opset8::Constant::create(element::i32, Shape{1}, {4}); + auto strides = opset8::Constant::create(element::i32, Shape{1}, {1}); + auto ss_node = make_shared(nms->output(0), begin, end, strides, vector{1, 0}, vector{1, 0}); + + // squeeze can be represented as reshape + auto squeeze_node = make_shared(ss_node, opset8::Constant::create(element::i32, Shape{1}, {-1}), true); + // usually input to gather data goes after reshape NMS scores + auto reshape_node = make_shared(scores, opset8::Constant::create(element::i32, Shape{1}, {-1}), true); + auto gather = make_shared(reshape_node, squeeze_node, opset8::Constant::create(element::i32, Shape{1}, {0})); + + f = make_shared(NodeVector{gather}, ParameterVector{boxes, scores}); + + pass::Manager manager; + manager.register_pass(); + manager.register_pass(); + manager.run_passes(f); + ASSERT_NO_THROW(check_rt_info(f)); + } + + { + auto boxes = make_shared(element::f32, Shape{1, 1000, 4}); + auto scores = make_shared(element::f32, Shape{1, 1, 1000}); + auto nms = make_shared(boxes, scores); + + auto begin = opset8::Constant::create(element::i32, Shape{1}, {3}); + auto end = opset8::Constant::create(element::i32, Shape{1}, {4}); + auto strides = opset8::Constant::create(element::i32, Shape{1}, {1}); + auto ss_node = make_shared(nms->output(0), begin, end, strides, vector{1, 0}, vector{1, 0}); + + // squeeze can be represented as reshape + auto squeeze_node = make_shared(ss_node, opset8::Constant::create(element::i32, Shape{1}, {-1}), true); + auto convert = make_shared(squeeze_node, element::Type_t::u64); + auto reshape_node = make_shared(scores, opset8::Constant::create(element::i32, Shape{1}, {-1}), true); + auto gather = make_shared(reshape_node, convert, opset8::Constant::create(element::i32, Shape{1}, {0})); + + f_ref = make_shared(NodeVector{gather}, ParameterVector{boxes, scores}); + } + + auto res = compare_functions(f, f_ref); + ASSERT_TRUE(res.first) << res.second; +} + +TEST(TransformationTests, test_convert_to_unsigned_nms_gather_2) { + // if Convert already exists + shared_ptr f(nullptr), f_ref(nullptr); + { + auto boxes = make_shared(element::f32, Shape{1, 1000, 4}); + auto scores = make_shared(element::f32, Shape{1, 1, 1000}); + auto nms = make_shared(boxes, scores); + + auto begin = opset8::Constant::create(element::i32, Shape{1}, {3}); + auto end = opset8::Constant::create(element::i32, Shape{1}, {4}); + auto strides = opset8::Constant::create(element::i32, Shape{1}, {1}); + auto ss_node = make_shared(nms->output(0), begin, end, strides, vector{1, 0}, vector{1, 0}); + + // squeeze can be represented as reshape + auto squeeze_node = make_shared(ss_node, opset8::Constant::create(element::i32, Shape{1}, {-1}), true); + auto convert = make_shared(squeeze_node, element::Type_t::i32); + // usually input to gather data goes after reshape NMS scores + auto reshape_node = make_shared(scores, opset8::Constant::create(element::i32, Shape{1}, {-1}), true); + auto gather = make_shared(reshape_node, convert, opset8::Constant::create(element::i32, Shape{1}, {0})); + + f = make_shared(NodeVector{gather}, ParameterVector{boxes, scores}); + + pass::Manager manager; + manager.register_pass(); + manager.register_pass(); + manager.run_passes(f); + ASSERT_NO_THROW(check_rt_info(f)); + } + + { + auto boxes = make_shared(element::f32, Shape{1, 1000, 4}); + auto scores = make_shared(element::f32, Shape{1, 1, 1000}); + auto nms = make_shared(boxes, scores); + + auto begin = opset8::Constant::create(element::i32, Shape{1}, {3}); + auto end = opset8::Constant::create(element::i32, Shape{1}, {4}); + auto strides = opset8::Constant::create(element::i32, Shape{1}, {1}); + auto ss_node = make_shared(nms->output(0), begin, end, strides, vector{1, 0}, vector{1, 0}); + + // squeeze can be represented as reshape + auto squeeze_node = make_shared(ss_node, opset8::Constant::create(element::i32, Shape{1}, {-1}), true); + auto convert = make_shared(squeeze_node, element::Type_t::u32); + auto reshape_node = make_shared(scores, opset8::Constant::create(element::i32, Shape{1}, {-1}), true); + auto gather = make_shared(reshape_node, convert, opset8::Constant::create(element::i32, Shape{1}, {0})); + + f_ref = make_shared(NodeVector{gather}, ParameterVector{boxes, scores}); + } + + auto res = compare_functions(f, f_ref); + ASSERT_TRUE(res.first) << res.second; +} + +TEST(TransformationTests, test_convert_to_unsigned_nms_gather_3) { + // if NMS output goes not into Gather indices no converts should be inserted + auto boxes = make_shared(element::f32, Shape{1, 1000, 4}); + auto scores = make_shared(element::f32, Shape{1, 1, 1000}); + auto nms = make_shared(boxes, scores); + + auto gather = make_shared(nms->output(0), opset8::Constant::create(element::i32, Shape{1}, {2}), + opset8::Constant::create(element::i32, Shape{1}, {0})); + + shared_ptr f = make_shared(NodeVector{gather}, ParameterVector{boxes, scores}); + + pass::Manager manager; + manager.register_pass(); + manager.register_pass(); + manager.run_passes(f); + ASSERT_NO_THROW(check_rt_info(f)); + ASSERT_EQ(count_ops_of_type(f), 0); +} From 2d75c7a894a692e3fb9b0af23fd2f16d9db64f3e Mon Sep 17 00:00:00 2001 From: Pavel Esir Date: Mon, 23 Aug 2021 18:39:00 +0300 Subject: [PATCH 09/76] [nG] [IE] use GatherBase in negative indices resolver (#7145) * updated pattern matcher into GatherBase in negative indices resolver, so that it is triggered in all versions of operation * copy_runtime_info fix * added constant folding --- .../gather_normalize_negative_indices.cpp | 15 ++++++++------- .../gather_normalize_negative_indices_test.cpp | 16 +++++++++++++--- 2 files changed, 21 insertions(+), 10 deletions(-) diff --git a/inference-engine/src/transformations/src/transformations/op_conversions/gather_normalize_negative_indices.cpp b/inference-engine/src/transformations/src/transformations/op_conversions/gather_normalize_negative_indices.cpp index 86713451869..ad16993c987 100644 --- a/inference-engine/src/transformations/src/transformations/op_conversions/gather_normalize_negative_indices.cpp +++ b/inference-engine/src/transformations/src/transformations/op_conversions/gather_normalize_negative_indices.cpp @@ -7,6 +7,7 @@ #include #include +#include #include #include #include "itt.hpp" @@ -18,11 +19,11 @@ ngraph::pass::GatherNegativeConstIndicesNormalize::GatherNegativeConstIndicesNor auto data_input = ngraph::pattern::any_input(pattern::has_static_rank()); auto axis_input = ngraph::pattern::wrap_type(); auto indices_input = ngraph::pattern::wrap_type(); - auto gather_node = std::make_shared(data_input, indices_input, axis_input); + auto gather_node = ngraph::pattern::wrap_type({data_input, indices_input, axis_input}); ngraph::matcher_pass_callback callback = [=](ngraph::pattern::Matcher& m) { auto& pattern_to_output = m.get_pattern_value_map(); - auto gather = std::dynamic_pointer_cast(pattern_to_output.at(gather_node).get_node_shared_ptr()); + auto gather = pattern_to_output.at(gather_node).get_node_shared_ptr(); auto data = pattern_to_output.at(data_input); auto axis_constant = std::dynamic_pointer_cast(pattern_to_output.at(axis_input).get_node_shared_ptr()); auto indices_constant = std::dynamic_pointer_cast(pattern_to_output.at(indices_input).get_node_shared_ptr()); @@ -62,12 +63,12 @@ ngraph::pass::GatherNegativeConstIndicesNormalize::GatherNegativeConstIndicesNor auto input_gather = std::make_shared(shape_of, ngraph::opset7::Constant::create(input_type, Shape{}, {axis_value}), ngraph::opset7::Constant::create(input_type, Shape{}, {0})); - auto add = std::make_shared(input_gather, indices_constant); - auto gather_new = gather_node->copy_with_new_inputs({data, add, axis_constant}); - gather_new->set_friendly_name(gather->get_friendly_name()); + std::shared_ptr add = std::make_shared(input_gather, indices_constant); + if (auto folded_const = ngraph::get_constant_from_source(add)) + add = folded_const; + gather->input(1).replace_source_output(add); - ngraph::copy_runtime_info(gather, {shape_of, input_gather, add, gather_new}); - ngraph::replace_node(gather, gather_new); + ngraph::copy_runtime_info(gather, {shape_of, input_gather, add}); return true; }; diff --git a/inference-engine/tests/functional/inference_engine/transformations/gather_normalize_negative_indices_test.cpp b/inference-engine/tests/functional/inference_engine/transformations/gather_normalize_negative_indices_test.cpp index ec6c4204a9b..1e600d5f300 100644 --- a/inference-engine/tests/functional/inference_engine/transformations/gather_normalize_negative_indices_test.cpp +++ b/inference-engine/tests/functional/inference_engine/transformations/gather_normalize_negative_indices_test.cpp @@ -7,6 +7,7 @@ #include #include +#include #include #include #include @@ -46,7 +47,10 @@ TEST(TransformationTests, GatherNegativeIndicesNormalize) { auto input_gather = std::make_shared(shape_of, ngraph::opset7::Constant::create(indices_type, ngraph::Shape{}, {1}), ngraph::opset7::Constant::create(indices_type, ngraph::Shape{}, {0})); auto add = std::make_shared(input_gather, indices); - auto gather = std::make_shared(data, add, axis); + auto const_add = ngraph::get_constant_from_source(add); + if (const_add == nullptr) + throw ngraph::ngraph_error("indices should've been constant folded"); + auto gather = std::make_shared(data, const_add, axis); f_ref = std::make_shared(ngraph::NodeVector{gather}, ngraph::ParameterVector{data}); } @@ -84,7 +88,10 @@ TEST(TransformationTests, GatherNegativeIndicesNormalize_neg_axis) { auto input_gather = std::make_shared(shape_of, ngraph::opset7::Constant::create(indices_type, ngraph::Shape{}, {1}), ngraph::opset7::Constant::create(indices_type, ngraph::Shape{}, {0})); auto add = std::make_shared(input_gather, indices); - auto gather = std::make_shared(data, add, axis); + auto const_add = ngraph::get_constant_from_source(add); + if (const_add == nullptr) + throw ngraph::ngraph_error("indices should've been constant folded"); + auto gather = std::make_shared(data, const_add, axis); f_ref = std::make_shared(ngraph::NodeVector{gather}, ngraph::ParameterVector{data}); } @@ -122,7 +129,10 @@ TEST(TransformationTests, GatherNegativeIndicesNormalize_dif_input_types) { auto input_gather = std::make_shared(shape_of, ngraph::opset7::Constant::create(indices_type, ngraph::Shape{}, {1}), ngraph::opset7::Constant::create(indices_type, ngraph::Shape{}, {0})); auto add = std::make_shared(input_gather, indices); - auto gather = std::make_shared(data, add, axis); + auto const_add = ngraph::get_constant_from_source(add); + if (const_add == nullptr) + throw ngraph::ngraph_error("indices should've been constant folded"); + auto gather = std::make_shared(data, const_add, axis); f_ref = std::make_shared(ngraph::NodeVector{gather}, ngraph::ParameterVector{data}); } From 70e0b7817f5cc914808808707d920fc5077e31c0 Mon Sep 17 00:00:00 2001 From: Svetlana Dolinina Date: Mon, 23 Aug 2021 23:11:39 +0300 Subject: [PATCH 10/76] Nested loop (#6710) * initial changes to support nested loop * fixed issues * fixed nested loop extraction * added comments * removed unneeded comments * review fix * added tests * turned off loop tests on GPU * set xfail for TF tests * removed TF test to move it in another repo * fix typo in comment * move duplicated code to separate functions; added asserts * add function for onnx constant creation; add function to create body of loop add comments to test * move main change for nested loop to separate function --- .../extensions/front/onnx/loop_ext.py | 163 +++++++--- tests/layer_tests/onnx_tests/test_loop.py | 285 ++++++++++++++++++ 2 files changed, 403 insertions(+), 45 deletions(-) create mode 100644 tests/layer_tests/onnx_tests/test_loop.py diff --git a/model-optimizer/extensions/front/onnx/loop_ext.py b/model-optimizer/extensions/front/onnx/loop_ext.py index 0a8fc3c36a2..b45dee7dae4 100644 --- a/model-optimizer/extensions/front/onnx/loop_ext.py +++ b/model-optimizer/extensions/front/onnx/loop_ext.py @@ -16,6 +16,95 @@ from mo.graph.graph import Graph, Node, add_opoutput from mo.utils.error import Error +def create_edge_with_attrs(graph, src_name, src_internal_id, src_port, dst_id, dst_port): + # src_name - name of input for edge + # src_internal_id - input node dst_id. Can be the same as src_name or different if Parameter was created + assert (graph.has_node(src_internal_id)) + edge_attrs = { + 'out': src_port, + 'in': dst_port, + 'name': src_name, + 'fw_tensor_debug_info': [(src_internal_id, src_name)], + 'in_attrs': ['in', 'name'], + 'out_attrs': ['out', 'name'], + 'data_attrs': ['fw_tensor_debug_info'] + } + graph.add_edge(src_internal_id, dst_id, **edge_attrs) + + +def create_parameter_with_empty_attrs(graph, param_name): + graph.add_node(param_name, kind='op', op='Parameter', name=param_name, pb=None, shape=None) + parameter_node = Node(graph, param_name) + # need to manually update necessary attrs for the node because extractor will not be called + # for it because the node does not have .pb attribute + Parameter.update_node_stat(parameter_node, {}) + parameter_node['internal_layer_id'] = len(graph.nodes) + + return parameter_node + + +def create_cross_body_edge(body_graph, external_edges, additional_params, src_internal_id, dst_id, dst_port): + cur_graph = body_graph + counter = 0 + is_finished = False + transit_parameter = None + # go through all levels of nested graphs starting from the deepest + while not is_finished and 'parent_node' in cur_graph.graph: + parent_graph = cur_graph.graph['parent_node'].graph + external_edges.append([]) + additional_params.append({}) + assert 0 <= counter < len(additional_params) + assert 0 <= counter < len(external_edges) + # if parent graph contains input node, create edge from outer to inner graph + if src_internal_id in parent_graph.graph['tensor_mapping']: + log.debug('The edge between outer and inner graphs detected: {} -> {}'.format(src_internal_id, dst_id)) + # if parameter in inner graph already created, use it. Otherwise - create new one + if parent_graph.graph['tensor_mapping'][src_internal_id] not in additional_params[counter - 1]: + # possibly we create edge through several levels and have created transit parameter + if transit_parameter is None: + # create new Parameter body node and connect the body node with the outer graph using it + param_id = str(src_internal_id) + parameter_node = create_parameter_with_empty_attrs(cur_graph, param_id) + src_id, src_port = param_id, 0 + else: + parameter_node = transit_parameter + src_id, src_port = transit_parameter.id, 0 + external_edges[counter].append((parent_graph.graph['tensor_mapping'][src_internal_id], + parameter_node, src_internal_id)) + additional_params[counter][parent_graph.graph['tensor_mapping'][src_internal_id][0]] = parameter_node + else: + src_id, src_port = additional_params[counter - 1][parent_graph.graph['tensor_mapping'][src_internal_id][0]].id, 0 + is_finished = True + else: + # check that we are not in process of creating edge through several borders + # if we have transit node, it becomes destination of edge + # otherwise create new Parameter + if transit_parameter is None: + # create new Parameter in inner graph in hope that we will find node later + param_id = str(src_internal_id).split(':')[0] + parameter_node = create_parameter_with_empty_attrs(cur_graph, param_id) + else: + parameter_node = transit_parameter + param_id = transit_parameter.id + + # create transit parameter in outer graph in hope that real input will be found later + parent_param_id = str(src_internal_id).split(':')[0] + "_transit" + parent_parameter_node = create_parameter_with_empty_attrs(parent_graph, parent_param_id) + + external_edges[counter].append(((parent_param_id, 0), parameter_node, parent_param_id)) + src_id, src_port = param_id, 0 + additional_params[counter][parent_param_id + ":0"] = parameter_node + transit_parameter = parent_parameter_node + + if cur_graph.has_node(dst_id): + create_edge_with_attrs(cur_graph, src_internal_id, src_id, src_port, dst_id, dst_port) + + cur_graph = parent_graph + counter += 1 + + return is_finished + + class LoopExtractor(FrontExtractorOp): op = 'Loop' enabled = True @@ -29,10 +118,14 @@ class LoopExtractor(FrontExtractorOp): # create a Graph object for the body and take graph attributes from the main graph body_graph = Graph() - main_graph_attrs_copy = copy.deepcopy(main_graph.graph) - del main_graph_attrs_copy['tensor_mapping'] + main_graph_attrs_copy = {} + for attr_key, attr_value in main_graph.graph.items(): + if attr_key not in ['tensor_mapping', 'parent_node']: + main_graph_attrs_copy[attr_key] = copy.deepcopy(attr_value) body_graph.graph.update(main_graph_attrs_copy) loop_node['body'] = body_graph + # save parent node for nested loops to know which node contains body (and which graph is on upper level) + body_graph.graph['parent_node'] = loop_node # maps a tensor name to a node produced it and the node port: str -> (node_id, node_port) data_nodes_map = {} @@ -41,7 +134,8 @@ class LoopExtractor(FrontExtractorOp): body_parameters = add_initializers_and_inputs_to_graph(body_graph, body_graph_proto, data_nodes_map) external_edges = [] # (src_node, src_out_port), dest_body_parameter_node - additional_params = {} # (src_node, src_out_port) -> parameter_node (for manually added Parameters) + # save additional edges information for graph on each level, the first one is the deepest + additional_params = [] # (src_node, src_out_port) -> parameter_node (for manually added Parameters) # Go through all nodes in the original model order because data nodes are defined on-the-fly and order matters for pb_node in body_graph_proto.node: # create an NX node @@ -52,43 +146,21 @@ class LoopExtractor(FrontExtractorOp): # add incoming edges based on data_nodes_map for dst_port, inp in enumerate(pb_node.input): - # should add edge inp --> id + # should add edge src_internal_id --> dst_id if inp not in data_nodes_map: if inp == '': # input is omitted; most likely it corresponds to an optional input for an operator continue - elif inp in main_graph.graph['tensor_mapping']: - log.debug('The edge between outer and inner graphs detected: {} -> {}'.format(inp, id)) - if main_graph.graph['tensor_mapping'][inp] not in additional_params: - # create new Parameter body node and connect the body node with the outer graph using it - param_id = str(inp) - body_graph.add_node(param_id, kind='op', op='Parameter', name=param_id, pb=None, shape=None) - parameter_node = Node(body_graph, param_id) - # need to manually update necessary attrs for the node because extractor will not be called - # for it because the node does not have .pb attribute - Parameter.update_node_stat(parameter_node, {}) - external_edges.append((main_graph.graph['tensor_mapping'][inp], parameter_node, inp)) - src_id, src_port = param_id, 0 - additional_params[main_graph.graph['tensor_mapping'][inp]] = parameter_node - else: - src_id, src_port = additional_params[main_graph.graph['tensor_mapping'][inp]].id, 0 else: - raise Error('Reference to "{}" is not satisfied. A node refer not existing data tensor. ONNX ' - 'model is not consistent. Protobuf fragment: {}', inp, pb_node) + is_finished = create_cross_body_edge(body_graph, external_edges, additional_params, + inp, id, dst_port) + if not is_finished: + raise Error( + 'Reference to "{}" is not satisfied. A node refer not existing data tensor. ONNX ' + 'model is not consistent. Protobuf fragment: {}', inp, pb_node) else: src_id, src_port = data_nodes_map[inp] - - assert (body_graph.has_node(src_id)) - edge_attrs = { - 'out': src_port, - 'in': dst_port, - 'name': inp, - 'fw_tensor_debug_info': [(src_id, inp)], - 'in_attrs': ['in', 'name'], - 'out_attrs': ['out', 'name'], - 'data_attrs': ['fw_tensor_debug_info'] - } - body_graph.add_edge(src_id, id, **edge_attrs) + create_edge_with_attrs(body_graph, inp, src_id, src_port, id, dst_port) # add outgoing edges to data_nodes_map for src_port, out in enumerate(pb_node.output): @@ -130,21 +202,22 @@ class LoopExtractor(FrontExtractorOp): # 1 .. loop_carried_dependencies_count - loop carried dependencies # loop_carried_dependencies_count + 1 .. - scan outputs - body_graph.stage = 'front' # some of the inputs/outputs may not be connected but the normalization transformation will take care of it # connection Loop body nodes with external input edges next_loop_input_port_idx = sorted(loop_node.in_edges().keys())[-1] + 1 - for (src_node, src_port), body_node, tensor_name in external_edges: - main_graph.add_edge(src_node, loop_node.id, **{'out': src_port, - 'in': next_loop_input_port_idx, - 'name': src_node, - 'fw_tensor_debug_info': [(src_node, tensor_name)], - 'in_attrs': ['in', 'name'], - 'out_attrs': ['out', 'name'], - 'data_attrs': ['fw_tensor_debug_info']} - ) - Loop.connect_body_input(loop_node, next_loop_input_port_idx, body_node) - next_loop_input_port_idx += 1 + cur_graph = body_graph + for external_edges_subg in external_edges: + if 'parent_node' not in cur_graph.graph: + continue + cur_loop_node = cur_graph.graph['parent_node'] + parent_graph = cur_loop_node.graph + for (src_node, src_port), body_node, tensor_name in external_edges_subg: + create_edge_with_attrs(parent_graph, tensor_name, src_node, src_port, + cur_loop_node.id, next_loop_input_port_idx) + + Loop.connect_body_input(cur_loop_node, next_loop_input_port_idx, body_node) + next_loop_input_port_idx += 1 + cur_graph = parent_graph # mark current iteration input Parameter node Loop.mark_current_iteration_parameter_node(loop_node, body_parameters[0]) diff --git a/tests/layer_tests/onnx_tests/test_loop.py b/tests/layer_tests/onnx_tests/test_loop.py new file mode 100644 index 00000000000..e5fab7b5adb --- /dev/null +++ b/tests/layer_tests/onnx_tests/test_loop.py @@ -0,0 +1,285 @@ +# Copyright (C) 2018-2021 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 + +import numpy as np +import pytest + +from common.onnx_layer_test_class import OnnxRuntimeLayerTest + + +class TestLoop(OnnxRuntimeLayerTest): + @staticmethod + def create_const(name, tensor_type, value): + import onnx + from onnx import helper + from onnx import TensorProto + + if tensor_type == TensorProto.INT64: + np_type = np.int64 + elif tensor_type == TensorProto.FLOAT: + np_type = np.float + elif tensor_type == TensorProto.BOOL: + np_type = np.bool + else: + return None + return helper.make_node('Constant', inputs=[], outputs=[name], + value=helper.make_tensor(name='const_tensor', + data_type=tensor_type, + dims=value.shape, + vals=value.flatten().astype(np_type))) + + @staticmethod + def create_body_graph(input_nodes, output_nodes, input_names, output_names, input_shape, graph_name): + # input_nodes - list of input nodes with structure {counter, condition, } + # output_nodes - list of output nodes with structure {condition, , }. + # In this function I assume that every have and + # input_shape - shape of all inputs from + import onnx + from onnx import helper + from onnx import TensorProto + + assert len(input_nodes) > 2 + assert len(output_nodes) == (len(input_nodes) - 2) * 2 + 1 + assert len(input_nodes) == len(input_names) + assert len(output_nodes) == len(output_names) + other_inputs_count = len(input_nodes) - 2 + one_value = np.ones(input_shape, dtype=np.float) + + one = TestLoop.create_const('one_'+graph_name, TensorProto.FLOAT, one_value) + one_int = TestLoop.create_const('one_int_'+graph_name, TensorProto.INT64, np.ones([1])) + + # add one to all inputs except counter and condition + add_one_nodes = [] + for i in range(2, len(input_names)): + add_one_nodes.append(helper.make_node('Add', inputs=[input_names[i], 'one_'+graph_name], + outputs=[output_names[other_inputs_count + i - 1]])) + + # add 1 to counter + add_one_to_m_node = helper.make_node( + 'Add', + inputs=[input_names[0], 'one_int_'+graph_name], + outputs=['counter_plus_1_'+graph_name] + ) + + # map inputs to outputs - back edges + identity_nodes = [] + for i in range(1, len(input_nodes)): + identity_nodes.append(helper.make_node('Identity', + inputs=[input_names[i]], outputs=[output_names[i-1]])) + + body_nodes = [one, one_int] + body_nodes.extend(add_one_nodes) + body_nodes.append(add_one_to_m_node) + body_nodes.extend(identity_nodes) + body_graph = helper.make_graph( + body_nodes, + graph_name, + input_nodes, + output_nodes + ) + + return body_graph + + def create_loop(self): + """ + ONNX net + + Input->Loop->Output => Only accuracy check + + """ + import onnx + from onnx import helper + from onnx import TensorProto + + # Create ONNX model + # Input ---> Loop ---> Identity ---> Result + input_shape = [1, 4, 64, 54] + + in_1 = helper.make_tensor_value_info('IN_1', TensorProto.FLOAT, input_shape) + in_1_int = helper.make_tensor_value_info('in_1_int', TensorProto.FLOAT, input_shape) + in_1_int_out = helper.make_tensor_value_info('in_1_int_out', TensorProto.FLOAT, input_shape) + + out_1 = helper.make_tensor_value_info('OUT_1', TensorProto.FLOAT, None) + res = helper.make_tensor_value_info('res', TensorProto.FLOAT, None) + + m_1 = helper.make_tensor_value_info('m_1', TensorProto.INT64, [1]) + + cond_int_1 = helper.make_tensor_value_info('cond_int_1', TensorProto.BOOL, [1]) + cond_out_1 = helper.make_tensor_value_info('cond_out_1', TensorProto.BOOL, [1]) + + m_1_value = np.array([10], dtype=np.int64) + cond_value = np.array([True], np.bool) + + M_1 = self.create_const('M_1', TensorProto.INT64, m_1_value) + cond = self.create_const('cond', TensorProto.BOOL, cond_value) + + body_graph_1 = self.create_body_graph([m_1, cond_int_1, in_1_int], [cond_out_1, in_1_int_out, out_1], + ['m_1', 'cond_int_1', 'in_1_int'], + ['cond_out_1', 'in_1_int_out', 'OUT_1'], + input_shape, 'body_graph_1') + + node_loop_1 = helper.make_node( + 'Loop', + inputs=['M_1', 'cond', 'IN_1'], + outputs=['cond_out_1', 'OUT_1'], + body=body_graph_1 + ) + + res_node = helper.make_node( + 'Identity', + inputs=['OUT_1'], + outputs=['res'], + ) + + graph_def = helper.make_graph( + [M_1, cond, node_loop_1, res_node], + 'graph', + [in_1], + [res] + ) + + onnx_net = helper.make_model(graph_def, producer_name='test_loop_model') + # We do not create reference graph, as it's too complicated to construct it + # So we return None to skip IR comparision + return onnx_net, None + + def create_loop_in_loop(self): + """ + ONNX net + + Input->Loop(Loop)->Output => Only accuracy check + + """ + import onnx + from onnx import helper + from onnx import TensorProto + + # Create ONNX model + input_shape = [1, 4, 64, 54] + + in_1 = helper.make_tensor_value_info('IN_1', TensorProto.FLOAT, input_shape) + in_1_int = helper.make_tensor_value_info('in_1_int', TensorProto.FLOAT, input_shape) + in_1_int_out = helper.make_tensor_value_info('in_1_int_out', TensorProto.FLOAT, input_shape) + + in_2 = helper.make_tensor_value_info('IN_2', TensorProto.FLOAT, input_shape) + in_2_int = helper.make_tensor_value_info('in_2_int', TensorProto.FLOAT, input_shape) + in_2_int_out = helper.make_tensor_value_info('in_2_int_out', TensorProto.FLOAT, input_shape) + + out_1 = helper.make_tensor_value_info('OUT_1', TensorProto.FLOAT, None) + out_2 = helper.make_tensor_value_info('OUT_2', TensorProto.FLOAT, None) + res = helper.make_tensor_value_info('res', TensorProto.FLOAT, None) + + m_1 = helper.make_tensor_value_info('m_1', TensorProto.INT64, [1]) + m_2 = helper.make_tensor_value_info('m_2', TensorProto.INT64, [1]) + + cond_int_1 = helper.make_tensor_value_info('cond_int_1', TensorProto.BOOL, [1]) + cond_out_1 = helper.make_tensor_value_info('cond_out_1', TensorProto.BOOL, [1]) + cond_int_2 = helper.make_tensor_value_info('cond_int_2', TensorProto.BOOL, [1]) + cond_out_2 = helper.make_tensor_value_info('cond_out_2', TensorProto.BOOL, [1]) + + m_1_value = np.array([10], dtype=np.int64) + m_2_value = np.array([5], dtype=np.int64) + cond_value = np.array([True], np.bool) + one_value = np.ones(input_shape, dtype=np.float) + + M_1 = self.create_const('M_1', TensorProto.INT64, m_1_value) + M_2 = self.create_const('M_2', TensorProto.INT64, m_2_value) + cond = self.create_const('cond', TensorProto.BOOL, cond_value) + one = self.create_const('one', TensorProto.FLOAT, one_value) + one_int = self.create_const('one_int', TensorProto.INT64, one_value) + + # create body of external loop + add_one_node = helper.make_node( + 'Add', + inputs=['in_1_int', 'one'], + outputs=['in_1_loop_1'] + ) + + add_one_to_m_node = helper.make_node( + 'Add', + inputs=['m_1', 'one_int'], + outputs=['m_1_loop_1'] + ) + + cond_2 = self.create_const('cond_2', TensorProto.BOOL, cond_value) + + # create body for internal loop + body_graph_2 = self.create_body_graph([m_2, cond_int_2, in_2_int], [cond_out_2, in_2_int_out, out_2], + ['m_2', 'cond_int_2', 'in_2_int'], + ['cond_out_2', 'in_2_int_out', 'OUT_2'], input_shape, 'body_graph_2') + node_loop_2 = helper.make_node( + 'Loop', + inputs=['M_2', 'cond_2', 'IN_2'], + outputs=['cond_out_2', 'OUT_2'], + body=body_graph_2 + ) + # internal loop created + + out_1_node = helper.make_node( + 'Identity', + inputs=['OUT_2'], + outputs=['OUT_1'], + ) + + cond_1_node = helper.make_node( + 'Identity', + inputs=['cond_int_1'], + outputs=['cond_out_1'], + ) + + in_1_int_node = helper.make_node( + 'Identity', + inputs=['in_1_int'], + outputs=['in_1_int_out'], + ) + + body_graph_1 = helper.make_graph( + [one, add_one_node, one_int, add_one_to_m_node, M_2, cond_2, node_loop_2, out_1_node, cond_1_node, + in_1_int_node], + 'body_graph_1', + [m_1, cond_int_1, in_1_int], + [cond_out_1, in_1_int_out, out_1], + ) + + node_loop_1 = helper.make_node( + 'Loop', + inputs=['M_1', 'cond', 'IN_1'], + outputs=['cond_out_1', 'OUT_1'], + body=body_graph_1 + ) + # external loop created + + res_node = helper.make_node( + 'Identity', + inputs=['OUT_1'], + outputs=['res'], + ) + + graph_def = helper.make_graph( + [M_1, cond, node_loop_1, res_node], + 'graph', + [in_1, in_2], + [res], + ) + + onnx_net = helper.make_model(graph_def, producer_name='test_loop_in_loop_model') + # We do not create reference graph, as it's too complicated to construct it + # So we return None to skip IR comparision + + return onnx_net, None + + @pytest.mark.precommit + @pytest.mark.timeout(250) + def test_loop_simple_precommit(self, ie_device, precision, ir_version, temp_dir): + if ie_device == 'GPU': + pytest.skip('Loop not supported on GPU') + self._test(*self.create_loop(), ie_device, precision, ir_version, temp_dir=temp_dir, + infer_timeout=150) + + @pytest.mark.precommit + @pytest.mark.timeout(250) + def test_loop_in_loop_simple_precommit(self, ie_device, precision, ir_version, temp_dir): + if ie_device == 'GPU': + pytest.skip('Loop not supported on GPU') + self._test(*self.create_loop_in_loop(), ie_device, precision, ir_version, temp_dir=temp_dir, + infer_timeout=150) From 1f4664162a25dcae165926fb0df05cf0a3610943 Mon Sep 17 00:00:00 2001 From: Victor Kuznetsov Date: Tue, 24 Aug 2021 00:39:12 +0300 Subject: [PATCH 11/76] install necessary dirs for tests (#7044) * install necessary dirs to tests * rem RUNTIME from install step * fix paths * fix install paths * fix install paths: add destination dirs * add pandas * fix requirements conflict - change pytest version to ~5 * remove comment from requirements.txt * upd numpy version --- tests/stress_tests/CMakeLists.txt | 3 +++ tests/stress_tests/scripts/requirements.txt | 1 + tests/time_tests/CMakeLists.txt | 3 +++ tests/time_tests/test_runner/requirements.txt | 6 +++--- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/tests/stress_tests/CMakeLists.txt b/tests/stress_tests/CMakeLists.txt index 3370d86b5c4..7bed0cf1bff 100644 --- a/tests/stress_tests/CMakeLists.txt +++ b/tests/stress_tests/CMakeLists.txt @@ -20,3 +20,6 @@ add_subdirectory(common) add_subdirectory(unittests) add_subdirectory(memleaks_tests) add_subdirectory(memcheck_tests) + +install(DIRECTORY scripts/ DESTINATION tests/stress_tests/scripts COMPONENT tests EXCLUDE_FROM_ALL) +install(DIRECTORY .automation/ DESTINATION tests/stress_tests/.automation COMPONENT tests EXCLUDE_FROM_ALL) diff --git a/tests/stress_tests/scripts/requirements.txt b/tests/stress_tests/scripts/requirements.txt index 5d067c92297..681af3a4261 100644 --- a/tests/stress_tests/scripts/requirements.txt +++ b/tests/stress_tests/scripts/requirements.txt @@ -2,5 +2,6 @@ pymongo Jinja2 PyYAML fastjsonschema~=2.15.1 +pandas h5py<3.0.0 # WA for OMZ Keras models. Details: https://github.com/openvinotoolkit/open_model_zoo/issues/1806 \ No newline at end of file diff --git a/tests/time_tests/CMakeLists.txt b/tests/time_tests/CMakeLists.txt index 442e76b99eb..69fbb56bd0c 100644 --- a/tests/time_tests/CMakeLists.txt +++ b/tests/time_tests/CMakeLists.txt @@ -23,3 +23,6 @@ if(NOT InferenceEngine_FOUND) endif() add_subdirectory(src) + +install(DIRECTORY test_runner/ DESTINATION tests/time_tests/test_runner COMPONENT tests EXCLUDE_FROM_ALL) +install(DIRECTORY scripts/ DESTINATION tests/time_tests/scripts COMPONENT tests EXCLUDE_FROM_ALL) diff --git a/tests/time_tests/test_runner/requirements.txt b/tests/time_tests/test_runner/requirements.txt index 37f153fdf6e..d8db3f72fb2 100644 --- a/tests/time_tests/test_runner/requirements.txt +++ b/tests/time_tests/test_runner/requirements.txt @@ -1,8 +1,8 @@ -pytest==4.0.1 -attrs==19.1.0 # required for pytest==4.0.1 to resolve compatibility issues +pytest~=5.0 +attrs==19.1.0 PyYAML==5.4.1 jsonschema==3.2.0 distro==1.5.0 -numpy==1.18.5 +numpy>=1.19.2 pymongo pytest-html From ed6624c489bb6dc4daa29fed1c0e496f0dd1ab53 Mon Sep 17 00:00:00 2001 From: Anton Pankratv Date: Tue, 24 Aug 2021 07:14:11 +0300 Subject: [PATCH 12/76] Added openvino infer request API (#7151) --- .../include/openvino/runtime/common.hpp | 3 +- .../openvino/runtime/infer_request.hpp | 178 ++++++++++++++++++ .../openvino/runtime/profiling_info.hpp | 65 +++++++ .../openvino/runtime/variable_state.hpp | 81 ++++++++ .../src/cpp/ie_infer_request.cpp | 132 ++++++++++++- .../src/cpp/ie_variable_state.cpp | 31 ++- .../src/os/lin/lin_shared_object_loader.cpp | 31 +++ .../src/os/win/win_shared_object_loader.cpp | 110 +++++++++++ .../src/plugin_api/shared_object.hpp | 44 +++++ .../ov_infer_request_test.cpp | 75 ++++++++ .../ov_shared_object_test.cpp | 61 ++++++ .../ov_variable_state_test.cpp | 31 +++ 12 files changed, 839 insertions(+), 3 deletions(-) create mode 100644 inference-engine/src/inference_engine/include/openvino/runtime/infer_request.hpp create mode 100644 inference-engine/src/inference_engine/include/openvino/runtime/profiling_info.hpp create mode 100644 inference-engine/src/inference_engine/include/openvino/runtime/variable_state.hpp create mode 100644 inference-engine/src/plugin_api/shared_object.hpp create mode 100644 inference-engine/tests/functional/inference_engine/ov_infer_request_test.cpp create mode 100644 inference-engine/tests/functional/inference_engine/ov_shared_object_test.cpp create mode 100644 inference-engine/tests/functional/inference_engine/ov_variable_state_test.cpp diff --git a/inference-engine/src/inference_engine/include/openvino/runtime/common.hpp b/inference-engine/src/inference_engine/include/openvino/runtime/common.hpp index 9c0c2e93192..4cb98fa034f 100644 --- a/inference-engine/src/inference_engine/include/openvino/runtime/common.hpp +++ b/inference-engine/src/inference_engine/include/openvino/runtime/common.hpp @@ -3,12 +3,13 @@ // /** - * @brief This is a header file for the OpenVINO Runtime common aliases that depend only from external API + * @brief This is a header file for the OpenVINO Runtime common aliases and data types * * @file openvino/runtime/common.hpp */ #pragma once +#include #include #include diff --git a/inference-engine/src/inference_engine/include/openvino/runtime/infer_request.hpp b/inference-engine/src/inference_engine/include/openvino/runtime/infer_request.hpp new file mode 100644 index 00000000000..d5993d9a09c --- /dev/null +++ b/inference-engine/src/inference_engine/include/openvino/runtime/infer_request.hpp @@ -0,0 +1,178 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +/** + * @brief A header file that provides wrapper classes for infer requests and callbacks. + * + * @file infer_request.hpp + */ +#pragma once + +#include +#include +#include + +#include "common.hpp" +#include "profiling_info.hpp" +#include "variable_state.hpp" + +namespace InferenceEngine { +class IInferRequestInternal; +class Blob; +} // namespace InferenceEngine + +namespace ov { +namespace runtime { +/** + * @brief This is an interface of asynchronous infer request + * + * It can throw exceptions safely for the application, where it is properly handled. + */ +class INFERENCE_ENGINE_API_CLASS(InferRequest) { + std::shared_ptr _so; + std::shared_ptr _impl; + + /** + * @brief Constructs InferRequest from the initialized std::shared_ptr + * @param so Plugin to use. This is required to ensure that InferRequest can work properly even if plugin object is + * destroyed. + * @param impl Initialized shared pointer + */ + InferRequest(const std::shared_ptr& so, const std::shared_ptr& impl); + friend class ExecutableNetwork; + +public: + /** + * @brief Default constructor + */ + InferRequest() = default; + + /** + * @brief Sets input/output data to infer + * + * @note Memory allocation does not happen + * @param name Name of input or output blob. + * @param data Reference to input or output blob. The type of a blob must match the network input precision and + * size. + */ + void set_blob(const std::string& name, const std::shared_ptr& data); + + /** + * @brief Gets input/output data for inference + * + * @note Memory allocation does not happen + * @param name A name of Blob to get + * @return A shared pointer to a Blob with a name @p name. If a blob is not found, an exception is thrown. + */ + std::shared_ptr get_blob(const std::string& name); + + /** + * @brief Infers specified input(s) in synchronous mode + * + * @note blocks all methods of InferRequest while request is ongoing (running or waiting in queue) + * + */ + void infer(); + + /** + * @brief Cancels inference request + */ + void cancel(); + + /** + * @brief Queries performance measures per layer to get feedback of what is the most time consuming layer + * + * @note not all plugins provide meaningful data + * @return Vector of profiling information for layers in network + */ + std::vector get_profiling_info() const; + + /** + * @brief Sets input data to infer + * + * @note Memory allocation doesn't happen + * @param inputs A reference to a map of input blobs accessed by input names. + * The type of Blob must correspond to the network input precision and size. + */ + void set_input(const std::map>& inputs); + + /** + * @brief Sets data that will contain result of the inference + * + * @note Memory allocation doesn't happen + * @param results - a reference to a map of result blobs accessed by output names. + * The type of Blob must correspond to the network output precision and size. + */ + void set_output(const std::map>& results); + + /** + * @brief Sets new batch size when dynamic batching is enabled in executable network that created this request. + * + * @param batch new batch size to be used by all the following inference calls for this request. + */ + void set_batch(const int batch); + + /** + * @brief Start inference of specified input(s) in asynchronous mode + * + * @note It returns immediately. Inference starts also immediately. + */ + void start_async(); + + /** + * @brief Waits for the result to become available. Blocks until the result + * becomes available + */ + void wait(); + + /** + * @brief Waits for the result to become available. Blocks until specified timeout has elapsed or the result + * becomes available, whichever comes first. + * + * @param timeout Maximum duration in milliseconds to block for + * @return true if inference request is ready and false otherwise + */ + bool wait_for(const std::chrono::milliseconds timeout); + + /** + * @brief Sets a callback function that will be called on success or failure of asynchronous request + * + * @param callback callback object which will be called on when inference finish. + */ + void set_callback(std::function callback); + + /** + * @brief Gets state control interface for given infer request. + * + * State control essential for recurrent networks + * @return A vector of Memory State objects + */ + std::vector query_state(); + + /** + * @brief Checks if current InferRequest object is not initialized + * @return true if current InferRequest object is not initialized, false - otherwise + */ + bool operator!() const noexcept; + + /** + * @brief Checks if current InferRequest object is initialized + * @return true if current InferRequest object is initialized, false - otherwise + */ + explicit operator bool() const noexcept; + + /** + * @brief Compares whether this request wraps the same impl underneath + * @return true if current InferRequest object doesn't wrap the same impl as the operator's arg + */ + bool operator!=(const InferRequest&) const noexcept; + + /** + * @brief Compares whether this request wraps the same impl underneath + * @return true if current InferRequest object wraps the same impl as the operator's arg + */ + bool operator==(const InferRequest&) const noexcept; +}; +} // namespace runtime +} // namespace ov diff --git a/inference-engine/src/inference_engine/include/openvino/runtime/profiling_info.hpp b/inference-engine/src/inference_engine/include/openvino/runtime/profiling_info.hpp new file mode 100644 index 00000000000..f72255071a9 --- /dev/null +++ b/inference-engine/src/inference_engine/include/openvino/runtime/profiling_info.hpp @@ -0,0 +1,65 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +/** + * @brief This is a header file for the ProfilingInfo objects that contains performance + * metric for single node + * + * @file openvino/runtime/profiling_info.hpp + */ +#pragma once + +#include +#include + +namespace ov { +namespace runtime { +/** + * @struct ProfilingInfo + * @brief Represents basic inference profiling information per node. + * + * If the node is executed using tiling, the sum time per each tile is indicated as the total execution time. + * Due to parallel execution, the total execution time for all nodes might be greater than the total inference time. + */ +struct ProfilingInfo { + /** + * @brief Defines the general status of the node + */ + enum class Status { + NOT_RUN, //!< A node is not executed + OPTIMIZED_OUT, //!< A node is optimized out during graph optimization phase + EXECUTED //!< A node is executed + }; + + /** + * @brief Defines a node status + */ + Status status; + + /** + * @brief The absolute time in microseconds that the node ran (in total) + */ + std::chrono::microseconds real_time; + /** + * @brief The net host cpu time that the node ran + */ + std::chrono::microseconds cpu_time; + + /** + * @brief A name of node + */ + std::string node_name; + + /** + * @brief An execution type of unit + */ + std::string exec_type; + + /** + * @brief A node type + */ + std::string node_type; +}; +} // namespace runtime +} // namespace ov \ No newline at end of file diff --git a/inference-engine/src/inference_engine/include/openvino/runtime/variable_state.hpp b/inference-engine/src/inference_engine/include/openvino/runtime/variable_state.hpp new file mode 100644 index 00000000000..e15679b118b --- /dev/null +++ b/inference-engine/src/inference_engine/include/openvino/runtime/variable_state.hpp @@ -0,0 +1,81 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +/** + * @brief A header file that provides VariableState + * + * @file variable_state.hpp + */ + +#pragma once + +#include +#include + +#include +#include + +#include "common.hpp" + +namespace InferenceEngine { +class IVariableStateInternal; +class Blob; +} // namespace InferenceEngine + +namespace ov { +namespace runtime { + +class SharedObject; +class InferRequest; + +/** + * @brief VariableState class + */ +class INFERENCE_ENGINE_API_CLASS(VariableState) { + std::shared_ptr _so; + std::shared_ptr _impl; + + /** + * @brief Constructs VariableState from the initialized std::shared_ptr + * @param impl Initialized shared pointer + * @param so Optional: Plugin to use. This is required to ensure that VariableState can work properly even if plugin + * object is destroyed. + */ + VariableState(const std::shared_ptr& so, const std::shared_ptr& impl); + + friend class ov::runtime::InferRequest; + +public: + /** + * @brief Default constructor + */ + VariableState() = default; + + /** + * @brief Reset internal variable state for relevant infer request, + * to a value specified as default for according ReadValue node + */ + void reset(); + + /** + * @brief Gets name of current variable state, if length of array is not enough name is truncated by len, null + * terminator is inserted as well. As variable state name `variable_id` from according `ReadValue` used. + * @return A string representing a state name + */ + std::string get_name() const; + + /** + * @brief Returns the value of the variable state. + * @return A blob representing a state + */ + std::shared_ptr get_state() const; + + /** + * @brief Sets the new state for the next inference. + * @param state The current state to set + */ + void set_state(const std::shared_ptr& state); +}; +} // namespace runtime +} // namespace ov diff --git a/inference-engine/src/inference_engine/src/cpp/ie_infer_request.cpp b/inference-engine/src/inference_engine/src/cpp/ie_infer_request.cpp index 135cf2d3391..11937e6309d 100644 --- a/inference-engine/src/inference_engine/src/cpp/ie_infer_request.cpp +++ b/inference-engine/src/inference_engine/src/cpp/ie_infer_request.cpp @@ -10,8 +10,10 @@ #include "cpp/exception2status.hpp" #include "cpp_interfaces/interface/ie_iinfer_request_internal.hpp" +#include "details/ie_so_loader.h" #include "ie_infer_async_request_base.hpp" #include "ie_remote_context.hpp" +#include "openvino/runtime/infer_request.hpp" namespace InferenceEngine { @@ -21,7 +23,7 @@ namespace InferenceEngine { try { \ __VA_ARGS__ \ } catch (...) { \ - details::Rethrow(); \ + ::InferenceEngine::details::Rethrow(); \ } InferRequest::InferRequest(const details::SharedObjectLoader& so, const IInferRequestInternal::Ptr& impl) @@ -190,3 +192,131 @@ bool InferRequest::operator==(const InferRequest& r) const noexcept { } } // namespace InferenceEngine + +namespace ov { +namespace runtime { + +InferRequest::InferRequest(const std::shared_ptr& so, const ie::IInferRequestInternal::Ptr& impl) + : _so{so}, + _impl{impl} { + IE_ASSERT(_impl != nullptr); +} + +void InferRequest::set_blob(const std::string& name, const ie::Blob::Ptr& data) { + INFER_REQ_CALL_STATEMENT(_impl->SetBlob(name, data);) +} + +ie::Blob::Ptr InferRequest::get_blob(const std::string& name) { + ie::Blob::Ptr blobPtr; + INFER_REQ_CALL_STATEMENT(blobPtr = _impl->GetBlob(name);) + std::string error = "Internal error: blob with name `" + name + "` is not allocated!"; + const bool remoteBlobPassed = blobPtr->is(); + if (blobPtr == nullptr) + IE_THROW() << error; + if (!remoteBlobPassed && blobPtr->buffer() == nullptr) + IE_THROW() << error; + return blobPtr; +} + +void InferRequest::infer() { + INFER_REQ_CALL_STATEMENT(_impl->Infer();) +} + +void InferRequest::cancel() { + INFER_REQ_CALL_STATEMENT(_impl->Cancel();) +} + +std::vector InferRequest::get_profiling_info() const { + INFER_REQ_CALL_STATEMENT({ + auto ieInfos = _impl->GetPerformanceCounts(); + std::vector infos; + infos.reserve(ieInfos.size()); + while (!ieInfos.empty()) { + auto itIeInfo = std::min_element( + std::begin(ieInfos), + std::end(ieInfos), + [](const decltype(ieInfos)::value_type& lhs, const decltype(ieInfos)::value_type& rhs) { + return lhs.second.execution_index < rhs.second.execution_index; + }); + IE_ASSERT(itIeInfo != ieInfos.end()); + auto& ieInfo = itIeInfo->second; + infos.push_back(ProfilingInfo{}); + auto& info = infos.back(); + switch (ieInfo.status) { + case ie::InferenceEngineProfileInfo::NOT_RUN: + info.status = ProfilingInfo::Status::NOT_RUN; + break; + case ie::InferenceEngineProfileInfo::OPTIMIZED_OUT: + info.status = ProfilingInfo::Status::OPTIMIZED_OUT; + break; + case ie::InferenceEngineProfileInfo::EXECUTED: + info.status = ProfilingInfo::Status::OPTIMIZED_OUT; + break; + } + info.real_time = std::chrono::microseconds{ieInfo.realTime_uSec}; + info.cpu_time = std::chrono::microseconds{ieInfo.cpu_uSec}; + info.node_name = itIeInfo->first; + info.exec_type = std::string{ieInfo.exec_type}; + info.node_type = std::string{ieInfo.layer_type}; + ieInfos.erase(itIeInfo); + } + return infos; + }) +} + +void InferRequest::set_input(const ie::BlobMap& inputs) { + INFER_REQ_CALL_STATEMENT(for (auto&& input : inputs) { _impl->SetBlob(input.first, input.second); }) +} + +void InferRequest::set_output(const ie::BlobMap& results) { + INFER_REQ_CALL_STATEMENT(for (auto&& result : results) { _impl->SetBlob(result.first, result.second); }) +} + +void InferRequest::set_batch(const int batch) { + INFER_REQ_CALL_STATEMENT(_impl->SetBatch(batch);) +} + +void InferRequest::start_async() { + INFER_REQ_CALL_STATEMENT(_impl->StartAsync();) +} + +void InferRequest::wait() { + INFER_REQ_CALL_STATEMENT(_impl->Wait(ie::InferRequest::RESULT_READY);) +} + +bool InferRequest::wait_for(const std::chrono::milliseconds timeout) { + INFER_REQ_CALL_STATEMENT(return _impl->Wait(timeout.count()) == ie::OK;) +} + +void InferRequest::set_callback(std::function callback) { + INFER_REQ_CALL_STATEMENT(_impl->SetCallback(std::move(callback));) +} + +std::vector InferRequest::query_state() { + std::vector variable_states; + INFER_REQ_CALL_STATEMENT({ + for (auto&& state : _impl->QueryState()) { + variable_states.emplace_back(VariableState{_so, state}); + } + }) + return variable_states; +} + +bool InferRequest::operator!() const noexcept { + return !_impl; +} + +InferRequest::operator bool() const noexcept { + return (!!_impl); +} + +bool InferRequest::operator!=(const InferRequest& r) const noexcept { + return !(r == *this); +} + +bool InferRequest::operator==(const InferRequest& r) const noexcept { + return r._impl == _impl; +} + +} // namespace runtime +} // namespace ov \ No newline at end of file diff --git a/inference-engine/src/inference_engine/src/cpp/ie_variable_state.cpp b/inference-engine/src/inference_engine/src/cpp/ie_variable_state.cpp index ff8547f13b3..e9aeb57d720 100644 --- a/inference-engine/src/inference_engine/src/cpp/ie_variable_state.cpp +++ b/inference-engine/src/inference_engine/src/cpp/ie_variable_state.cpp @@ -6,6 +6,7 @@ #include "cpp_interfaces/interface/ie_ivariable_state_internal.hpp" #include "details/ie_so_loader.h" #include "exception2status.hpp" +#include "openvino/runtime/variable_state.hpp" #define VARIABLE_CALL_STATEMENT(...) \ if (_impl == nullptr) \ @@ -13,7 +14,7 @@ try { \ __VA_ARGS__; \ } catch (...) { \ - details::Rethrow(); \ + ::InferenceEngine::details::Rethrow(); \ } namespace InferenceEngine { @@ -44,3 +45,31 @@ void VariableState::SetState(Blob::Ptr state) { } } // namespace InferenceEngine + +namespace ov { +namespace runtime { + +VariableState::VariableState(const std::shared_ptr& so, const ie::IVariableStateInternal::Ptr& impl) + : _so{so}, + _impl{impl} { + IE_ASSERT(_impl != nullptr); +} + +void VariableState::reset() { + VARIABLE_CALL_STATEMENT(_impl->Reset()); +} + +std::string VariableState::get_name() const { + VARIABLE_CALL_STATEMENT(return _impl->GetName()); +} + +ie::Blob::CPtr VariableState::get_state() const { + VARIABLE_CALL_STATEMENT(return _impl->GetState()); +} + +void VariableState::set_state(const ie::Blob::Ptr& state) { + VARIABLE_CALL_STATEMENT(_impl->SetState(state)); +} + +} // namespace runtime +} // namespace ov diff --git a/inference-engine/src/inference_engine/src/os/lin/lin_shared_object_loader.cpp b/inference-engine/src/inference_engine/src/os/lin/lin_shared_object_loader.cpp index 6d3cfa87e31..1961c1a7130 100644 --- a/inference-engine/src/inference_engine/src/os/lin/lin_shared_object_loader.cpp +++ b/inference-engine/src/inference_engine/src/os/lin/lin_shared_object_loader.cpp @@ -8,6 +8,7 @@ #include "details/ie_so_loader.h" #include "file_utils.h" +#include "shared_object.hpp" namespace InferenceEngine { namespace details { @@ -71,3 +72,33 @@ void* SharedObjectLoader::get_symbol(const char* symbolName) const { } // namespace details } // namespace InferenceEngine + +namespace ov { +namespace runtime { +SharedObject::SharedObject(const char* path) { + shared_object = dlopen(path, RTLD_NOW); + + if (shared_object == nullptr) + IE_THROW() << "Cannot load library '" << path << "': " << dlerror(); +} + +#ifdef ENABLE_UNICODE_PATH_SUPPORT +SharedObject::SharedObject(const wchar_t* path) : SharedObject(FileUtils::wStringtoMBCSstringChar(path).c_str()) {} +#endif // ENABLE_UNICODE_PATH_SUPPORT + +SharedObject::~SharedObject() { + if (0 != dlclose(shared_object)) { + std::cerr << "dlclose failed: " << dlerror() << std::endl; + } +} + +void* SharedObject::get_symbol(const char* symbolName) const { + void* procAddr = nullptr; + + procAddr = dlsym(shared_object, symbolName); + if (procAddr == nullptr) + IE_THROW(NotFound) << "dlSym cannot locate method '" << symbolName << "': " << dlerror(); + return procAddr; +} +} // namespace runtime +} // namespace ov diff --git a/inference-engine/src/inference_engine/src/os/win/win_shared_object_loader.cpp b/inference-engine/src/inference_engine/src/os/win/win_shared_object_loader.cpp index 31c148ec111..7896b56e5d2 100644 --- a/inference-engine/src/inference_engine/src/os/win/win_shared_object_loader.cpp +++ b/inference-engine/src/inference_engine/src/os/win/win_shared_object_loader.cpp @@ -5,6 +5,7 @@ #include "ie_common.h" #include "details/ie_so_loader.h" #include "file_utils.h" +#include "shared_object.hpp" // // LoadLibraryA, LoadLibraryW: @@ -274,3 +275,112 @@ void* SharedObjectLoader::get_symbol(const char* symbolName) const { } // namespace details } // namespace InferenceEngine + + +namespace ov { +namespace runtime { +SharedObject::SharedObject(const char* path) { + using GetDllDirectoryA_Fnc = DWORD(*)(DWORD, LPSTR); + GetDllDirectoryA_Fnc IEGetDllDirectoryA = nullptr; + if (HMODULE hm = GetModuleHandleW(L"kernel32.dll")) { + IEGetDllDirectoryA = reinterpret_cast(GetProcAddress(hm, "GetDllDirectoryA")); + } +#if !WINAPI_PARTITION_SYSTEM + // ExcludeCurrentDirectory + if (IEGetDllDirectoryA && IEGetDllDirectoryA(0, NULL) <= 1) { + SetDllDirectoryA(""); + } + // LoadPluginFromDirectory + if (IEGetDllDirectoryA) { + DWORD nBufferLength = IEGetDllDirectoryA(0, NULL); + std::vector lpBuffer(nBufferLength); + IEGetDllDirectoryA(nBufferLength, &lpBuffer.front()); + + // GetDirname + auto dirname = [&] { + auto pos = strchr(path, '\\'); + if (pos == nullptr) { + return std::string{path}; + } + std::string original(path); + original[pos - path] = 0; + return original; + } (); + + SetDllDirectoryA(dirname.c_str()); + shared_object = LoadLibraryA(path); + + SetDllDirectoryA(&lpBuffer.front()); + } +#endif + if (!shared_object) { + shared_object = LoadLibraryA(path); + } + if (!shared_object) { + char cwd[1024]; + IE_THROW() << "Cannot load library '" << path << "': " << GetLastError() + << " from cwd: " << _getcwd(cwd, sizeof(cwd)); + } +} + +#ifdef ENABLE_UNICODE_PATH_SUPPORT +SharedObject::SharedObject(const wchar_t* path) { + using GetDllDirectoryW_Fnc = DWORD(*)(DWORD, LPWSTR); + static GetDllDirectoryW_Fnc IEGetDllDirectoryW = nullptr; + if (HMODULE hm = GetModuleHandleW(L"kernel32.dll")) { + IEGetDllDirectoryW = reinterpret_cast(GetProcAddress(hm, "GetDllDirectoryW")); + } + // ExcludeCurrentDirectory +#if !WINAPI_PARTITION_SYSTEM + if (IEGetDllDirectoryW && IEGetDllDirectoryW(0, NULL) <= 1) { + SetDllDirectoryW(L""); + } + if (IEGetDllDirectoryW) { + DWORD nBufferLength = IEGetDllDirectoryW(0, NULL); + std::vector lpBuffer(nBufferLength); + IEGetDllDirectoryW(nBufferLength, &lpBuffer.front()); + + auto dirname = [&] { + auto pos = wcsrchr(path, '\\'); + if (pos == nullptr) { + return std::wstring{path}; + } + std::wstring original(path); + original[pos - path] = 0; + return original; + } (); + SetDllDirectoryW(dirname.c_str()); + shared_object = LoadLibraryW(path); + + SetDllDirectoryW(&lpBuffer.front()); + } +#endif + if (!shared_object) { + shared_object = LoadLibraryW(path); + } + if (!shared_object) { + char cwd[1024]; + IE_THROW() << "Cannot load library '" << FileUtils::wStringtoMBCSstringChar(std::wstring(path)) << "': " << GetLastError() + << " from cwd: " << _getcwd(cwd, sizeof(cwd)); + } +} +#endif + +SharedObject::~SharedObject() { + FreeLibrary(reinterpret_cast(shared_object)); +} + +void* SharedObject::get_symbol(const char* symbolName) const { + if (!shared_object) { + IE_THROW() << "Cannot get '" << symbolName << "' content from unknown library!"; + } + auto procAddr = reinterpret_cast(GetProcAddress( + reinterpret_cast(const_cast(shared_object)), symbolName)); + if (procAddr == nullptr) + IE_THROW(NotFound) + << "GetProcAddress cannot locate method '" << symbolName << "': " << GetLastError(); + + return procAddr; +} +} // namespace runtime +} // namespace ov diff --git a/inference-engine/src/plugin_api/shared_object.hpp b/inference-engine/src/plugin_api/shared_object.hpp new file mode 100644 index 00000000000..de2523375c7 --- /dev/null +++ b/inference-engine/src/plugin_api/shared_object.hpp @@ -0,0 +1,44 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +/** + * @brief A header file for definition of abstraction over platform specific shared objects + * @file ie_system_conf.h + */ + +#pragma once + +#include "ie_api.h" + +namespace ov { +namespace runtime { +struct INFERENCE_ENGINE_API_CLASS(SharedObject) { + void* shared_object = nullptr; + + /** + * @brief Loads a library with the name specified. + * @param path Full or relative path to the plugin library + */ + explicit SharedObject(const char* path); + +#ifdef ENABLE_UNICODE_PATH_SUPPORT + /** + * @brief Loads a library with the wide char name specified. + * @param path Full or relative path to the plugin library + */ + explicit SharedObject(const wchar_t* path); +#endif // ENABLE_UNICODE_PATH_SUPPORT + + ~SharedObject(); + + /** + * @brief Searches for a function symbol in the loaded module + * @param symbolName Name of the function to find + * @return A pointer to the function if found + * @throws Exception if the function is not found + */ + void* get_symbol(const char* symbolName) const; +}; +} // namespace runtime +} // namespace ov diff --git a/inference-engine/tests/functional/inference_engine/ov_infer_request_test.cpp b/inference-engine/tests/functional/inference_engine/ov_infer_request_test.cpp new file mode 100644 index 00000000000..1cfdb17941c --- /dev/null +++ b/inference-engine/tests/functional/inference_engine/ov_infer_request_test.cpp @@ -0,0 +1,75 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include + +#include +#include + +using namespace ::testing; +using namespace std; +using namespace InferenceEngine; +using namespace InferenceEngine::details; + + +TEST(InferRequestOVTests, throwsOnUninitializedSetBlob) { + ov::runtime::InferRequest req; + ASSERT_THROW(req.set_blob({}, {}), InferenceEngine::NotAllocated); +} + +TEST(InferRequestOVTests, throwsOnUninitializedGetBlob) { + ov::runtime::InferRequest req; + ASSERT_THROW(req.get_blob({}), InferenceEngine::NotAllocated); +} + +TEST(InferRequestOVTests, throwsOnUninitializedInfer) { + ov::runtime::InferRequest req; + ASSERT_THROW(req.infer(), InferenceEngine::NotAllocated); +} + +TEST(InferRequestOVTests, throwsOnUninitializedGetPerformanceCounts) { + ov::runtime::InferRequest req; + ASSERT_THROW(req.get_profiling_info(), InferenceEngine::NotAllocated); +} + +TEST(InferRequestOVTests, throwsOnUninitializedSetInput) { + ov::runtime::InferRequest req; + ASSERT_THROW(req.set_input({{}}), InferenceEngine::NotAllocated); +} + +TEST(InferRequestOVTests, throwsOnUninitializedSetOutput) { + ov::runtime::InferRequest req; + ASSERT_THROW(req.set_output({{}}), InferenceEngine::NotAllocated); +} + +TEST(InferRequestOVTests, throwsOnUninitializedSetBatch) { + ov::runtime::InferRequest req; + ASSERT_THROW(req.set_batch({}), InferenceEngine::NotAllocated); +} + +TEST(InferRequestOVTests, throwsOnUninitializedStartAsync) { + ov::runtime::InferRequest req; + ASSERT_THROW(req.start_async(), InferenceEngine::NotAllocated); +} + +TEST(InferRequestOVTests, throwsOnUninitializedWait) { + ov::runtime::InferRequest req; + ASSERT_THROW(req.wait(), InferenceEngine::NotAllocated); +} + +TEST(InferRequestOVTests, throwsOnUninitializedWaitFor) { + ov::runtime::InferRequest req; + ASSERT_THROW(req.wait_for({}), InferenceEngine::NotAllocated); +} + +TEST(InferRequestOVTests, throwsOnUninitializedSetCompletionCallback) { + ov::runtime::InferRequest req; + std::function f; + ASSERT_THROW(req.set_callback(f), InferenceEngine::NotAllocated); +} + +TEST(InferRequestOVTests, throwsOnUninitializedQueryState) { + ov::runtime::InferRequest req; + ASSERT_THROW(req.query_state(), InferenceEngine::NotAllocated); +} diff --git a/inference-engine/tests/functional/inference_engine/ov_shared_object_test.cpp b/inference-engine/tests/functional/inference_engine/ov_shared_object_test.cpp new file mode 100644 index 00000000000..a396df7afc9 --- /dev/null +++ b/inference-engine/tests/functional/inference_engine/ov_shared_object_test.cpp @@ -0,0 +1,61 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include + +#include +#include "shared_object.hpp" +#include + +using namespace ::testing; +using namespace std; + +class SharedObjectOVTests: public ::testing::Test { +protected: + std::string get_mock_engine_name() { + return FileUtils::makePluginLibraryName(InferenceEngine::getIELibraryPath(), + std::string("mock_engine") + IE_BUILD_POSTFIX); + } + + void loadDll(const string &libraryName) { + sharedObject.reset(new ov::runtime::SharedObject(libraryName.c_str())); + } + unique_ptr sharedObject; + + using CreateF = void(std::shared_ptr&); + + std::function make_std_function(const std::string& functionName) { + std::function ptr(reinterpret_cast(sharedObject->get_symbol(functionName.c_str()))); + return ptr; + } +}; + +TEST_F(SharedObjectOVTests, canLoadExistedPlugin) { + loadDll(get_mock_engine_name()); + EXPECT_NE(nullptr, sharedObject.get()); +} + +TEST_F(SharedObjectOVTests, loaderThrowsIfNoPlugin) { + EXPECT_THROW(loadDll("wrong_name"), InferenceEngine::Exception); +} + +TEST_F(SharedObjectOVTests, canFindExistedMethod) { + loadDll(get_mock_engine_name()); + + auto factory = make_std_function("CreatePluginEngine"); + EXPECT_NE(nullptr, factory); +} + +TEST_F(SharedObjectOVTests, throwIfMethodNofFoundInLibrary) { + loadDll(get_mock_engine_name()); + EXPECT_THROW(make_std_function("wrong_function"), InferenceEngine::Exception); +} + +TEST_F(SharedObjectOVTests, canCallExistedMethod) { + loadDll(get_mock_engine_name()); + + auto factory = make_std_function("CreatePluginEngine"); + std::shared_ptr ptr; + EXPECT_NO_THROW(factory(ptr)); +} diff --git a/inference-engine/tests/functional/inference_engine/ov_variable_state_test.cpp b/inference-engine/tests/functional/inference_engine/ov_variable_state_test.cpp new file mode 100644 index 00000000000..f9233e5eebc --- /dev/null +++ b/inference-engine/tests/functional/inference_engine/ov_variable_state_test.cpp @@ -0,0 +1,31 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include + +#include + +using namespace ::testing; +using namespace std; + +TEST(VariableStateOVTests, throwsOnUninitializedReset) { + ov::runtime::VariableState state; + ASSERT_THROW(state.reset(), InferenceEngine::NotAllocated); +} + +TEST(VariableStateOVTests, throwsOnUninitializedGetname) { + ov::runtime::VariableState state; + ASSERT_THROW(state.get_name(), InferenceEngine::NotAllocated); +} + +TEST(VariableStateOVTests, throwsOnUninitializedGetState) { + ov::runtime::VariableState state; + ASSERT_THROW(state.get_state(), InferenceEngine::NotAllocated); +} + +TEST(VariableStateOVTests, throwsOnUninitializedSetState) { + ov::runtime::VariableState state; + InferenceEngine::Blob::Ptr blob; + ASSERT_THROW(state.set_state(blob), InferenceEngine::NotAllocated); +} From e697d85afbe8541f706aaf896a9b40762774d31c Mon Sep 17 00:00:00 2001 From: Alexandra Sidorova Date: Tue, 24 Aug 2021 09:44:25 +0300 Subject: [PATCH 13/76] [CPU] Removed eltwise overhead on execution stage (#6760) --- .../mkldnn_plugin/mkldnn_graph_optimizer.cpp | 3 +- .../nodes/mkldnn_eltwise_node.cpp | 167 +++++++++--------- .../mkldnn_plugin/nodes/mkldnn_eltwise_node.h | 34 ++-- .../single_layer_tests/activation.cpp | 4 +- 4 files changed, 108 insertions(+), 100 deletions(-) diff --git a/inference-engine/src/mkldnn_plugin/mkldnn_graph_optimizer.cpp b/inference-engine/src/mkldnn_plugin/mkldnn_graph_optimizer.cpp index 9cbc9b79aeb..0cad8e15e3b 100644 --- a/inference-engine/src/mkldnn_plugin/mkldnn_graph_optimizer.cpp +++ b/inference-engine/src/mkldnn_plugin/mkldnn_graph_optimizer.cpp @@ -330,7 +330,8 @@ void MKLDNNGraphOptimizer::FuseMultiplyAndAdd(MKLDNNGraph &graph) { if (childNode->getAlgorithm() != EltwiseAdd || !childNode->getFusedWith().empty() || childNode->getParentEdges().size() != 2) return false; - return isSutableSecondInput(childNode->getParentEdgesAtPort(1)[0]->getParent(), childNode->getParentEdgesAtPort(0)[0]->getShape().getDims()); + return isSutableSecondInput(childNode->getParentEdgesAtPort(1)[0]->getParent(), childNode->getParentEdgesAtPort(0)[0]->getShape().getDims()) && + parentNode->canFuse(childNode); }; auto parent = graphNodes.begin(); diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_eltwise_node.cpp b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_eltwise_node.cpp index d777e22210f..1bba69c7cfb 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_eltwise_node.cpp +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_eltwise_node.cpp @@ -45,7 +45,7 @@ using namespace mkldnn::impl::cpu; using namespace mkldnn::impl::cpu::x64; using namespace Xbyak; -#define GET_OFF(field) offsetof(jit_eltwise_call_args, field) +#define GET_OFF(field) offsetof(jit_eltwise_call_args_ptrs, field) namespace { @@ -140,11 +140,31 @@ struct jit_uni_eltwise_generic : public MKLDNNPlugin::jit_uni_eltwise_kernel, pu this->preamble(); - for (int i = 0; i < jep.inputs_number; i++) - mov(get_src_reg(i), ptr[reg_params + GET_OFF(src_ptr[0]) + i * sizeof(size_t)]); - mov(reg_dst, ptr[reg_params + GET_OFF(dst)]); - mov(reg_work_amount, ptr[reg_params + GET_OFF(work_amount)]); - mov(reg_oc_off, ptr[reg_params + GET_OFF(oc_off)]); + const int offset_count = jep.input_size - 1; + + // ptrs initializing + auto init_ptrs_with_offsets = [this, offset_count](Reg64 pointer, const std::vector& offsets) { + for (int j = 0; j < offset_count; j++) { + if (jep_.dims[j] != 1 && offsets[j] != 0) { + mov(reg_tmp_64, offsets[j]); + imul(reg_tmp_64, ptr[reg_indexes + j * sizeof(size_t)]); + add(pointer, reg_tmp_64); + } + } + }; + + for (int i = 0; i < jep.inputs_number; i++) { + mov(get_src_reg(i), ptr[reg_const_params + GET_OFF(src_ptr[0]) + i * sizeof(size_t)]); + init_ptrs_with_offsets(get_src_reg(i), jep.src_offsets[i]); + } + + mov(reg_dst, ptr[reg_const_params + GET_OFF(dst_ptr)]); + init_ptrs_with_offsets(reg_dst, jep.dst_offsets); + + xor_(reg_oc_off, reg_oc_off); + init_ptrs_with_offsets(reg_oc_off, jep.oc_offsets); + + mov(reg_work_amount, jep.work_amount); Xbyak::Label unroll_loop_label; Xbyak::Label unroll_loop_end_label; @@ -335,7 +355,8 @@ private: Reg64 reg_work_amount = rdx; Reg64 reg_oc_off = abi_not_param1; - Reg64 reg_params = abi_param1; + Reg64 reg_const_params = abi_param1; + Reg64 reg_indexes = abi_param2; // reg_d_bias Reg8 reg_tmp_8 = Reg8(r15.getIdx()); Reg32 reg_tmp_32 = Reg32(r15.getIdx()); @@ -996,7 +1017,8 @@ void MKLDNNEltwiseNode::initSupportedPrimitiveDescriptors() { if (!supportedPrimitiveDescriptors.empty()) return; - canUseOptimizedImpl = mayiuse(x64::sse41); + // if dim rank is greater than the maximum possible, we should use the reference execution + canUseOptimizedImpl = mayiuse(x64::sse41) && inputShapes[0].getRank() <= MAX_ELTWISE_DIM_RANK; size_t expectedInputsNum = getOpInputsNum(); for (auto& postOp : fusedWith) { @@ -1180,9 +1202,10 @@ void MKLDNNEltwiseNode::initSupportedPrimitiveDescriptors() { } void MKLDNNEltwiseNode::createPrimitive() { - auto initDims = [this](size_t maxInputSize) { - size_t inputNum = getParentEdges().size(); + auto config = getSelectedPrimitiveDescriptor()->getConfig(); + inputNum = getParentEdges().size(); + auto initDims = [this, config](size_t maxInputSize) { dims_in.resize(inputNum); for (int i = 0; i < inputNum; i++) { dims_in[i].resize(maxInputSize, 1); @@ -1232,9 +1255,7 @@ void MKLDNNEltwiseNode::createPrimitive() { } }; - auto initOffsets = [this](size_t maxInputSize) { - size_t inputNum = getParentEdges().size(); - + auto initOffsets = [this, config](size_t maxInputSize) { offsets_out.resize(maxInputSize, 1); offset_out_calc(offsets_out, dims_out); for (int j = 0; j < maxInputSize; j++) { @@ -1381,24 +1402,33 @@ void MKLDNNEltwiseNode::createPrimitive() { initOffsets(tensorRank); - const size_t inpuPortsCount = getSelectedPrimitiveDescriptor()->getConfig().inConfs.size(); + for (auto i = 0; i < inputNum; i++) + memPtrs.push_back(getParentEdgeAt(i)->getMemoryPtr()); + memPtrs.push_back(getChildEdgeAt(0)->getMemoryPtr()); - jep.inputs_number = inpuPortsCount; + if (!canUseOptimizedImpl) + return; + + jep.inputs_number = inputNum; jep.input_size = tensorRank; - for (int i = 0; i < inpuPortsCount; i++) { + for (int i = 0; i < inputNum; i++) { jep.src_size[i] = dims_in[i][dims_in[i].size() - 1]; jep.src_prc[i] = getParentEdgesAtPort(i).front()->getMemory().GetDesc().getPrecision(); } jep.dst_size = dims_out[dims_out.size() - 1]; jep.dst_prc = getChildEdgesAtPort(0).front()->getMemory().GetDesc().getPrecision(); - for (int i = 0; i < inpuPortsCount; i++) { - jep.src_offsets[i] = offsets_in[i]; - } - jep.dst_offsets = offsets_out; - jep.oc_size = oc_size; + jep.work_amount = dims_out.back(); + + jep.dims = dims_out; + for (size_t i = 0; i < inputNum; i++) + jep.src_offsets[i] = offsets_in[i]; + jep.dst_offsets = offsets_out; + jep.oc_offsets = offsets_oc; + std::transform(jep.oc_offsets.begin(), jep.oc_offsets.end(), jep.oc_offsets.begin(), + [](size_t& offset) { return offset * sizeof(float);}); if (mayiuse(x64::avx512_common)) { eltwise_kernel.reset(new jit_uni_eltwise_generic(jep, *this)); @@ -1452,42 +1482,27 @@ void MKLDNNEltwiseNode::offset_in_calc(std::vector& offset, std::vector< } } -void MKLDNNEltwiseNode::executeOptimized6D(const std::vector& src_ptrs, uint8_t *dst_ptr) { - size_t inputNum = src_ptrs.size(); - +void MKLDNNEltwiseNode::executeOptimized6D() { parallel_for5d(dims_out[0], dims_out[1], dims_out[2], dims_out[3], dims_out[4], [&](size_t i0, size_t i1, size_t i2, size_t i3, size_t i4) { - // TODO: reimplement initializer via jit approach - size_t index_in[MAX_ELTWISE_INPUTS] = {0}; - for (int i = 0; i < inputNum; i++) { - index_in[i] = i0 * offsets_in[i][0] + i1 * offsets_in[i][1] + i2 * offsets_in[i][2] + - i3 * offsets_in[i][3] + i4 * offsets_in[i][4]; - } - size_t index_out = i0 * offsets_out[0] + i1 * offsets_out[1] + i2 * offsets_out[2] + - i3 * offsets_out[3] + i4 * offsets_out[4]; + auto args = jit_eltwise_call_args_indexes(); + args.indexes[0] = i0; + args.indexes[1] = i1; + args.indexes[2] = i2; + args.indexes[3] = i3; + args.indexes[4] = i4; - auto arg = jit_eltwise_call_args(); - for (int i = 0; i < inputNum; i++) { - arg.src_ptr[i] = src_ptrs[i] + index_in[i]; - } - arg.dst = dst_ptr + index_out; - arg.work_amount = static_cast(dims_out[dims_out.size() - 1]); - arg.oc_off = (i0 * offsets_oc[0] + i1 * offsets_oc[1] + i2 * offsets_oc[2] + - i3 * offsets_oc[3] + i4 * offsets_oc[4]) * sizeof(float); - - (*eltwise_kernel)(&arg); + (*eltwise_kernel)(&args_ptrs, &args); }); } -void MKLDNNEltwiseNode::executeOptimizedGeneric(const std::vector& src_ptrs, uint8_t *dst_ptr) { - size_t inputNum = src_ptrs.size(); - +void MKLDNNEltwiseNode::executeOptimizedGeneric() { parallel_nt(0, [&](const int ithr, const int nthr) { size_t start = 0, end = 0; splitter(schedulerWorkAmount, nthr, ithr, start, end); std::vector counters(dims_out.size() - 1, 0); - + auto args = jit_eltwise_call_args_indexes(); for (size_t iwork = start; iwork < end; ++iwork) { size_t tmp = iwork; for (ptrdiff_t j = dims_out.size() - 2; j >= 0; j--) { @@ -1495,39 +1510,15 @@ void MKLDNNEltwiseNode::executeOptimizedGeneric(const std::vector(dims_out[dims_out.size() - 1]); - - arg.oc_off = 0; - for (int j = 0; j < counters.size(); j++) { - arg.oc_off += counters[j] * offsets_oc[j] * sizeof(float); - } - - (*eltwise_kernel)(&arg); + (*eltwise_kernel)(&args_ptrs, &args); } }); } -void MKLDNNEltwiseNode::executeReference(const std::vector& src_ptrs, uint8_t *dst_ptr) { - size_t inputNum = src_ptrs.size(); - +void MKLDNNEltwiseNode::executeReference() { std::shared_ptr ref_eltwise_injector = nullptr; if (getMKLDNNAlgorithm() != mkldnn::algorithm::undef) { ref_eltwise_injector = std::make_shared(static_cast(getMKLDNNAlgorithm()), alpha, beta, 1.f); @@ -1552,18 +1543,20 @@ void MKLDNNEltwiseNode::executeReference(const std::vector& src for (int j = 0; j < counters.size(); j++) { index_in[i] += counters[j] * offsets_in[i][j]; } + index_in[i] /= sizeof(float); } size_t index_out = 0; for (int j = 0; j < counters.size(); j++) { index_out += counters[j] * offsets_out[j]; } + index_out /= sizeof(float); std::vector src_f(inputNum); for (int i = 0; i < inputNum; i++) { - src_f[i] = reinterpret_cast(src_ptrs[i] + index_in[i])[0]; + src_f[i] = (reinterpret_cast(args_ptrs.src_ptr[i]) + index_in[i])[0]; } - float* dst_ptr_f = reinterpret_cast(dst_ptr + index_out); + float* dst_ptr_f = reinterpret_cast(args_ptrs.dst_ptr) + index_out; switch (getAlgorithm()) { case EltwiseRelu: case EltwiseGelu: case EltwiseElu: case EltwiseTanh: case EltwiseSigmoid: case EltwiseAbs: @@ -1593,6 +1586,7 @@ void MKLDNNEltwiseNode::executeReference(const std::vector& src case EltwiseLogicalNot: *dst_ptr_f = !src_f[0]; break; case EltwisePowerStatic: *dst_ptr_f = powf(beta * src_f[0] + gamma, alpha); break; case EltwisePrelu: *dst_ptr_f = src_f[0] > 0 ? src_f[0] : src_f[0] * src_f[1]; break; + case EltwiseErf: *dst_ptr_f = std::erf(src_f[0]); break; default: IE_THROW() << "Unsupported operation type for Eltwise node with name `" << getName() << "`"; } } @@ -1600,13 +1594,10 @@ void MKLDNNEltwiseNode::executeReference(const std::vector& src } void MKLDNNEltwiseNode::execute(mkldnn::stream strm) { - size_t inputNum = getParentEdges().size(); - std::vector src_ptrs(inputNum); - for (int i = 0; i < inputNum; i++) { - src_ptrs[i] = reinterpret_cast(getParentEdgeAt(i)->getMemory().GetData()) + start_offset_in[i]; - } - uint8_t *dst_ptr = reinterpret_cast(getChildEdgeAt(0)->getMemory().GetData()) + start_offset_out; + for (int i = 0; i < inputNum; i++) + args_ptrs.src_ptr[i] = reinterpret_cast(memPtrs[i]->GetData()) + start_offset_in[i]; + args_ptrs.dst_ptr = reinterpret_cast(memPtrs.back()->GetData()) + start_offset_out; // In general case we need to recompute offsets as well but currently all supported layout assumes batch to be outermost dimension if (isDynBatchEnabled) @@ -1614,12 +1605,12 @@ void MKLDNNEltwiseNode::execute(mkldnn::stream strm) { if (eltwise_kernel) { if (tensorRank == optimalTensorRank) { - executeOptimized6D(src_ptrs, dst_ptr); + executeOptimized6D(); } else { - executeOptimizedGeneric(src_ptrs, dst_ptr); + executeOptimizedGeneric(); } } else { - executeReference(src_ptrs, dst_ptr); + executeReference(); } } @@ -1727,7 +1718,7 @@ bool MKLDNNEltwiseNode::canFuse(const MKLDNNNodePtr& node) const { return true; }; - if (!mayiuse(x64::sse41)) + if (!mayiuse(x64::sse41) || inputShapes[0].getRank() > MAX_ELTWISE_DIM_RANK) return false; if (!isSuitableNode(this)) { @@ -1756,6 +1747,10 @@ bool MKLDNNEltwiseNode::canFuse(const MKLDNNNodePtr& node) const { } } + // We can use optimized execution with fusions only in cases when dim rank is less or equal to the maximum possible + if (node->getParentEdgesAtPort(0).front()->getShape().getRank() > MAX_ELTWISE_DIM_RANK) + return false; + return true; } diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_eltwise_node.h b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_eltwise_node.h index 34e95d45ae0..e1719be037f 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_eltwise_node.h +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_eltwise_node.h @@ -14,6 +14,7 @@ namespace MKLDNNPlugin { #define MAX_ELTWISE_INPUTS 7 +#define MAX_ELTWISE_DIM_RANK 12 struct jit_eltwise_params { size_t inputs_number; @@ -22,30 +23,35 @@ struct jit_eltwise_params { InferenceEngine::Precision src_prc[MAX_ELTWISE_INPUTS]; InferenceEngine::Precision dst_prc; + std::vector dims; std::vector src_offsets[MAX_ELTWISE_INPUTS]; std::vector dst_offsets; + std::vector oc_offsets; size_t src_size[MAX_ELTWISE_INPUTS]; size_t dst_size; size_t oc_size; -}; - -struct jit_eltwise_call_args { - const void *src_ptr[MAX_ELTWISE_INPUTS]; - void *dst; size_t work_amount; - size_t oc_off; +}; + +struct jit_eltwise_call_args_ptrs { + const void *src_ptr[MAX_ELTWISE_INPUTS]; + void *dst_ptr; +}; + +struct jit_eltwise_call_args_indexes { + size_t indexes[MAX_ELTWISE_DIM_RANK]; }; class MKLDNNEltwiseNode; struct jit_uni_eltwise_kernel { - void (*ker_)(const jit_eltwise_call_args *); + void (*ker_)(const jit_eltwise_call_args_ptrs*, const jit_eltwise_call_args_indexes*); - void operator()(const jit_eltwise_call_args *args) { + void operator()(const jit_eltwise_call_args_ptrs* const_args, const jit_eltwise_call_args_indexes* indexes) { assert(ker_); - ker_(args); + ker_(const_args, indexes); } explicit jit_uni_eltwise_kernel(jit_eltwise_params jep, MKLDNNEltwiseNode& node) : ker_(nullptr), jep_(jep), eltwiseNode(node) {} @@ -87,6 +93,7 @@ private: std::shared_ptr eltwise_kernel = nullptr; jit_eltwise_params jep = {}; + jit_eltwise_call_args_ptrs args_ptrs = {}; int optimalTensorRank = 6; bool canUseOptimizedImpl = false; @@ -96,6 +103,7 @@ private: size_t tensorRank = 0; size_t fullWorkAmount = 0; size_t schedulerWorkAmount = 0; + size_t inputNum = 0; std::vector> dims_in = {}; std::vector> offsets_in = {}; std::vector dims_out = {}; @@ -111,11 +119,13 @@ private: std::vector scales = {}; std::vector shifts = {}; + std::vector memPtrs = {}; + static std::map&, MKLDNNEltwiseNode& node)>> initializers; - inline void executeOptimized6D(const std::vector& src_ptrs, uint8_t *dst_ptr); - inline void executeOptimizedGeneric(const std::vector& src_ptrs, uint8_t *dst_ptr); - inline void executeReference(const std::vector& src_ptrs, uint8_t *dst_ptr); + inline void executeOptimized6D(); + inline void executeOptimizedGeneric(); + inline void executeReference(); void offset_out_calc(std::vector& offset, std::vector& dims); void offset_in_calc(std::vector& offset, std::vector& dims_in, std::vector& dims_out); diff --git a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/single_layer_tests/activation.cpp b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/single_layer_tests/activation.cpp index f78179275e2..78b536b5acf 100644 --- a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/single_layer_tests/activation.cpp +++ b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/single_layer_tests/activation.cpp @@ -88,7 +88,8 @@ const std::map>> activationParam std::map, std::vector>> basic = { {{1, 50}, {{}}}, - {{1, 128}, {{}}}, + {{5, 128}, {{}}}, + {{2, 2, 2, 2, 2, 2, 2, 2}, {{}}}, }; std::map, std::vector>> preluBasic = { @@ -100,6 +101,7 @@ std::map, std::vector>> preluBasic = { {{3, 2, 5}, {{1}, {2}, {5}, {2, 5}, {3, 1, 5}, {1, 2, 1}, {1, 1, 5}, {3, 1, 1}, {3, 2, 5}}}, {{2, 1, 2}, {{2}, {2, 1, 1}}}, {{3, 2, 5, 7}, {{1}, {7}, {2}, {5, 7}, {2, 5, 7}, {2, 1, 1}, {1, 2, 1, 1}, {3, 2, 1, 1}, {3, 2, 5, 7}}}, + {{2, 2, 2, 2, 2, 2, 2, 2}, {{2}, {2, 2}, {2, 1, 1, 2}}}, }; const auto basicCases = ::testing::Combine( From 194ae3495e4c2ee8b0e56dc9b2e1ffd5d5334215 Mon Sep 17 00:00:00 2001 From: Dmitrii Khurtin Date: Tue, 24 Aug 2021 10:30:47 +0300 Subject: [PATCH 14/76] [GNA] For similar records, the pattern length was increased to 4 in the algorithm for determining infinite cycles. (#7165) * for similar records, the pattern length was increased to 4 * Added comments --- .../gna_plugin/frontend/model_quantizer.hpp | 31 +++++++++++++++++-- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/inference-engine/src/gna_plugin/frontend/model_quantizer.hpp b/inference-engine/src/gna_plugin/frontend/model_quantizer.hpp index cd15b1c1b13..a2e638c9d75 100644 --- a/inference-engine/src/gna_plugin/frontend/model_quantizer.hpp +++ b/inference-engine/src/gna_plugin/frontend/model_quantizer.hpp @@ -115,7 +115,8 @@ class ModelQuantizer { } } - // looking for infinite loop by using algorithm of compute prefix function, complexity O(N) + // We are looking for infinite loop by using algorithm of compute prefix function, complexity O(N) + // (a part of the Knuth–Morris–Pratt algorithm). std::map prefixFunction; int k = infiniteLoopHistory.size(); for (int i = infiniteLoopHistory.size() - 2; i >= 0; i--) { @@ -128,12 +129,36 @@ class ModelQuantizer { k--; } - if ((infiniteLoopHistory.size() - i) % 2 == 0 && (infiniteLoopHistory.size() - i) / 2 == infiniteLoopHistory.size() - k) { + // The pattern length is a length of a repeating string sequence (it is 2 in the example below). + // concat_14_input_0_reshape#concat_15 + // concat_15_input_1_reshape#add_12 + // add_12#Add_16 + // Reshape_41#add_12 + // add_12#Add_16 + // Reshape_41#add_12 + // + // In the case of pattern length is 1, an infinite loop can be found on 2 consecutive strings. + // To avoid this, we will expect the appearance of 4 equal strings for the case pattern length is 1. + if ((infiniteLoopHistory.size() - i) % 2 == 0 && + (infiniteLoopHistory.size() - i) / 2 == infiniteLoopHistory.size() - k && + ((infiniteLoopHistory.size() - i) / 2 > 1 || + std::distance(infiniteLoopHistory.rbegin(), + std::find_if_not(infiniteLoopHistory.rbegin(), infiniteLoopHistory.rend(), + [&infiniteLoopHistory](const std::string& str) { return str == infiniteLoopHistory.back(); })) > 3)) { + gnalog() << "infiniteLoopPattern:\n"; + for (const auto& s : infiniteLoopPattern) { + gnalog() << "\t " << s << '\n'; + } infiniteLoopPattern.clear(); - int patternLength = (infiniteLoopHistory.size() - i)/2; + int patternLength = (infiniteLoopHistory.size() - i) / 2; + gnalog() << "patternLength: " << patternLength << '\n'; for (int j = 0; j < patternLength; j++) { infiniteLoopPattern.emplace_back(infiniteLoopHistory[infiniteLoopHistory.size() - patternLength + j]); } + gnalog() << "infiniteLoopHistory:\n"; + for (const auto& s : infiniteLoopHistory) { + gnalog() << "\t " << s << '\n'; + } infiniteLoopHistory.clear(); gnalog() << "infinite loop detected\n"; break; From 48460d3efb475126ae81ff9be190550fd1e9c97c Mon Sep 17 00:00:00 2001 From: Ivan Novoselov Date: Tue, 24 Aug 2021 10:50:07 +0300 Subject: [PATCH 15/76] [CPU] Enable direct copy implementation for u8->u8 reorder. (#7043) --- inference-engine/thirdparty/mkl-dnn | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inference-engine/thirdparty/mkl-dnn b/inference-engine/thirdparty/mkl-dnn index 7e4430d9398..aa5a4685377 160000 --- a/inference-engine/thirdparty/mkl-dnn +++ b/inference-engine/thirdparty/mkl-dnn @@ -1 +1 @@ -Subproject commit 7e4430d9398af63e94943815dace4b44f12ddbee +Subproject commit aa5a4685377992ae0733372c1568146872706670 From c69425a96a40b6c42c7c7174a94bda7b2136778f Mon Sep 17 00:00:00 2001 From: Aleksandr Pertovsky Date: Tue, 24 Aug 2021 10:58:10 +0300 Subject: [PATCH 16/76] [CPU] Fix not expected No-Preprocess Exception with RGB to BGR conversion (#6954) --- .../mkldnn_plugin/mkldnn_infer_request.cpp | 14 ++++---- .../include/behavior/set_preprocess.hpp | 34 +++++++++++++++++++ 2 files changed, 42 insertions(+), 6 deletions(-) diff --git a/inference-engine/src/mkldnn_plugin/mkldnn_infer_request.cpp b/inference-engine/src/mkldnn_plugin/mkldnn_infer_request.cpp index 77dbe3e1215..1ce31f3ecb8 100644 --- a/inference-engine/src/mkldnn_plugin/mkldnn_infer_request.cpp +++ b/inference-engine/src/mkldnn_plugin/mkldnn_infer_request.cpp @@ -247,12 +247,14 @@ InferenceEngine::Blob::Ptr MKLDNNPlugin::MKLDNNInferRequest::GetBlob(const std:: checkBlob(data, name, true); // check if preprocess required, but still wasn't set auto preProcessedInput = std::find_if(std::begin(_networkInputs), std::end(_networkInputs), - [&](const std::pair& pair) - {return pair.first == name;}); - if (preProcessedInput!= std::end(_networkInputs)) { - auto preProcess = preProcessedInput->second->getPreProcess(); - if (preProcess.getColorFormat() != InferenceEngine::ColorFormat::RAW || - preProcess.getResizeAlgorithm() != InferenceEngine::ResizeAlgorithm::NO_RESIZE) { + [&](const std::pair& pair) { + return pair.first == name; + }); + if (preProcessedInput != std::end(_networkInputs)) { + InferenceEngine::InputInfo::Ptr foundInput; + InferenceEngine::DataPtr foundOutput; + findInputAndOutputBlobByName(name, foundInput, foundOutput); + if (preProcessingRequired(foundInput, data)) { _preProcData.emplace(name, InferenceEngine::CreatePreprocDataHelper()); _preProcData[name]->isApplicable(data, _inputs[name]); _preProcData[name]->setRoiBlob(data); diff --git a/inference-engine/tests/functional/plugin/shared/include/behavior/set_preprocess.hpp b/inference-engine/tests/functional/plugin/shared/include/behavior/set_preprocess.hpp index ff294866858..a3a53f160ed 100644 --- a/inference-engine/tests/functional/plugin/shared/include/behavior/set_preprocess.hpp +++ b/inference-engine/tests/functional/plugin/shared/include/behavior/set_preprocess.hpp @@ -992,4 +992,38 @@ TEST_P(PreprocessDynamicallyInSetBlobTest, Infer) { } } +TEST_P(PreprocessTest, InferWithRGB2BGRConversion) { + // Skip test according to plugin specific disabledTestPatterns() (if any) + SKIP_IF_CURRENT_TEST_IS_DISABLED() + std::shared_ptr ngraphFunc; + const unsigned int shape_size = 9, channels = 3, batch = 1; + { + ngraph::PartialShape shape({batch, channels, shape_size, shape_size}); + ngraph::element::Type type(InferenceEngine::details::convertPrecision(netPrecision)); + auto param = std::make_shared(type, shape); + param->set_friendly_name("param"); + auto relu = std::make_shared(param); + relu->set_friendly_name("relu"); + auto result = std::make_shared(relu); + result->set_friendly_name("result"); + + ngraph::ParameterVector params = {param}; + ngraph::ResultVector results = {result}; + + ngraphFunc = std::make_shared(results, params); + } + + // Create CNNNetwork from ngraph::Function + InferenceEngine::CNNNetwork cnnNet(ngraphFunc); + + auto &preProcess = cnnNet.getInputsInfo().begin()->second->getPreProcess(); + preProcess.setColorFormat(InferenceEngine::ColorFormat::BGR); + // Load CNNNetwork to target plugins + auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); + // Create InferRequest + auto req = execNet.CreateInferRequest(); + + ASSERT_NO_THROW(req.Infer()); +} + } // namespace BehaviorTestsDefinitions From de46168e98e0469a2a4bbd257bc577ae3ccf2165 Mon Sep 17 00:00:00 2001 From: Nikolay Shchegolev Date: Tue, 24 Aug 2021 12:28:23 +0300 Subject: [PATCH 17/76] [CPU] Avoid inserting additional transpose + reorder after RNN node. (#5921) --- .../mkldnn_plugin/mkldnn_graph_optimizer.cpp | 49 ++++++++++++++++++- .../mkldnn_plugin/mkldnn_graph_optimizer.h | 1 + .../rnn_sequences_optimization.cpp | 25 ++-------- .../nodes/mkldnn_reshape_node.cpp | 9 ++++ .../mkldnn_plugin/nodes/mkldnn_reshape_node.h | 6 +++ .../src/mkldnn_plugin/nodes/mkldnn_rnn.cpp | 9 +++- .../src/mkldnn_plugin/nodes/mkldnn_rnn.h | 4 ++ .../cpu/single_layer_tests/gru_sequence.cpp | 11 ++--- .../cpu/single_layer_tests/lstm_sequence.cpp | 11 ++--- .../cpu/single_layer_tests/rnn_sequence.cpp | 4 +- .../plugin/cpu/test_utils/cpu_test_utils.cpp | 16 +++++- 11 files changed, 102 insertions(+), 43 deletions(-) diff --git a/inference-engine/src/mkldnn_plugin/mkldnn_graph_optimizer.cpp b/inference-engine/src/mkldnn_plugin/mkldnn_graph_optimizer.cpp index 0cad8e15e3b..c450fc63ece 100644 --- a/inference-engine/src/mkldnn_plugin/mkldnn_graph_optimizer.cpp +++ b/inference-engine/src/mkldnn_plugin/mkldnn_graph_optimizer.cpp @@ -17,6 +17,7 @@ #include #include "nodes/mkldnn_interpolate_node.h" #include "nodes/mkldnn_input_node.h" +#include "nodes/mkldnn_rnn.h" #include "nodes/common/cpu_convert.h" #include "mkldnn/ie_mkldnn.h" @@ -132,6 +133,10 @@ void MKLDNNGraphOptimizer::ApplyCommonGraphOptimizations(MKLDNNGraph &graph) { FuseEltwiseAndSimple(graph); graph.RemoveDroppedNodes(); + OV_ITT_SCOPE_NEXT(FIRST_INFERENCE, taskChain, "reshapeRnnSeq"); + reshapeRnnSeq(graph); + graph.RemoveDroppedNodes(); + OV_ITT_SCOPE_NEXT(FIRST_INFERENCE, taskChain, "RemoveDroppedEdges"); graph.RemoveDroppedEdges(); } @@ -973,7 +978,7 @@ static bool is_data_dependency(const std::shared_ptr &parent, */ void MKLDNNGraphOptimizer::FuseConvolutionSumAndConvolutionSumActivation(MKLDNNGraph &graph) { - std::vector &graphNodes = graph.GetNodes(); + auto &graphNodes = graph.GetNodes(); auto isFusingSupported = [&](MKLDNNNodePtr conv, MKLDNNNodePtr child) { return child->getType() == Eltwise && @@ -1444,7 +1449,7 @@ void MKLDNNGraphOptimizer::DropDoubleReorders(MKLDNNGraph &graph) { } void MKLDNNGraphOptimizer::FuseBroadcastAndEltwise(MKLDNNGraph &graph) { - std::vector& graphNodes = graph.GetNodes(); + auto& graphNodes = graph.GetNodes(); for (auto &graphNode : graphNodes) { if (graphNode->getType() != Generic @@ -1816,3 +1821,43 @@ void MKLDNNGraphOptimizer::MergeTransposeAndReorder(MKLDNNGraph &graph) { } } } + +void MKLDNNGraphOptimizer::reshapeRnnSeq(MKLDNNGraph &graph) { + auto& graphNodes = graph.GetNodes(); + + auto isSutableParentNode = [](MKLDNNNodePtr node) { + if (node->type != RNNSeq) + return false; + auto rnnNode = std::dynamic_pointer_cast(node); + return rnnNode && !rnnNode->hasNativeOrder() && node->outputShapes[0].getRank() == 4 && node->outputShapes[0].getDims()[1] == 1; + }; + + for (int i = 0; i < graphNodes.size(); i++) { + auto& parentNode = graphNodes[i]; + if (!isSutableParentNode(parentNode)) { + continue; + } + + auto childrenEdges = parentNode->getChildEdgesAtPort(0); + auto newRnnOutDims = parentNode->outputShapes[0].getDims(); + newRnnOutDims.erase(newRnnOutDims.begin() + 1); + parentNode->outputShapes[0] = Shape{newRnnOutDims}; + + for (size_t i = 0; i < childrenEdges.size(); i++) { + auto edge = childrenEdges[i]; + auto childNode = edge->getChild(); + + const MKLDNNNodePtr newReshape = std::make_shared( + parentNode->getName() + "_abc_a1bc_" + std::to_string(i), + parentNode->outputShapes[0], + childNode->inputShapes[edge->getOutputNum()], + parentNode->getOriginalOutputPrecisionAtPort(0), + graph.getEngine(), graph.weightsCache); + + graph.InsertNode(parentNode, childNode, newReshape, edge->getInputNum(), edge->getOutputNum(), false); + + edge->drop(); + graph.RemoveEdge(edge); + } + } +} diff --git a/inference-engine/src/mkldnn_plugin/mkldnn_graph_optimizer.h b/inference-engine/src/mkldnn_plugin/mkldnn_graph_optimizer.h index cd263547750..a28f7c73431 100644 --- a/inference-engine/src/mkldnn_plugin/mkldnn_graph_optimizer.h +++ b/inference-engine/src/mkldnn_plugin/mkldnn_graph_optimizer.h @@ -39,6 +39,7 @@ private: void FusePerformedAsScaleShiftAndFakeQuantize(MKLDNNGraph &graph); void FuseClampAndFakeQuantize(MKLDNNGraph &graph); void MergeTransposeAndReorder(MKLDNNGraph &graph); + void reshapeRnnSeq(MKLDNNGraph &graph); }; } // namespace MKLDNNPlugin diff --git a/inference-engine/src/mkldnn_plugin/ngraph_transformations/rnn_sequences_optimization.cpp b/inference-engine/src/mkldnn_plugin/ngraph_transformations/rnn_sequences_optimization.cpp index 196af3640bd..0b81fdcc81e 100644 --- a/inference-engine/src/mkldnn_plugin/ngraph_transformations/rnn_sequences_optimization.cpp +++ b/inference-engine/src/mkldnn_plugin/ngraph_transformations/rnn_sequences_optimization.cpp @@ -56,34 +56,15 @@ namespace { auto reshape1 = std::make_shared(in_0, newInShape, false); ngraph::replace_node(sequenceOp->get_input_node_shared_ptr(0), {reshape1->output(0)}); - const auto &gruTargetInputs = sequenceOp->output(0).get_target_inputs(); - if (gruTargetInputs.empty()) + const auto &seqTargetInputs = sequenceOp->output(0).get_target_inputs(); + if (seqTargetInputs.empty()) return false; - auto transposeAfter = gruTargetInputs.begin()->get_node()->shared_from_this(); + auto transposeAfter = seqTargetInputs.begin()->get_node()->shared_from_this(); auto newOutShape = ngraph::op::v0::Constant::create(ngraph::element::i32, ngraph::Shape{4}, transposeAfter->get_output_shape(0)); auto reshape2 = std::make_shared(sequenceOp->output(0), newOutShape, false); reshape2->set_friendly_name(transposeAfter->get_friendly_name()); ngraph::replace_node(transposeAfter, {reshape2->output(0)}); - } else { - auto originShape = sequenceOp->get_output_shape(0); - const auto targetInputs = sequenceOp->get_output_target_inputs(0); - if (targetInputs.empty()) { - return false; - } - auto seqOut = targetInputs.begin()->get_node()->shared_from_this(); - - auto tncShape = ngraph::op::v0::Constant::create(ngraph::element::i32, ngraph::Shape{3}, {originShape[2], originShape[0], originShape[3]}); - auto reshape1 = std::make_shared(sequenceOp->output(0), tncShape, false); - - auto order = ngraph::op::v0::Constant::create(ngraph::element::i32, ngraph::Shape{3}, {1, 0, 2}); - auto transpose = std::make_shared(reshape1->output(0), order); - - auto ndtcShape = ngraph::op::v0::Constant::create(ngraph::element::i32, ngraph::Shape{4}, originShape); - auto reshape2 = std::make_shared(transpose->output(0), ndtcShape, false); - reshape2->set_friendly_name(sequenceOp->get_friendly_name()+".0"); - - ngraph::insert_new_node_between(sequenceOp, seqOut, reshape2); } sequenceOp->get_rt_info()["seqAxis"] = std::make_shared>(seqAxis); diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_reshape_node.cpp b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_reshape_node.cpp index 81175dcaf41..f4256042379 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_reshape_node.cpp +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_reshape_node.cpp @@ -14,6 +14,15 @@ using namespace InferenceEngine; MKLDNNReshapeNode::MKLDNNReshapeNode(const std::shared_ptr& op, const mkldnn::engine& eng, MKLDNNWeightsSharing::Ptr &cache) : MKLDNNNode(op, eng, cache) {} +MKLDNNReshapeNode::MKLDNNReshapeNode(const std::string& name, const Shape& inDims, const Shape& outDims, Precision precision, + const mkldnn::engine& eng, MKLDNNWeightsSharing::Ptr &wCache) + : MKLDNNNode("Reshape", name, eng, wCache) { + this->inputShapes.push_back(inDims); + this->outputShapes.push_back(outDims); + addOriginalInputPrecision(precision); + addOriginalOutputPrecision(precision); +} + void MKLDNNReshapeNode::getSupportedDescriptors() { if (getParentEdges().size() != 1 && getParentEdges().size() != 2) IE_THROW() << "Incorrect number of input edges for layer " << getName(); diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_reshape_node.h b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_reshape_node.h index fcd44b3ba03..cf88872f195 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_reshape_node.h +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_reshape_node.h @@ -15,6 +15,12 @@ namespace MKLDNNPlugin { class MKLDNNReshapeNode : public MKLDNNNode { public: MKLDNNReshapeNode(const std::shared_ptr& op, const mkldnn::engine& eng, MKLDNNWeightsSharing::Ptr &cache); + MKLDNNReshapeNode(const std::string& name, + const Shape& inDims, + const Shape& outDims, + InferenceEngine::Precision precision, + const mkldnn::engine& eng, + MKLDNNWeightsSharing::Ptr &wCache); void getSupportedDescriptors() override; void initSupportedPrimitiveDescriptors() override; diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_rnn.cpp b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_rnn.cpp index 91201da8592..6e9086274d5 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_rnn.cpp +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_rnn.cpp @@ -412,6 +412,9 @@ void MKLDNNRNN::fillSeqDesc() { if (nativeOrder) in_candidate.emplace_back(inputShapes[RNNInOutKind::Layer].getStaticDims(), dataType, memory::format_tag::tnc); + else if (N == 1) + // WA to avoid reorder before sequence for some models + in_candidate.emplace_back(std::vector{N, T, DC}, dataType, memory::format_tag::tnc); else in_candidate.emplace_back(std::vector{N, T, DC}, dataType, memory::format_tag::ntc); @@ -428,9 +431,11 @@ void MKLDNNRNN::fillSeqDesc() { if (nativeOrder) { out_candidate.emplace_back(out_data_d[RNNInOutKind::Layer]); + } else if (N == 1) { + // WA to avoid reorder after sequence for some models + out_candidate.emplace_back(std::vector{N, T, SC}, dataType, memory::format_tag::tnc); } else { - // TODO reorder ntc -> ndtc does not work, thus use tnc(plain) + transformation reshape-transpose-reshape for now. - out_candidate.emplace_back(std::vector{T, N, SC}, dataType, memory::format_tag::tnc); + out_candidate.emplace_back(std::vector{N, T, SC}, dataType, memory::format_tag::ntc); } out_candidate.emplace_back(std::vector{N, D, SC}, dataType, memory::format_tag::ntc); diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_rnn.h b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_rnn.h index 0a2bd93d3d9..9e47637235f 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_rnn.h +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_rnn.h @@ -24,6 +24,10 @@ public: void execute(mkldnn::stream strm) override; + inline bool hasNativeOrder() const { + return nativeOrder; + } + private: void initCell(const std::shared_ptr& op); void initSeq(const std::shared_ptr& op); diff --git a/inference-engine/tests/functional/plugin/cpu/single_layer_tests/gru_sequence.cpp b/inference-engine/tests/functional/plugin/cpu/single_layer_tests/gru_sequence.cpp index b34136facf9..a7b6163af45 100644 --- a/inference-engine/tests/functional/plugin/cpu/single_layer_tests/gru_sequence.cpp +++ b/inference-engine/tests/functional/plugin/cpu/single_layer_tests/gru_sequence.cpp @@ -115,13 +115,10 @@ protected: // returned output format always tnc if (ngraph::shape_size(gru_sequence->get_output_shape(0)) == 1) { outFmts[0] = tnc; - } else if (ngraph::shape_size(gru_sequence->get_output_shape(1)) == 1) { + } else if (ngraph::shape_size(gru_sequence->get_output_shape(1)) == 1 || + gru_sequence->get_output_shape(0)[0] == 1) { outFmts[1] = tnc; } - // if output format equals for all outputs, runtime info return only one formats - if (outFmts[0] == outFmts[1]) { - outFmts.erase(outFmts.begin()); - } ngraph::ResultVector results{std::make_shared(gru_sequence->output(0)), std::make_shared(gru_sequence->output(1))}; @@ -170,8 +167,8 @@ namespace { std::vector> additionalConfig = {{{PluginConfigParams::KEY_ENFORCE_BF16, PluginConfigParams::NO}}, {{PluginConfigParams::KEY_ENFORCE_BF16, PluginConfigParams::YES}}}; -CPUSpecificParams cpuParams{{ntc, ntc}, {tnc, ntc}, {"ref_any"}, "ref_any"}; -CPUSpecificParams cpuParamsBatchSizeOne{{ntc, ntc}, {tnc, ntc}, {"ref_any"}, "ref_any"};; +CPUSpecificParams cpuParams{{ntc, ntc}, {ntc, ntc}, {"ref_any"}, "ref_any"}; +CPUSpecificParams cpuParamsBatchSizeOne{{tnc, ntc}, {tnc, ntc}, {"ref_any"}, "ref_any"};; std::vector mode{ngraph::helpers::SequenceTestsMode::PURE_SEQ}; // output values increase rapidly without clip, so use only seq_lengths = 2 diff --git a/inference-engine/tests/functional/plugin/cpu/single_layer_tests/lstm_sequence.cpp b/inference-engine/tests/functional/plugin/cpu/single_layer_tests/lstm_sequence.cpp index 47453bde9ee..044a70f820b 100644 --- a/inference-engine/tests/functional/plugin/cpu/single_layer_tests/lstm_sequence.cpp +++ b/inference-engine/tests/functional/plugin/cpu/single_layer_tests/lstm_sequence.cpp @@ -119,15 +119,12 @@ protected: // returned output format always tnc if (outFmts.size() >= 3) { for (size_t i = 1; i < 3; i++) { - if (ngraph::shape_size(lstm_sequence->get_output_shape(i)) == 1) { + if (ngraph::shape_size(lstm_sequence->get_output_shape(i)) == 1 || + lstm_sequence->get_output_shape(0) == ngraph::Shape{1, 1, 2, 10}) { outFmts[i] = tnc; } } } - // if output format equals for all outputs, runtime info return only one formats - if (std::adjacent_find(outFmts.begin(), outFmts.end(), std::not_equal_to()) == outFmts.end()) { - outFmts.resize(1); - } ngraph::ResultVector results{std::make_shared(lstm_sequence->output(0)), std::make_shared(lstm_sequence->output(1)), @@ -179,8 +176,8 @@ std::vector> additionalConfig = {{{PluginConfigParams::KEY_ENFORCE_BF16, PluginConfigParams::NO}}, {{PluginConfigParams::KEY_ENFORCE_BF16, PluginConfigParams::YES}}}; -CPUSpecificParams cpuParams{{ntc, ntc, ntc}, {tnc, ntc, ntc}, {"ref_any"}, "ref_any"}; -CPUSpecificParams cpuParamsBatchSizeOne{{ntc, ntc, ntc}, {tnc, ntc, ntc}, {"ref_any"}, "ref_any"}; +CPUSpecificParams cpuParams{{ntc, ntc, ntc}, {ntc, ntc, ntc}, {"ref_any"}, "ref_any"}; +CPUSpecificParams cpuParamsBatchSizeOne{{tnc, ntc, ntc}, {tnc, ntc, ntc}, {"ref_any"}, "ref_any"}; std::vector mode{ngraph::helpers::SequenceTestsMode::PURE_SEQ}; std::vector seq_lengths_zero_clip{2}; diff --git a/inference-engine/tests/functional/plugin/cpu/single_layer_tests/rnn_sequence.cpp b/inference-engine/tests/functional/plugin/cpu/single_layer_tests/rnn_sequence.cpp index f2030fe8c0e..f70eace878c 100644 --- a/inference-engine/tests/functional/plugin/cpu/single_layer_tests/rnn_sequence.cpp +++ b/inference-engine/tests/functional/plugin/cpu/single_layer_tests/rnn_sequence.cpp @@ -148,8 +148,8 @@ namespace { std::vector> additionalConfig = {{{PluginConfigParams::KEY_ENFORCE_BF16, PluginConfigParams::NO}}, {{PluginConfigParams::KEY_ENFORCE_BF16, PluginConfigParams::YES}}}; -CPUSpecificParams cpuParams{{ntc, ntc}, {tnc, ntc}, {"ref_any"}, "ref_any"}; -CPUSpecificParams cpuParamsBatchSizeOne{{ntc, ntc}, {tnc, ntc}, {"ref_any"}, "ref_any"}; +CPUSpecificParams cpuParams{{ntc, ntc}, {ntc, ntc}, {"ref_any"}, "ref_any"}; +CPUSpecificParams cpuParamsBatchSizeOne{{tnc, ntc}, {tnc, tnc}, {"ref_any"}, "ref_any"}; std::vector mode{ngraph::helpers::SequenceTestsMode::PURE_SEQ}; // output values increase rapidly without clip, so use only seq_lengths = 2 diff --git a/inference-engine/tests/functional/plugin/cpu/test_utils/cpu_test_utils.cpp b/inference-engine/tests/functional/plugin/cpu/test_utils/cpu_test_utils.cpp index 39bae3546ee..dba15ff1d48 100644 --- a/inference-engine/tests/functional/plugin/cpu/test_utils/cpu_test_utils.cpp +++ b/inference-engine/tests/functional/plugin/cpu/test_utils/cpu_test_utils.cpp @@ -176,7 +176,21 @@ void CPUTestsBase::CheckPluginRelatedResults(InferenceEngine::ExecutableNetwork auto actualOutputMemoryFormats = getActualOutputMemoryFormats(getExecValueOutputsLayout(node)); - for (size_t i = 0; i < outFmts.size(); i++) { + bool isAllEqual = true; + for (size_t i = 1; i < outFmts.size(); i++) { + if (outFmts[i - 1] != outFmts[i]) { + isAllEqual = false; + break; + } + } + size_t fmtsNum = outFmts.size(); + if (isAllEqual) { + fmtsNum = fmtsNum == 0 ? 0 : 1; + } else { + ASSERT_EQ(fmtsNum, actualOutputMemoryFormats.size()); + } + + for (size_t i = 0; i < fmtsNum; i++) { const auto actualOutputMemoryFormat = getExecValue(ExecGraphInfoSerialization::OUTPUT_LAYOUTS); const auto shape = node->get_output_shape(i); From 14dcd43c3209973b07f6030b203bd8013f049009 Mon Sep 17 00:00:00 2001 From: Yegor Kruglov Date: Tue, 24 Aug 2021 13:19:40 +0300 Subject: [PATCH 18/76] [MO] Replacing StridedSlice with Squeeze/Unsqueeze (#6693) * added reinterp_shape parameter to tf ss extractor * removed reinterp_shape * added transformation to replace ss * updated bom * fix for e2e tests * updated a case when shrink_axis_mask and new_axis_mask are both initialized * unittests * added comments * updated graph_condition * comments resolving * updated the case, when shrink_axis_mask and new_axis_mask are both initialized * added layer tests for squeeze/unsqueeze cases * remove case when shrink and new axis masks are both set --- model-optimizer/automation/package_BOM.txt | 1 + .../extensions/middle/StridedSliceReplacer.py | 64 +++++++++++ .../middle/StridedSliceReplacer_test.py | 108 ++++++++++++++++++ .../tensorflow_tests/test_tf_StridedSlice.py | 90 +++++++++++++++ 4 files changed, 263 insertions(+) create mode 100644 model-optimizer/extensions/middle/StridedSliceReplacer.py create mode 100644 model-optimizer/unit_tests/extensions/middle/StridedSliceReplacer_test.py create mode 100644 tests/layer_tests/tensorflow_tests/test_tf_StridedSlice.py diff --git a/model-optimizer/automation/package_BOM.txt b/model-optimizer/automation/package_BOM.txt index 7ab49918925..50c5dadb498 100644 --- a/model-optimizer/automation/package_BOM.txt +++ b/model-optimizer/automation/package_BOM.txt @@ -640,6 +640,7 @@ extensions/middle/sparse_reshape.py extensions/middle/split_tdnn_memoryoffset.py extensions/middle/SplitConcatPairToInterpolate.py extensions/middle/StridedSliceNormalizer.py +extensions/middle/StridedSliceReplacer.py extensions/middle/SwapAxesMiddleReplacer.py extensions/middle/TensorIterator_utils.py extensions/middle/TensorIteratorBackEdge.py diff --git a/model-optimizer/extensions/middle/StridedSliceReplacer.py b/model-optimizer/extensions/middle/StridedSliceReplacer.py new file mode 100644 index 00000000000..4dd26baac18 --- /dev/null +++ b/model-optimizer/extensions/middle/StridedSliceReplacer.py @@ -0,0 +1,64 @@ +# Copyright (C) 2018-2021 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 + +import numpy as np + +from extensions.middle.InsertLayoutPropagationTransposes import InsertLayoutPropagationTranspose +from extensions.middle.StridedSliceNormalizer import StridedSliceNormalizer +from mo.front.common.partial_infer.utils import int64_array +from mo.front.tf.graph_utils import create_op_node_with_second_input +from mo.graph.graph import Graph, rename_nodes, Node +from mo.middle.replacement import MiddleReplacementPattern +from mo.ops.squeeze import Squeeze +from mo.ops.unsqueeze import Unsqueeze + + +def replace_strided_slice(node: Node, mask: np.ndarray, op: callable): + node_name = node.soft_get('name', node.id) + axes = np.where(mask == 1)[0] + new_node = create_op_node_with_second_input(node.graph, op, int64_array(axes)) + node.in_port(0).get_connection().set_destination(new_node.in_port(0)) + node.out_port(0).get_connection().set_source(new_node.out_port(0)) + + rename_nodes([(node, node_name + '/ShouldBeDeleted'), (new_node, node_name)]) + node.graph.remove_node(node.id) + + +class ReplaceStridedSliceWithSqueezeUnsqueeze(MiddleReplacementPattern): + r""" + The transformation replaces StridedSlice with a Squeeze/Unsqueeze node if StridedSlice executes like a Squeeze/Unsqueeze + and does not slice values. This is necessary if StridedSlice is to be executed in original N(D)HWC layout, because + the operation does not have reinterp_shape attribute and MO can not insert NC(D)HW -> N(D)HWC Transpose in + extensions/middle/InsertLayoutPropagationTransposes.py. + """ + enabled = True + + graph_condition = [lambda graph: graph.graph['layout'] == 'NHWC'] + + def run_before(self): + return [InsertLayoutPropagationTranspose] + + def run_after(self): + return [StridedSliceNormalizer] + + def find_and_replace_pattern(self, graph: Graph): + for node in graph.get_op_nodes(op='StridedSlice'): + input_shape = node.in_port(0).data.get_shape() + output_shape = node.out_port(0).data.get_shape() + + if np.prod(input_shape) != np.prod(output_shape): + continue + + shrink_axis_mask = node.soft_get('shrink_axis_mask', np.zeros(len(input_shape))) + new_axis_mask = node.soft_get('new_axis_mask', np.zeros(len(input_shape))) + + is_shrink_axis_mask = any(x == 1 for x in shrink_axis_mask) + is_new_axis_mask = any(x == 1 for x in new_axis_mask) + + if is_shrink_axis_mask and is_new_axis_mask: + # TODO: make it in a separate ticket + continue + elif is_shrink_axis_mask and not is_new_axis_mask: + replace_strided_slice(node, shrink_axis_mask, Squeeze) + elif not is_shrink_axis_mask and is_new_axis_mask: + replace_strided_slice(node, new_axis_mask, Unsqueeze) diff --git a/model-optimizer/unit_tests/extensions/middle/StridedSliceReplacer_test.py b/model-optimizer/unit_tests/extensions/middle/StridedSliceReplacer_test.py new file mode 100644 index 00000000000..917fd923deb --- /dev/null +++ b/model-optimizer/unit_tests/extensions/middle/StridedSliceReplacer_test.py @@ -0,0 +1,108 @@ +# Copyright (C) 2018-2021 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 + +import unittest + +from extensions.middle.StridedSliceReplacer import ReplaceStridedSliceWithSqueezeUnsqueeze +from mo.utils.ir_engine.compare_graphs import compare_graphs +from unit_tests.utils.graph import regular_op_with_shaped_data, regular_op_with_empty_data, shaped_const_with_data, \ + result, connect, build_graph + +nodes = { + **regular_op_with_shaped_data('input', [1, 3, 5, 5], {'type': 'Parameter', 'op': 'Parameter'}), + **regular_op_with_empty_data('strided_slice', {'type': 'StridedSlice', 'op': 'StridedSlice', + 'begin_mask': [0, 0, 0, 0], 'end_mask': [0, 0, 0, 0]}), + **shaped_const_with_data('begin', [4]), + **shaped_const_with_data('end', [4]), + **result('result'), + + **regular_op_with_empty_data('squeeze', {'type': 'Squeeze', 'op': 'Squeeze'}), + **shaped_const_with_data('squeeze_axes', None), + + **regular_op_with_empty_data('unsqueeze', {'type': 'Unsqueeze', 'op': 'Unsqueeze'}), + **shaped_const_with_data('unsqueeze_axes', None) +} + +pattern_edges = [ + *connect('input', '0:strided_slice'), + *connect('begin', '1:strided_slice'), + *connect('end', '2:strided_slice'), + *connect('strided_slice', 'result') +] + + +class TestStridedSliceReplacer(unittest.TestCase): + + def test_negative_different_input_and_output_shapes(self): + graph = build_graph( + nodes_attrs=nodes, + edges=pattern_edges, + update_attributes={ + 'strided_slice_d': {'shape': [1, 3, 3, 3]} + }, + nodes_with_edges_only=True + ) + + ref_graph = graph.copy() + + ReplaceStridedSliceWithSqueezeUnsqueeze().find_and_replace_pattern(graph) + (flag, resp) = compare_graphs(graph, ref_graph, 'result', check_op_attrs=True) + self.assertTrue(flag, resp) + + def test_replace_with_squeeze(self): + graph = build_graph( + nodes_attrs=nodes, + edges=pattern_edges, + update_attributes={ + 'strided_slice': {'shrink_axis_mask': [1, 0, 0, 0], 'new_axis_mask': [0, 0, 0, 0]}, + 'strided_slice_d': {'shape': [3, 5, 5]} + }, + nodes_with_edges_only=True + ) + + ref_graph = build_graph( + nodes_attrs=nodes, + edges=[ + *connect('input', '0:squeeze'), + *connect('squeeze_axes', '1:squeeze'), + *connect('squeeze', 'result') + ], + update_attributes={ + 'squeeze_axes_d': {'value': [0]}, + 'squeeze_d': {'shape': [3, 5, 5]} + }, + nodes_with_edges_only=True + ) + + ReplaceStridedSliceWithSqueezeUnsqueeze().find_and_replace_pattern(graph) + (flag, resp) = compare_graphs(graph, ref_graph, 'result', check_op_attrs=True) + self.assertTrue(flag, resp) + + def test_replace_with_unsqueeze(self): + graph = build_graph( + nodes_attrs=nodes, + edges=pattern_edges, + update_attributes={ + 'strided_slice': {'shrink_axis_mask': [0, 0, 0, 0], 'new_axis_mask': [1, 0, 0, 0]}, + 'strided_slice_d': {'shape': [1, 1, 3, 5, 5]} + }, + nodes_with_edges_only=True + ) + + ref_graph = build_graph( + nodes_attrs=nodes, + edges=[ + *connect('input', '0:unsqueeze'), + *connect('unsqueeze_axes', '1:unsqueeze'), + *connect('unsqueeze', 'result') + ], + update_attributes={ + 'unsqueeze_axes_d': {'value': [0]}, + 'unsqueeze_d': {'shape': [1, 1, 3, 5, 5]} + }, + nodes_with_edges_only=True + ) + + ReplaceStridedSliceWithSqueezeUnsqueeze().find_and_replace_pattern(graph) + (flag, resp) = compare_graphs(graph, ref_graph, 'result', check_op_attrs=True) + self.assertTrue(flag, resp) diff --git a/tests/layer_tests/tensorflow_tests/test_tf_StridedSlice.py b/tests/layer_tests/tensorflow_tests/test_tf_StridedSlice.py new file mode 100644 index 00000000000..d03994c7052 --- /dev/null +++ b/tests/layer_tests/tensorflow_tests/test_tf_StridedSlice.py @@ -0,0 +1,90 @@ +# Copyright (C) 2018-2021 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 + +import pytest + +from common.tf_layer_test_class import CommonTFLayerTest + + +class TestStridedSlice(CommonTFLayerTest): + + @staticmethod + def create_strided_slice_net(input_shape, begin, end, strides, begin_mask, end_mask, ellipsis_mask, + new_axis_mask, shrink_axis_mask, ir_version): + + # + # Create Tensorflow model + # + import tensorflow as tf + + tf.compat.v1.reset_default_graph() + + with tf.compat.v1.Session() as sess: + input_node = tf.compat.v1.placeholder(tf.float32, input_shape, 'Input') + strided_slice = tf.compat.v1.strided_slice(input_node, begin=begin, end=end, strides=strides, + begin_mask=begin_mask, end_mask=end_mask, + ellipsis_mask=ellipsis_mask, new_axis_mask=new_axis_mask, + shrink_axis_mask=shrink_axis_mask) + tf.compat.v1.global_variables_initializer() + tf_net = sess.graph_def + + ref_net = None + return tf_net, ref_net + + test_squeeze_data = [ + dict(input_shape=[1, 5], begin=[0, 0], end=[1, 5], strides=[1, 1], begin_mask=0, + end_mask=0, ellipsis_mask=0, new_axis_mask=0, shrink_axis_mask=1), + dict(input_shape=[5, 1], begin=[0, 0], end=[5, 1], strides=[1, 1], begin_mask=0, + end_mask=0, ellipsis_mask=0, new_axis_mask=0, shrink_axis_mask=2), + dict(input_shape=[1, 5, 3], begin=[0, 0, 0], end=[1, 5, 3], strides=[1, 1, 1], begin_mask=0, + end_mask=0, ellipsis_mask=0, new_axis_mask=0, shrink_axis_mask=1), + dict(input_shape=[1, 1, 3], begin=[0, 0, 0], end=[1, 1, 3], strides=[1, 1, 1], begin_mask=0, + end_mask=0, ellipsis_mask=0, new_axis_mask=0, shrink_axis_mask=2), + dict(input_shape=[1, 5, 1], begin=[0, 0, 0], end=[1, 5, 1], strides=[1, 1, 1], begin_mask=0, + end_mask=0, ellipsis_mask=0, new_axis_mask=0, shrink_axis_mask=4), + dict(input_shape=[1, 5, 5, 3], begin=[0, 0, 0, 0], end=[1, 5, 5, 3], strides=[1, 1, 1, 1], begin_mask=0, + end_mask=0, ellipsis_mask=0, new_axis_mask=0, shrink_axis_mask=1), + dict(input_shape=[1, 1, 5, 3], begin=[0, 0, 0, 0], end=[1, 1, 5, 3], strides=[1, 1, 1, 1], begin_mask=0, + end_mask=0, ellipsis_mask=0, new_axis_mask=0, shrink_axis_mask=2), + dict(input_shape=[1, 5, 1, 3], begin=[0, 0, 0, 0], end=[1, 5, 1, 3], strides=[1, 1, 1, 1], begin_mask=0, + end_mask=0, ellipsis_mask=0, new_axis_mask=0, shrink_axis_mask=4), + dict(input_shape=[1, 5, 5, 1], begin=[0, 0, 0, 0], end=[1, 5, 1, 1], strides=[1, 1, 1, 1], begin_mask=0, + end_mask=0, ellipsis_mask=0, new_axis_mask=0, shrink_axis_mask=8), + dict(input_shape=[1, 1, 5, 5, 3], begin=[0, 0, 0, 0, 0], end=[1, 1, 5, 5, 3], strides=[1, 1, 1, 1, 1], + begin_mask=0, end_mask=0, ellipsis_mask=0, new_axis_mask=0, shrink_axis_mask=3), + dict(input_shape=[1, 5, 1, 5, 3], begin=[0, 0, 0, 0, 0], end=[1, 5, 1, 5, 3], strides=[1, 1, 1, 1, 1], + begin_mask=0, end_mask=0, ellipsis_mask=0, new_axis_mask=0, shrink_axis_mask=5), + dict(input_shape=[1, 5, 1, 5, 1], begin=[0, 0, 0, 0, 0], end=[1, 5, 1, 5, 1], strides=[1, 1, 1, 1, 1], + begin_mask=0, end_mask=0, ellipsis_mask=0, new_axis_mask=0, shrink_axis_mask=21), + ] + + @pytest.mark.parametrize('params', test_squeeze_data) + @pytest.mark.nightly + def test_strided_slice_replace_with_squeeze(self, params, ie_device, precision, ir_version, temp_dir): + self._test(*self.create_strided_slice_net(**params, ir_version=ir_version), + ie_device, precision, ir_version, temp_dir=temp_dir) + + test_unsqueeze_data = [ + dict(input_shape=[1, 5], begin=[0, 0], end=[1, 5], strides=[1, 1], begin_mask=0, + end_mask=0, ellipsis_mask=0, new_axis_mask=1, shrink_axis_mask=0), + dict(input_shape=[1, 5], begin=[0, 0], end=[1, 5], strides=[1, 1], begin_mask=0, + end_mask=0, ellipsis_mask=0, new_axis_mask=3, shrink_axis_mask=0), + dict(input_shape=[1, 5, 3], begin=[0, 0, 0], end=[1, 5, 3], strides=[1, 1, 1], begin_mask=0, + end_mask=0, ellipsis_mask=0, new_axis_mask=3, shrink_axis_mask=0), + dict(input_shape=[1, 5, 3], begin=[0, 0, 0], end=[1, 5, 3], strides=[1, 1, 1], begin_mask=0, + end_mask=0, ellipsis_mask=0, new_axis_mask=4, shrink_axis_mask=0), + dict(input_shape=[1, 5, 3], begin=[0, 0, 0], end=[1, 5, 3], strides=[1, 1, 1], begin_mask=0, + end_mask=0, ellipsis_mask=0, new_axis_mask=5, shrink_axis_mask=0), + dict(input_shape=[1, 5, 5, 3], begin=[0, 0, 0, 0], end=[1, 5, 5, 3], strides=[1, 1, 1, 1], begin_mask=0, + end_mask=0, ellipsis_mask=0, new_axis_mask=8, shrink_axis_mask=0), + dict(input_shape=[1, 5, 5, 3], begin=[0, 0, 0, 0], end=[1, 5, 5, 3], strides=[1, 1, 1, 1], begin_mask=0, + end_mask=0, ellipsis_mask=0, new_axis_mask=4, shrink_axis_mask=0), + dict(input_shape=[1, 5, 5, 3], begin=[0, 0, 0, 0], end=[1, 5, 5, 3], strides=[1, 1, 1, 1], begin_mask=0, + end_mask=0, ellipsis_mask=0, new_axis_mask=2, shrink_axis_mask=0), + ] + + @pytest.mark.parametrize('params', test_unsqueeze_data) + @pytest.mark.nightly + def test_strided_slice_replace_with_unsqueeze(self, params, ie_device, precision, ir_version, temp_dir): + self._test(*self.create_strided_slice_net(**params, ir_version=ir_version), + ie_device, precision, ir_version, temp_dir=temp_dir) From 83e1359c9ec0e672f66a0899ed754ccae7f530ff Mon Sep 17 00:00:00 2001 From: Polina Brzezinskaya Date: Tue, 24 Aug 2021 13:43:08 +0300 Subject: [PATCH 19/76] [VPU] Added ConvertGather7ToGather1 pass to frontend (#7183) This pr adds ConvertGather7ToGather1 pass to frontend before MergeGatherGatherElements pass, to make it so that when MergeGatherGatherElements is ran, any v7::Gather will be replaced with v1::Gather --- .../src/vpu/graph_transformer/src/frontend/frontend.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/inference-engine/src/vpu/graph_transformer/src/frontend/frontend.cpp b/inference-engine/src/vpu/graph_transformer/src/frontend/frontend.cpp index c2e5c054de4..0fc9a4f6b01 100644 --- a/inference-engine/src/vpu/graph_transformer/src/frontend/frontend.cpp +++ b/inference-engine/src/vpu/graph_transformer/src/frontend/frontend.cpp @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -181,6 +182,7 @@ ie::CNNNetwork FrontEnd::convertNetwork(ie::CNNNetwork& network) { manager.register_pass(); manager.register_pass(); manager.register_pass(); + manager.register_pass(); manager.register_pass(); manager.register_pass(); From f8e90f0c56b11c731f5b049fc80454546dcfa938 Mon Sep 17 00:00:00 2001 From: Anton Chetverikov Date: Tue, 24 Aug 2021 15:42:27 +0300 Subject: [PATCH 20/76] [MO] Add transformation for single CTCGreedyDecoder operation (#7023) * Add transformation for single CTCGreedyDecoder operation * Fix style in op specification * Update transformation logic * refactor old tests and add tests for new transformation * Move tf specific front transformations to tf folder * Update transformation logic and comments * Add run_after function and update comments * Add output_sparse_format attribute to extractor * Update transformation conditions and tests * Fix incorrect comment * Move sparse_to_dense_replacer to front/tf folder to fix problems with class registration * Update import * Update output ports handling in transformation * Update test * Fix BOM file * Update pattern for ctcloss transformation * Fix and refactor tests for ctcloss transform * Update transformation conditions --- docs/ops/sequence/CTCGreedyDecoderSeqLen_6.md | 3 +- model-optimizer/automation/package_BOM.txt | 6 +- .../front/CTCGreedyDecoderReplacement.py | 91 ---------- .../front/tf/CTCGreedyDecoderReplacement.py | 155 ++++++++++++++++++ .../front/tf/CTCGreedyDecoder_ext.py | 1 + .../front/{ => tf}/CTCLossReplacement.py | 4 +- .../{ => tf}/sparse_to_dense_replacer.py | 4 +- .../front/CTCGreedyDecoderReplacement_test.py | 96 ----------- .../front/CTCLossReplacement_test.py | 115 ------------- .../tf/CTCGreedyDecoderReplacement_test.py | 149 +++++++++++++++++ .../front/tf/CTCLossReplacement_test.py | 107 ++++++++++++ .../{ => tf}/sparse_to_dense_replacer_test.py | 2 +- 12 files changed, 422 insertions(+), 311 deletions(-) delete mode 100644 model-optimizer/extensions/front/CTCGreedyDecoderReplacement.py create mode 100644 model-optimizer/extensions/front/tf/CTCGreedyDecoderReplacement.py rename model-optimizer/extensions/front/{ => tf}/CTCLossReplacement.py (97%) rename model-optimizer/extensions/front/{ => tf}/sparse_to_dense_replacer.py (93%) delete mode 100644 model-optimizer/unit_tests/extensions/front/CTCGreedyDecoderReplacement_test.py delete mode 100644 model-optimizer/unit_tests/extensions/front/CTCLossReplacement_test.py create mode 100644 model-optimizer/unit_tests/extensions/front/tf/CTCGreedyDecoderReplacement_test.py create mode 100644 model-optimizer/unit_tests/extensions/front/tf/CTCLossReplacement_test.py rename model-optimizer/unit_tests/extensions/front/{ => tf}/sparse_to_dense_replacer_test.py (96%) diff --git a/docs/ops/sequence/CTCGreedyDecoderSeqLen_6.md b/docs/ops/sequence/CTCGreedyDecoderSeqLen_6.md index c4122cb50fb..956ca032179 100644 --- a/docs/ops/sequence/CTCGreedyDecoderSeqLen_6.md +++ b/docs/ops/sequence/CTCGreedyDecoderSeqLen_6.md @@ -74,7 +74,8 @@ The main difference between [CTCGreedyDecoder](CTCGreedyDecoder_1.md) and CTCGre **Example** ```xml - + + 8 diff --git a/model-optimizer/automation/package_BOM.txt b/model-optimizer/automation/package_BOM.txt index 50c5dadb498..87976b57117 100644 --- a/model-optimizer/automation/package_BOM.txt +++ b/model-optimizer/automation/package_BOM.txt @@ -133,8 +133,6 @@ extensions/front/caffe/split_to_identity.py extensions/front/caffe/tanh.py extensions/front/ChangePlaceholderTypes.py extensions/front/create_tensor_nodes.py -extensions/front/CTCGreedyDecoderReplacement.py -extensions/front/CTCLossReplacement.py extensions/front/disable_weights_quantize_value_propagation.py extensions/front/div.py extensions/front/DropoutWithRandomUniformReplacer.py @@ -370,7 +368,6 @@ extensions/front/scatter_normalizer.py extensions/front/SizeReplacer.py extensions/front/softmax.py extensions/front/softsign_replacer.py -extensions/front/sparse_to_dense_replacer.py extensions/front/split_normalizer.py extensions/front/SqueezeNormalize.py extensions/front/sub.py @@ -401,7 +398,9 @@ extensions/front/tf/CorrectRollAxes.py extensions/front/tf/crop_and_resize_ext.py extensions/front/tf/CropAndResizeReplacement.py extensions/front/tf/CTCGreedyDecoder_ext.py +extensions/front/tf/CTCGreedyDecoderReplacement.py extensions/front/tf/CTCLoss_ext.py +extensions/front/tf/CTCLossReplacement.py extensions/front/tf/cumsum_ext.py extensions/front/tf/deconv_ext.py extensions/front/tf/depth_to_space.py @@ -496,6 +495,7 @@ extensions/front/tf/sparse_fill_empty_rows_ext.py extensions/front/tf/sparse_segment_mean_ext.py extensions/front/tf/sparse_segment_sqrtn_ext.py extensions/front/tf/sparse_segment_sum_ext.py +extensions/front/tf/sparse_to_dense_replacer.py extensions/front/tf/split_ext.py extensions/front/tf/ssd_support.json extensions/front/tf/ssd_support_api_v1.14.json diff --git a/model-optimizer/extensions/front/CTCGreedyDecoderReplacement.py b/model-optimizer/extensions/front/CTCGreedyDecoderReplacement.py deleted file mode 100644 index 143509a0a2f..00000000000 --- a/model-optimizer/extensions/front/CTCGreedyDecoderReplacement.py +++ /dev/null @@ -1,91 +0,0 @@ -# Copyright (C) 2018-2021 Intel Corporation -# SPDX-License-Identifier: Apache-2.0 - -from extensions.ops.ctc_greedy_decoder_seq_len import CTCGreedyDecoderSeqLenOp -from extensions.ops.transpose import Transpose -from mo.front.common.partial_infer.utils import int64_array -from mo.front.common.replacement import FrontReplacementSubgraph -from mo.front.tf.graph_utils import create_op_with_const_inputs -from mo.graph.graph import Graph, rename_nodes - - -def replace_ctc_greedy_decoder(graph: Graph, match: dict): - ctc_greedy_decoder_tf = match['decoder'] - cast = match['cast'] - sparse_to_dense = match['sparse_to_dense'] - sparse_to_dense_name = sparse_to_dense.soft_get('name', sparse_to_dense.id) - ctc_greedy_decoder_tf_name = ctc_greedy_decoder_tf.soft_get('name', ctc_greedy_decoder_tf.id) - - # for normalizing input chanel need to transpose input data from [T, N, C] to [N, T, C] - # which supported CTCGreedyDecoderSeqLen op. - ctc_data_permute = create_op_with_const_inputs(graph, Transpose, {1: int64_array([1, 0, 2])}, - {'name': ctc_greedy_decoder_tf_name + '/ctc_data_permute'}) - - assert ctc_greedy_decoder_tf.has_valid('merge_repeated'), \ - 'The CTCGreedyDecoderSeqLen node "{}" misses "merge_repeated" attribute'.format(ctc_greedy_decoder_tf_name) - - ctc_greedy_decoder_tf.in_port(0).get_source().connect(ctc_data_permute.in_port(0)) - merge_repeated_tf = ctc_greedy_decoder_tf.merge_repeated - ctc_greedy_decoder = CTCGreedyDecoderSeqLenOp(graph, {'name': sparse_to_dense_name, - 'merge_repeated': merge_repeated_tf}).create_node() - rename_nodes( - [(sparse_to_dense, sparse_to_dense_name + '/AbandonedName'), (ctc_greedy_decoder, sparse_to_dense_name)]) - ctc_greedy_decoder.in_port(0).connect(ctc_data_permute.out_port(0)) - ctc_greedy_decoder_tf.in_port(1).get_source().connect(ctc_greedy_decoder.in_port(1)) - - # set output of the new sub-graph as a source for SparseToDense consumer - sparse_to_dense.out_port(0).get_connection().set_source(ctc_greedy_decoder.out_port(0)) - - # remove no longer needed nodes - graph.remove_nodes_from([sparse_to_dense.id, cast.id, ctc_greedy_decoder_tf.id]) - - -class CTCGreedyDecoderReplacement(FrontReplacementSubgraph): - """ - TensorFlow CTCGreedyDecoder produces output in a sparse tensor that is not supported by Inference Engine and - Inference Engine's CTCGreedyDecoderSeqLen has different output that is in a dense format. So this transformation - intents to replace TF CTCGreedyDecoder+SparseToDense where SparseToDense third input get from input parameter - to CTCGreedyDecoderSeqLen which compatible with IE. - """ - enabled = True - - @staticmethod - def pattern(**kwargs): - return dict( - nodes=[('decoder', dict(op='CTCGreedyDecoderSeqLen')), - ('cast', dict(op='Cast')), - ('sparse_to_dense', dict(op='SparseToDense')) - ], - edges=[('decoder', 'sparse_to_dense', {'out': 0}), - ('decoder', 'cast', {'out': 1}), - ('cast', 'sparse_to_dense', {'out': 0})] - ) - - def replace_sub_graph(self, graph: Graph, match: dict): - replace_ctc_greedy_decoder(graph, match) - - -class CTCGreedyDecoderWithSparseToDenseShapeReplacement(FrontReplacementSubgraph): - """ - TensorFlow CTCGreedyDecoder produces output in a sparse tensor that is not supported by Inference Engine and - Inference Engine's CTCGreedyDecoderSeqLen has different output that is in a dense format. So this transformation - intents to replace TF CTCGreedyDecoder+SparseToDense where SparseToDense third input get from CTCGreedyDecoder - second output to CTCGreedyDecoderSeqLen which compatible with IE. - """ - enabled = True - - @staticmethod - def pattern(**kwargs): - return dict( - nodes=[('decoder', dict(op='CTCGreedyDecoderSeqLen')), - ('cast', dict(op='Cast')), - ('sparse_to_dense', dict(op='SparseToDense')) - ], - edges=[('decoder', 'sparse_to_dense', {'out': 0}), - ('decoder', 'cast', {'out': 1}), - ('decoder', 'sparse_to_dense', {'out': 2}), - ('cast', 'sparse_to_dense', {'out': 0})] - ) - - def replace_sub_graph(self, graph: Graph, match: dict): - replace_ctc_greedy_decoder(graph, match) diff --git a/model-optimizer/extensions/front/tf/CTCGreedyDecoderReplacement.py b/model-optimizer/extensions/front/tf/CTCGreedyDecoderReplacement.py new file mode 100644 index 00000000000..070c98d7bc8 --- /dev/null +++ b/model-optimizer/extensions/front/tf/CTCGreedyDecoderReplacement.py @@ -0,0 +1,155 @@ +# Copyright (C) 2018-2021 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 + +import logging as log + +from extensions.ops.ctc_greedy_decoder_seq_len import CTCGreedyDecoderSeqLenOp +from extensions.ops.transpose import Transpose +from mo.front.common.partial_infer.utils import int64_array +from mo.front.common.replacement import FrontReplacementSubgraph, FrontReplacementPattern +from mo.front.tf.graph_utils import create_op_with_const_inputs +from mo.graph.graph import Graph, rename_nodes +from mo.ops.result import Result + + +def replace_ctc_greedy_decoder(graph: Graph, match: dict): + ctc_greedy_decoder_tf = match['decoder'] + cast = match['cast'] + sparse_to_dense = match['sparse_to_dense'] + sparse_to_dense_name = sparse_to_dense.soft_get('name', sparse_to_dense.id) + ctc_greedy_decoder_tf_name = ctc_greedy_decoder_tf.soft_get('name', ctc_greedy_decoder_tf.id) + + # For normalizing input channel needs to transpose input data from [T, N, C] to [N, T, C] + # which supported CTCGreedyDecoderSeqLen op. + ctc_data_permute = create_op_with_const_inputs(graph, Transpose, {1: int64_array([1, 0, 2])}, + {'name': ctc_greedy_decoder_tf_name + '/ctc_data_permute'}) + + assert ctc_greedy_decoder_tf.has_valid('merge_repeated'), \ + 'The CTCGreedyDecoderSeqLen node "{}" misses "merge_repeated" attribute'.format(ctc_greedy_decoder_tf_name) + + ctc_greedy_decoder_tf.in_port(0).get_source().connect(ctc_data_permute.in_port(0)) + merge_repeated_tf = ctc_greedy_decoder_tf.merge_repeated + ctc_greedy_decoder = CTCGreedyDecoderSeqLenOp(graph, {'name': sparse_to_dense_name, + 'merge_repeated': merge_repeated_tf}).create_node() + rename_nodes( + [(sparse_to_dense, sparse_to_dense_name + '/AbandonedName'), (ctc_greedy_decoder, sparse_to_dense_name)]) + ctc_greedy_decoder.in_port(0).connect(ctc_data_permute.out_port(0)) + ctc_greedy_decoder_tf.in_port(1).get_source().connect(ctc_greedy_decoder.in_port(1)) + + # Set output of the new sub-graph as a source for SparseToDense consumer + sparse_to_dense.out_port(0).get_connection().set_source(ctc_greedy_decoder.out_port(0)) + + # Remove no longer needed nodes + graph.remove_nodes_from([sparse_to_dense.id, cast.id, ctc_greedy_decoder_tf.id]) + + +class CTCGreedyDecoderReplacement(FrontReplacementSubgraph): + """ + TensorFlow CTCGreedyDecoder produces output in a sparse tensor that is not supported by Inference Engine, and + Inference Engine's CTCGreedyDecoderSeqLen has a different output that is in a dense format. So this transformation + intents to replace TF CTCGreedyDecoder+SparseToDense where SparseToDense third input get from input parameter + to CTCGreedyDecoderSeqLen which compatible with IE. + """ + enabled = True + + @staticmethod + def pattern(**kwargs): + return dict( + nodes=[('decoder', dict(op='CTCGreedyDecoderSeqLen', output_sparse_format=True)), + ('cast', dict(op='Cast')), + ('sparse_to_dense', dict(op='SparseToDense')) + ], + edges=[('decoder', 'sparse_to_dense', {'out': 0}), + ('decoder', 'cast', {'out': 1}), + ('cast', 'sparse_to_dense', {'out': 0})] + ) + + def replace_sub_graph(self, graph: Graph, match: dict): + replace_ctc_greedy_decoder(graph, match) + + +class CTCGreedyDecoderWithSparseToDenseShapeReplacement(FrontReplacementSubgraph): + """ + TensorFlow CTCGreedyDecoder produces output in a sparse tensor that is not supported by Inference Engine, and + Inference Engine's CTCGreedyDecoderSeqLen has a different output that is in a dense format. So this transformation + intents to replace TF CTCGreedyDecoder+SparseToDense where SparseToDense third input get from CTCGreedyDecoder + second output to CTCGreedyDecoderSeqLen which compatible with IE. + """ + enabled = True + + @staticmethod + def pattern(**kwargs): + return dict( + nodes=[('decoder', dict(op='CTCGreedyDecoderSeqLen', output_sparse_format=True)), + ('cast', dict(op='Cast')), + ('sparse_to_dense', dict(op='SparseToDense')) + ], + edges=[('decoder', 'sparse_to_dense', {'out': 0}), + ('decoder', 'cast', {'out': 1}), + ('decoder', 'sparse_to_dense', {'out': 2}), + ('cast', 'sparse_to_dense', {'out': 0})] + ) + + def replace_sub_graph(self, graph: Graph, match: dict): + replace_ctc_greedy_decoder(graph, match) + + +class CTCGreedyDecoderSingleReplacement(FrontReplacementPattern): + """ + TensorFlow CTCGreedyDecoder produces output in a sparse tensor that is not supported by Inference Engine, and + Inference Engine's CTCGreedyDecoderSeqLen has a different output that is in a dense format. So this transformation + handles a single TF CTCGreedyDecoder and warns the user about another format of the output + """ + enabled = True + + def run_after(self): + return [CTCGreedyDecoderReplacement, CTCGreedyDecoderWithSparseToDenseShapeReplacement] + + def find_and_replace_pattern(self, graph: Graph): + for ctc_greedy_decoder_tf in graph.get_op_nodes(op='CTCGreedyDecoderSeqLen', output_sparse_format=True): + ctc_greedy_decoder_tf_name = ctc_greedy_decoder_tf.soft_get('name', ctc_greedy_decoder_tf.id) + + # TF CTCGreedyDecoder have 4 output tensors. If any of them connected to not Result operation then + # transformation in not applicable + for port_num in ctc_greedy_decoder_tf.out_ports(): + if not ctc_greedy_decoder_tf.out_port(port_num).disconnected()\ + and ctc_greedy_decoder_tf.out_port(port_num).get_destination().node.soft_get('op') != 'Result': + return + + # If the first and second output are not connected to Result operations - + # create Result operation and connect it to appropriate output + if ctc_greedy_decoder_tf.out_port(0).disconnected(): + first_result = Result(graph, + {'name': ctc_greedy_decoder_tf_name + '/decoded_classes'} + ).create_node() + ctc_greedy_decoder_tf.out_port(0).connect(first_result.in_port(0)) + + if ctc_greedy_decoder_tf.out_port(1).disconnected(): + second_result = Result(graph, + {'name': ctc_greedy_decoder_tf_name + '/seq_lengths_output'} + ).create_node() + ctc_greedy_decoder_tf.out_port(1).connect(second_result.in_port(0)) + + + # For normalizing input channel needs to transpose input data from [T, N, C] to [N, T, C] + # which supported CTCGreedyDecoderSeqLen op. + log.warning('Found TF CTCGreedyDecoder operation at the end of network. ' + 'PLEASE NOTE, appropriate network output operation CTCGreedyDecoderSeqLen {} ' + 'will have dense format, not sparse format!'.format(ctc_greedy_decoder_tf_name)) + ctc_data_permute = create_op_with_const_inputs(graph, Transpose, {1: int64_array([1, 0, 2])}, + {'name': ctc_greedy_decoder_tf_name + '/ctc_data_permute'}) + + assert ctc_greedy_decoder_tf.has_valid('merge_repeated'), \ + 'The CTCGreedyDecoderSeqLen node "{}" misses "merge_repeated" attribute'.format( + ctc_greedy_decoder_tf_name) + + ctc_greedy_decoder_tf.in_port(0).get_source().connect(ctc_data_permute.in_port(0)) + ctc_greedy_decoder_tf.in_port(0).disconnect() + ctc_data_permute.out_port(0).connect(ctc_greedy_decoder_tf.in_port(0)) + + del ctc_greedy_decoder_tf['output_sparse_format'] + + for port_num in [2, 3]: # MO CTCGreedyDecoderSeqLen may have 2 outputs + if port_num in ctc_greedy_decoder_tf.out_ports(): + if not ctc_greedy_decoder_tf.out_port(port_num).disconnected(): + ctc_greedy_decoder_tf.out_port(port_num).disconnect() diff --git a/model-optimizer/extensions/front/tf/CTCGreedyDecoder_ext.py b/model-optimizer/extensions/front/tf/CTCGreedyDecoder_ext.py index 5efbaed7aa3..4e2577da98e 100644 --- a/model-optimizer/extensions/front/tf/CTCGreedyDecoder_ext.py +++ b/model-optimizer/extensions/front/tf/CTCGreedyDecoder_ext.py @@ -13,6 +13,7 @@ class CTCCGreedyDecoderFrontExtractor(FrontExtractorOp): def extract(cls, node): attrs = { 'merge_repeated': bool(node.pb.attr['merge_repeated'].b), + 'output_sparse_format': True, # Special argument for TF CTCGreedyDecoder replacement transformations } CTCGreedyDecoderSeqLenOp.update_node_stat(node, attrs) return cls.enabled diff --git a/model-optimizer/extensions/front/CTCLossReplacement.py b/model-optimizer/extensions/front/tf/CTCLossReplacement.py similarity index 97% rename from model-optimizer/extensions/front/CTCLossReplacement.py rename to model-optimizer/extensions/front/tf/CTCLossReplacement.py index ea2e6cbd3bc..55045b8de29 100644 --- a/model-optimizer/extensions/front/CTCLossReplacement.py +++ b/model-optimizer/extensions/front/tf/CTCLossReplacement.py @@ -20,14 +20,14 @@ class CTCLossReplacement(FrontReplacementSubgraph): enabled = True def run_before(self): - from extensions.front.CTCGreedyDecoderReplacement import CTCGreedyDecoderReplacement + from extensions.front.tf.CTCGreedyDecoderReplacement import CTCGreedyDecoderReplacement return [CTCGreedyDecoderReplacement] def pattern(self): return dict( nodes=[ ('transpose', dict(op='Transpose')), - ('ctc_greedy_decoder', dict(op='CTCGreedyDecoderSeqLen')), + ('ctc_greedy_decoder', dict(op='CTCGreedyDecoderSeqLen', output_sparse_format=True)), ('cast', dict(op='Cast')), ('sparse_to_dense', dict(op='SparseToDense')), ('const', dict(op='Const')), diff --git a/model-optimizer/extensions/front/sparse_to_dense_replacer.py b/model-optimizer/extensions/front/tf/sparse_to_dense_replacer.py similarity index 93% rename from model-optimizer/extensions/front/sparse_to_dense_replacer.py rename to model-optimizer/extensions/front/tf/sparse_to_dense_replacer.py index f285192a5a0..1440b150696 100644 --- a/model-optimizer/extensions/front/sparse_to_dense_replacer.py +++ b/model-optimizer/extensions/front/tf/sparse_to_dense_replacer.py @@ -21,8 +21,8 @@ class SparseToDenseReplacer(FrontReplacementOp): enabled = True def run_after(self): - from extensions.front.CTCGreedyDecoderReplacement import CTCGreedyDecoderReplacement - from extensions.front.CTCLossReplacement import CTCLossReplacement + from extensions.front.tf.CTCGreedyDecoderReplacement import CTCGreedyDecoderReplacement + from extensions.front.tf.CTCLossReplacement import CTCLossReplacement return [CTCGreedyDecoderReplacement, CTCLossReplacement] def replace_op(self, graph: Graph, node: Node): diff --git a/model-optimizer/unit_tests/extensions/front/CTCGreedyDecoderReplacement_test.py b/model-optimizer/unit_tests/extensions/front/CTCGreedyDecoderReplacement_test.py deleted file mode 100644 index 063d71173e1..00000000000 --- a/model-optimizer/unit_tests/extensions/front/CTCGreedyDecoderReplacement_test.py +++ /dev/null @@ -1,96 +0,0 @@ -# Copyright (C) 2018-2021 Intel Corporation -# SPDX-License-Identifier: Apache-2.0 - -import unittest - -from extensions.front.CTCGreedyDecoderReplacement import CTCGreedyDecoderReplacement, CTCGreedyDecoderWithSparseToDenseShapeReplacement -from mo.front.common.partial_infer.utils import int64_array -from mo.utils.ir_engine.compare_graphs import compare_graphs -from unit_tests.utils.graph import build_graph, const - - -class CTCGreedyDecoderReplacementTests(unittest.TestCase): - def test1(self): - nodes_attributes = { - # nodes from original graph - 'logits': {'type': 'Parameter', 'kind': 'op', 'op': 'Parameter'}, - 'seq_len': {'type': 'Parameter', 'kind': 'op', 'op': 'Parameter'}, - 'order_arr': {'kind': 'op', 'op': 'Const'}, - 'transpose': {'type': 'Transpose', 'kind': 'op', 'op': 'Transpose'}, - 'decoder': {'kind': 'op', 'op': 'CTCGreedyDecoderSeqLen', 'merge_repeated': True}, - 'cast': {'kind': 'op', 'op': 'Cast'}, - 'sparse_to_dense': {'kind': 'op', 'op': 'SparseToDense'}, - 'last': {'type': None, 'value': None, 'kind': 'op', 'op': 'Result'}, - - # new nodes - 'new_decoder': {'kind': 'op', 'op': 'CTCGreedyDecoderSeqLen', 'use_mask_format': True}, - **const('squeeze_axes', int64_array([2, 3])), - 'squeeze_dec_seq': {'kind': 'op', 'op': 'Squeeze'}, - 'cast_to_int': {'kind': 'op', 'op': 'Cast'}, - } - - graph = build_graph(nodes_attributes, - [('logits', 'decoder', {'out': 0, 'in': 0}), - ('seq_len', 'decoder', {'out': 0, 'in': 1}), - ('decoder', 'sparse_to_dense', {'out': 0, 'in': 0}), - ('decoder', 'sparse_to_dense', {'out': 2, 'in': 1}), - ('decoder', 'cast', {'out': 1, 'in': 0}), - ('cast', 'sparse_to_dense', {'out': 0}), - ('sparse_to_dense', 'last', {'out': 0, 'in': 0}), - ], nodes_with_edges_only=True) - graph.stage = 'front' - CTCGreedyDecoderWithSparseToDenseShapeReplacement().find_and_replace_pattern(graph) - - graph_ref = build_graph(nodes_attributes, - [('logits', 'transpose', {'out': 0, 'in': 0}), - ('order_arr', 'transpose', {'out': 0, 'in': 1}), - ('transpose', 'decoder', {'out': 0, 'in': 0}), - ('seq_len', 'decoder', {'out': 0, 'in': 1}), - ('decoder', 'last', {'out': 0, 'in': 0}), - ], - nodes_with_edges_only=True) - - (flag, resp) = compare_graphs(graph, graph_ref, 'last', check_op_attrs=True) - self.assertTrue(flag, resp) - - def test2(self): - nodes_attributes = { - # nodes from original graph - 'logits': {'type': 'Parameter', 'kind': 'op', 'op': 'Parameter'}, - 'seq_len': {'type': 'Parameter', 'kind': 'op', 'op': 'Parameter'}, - 'order_arr': {'kind': 'op', 'op': 'Const'}, - 'transpose': {'type': 'Transpose', 'kind': 'op', 'op': 'Transpose'}, - 'decoder': {'kind': 'op', 'op': 'CTCGreedyDecoderSeqLen', 'merge_repeated': True}, - 'cast': {'kind': 'op', 'op': 'Cast'}, - 'sparse_to_dense': {'kind': 'op', 'op': 'SparseToDense'}, - 'last': {'type': None, 'value': None, 'kind': 'op', 'op': 'Result'}, - - # new nodes - 'new_decoder': {'kind': 'op', 'op': 'CTCGreedyDecoderSeqLen', 'use_mask_format': True}, - **const('squeeze_axes', int64_array([2, 3])), - 'squeeze_dec_seq': {'kind': 'op', 'op': 'Squeeze'}, - 'cast_to_int': {'kind': 'op', 'op': 'Cast'}, - } - - graph = build_graph(nodes_attributes, - [('logits', 'decoder', {'out': 0, 'in': 0}), - ('seq_len', 'decoder', {'out': 0, 'in': 1}), - ('decoder', 'sparse_to_dense', {'out': 0, 'in': 0}), - ('decoder', 'cast', {'out': 1, 'in': 0}), - ('cast', 'sparse_to_dense', {'out': 0}), - ('sparse_to_dense', 'last', {'out': 0, 'in': 0}), - ], nodes_with_edges_only=True) - graph.stage = 'front' - CTCGreedyDecoderReplacement().find_and_replace_pattern(graph) - - graph_ref = build_graph(nodes_attributes, - [('logits', 'transpose', {'out': 0, 'in': 0}), - ('order_arr', 'transpose', {'out': 0, 'in': 1}), - ('transpose', 'decoder', {'out': 0, 'in': 0}), - ('seq_len', 'decoder', {'out': 0, 'in': 1}), - ('decoder', 'last', {'out': 0, 'in': 0}), - ], - nodes_with_edges_only=True) - - (flag, resp) = compare_graphs(graph, graph_ref, 'last', check_op_attrs=True) - self.assertTrue(flag, resp) diff --git a/model-optimizer/unit_tests/extensions/front/CTCLossReplacement_test.py b/model-optimizer/unit_tests/extensions/front/CTCLossReplacement_test.py deleted file mode 100644 index 77ecfc8fa1a..00000000000 --- a/model-optimizer/unit_tests/extensions/front/CTCLossReplacement_test.py +++ /dev/null @@ -1,115 +0,0 @@ -# Copyright (C) 2018-2021 Intel Corporation -# SPDX-License-Identifier: Apache-2.0 - -import numpy as np -import unittest -from argparse import Namespace - -from extensions.front.CTCLossReplacement import CTCLossReplacement -from mo.front.common.partial_infer.utils import int64_array -from mo.utils.ir_engine.compare_graphs import compare_graphs -from unit_tests.utils.graph import build_graph, const - - -class CTCLossFrontReplacementTest(unittest.TestCase): - def test1(self): - nodes_attributes = { - 'logits': {'shape': int64_array([2, 6, 100]), 'type': 'Parameter', 'kind': 'op', 'op': 'Parameter'}, - 'seq_mask': {'shape': int64_array([2]), 'data_type': np.int32, 'kind': 'op', 'op': 'Parameter'}, - 'transpose': {'kind': 'op', 'op': 'Transpose'}, - 'ctc_greedy_decoder': {'kind': 'op', 'op': 'CTCGreedyDecoderSeqLen', 'merge_repeated': True}, - 'cast': {'kind': 'op', 'op': 'Cast'}, - 'sparse_to_dense': {'kind': 'op', 'op': 'SparseToDense'}, - 'tf_ctc_loss': {'kind': 'op', 'op': 'CTCLoss', 'preprocess_collapse_repeated': False, - 'ctc_merge_repeated': True, 'unique': False, 'logits_time_major': True}, - 'ctc_loss': {'kind': 'op', 'op': 'CTCLoss', 'preprocess_collapse_repeated': False, - 'ctc_merge_repeated': True, 'unique': False}, - **const('default_value', int64_array(-1)), - 'last': {'type': None, 'value': None, 'kind': 'op', 'op': 'Result'}, - 'transpose2': {'kind': 'op', 'op': 'Transpose'}, - **const('transpose2_axis', int64_array([1, 0, 2])), - } - graph = build_graph(nodes_attributes, [('logits', 'transpose', {'out': 0, 'in': 0}), - ('transpose', 'ctc_greedy_decoder', {'out': 0, 'in': 0}), - ('seq_mask', 'ctc_greedy_decoder', {'out': 0, 'in': 1}), - ('transpose', 'tf_ctc_loss', {'out': 0, 'in': 0}), - ('seq_mask', 'tf_ctc_loss', {'out': 0, 'in': 3}), - ('ctc_greedy_decoder', 'sparse_to_dense', {'out': 0, 'in': 0}), - ('ctc_greedy_decoder', 'sparse_to_dense', {'out': 2, 'in': 1}), - ('ctc_greedy_decoder', 'sparse_to_dense', {'out': 1, 'in': 2}), - ('default_value', 'sparse_to_dense', {'out': 0, 'in': 3}), - ('ctc_greedy_decoder', 'cast', {'out': 1, 'in': 0}), - ('ctc_greedy_decoder', 'tf_ctc_loss', {'out': 0, 'in': 1}), - ('cast', 'tf_ctc_loss', {'out': 0, 'in': 2}), - ('tf_ctc_loss', 'last', {'out': 0, 'in': 0})], - nodes_with_edges_only=True) - graph.graph['cmd_params'] = Namespace(data_type='FP32') - graph.stage = 'front' - CTCLossReplacement().find_and_replace_pattern(graph) - - graph_ref = build_graph(nodes_attributes, - [('logits', 'transpose', {'out': 0, 'in': 0}), - ('transpose', 'transpose2', {'out': 0, 'in': 0}), - ('transpose2_axis', 'transpose2', {'out': 0, 'in': 1}), - ('transpose2', 'ctc_greedy_decoder', {'out': 0, 'in': 0}), - ('seq_mask', 'ctc_greedy_decoder', {'out': 0, 'in': 1}), - ('transpose2', 'ctc_loss', {'out': 0, 'in': 0}), - ('ctc_greedy_decoder', 'ctc_loss', {'out': 0, 'in': 2}), - ('ctc_greedy_decoder', 'ctc_loss', {'out': 1, 'in': 3}), - ('seq_mask', 'ctc_loss', {'out': 0, 'in': 1}), - ('ctc_loss', 'last', {'out': 0, 'in': 0})], - nodes_with_edges_only=True) - - (flag, resp) = compare_graphs(graph, graph_ref, 'last', check_op_attrs=True) - self.assertTrue(flag, resp) - - def test2(self): - nodes_attributes = { - 'logits': {'shape': int64_array([2, 6, 100]), 'type': 'Parameter', 'kind': 'op', 'op': 'Parameter'}, - 'seq_mask': {'shape': int64_array([2]), 'data_type': np.int32, 'kind': 'op', 'op': 'Parameter'}, - 'transpose': {'kind': 'op', 'op': 'Transpose'}, - 'ctc_greedy_decoder': {'kind': 'op', 'op': 'CTCGreedyDecoderSeqLen', 'merge_repeated': True}, - 'cast': {'kind': 'op', 'op': 'Cast'}, - 'sparse_to_dense': {'kind': 'op', 'op': 'SparseToDense'}, - 'tf_ctc_loss': {'kind': 'op', 'op': 'CTCLoss', 'preprocess_collapse_repeated': False, - 'ctc_merge_repeated': True, 'unique': False, 'logits_time_major': False}, - 'ctc_loss': {'kind': 'op', 'op': 'CTCLoss', 'preprocess_collapse_repeated': False, - 'ctc_merge_repeated': True, 'unique': False}, - **const('default_value', int64_array(-1)), - 'last': {'type': None, 'value': None, 'kind': 'op', 'op': 'Result'}, - 'transpose2': {'kind': 'op', 'op': 'Transpose'}, - **const('transpose2_axis', int64_array([1, 0, 2])), - } - graph = build_graph(nodes_attributes, [('logits', 'transpose', {'out': 0, 'in': 0}), - ('transpose', 'ctc_greedy_decoder', {'out': 0, 'in': 0}), - ('seq_mask', 'ctc_greedy_decoder', {'out': 0, 'in': 1}), - ('transpose', 'tf_ctc_loss', {'out': 0, 'in': 0}), - ('seq_mask', 'tf_ctc_loss', {'out': 0, 'in': 3}), - ('ctc_greedy_decoder', 'sparse_to_dense', {'out': 0, 'in': 0}), - ('ctc_greedy_decoder', 'sparse_to_dense', {'out': 2, 'in': 1}), - ('ctc_greedy_decoder', 'sparse_to_dense', {'out': 1, 'in': 2}), - ('default_value', 'sparse_to_dense', {'out': 0, 'in': 3}), - ('ctc_greedy_decoder', 'cast', {'out': 1, 'in': 0}), - ('ctc_greedy_decoder', 'tf_ctc_loss', {'out': 0, 'in': 1}), - ('cast', 'tf_ctc_loss', {'out': 0, 'in': 2}), - ('tf_ctc_loss', 'last', {'out': 0, 'in': 0})], - nodes_with_edges_only=True) - graph.graph['cmd_params'] = Namespace(data_type='FP32') - graph.stage = 'front' - CTCLossReplacement().find_and_replace_pattern(graph) - - graph_ref = build_graph(nodes_attributes, - [('logits', 'transpose', {'out': 0, 'in': 0}), - ('transpose', 'transpose2', {'out': 0, 'in': 0}), - ('transpose2_axis', 'transpose2', {'out': 0, 'in': 1}), - ('transpose2', 'ctc_greedy_decoder', {'out': 0, 'in': 0}), - ('seq_mask', 'ctc_greedy_decoder', {'out': 0, 'in': 1}), - ('transpose', 'ctc_loss', {'out': 0, 'in': 0}), - ('ctc_greedy_decoder', 'ctc_loss', {'out': 0, 'in': 2}), - ('ctc_greedy_decoder', 'ctc_loss', {'out': 1, 'in': 3}), - ('seq_mask', 'ctc_loss', {'out': 0, 'in': 1}), - ('ctc_loss', 'last', {'out': 0, 'in': 0})], - nodes_with_edges_only=True) - - (flag, resp) = compare_graphs(graph, graph_ref, 'last', check_op_attrs=True) - self.assertTrue(flag, resp) diff --git a/model-optimizer/unit_tests/extensions/front/tf/CTCGreedyDecoderReplacement_test.py b/model-optimizer/unit_tests/extensions/front/tf/CTCGreedyDecoderReplacement_test.py new file mode 100644 index 00000000000..ff93aa30240 --- /dev/null +++ b/model-optimizer/unit_tests/extensions/front/tf/CTCGreedyDecoderReplacement_test.py @@ -0,0 +1,149 @@ +# Copyright (C) 2018-2021 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 + +import unittest + +from extensions.front.tf.CTCGreedyDecoderReplacement import CTCGreedyDecoderReplacement, \ + CTCGreedyDecoderWithSparseToDenseShapeReplacement, CTCGreedyDecoderSingleReplacement +from mo.front.common.partial_infer.utils import int64_array +from mo.utils.ir_engine.compare_graphs import compare_graphs +from unit_tests.utils.graph import build_graph, const + + +class CTCGreedyDecoderReplacementTests(unittest.TestCase): + nodes_attributes = { + # nodes from original graph + 'logits': {'type': 'Parameter', 'kind': 'op', 'op': 'Parameter'}, + 'seq_len': {'type': 'Parameter', 'kind': 'op', 'op': 'Parameter'}, + 'order_arr': {'kind': 'op', 'op': 'Const'}, + 'transpose': {'type': 'Transpose', 'kind': 'op', 'op': 'Transpose'}, + 'decoder': {'kind': 'op', 'op': 'CTCGreedyDecoderSeqLen', 'merge_repeated': True, 'output_sparse_format': True}, + 'cast': {'kind': 'op', 'op': 'Cast'}, + 'sparse_to_dense': {'kind': 'op', 'op': 'SparseToDense'}, + 'last': {'type': None, 'value': None, 'kind': 'op', 'op': 'Result'}, + 'last_1': {'type': None, 'value': None, 'kind': 'op', 'op': 'Result'}, + + # new nodes + 'new_decoder': {'kind': 'op', 'op': 'CTCGreedyDecoderSeqLen', 'merge_repeated': True}, + **const('squeeze_axes', int64_array([2, 3])), + 'squeeze_dec_seq': {'kind': 'op', 'op': 'Squeeze'}, + 'cast_to_int': {'kind': 'op', 'op': 'Cast'}, + 'out_seq_len': {'type': None, 'value': None, 'kind': 'op', 'op': 'Result'}, + } + + def test_CTCGreedyDecoderWithSparseToDenseShape(self): + graph = build_graph(self.nodes_attributes, + [('logits', 'decoder', {'out': 0, 'in': 0}), + ('seq_len', 'decoder', {'out': 0, 'in': 1}), + ('decoder', 'sparse_to_dense', {'out': 0, 'in': 0}), + ('decoder', 'sparse_to_dense', {'out': 2, 'in': 1}), + ('decoder', 'cast', {'out': 1, 'in': 0}), + ('cast', 'sparse_to_dense', {'out': 0}), + ('sparse_to_dense', 'last', {'out': 0, 'in': 0}), + ], nodes_with_edges_only=True) + graph.stage = 'front' + CTCGreedyDecoderWithSparseToDenseShapeReplacement().find_and_replace_pattern(graph) + + graph_ref = build_graph(self.nodes_attributes, + [('logits', 'transpose', {'out': 0, 'in': 0}), + ('order_arr', 'transpose', {'out': 0, 'in': 1}), + ('transpose', 'new_decoder', {'out': 0, 'in': 0}), + ('seq_len', 'new_decoder', {'out': 0, 'in': 1}), + ('new_decoder', 'last', {'out': 0, 'in': 0}), + ], + nodes_with_edges_only=True) + + (flag, resp) = compare_graphs(graph, graph_ref, 'last', check_op_attrs=True) + self.assertTrue(flag, resp) + + def test_CTCGreedyDecoderReplacement(self): + graph = build_graph(self.nodes_attributes, + [('logits', 'decoder', {'out': 0, 'in': 0}), + ('seq_len', 'decoder', {'out': 0, 'in': 1}), + ('decoder', 'sparse_to_dense', {'out': 0, 'in': 0}), + ('decoder', 'cast', {'out': 1, 'in': 0}), + ('cast', 'sparse_to_dense', {'out': 0}), + ('sparse_to_dense', 'last', {'out': 0, 'in': 0}), + ], nodes_with_edges_only=True) + graph.stage = 'front' + CTCGreedyDecoderReplacement().find_and_replace_pattern(graph) + + graph_ref = build_graph(self.nodes_attributes, + [('logits', 'transpose', {'out': 0, 'in': 0}), + ('order_arr', 'transpose', {'out': 0, 'in': 1}), + ('transpose', 'new_decoder', {'out': 0, 'in': 0}), + ('seq_len', 'new_decoder', {'out': 0, 'in': 1}), + ('new_decoder', 'last', {'out': 0, 'in': 0}), + ], + nodes_with_edges_only=True) + + (flag, resp) = compare_graphs(graph, graph_ref, 'last', check_op_attrs=True) + self.assertTrue(flag, resp) + + def test_CTCGreedyDecoderSingle(self): + graph = build_graph(self.nodes_attributes, + [('logits', 'decoder', {'out': 0, 'in': 0}), + ('seq_len', 'decoder', {'out': 0, 'in': 1}), + ('decoder', 'last', {'out': 0, 'in': 0}), + ('decoder', 'last_1', {'out': 1, 'in': 0}), + ], nodes_with_edges_only=True) + graph.stage = 'front' + CTCGreedyDecoderSingleReplacement().find_and_replace_pattern(graph) + + graph_ref = build_graph(self.nodes_attributes, + [('logits', 'transpose', {'out': 0, 'in': 0}), + ('order_arr', 'transpose', {'out': 0, 'in': 1}), + ('transpose', 'new_decoder', {'out': 0, 'in': 0}), + ('seq_len', 'new_decoder', {'out': 0, 'in': 1}), + ('new_decoder', 'last', {'out': 0, 'in': 0}), + ('new_decoder', 'last_1', {'out': 1, 'in': 0}), + ], + nodes_with_edges_only=True) + + (flag, resp) = compare_graphs(graph, graph_ref, 'last', check_op_attrs=True) + self.assertTrue(flag, resp) + + def test_CTCGreedyDecoderSingle_negative(self): + edges = [('logits', 'decoder', {'out': 0, 'in': 0}), + ('seq_len', 'decoder', {'out': 0, 'in': 1}), + ('decoder', 'sparse_to_dense', {'out': 0, 'in': 0}), + ('decoder', 'cast', {'out': 1, 'in': 0}), + ('cast', 'sparse_to_dense', {'out': 0}), + ('sparse_to_dense', 'last', {'out': 0, 'in': 0}), + ] + graph = build_graph(self.nodes_attributes, + edges, nodes_with_edges_only=True) + graph.stage = 'front' + CTCGreedyDecoderSingleReplacement().find_and_replace_pattern(graph) + + graph_ref = build_graph(self.nodes_attributes, + edges, nodes_with_edges_only=True) + + (flag, resp) = compare_graphs(graph, graph_ref, 'last', check_op_attrs=True) + self.assertTrue(flag, resp) + + def test_CTCGreedyDecoder_no_consequent_transforms(self): + graph = build_graph(self.nodes_attributes, + [('logits', 'decoder', {'out': 0, 'in': 0}), + ('seq_len', 'decoder', {'out': 0, 'in': 1}), + ('decoder', 'sparse_to_dense', {'out': 0, 'in': 0}), + ('decoder', 'sparse_to_dense', {'out': 2, 'in': 1}), + ('decoder', 'cast', {'out': 1, 'in': 0}), + ('cast', 'sparse_to_dense', {'out': 0}), + ('sparse_to_dense', 'last', {'out': 0, 'in': 0}), + ], nodes_with_edges_only=True) + graph.stage = 'front' + CTCGreedyDecoderWithSparseToDenseShapeReplacement().find_and_replace_pattern(graph) + CTCGreedyDecoderSingleReplacement().find_and_replace_pattern(graph) + + graph_ref = build_graph(self.nodes_attributes, + [('logits', 'transpose', {'out': 0, 'in': 0}), + ('order_arr', 'transpose', {'out': 0, 'in': 1}), + ('transpose', 'new_decoder', {'out': 0, 'in': 0}), + ('seq_len', 'new_decoder', {'out': 0, 'in': 1}), + ('new_decoder', 'last', {'out': 0, 'in': 0}), + ], + nodes_with_edges_only=True) + + (flag, resp) = compare_graphs(graph, graph_ref, 'last', check_op_attrs=True) + self.assertTrue(flag, resp) diff --git a/model-optimizer/unit_tests/extensions/front/tf/CTCLossReplacement_test.py b/model-optimizer/unit_tests/extensions/front/tf/CTCLossReplacement_test.py new file mode 100644 index 00000000000..3367a94fe85 --- /dev/null +++ b/model-optimizer/unit_tests/extensions/front/tf/CTCLossReplacement_test.py @@ -0,0 +1,107 @@ +# Copyright (C) 2018-2021 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 + +import numpy as np +import unittest +from argparse import Namespace + +from extensions.front.tf.CTCLossReplacement import CTCLossReplacement +from mo.front.common.partial_infer.utils import int64_array +from mo.utils.ir_engine.compare_graphs import compare_graphs +from unit_tests.utils.graph import build_graph, const + + +class CTCLossFrontReplacementTest(unittest.TestCase): + nodes_attributes = { + 'logits': {'shape': int64_array([2, 6, 100]), 'type': 'Parameter', 'kind': 'op', 'op': 'Parameter'}, + 'seq_mask': {'shape': int64_array([2]), 'data_type': np.int32, 'kind': 'op', 'op': 'Parameter'}, + 'transpose': {'kind': 'op', 'op': 'Transpose'}, + 'ctc_greedy_decoder': {'kind': 'op', 'op': 'CTCGreedyDecoderSeqLen', 'merge_repeated': True, + 'output_sparse_format': True}, + 'cast': {'kind': 'op', 'op': 'Cast'}, + 'sparse_to_dense': {'kind': 'op', 'op': 'SparseToDense'}, + 'tf_ctc_loss_true_logits': {'kind': 'op', 'op': 'CTCLoss', 'preprocess_collapse_repeated': False, + 'ctc_merge_repeated': True, 'unique': False, 'logits_time_major': True}, + 'tf_ctc_loss_false_logits': {'kind': 'op', 'op': 'CTCLoss', 'preprocess_collapse_repeated': False, + 'ctc_merge_repeated': True, 'unique': False, 'logits_time_major': False}, + 'ctc_loss': {'kind': 'op', 'op': 'CTCLoss', 'preprocess_collapse_repeated': False, + 'ctc_merge_repeated': True, 'unique': False}, + **const('default_value', int64_array(-1)), + 'last': {'type': None, 'value': None, 'kind': 'op', 'op': 'Result'}, + 'transpose2': {'kind': 'op', 'op': 'Transpose'}, + **const('transpose2_axis', int64_array([1, 0, 2])), + + 'new_ctc_greedy_decoder': {'kind': 'op', 'op': 'CTCGreedyDecoderSeqLen', 'merge_repeated': True}, + } + + def CTCLossReplacement_test_true_logits(self): + graph = build_graph(self.nodes_attributes, + [('logits', 'transpose', {'out': 0, 'in': 0}), + ('transpose', 'ctc_greedy_decoder', {'out': 0, 'in': 0}), + ('seq_mask', 'ctc_greedy_decoder', {'out': 0, 'in': 1}), + ('transpose', 'tf_ctc_loss_true_logits', {'out': 0, 'in': 0}), + ('seq_mask', 'tf_ctc_loss_true_logits', {'out': 0, 'in': 3}), + ('ctc_greedy_decoder', 'sparse_to_dense', {'out': 0, 'in': 0}), + ('ctc_greedy_decoder', 'sparse_to_dense', {'out': 2, 'in': 1}), + ('ctc_greedy_decoder', 'sparse_to_dense', {'out': 1, 'in': 2}), + ('default_value', 'sparse_to_dense', {'out': 0, 'in': 3}), + ('ctc_greedy_decoder', 'cast', {'out': 1, 'in': 0}), + ('ctc_greedy_decoder', 'tf_ctc_loss_true_logits', {'out': 0, 'in': 1}), + ('cast', 'tf_ctc_loss_true_logits', {'out': 0, 'in': 2}), + ('tf_ctc_loss_true_logits', 'last', {'out': 0, 'in': 0})], + nodes_with_edges_only=True) + graph.graph['cmd_params'] = Namespace(data_type='FP32') + graph.stage = 'front' + CTCLossReplacement().find_and_replace_pattern(graph) + + graph_ref = build_graph(self.nodes_attributes, + [('logits', 'transpose', {'out': 0, 'in': 0}), + ('transpose', 'transpose2', {'out': 0, 'in': 0}), + ('transpose2_axis', 'transpose2', {'out': 0, 'in': 1}), + ('transpose2', 'new_ctc_greedy_decoder', {'out': 0, 'in': 0}), + ('seq_mask', 'new_ctc_greedy_decoder', {'out': 0, 'in': 1}), + ('transpose2', 'ctc_loss', {'out': 0, 'in': 0}), + ('new_ctc_greedy_decoder', 'ctc_loss', {'out': 0, 'in': 2}), + ('new_ctc_greedy_decoder', 'ctc_loss', {'out': 1, 'in': 3}), + ('seq_mask', 'ctc_loss', {'out': 0, 'in': 1}), + ('ctc_loss', 'last', {'out': 0, 'in': 0})], + nodes_with_edges_only=True) + + (flag, resp) = compare_graphs(graph, graph_ref, 'last', check_op_attrs=True) + self.assertTrue(flag, resp) + + def CTCLossReplacement_test_false_logits(self): + graph = build_graph(self.nodes_attributes, + [('logits', 'transpose', {'out': 0, 'in': 0}), + ('transpose', 'ctc_greedy_decoder', {'out': 0, 'in': 0}), + ('seq_mask', 'ctc_greedy_decoder', {'out': 0, 'in': 1}), + ('transpose', 'tf_ctc_loss_false_logits', {'out': 0, 'in': 0}), + ('seq_mask', 'tf_ctc_loss_false_logits', {'out': 0, 'in': 3}), + ('ctc_greedy_decoder', 'sparse_to_dense', {'out': 0, 'in': 0}), + ('ctc_greedy_decoder', 'sparse_to_dense', {'out': 2, 'in': 1}), + ('ctc_greedy_decoder', 'sparse_to_dense', {'out': 1, 'in': 2}), + ('default_value', 'sparse_to_dense', {'out': 0, 'in': 3}), + ('ctc_greedy_decoder', 'cast', {'out': 1, 'in': 0}), + ('ctc_greedy_decoder', 'tf_ctc_loss_false_logits', {'out': 0, 'in': 1}), + ('cast', 'tf_ctc_loss_false_logits', {'out': 0, 'in': 2}), + ('tf_ctc_loss_false_logits', 'last', {'out': 0, 'in': 0})], + nodes_with_edges_only=True) + graph.graph['cmd_params'] = Namespace(data_type='FP32') + graph.stage = 'front' + CTCLossReplacement().find_and_replace_pattern(graph) + + graph_ref = build_graph(self.nodes_attributes, + [('logits', 'transpose', {'out': 0, 'in': 0}), + ('transpose', 'transpose2', {'out': 0, 'in': 0}), + ('transpose2_axis', 'transpose2', {'out': 0, 'in': 1}), + ('transpose2', 'new_ctc_greedy_decoder', {'out': 0, 'in': 0}), + ('seq_mask', 'new_ctc_greedy_decoder', {'out': 0, 'in': 1}), + ('transpose', 'ctc_loss', {'out': 0, 'in': 0}), + ('new_ctc_greedy_decoder', 'ctc_loss', {'out': 0, 'in': 2}), + ('new_ctc_greedy_decoder', 'ctc_loss', {'out': 1, 'in': 3}), + ('seq_mask', 'ctc_loss', {'out': 0, 'in': 1}), + ('ctc_loss', 'last', {'out': 0, 'in': 0})], + nodes_with_edges_only=True) + + (flag, resp) = compare_graphs(graph, graph_ref, 'last', check_op_attrs=True) + self.assertTrue(flag, resp) diff --git a/model-optimizer/unit_tests/extensions/front/sparse_to_dense_replacer_test.py b/model-optimizer/unit_tests/extensions/front/tf/sparse_to_dense_replacer_test.py similarity index 96% rename from model-optimizer/unit_tests/extensions/front/sparse_to_dense_replacer_test.py rename to model-optimizer/unit_tests/extensions/front/tf/sparse_to_dense_replacer_test.py index 588d52198c9..4e624dfd069 100644 --- a/model-optimizer/unit_tests/extensions/front/sparse_to_dense_replacer_test.py +++ b/model-optimizer/unit_tests/extensions/front/tf/sparse_to_dense_replacer_test.py @@ -3,7 +3,7 @@ import unittest -from extensions.front.sparse_to_dense_replacer import SparseToDenseReplacer +from extensions.front.tf.sparse_to_dense_replacer import SparseToDenseReplacer from mo.front.common.partial_infer.utils import int64_array from mo.utils.ir_engine.compare_graphs import compare_graphs from unit_tests.utils.graph import build_graph, const From 80c5f1a325c835ba4f819119a5294c3af5f89fa7 Mon Sep 17 00:00:00 2001 From: iliya mironov Date: Tue, 24 Aug 2021 15:43:19 +0300 Subject: [PATCH 21/76] Add support opset11 for gemm normalizer (#6733) * Add support opset11 for gemm normolizer * Add layer test for gemm opset 11 * Fix layer test * Fix layer test * Refactoring according to code review * Fix * Update biases norm * Refactoring matmul norm * Fix accoding to review * Fix alpha parameter * Fix variable naming * Refactoring according to code review --- .../extensions/front/MatMul_normalizer.py | 59 +++++++++---------- tests/layer_tests/onnx_tests/test_gemm.py | 51 ++++++++++------ 2 files changed, 60 insertions(+), 50 deletions(-) diff --git a/model-optimizer/extensions/front/MatMul_normalizer.py b/model-optimizer/extensions/front/MatMul_normalizer.py index 81588336d68..44bd5dce318 100644 --- a/model-optimizer/extensions/front/MatMul_normalizer.py +++ b/model-optimizer/extensions/front/MatMul_normalizer.py @@ -11,6 +11,7 @@ from extensions.ops.transpose import Transpose from mo.front.common.partial_infer.utils import int64_array from mo.front.common.replacement import FrontReplacementSubgraph from mo.front.subgraph_matcher import SubgraphMatch +from mo.front.tf.graph_utils import create_op_with_const_inputs from mo.graph.graph import Graph, rename_nodes from mo.ops.reshape import Reshape @@ -72,36 +73,32 @@ class GemmDecomposer(FrontReplacementSubgraph): """ enabled = True - def pattern(self): - return dict( - nodes=[('op', dict(kind='op', op='Gemm'))], - edges=[], - ) + def find_and_replace_pattern(self, graph: Graph): + for node in graph.get_op_nodes(op='Gemm'): + name = node.soft_get('name', node.id) + node_output_port = node.out_port(0) + if node.has_valid('alpha') and not math.isclose(node.alpha, 1): + mul_alpha = create_op_with_const_inputs(graph, Mul, {1: np.array(node.alpha)}, + {'name': name + '/Alpha', 'can_be_scaleshift': False}) + node_output_port.get_connection().insert_node(mul_alpha) + node_output_port = mul_alpha.out_port(0) + del node['alpha'] - def replace_sub_graph(self, graph: Graph, match: [dict, SubgraphMatch]): - node = match['op'] - name = node.soft_get('name', node.id) + if node.is_in_port_connected(2): + # biases normalization + bias_node = Add(graph, {'name': name + '/Bias_', 'can_be_scaleshift': False}).create_node() + without_biases_node_name = name + '/WithoutBiases' + rename_nodes([(node, without_biases_node_name), (bias_node, name)]) + node_output_port.get_connection().set_source(bias_node.out_port(0)) + node.in_port(2).get_connection().set_destination(bias_node.in_port(1)) + node_output_port.connect(bias_node.in_port(0)) + if node.has_valid('beta') and not math.isclose(node.beta, 1): + bias_node.insert_op_on_input_port(in_port_idx=1, new_op_class=Mul, value=np.array(node.beta), + new_op_attrs={'name': name + '/Beta', + 'can_be_scaleshift': False}) + del node['beta'] - # biases normalization - bias_node = Add(graph, {'name': name + '/Bias_', 'can_be_scaleshift': False}).create_node() - node_name = node.name + '/WithoutBiases' - bias_node_name = node.name - rename_nodes([(node, node_name), (bias_node, bias_node_name)]) - node.out_port(0).get_connection().set_source(bias_node.out_port(0)) - node.in_port(2).get_connection().set_destination(bias_node.in_port(1)) - node.out_port(0).connect(bias_node.in_port(0)) - - if node.has_valid('alpha') and not math.isclose(node.alpha, 1): - bias_node.insert_op_on_input_port(in_port_idx=0, new_op_class=Mul, value=np.array(node.alpha), - new_op_attrs={'name': name + '/Alpha_', 'can_be_scaleshift': False}) - del node['alpha'] - - if node.has_valid('beta') and not math.isclose(node.beta, 1): - bias_node.insert_op_on_input_port(in_port_idx=1, new_op_class=Mul, value=np.array(node.beta), - new_op_attrs={'name': name + '/Beta_', 'can_be_scaleshift': False}) - del node['beta'] - - MatMul.update_node_stat(node, { - 'transpose_a': node.has_and_set('transpose_a'), - 'transpose_b': node.has_and_set('transpose_b'), - }) + MatMul.update_node_stat(node, { + 'transpose_a': node.has_and_set('transpose_a'), + 'transpose_b': node.has_and_set('transpose_b'), + }) diff --git a/tests/layer_tests/onnx_tests/test_gemm.py b/tests/layer_tests/onnx_tests/test_gemm.py index 83bbe411c04..2aa78eca591 100644 --- a/tests/layer_tests/onnx_tests/test_gemm.py +++ b/tests/layer_tests/onnx_tests/test_gemm.py @@ -16,7 +16,7 @@ class TestGemm(OnnxRuntimeLayerTest): inputs_dict[input] = np.random.randn(*inputs_dict[input]).astype(np.float32) return inputs_dict - def create_net(self, shapeA, shapeB, shapeC, alpha, beta, trans_a, trans_b, precision, ir_version): + def create_net(self, shapeA, shapeB, shapeC, alpha, beta, trans_a, trans_b, precision, opset, ir_version,): """ ONNX net IR net @@ -46,6 +46,7 @@ class TestGemm(OnnxRuntimeLayerTest): const1 = np.random.ranf(_shapeB).astype(np.float) const2 = np.random.ranf(shapeC).astype(np.float) + nodes = list() node_const1_def = onnx.helper.make_node( 'Constant', inputs=[], @@ -57,18 +58,24 @@ class TestGemm(OnnxRuntimeLayerTest): vals=const1.flatten(), ), ) + nodes.append(node_const1_def) - node_const2_def = onnx.helper.make_node( - 'Constant', - inputs=[], - outputs=['const2'], - value=helper.make_tensor( - name='const_tensor', - data_type=TensorProto.FLOAT, - dims=const2.shape, - vals=const2.flatten(), - ), - ) + inputs = ['input', 'const1'] + + if opset is None or opset < 11: + node_const2_def = onnx.helper.make_node( + 'Constant', + inputs=[], + outputs=['const2'], + value=helper.make_tensor( + name='const_tensor', + data_type=TensorProto.FLOAT, + dims=const2.shape, + vals=const2.flatten(), + ), + ) + inputs.append('const2') + nodes.append(node_const2_def) attrs = dict() if alpha: @@ -81,21 +88,25 @@ class TestGemm(OnnxRuntimeLayerTest): attrs['transB'] = trans_b node_def = onnx.helper.make_node( 'Gemm', - inputs=['input', 'const1', 'const2'], + inputs=inputs, outputs=['output'], **attrs ) + nodes.append(node_def) # Create the graph (GraphProto) graph_def = helper.make_graph( - [node_const1_def, node_const2_def, node_def], + nodes, 'test_model', [input], [output], ) # Create the model (ModelProto) - onnx_net = helper.make_model(graph_def, producer_name='test_model') + args = dict(producer_name='test_model') + if opset: + args['opset_imports'] = [helper.make_opsetid("", opset)] + onnx_net = helper.make_model(graph_def, **args) # # Create reference IR net @@ -209,11 +220,12 @@ class TestGemm(OnnxRuntimeLayerTest): @pytest.mark.parametrize("beta", [None, 0.1, 2.0]) @pytest.mark.parametrize("trans_a", [None]) @pytest.mark.parametrize("trans_b", [None, 1]) + @pytest.mark.parametrize("opset", [None, 11]) @pytest.mark.nightly @pytest.mark.precommit - def test_gemm(self, params, alpha, beta, trans_a, trans_b, ie_device, precision, ir_version, temp_dir): + def test_gemm(self, params, alpha, beta, trans_a, trans_b, ie_device, precision, opset, ir_version, temp_dir): self._test(*self.create_net(params['shapeA'], params['shapeB'], params['shapeC'], alpha, beta, trans_a, - trans_b, precision, ir_version), ie_device, precision, ir_version, + trans_b, precision, opset, ir_version), ie_device, precision, ir_version, temp_dir=temp_dir) @pytest.mark.parametrize("params", test_data_bc) @@ -221,11 +233,12 @@ class TestGemm(OnnxRuntimeLayerTest): @pytest.mark.parametrize("beta", [None, 0.1, 2.0]) @pytest.mark.parametrize("trans_a", [None]) # transA is not supported @pytest.mark.parametrize("trans_b", [None, 1]) + @pytest.mark.parametrize("opset", [None, 11]) @pytest.mark.nightly @pytest.mark.precommit - def test_gemm_bc(self, params, alpha, beta, trans_a, trans_b, ie_device, precision, ir_version, temp_dir): + def test_gemm_bc(self, params, alpha, beta, trans_a, trans_b, ie_device, precision, opset, ir_version, temp_dir): self._test(*self.create_net(params['shapeA'], params['shapeB'], params['shapeC'], alpha, beta, trans_a, - trans_b, precision, ir_version), ie_device, precision, ir_version, + trans_b, precision, opset, ir_version), ie_device, precision, ir_version, temp_dir=temp_dir) @pytest.mark.parametrize("params", test_data) From 9228200ce56142d1e37a709858a52140fb0f3e6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Karzy=C5=84ski?= Date: Tue, 24 Aug 2021 16:36:30 +0200 Subject: [PATCH 22/76] Add support for ONNX RandomUniform and RandomUniformLike ops (#7190) --- .../onnx/frontend/src/op/random_uniform.cpp | 50 ++++++++++++++++ .../onnx/frontend/src/op/random_uniform.hpp | 20 +++++++ .../frontend/src/op/random_uniform_like.cpp | 56 +++++++++++++++++ .../frontend/src/op/random_uniform_like.hpp | 20 +++++++ .../frontend/onnx/frontend/src/ops_bridge.cpp | 4 ++ .../test/models/onnx/random_uniform.prototxt | 49 +++++++++++++++ .../models/onnx/random_uniform_like.prototxt | 60 +++++++++++++++++++ ngraph/test/onnx/onnx_import.in.cpp | 24 ++++++++ ngraph/test/runtime/ie/unit_test.manifest | 4 ++ .../runtime/interpreter/unit_test.manifest | 4 ++ 10 files changed, 291 insertions(+) create mode 100644 ngraph/frontend/onnx/frontend/src/op/random_uniform.cpp create mode 100644 ngraph/frontend/onnx/frontend/src/op/random_uniform.hpp create mode 100644 ngraph/frontend/onnx/frontend/src/op/random_uniform_like.cpp create mode 100644 ngraph/frontend/onnx/frontend/src/op/random_uniform_like.hpp create mode 100644 ngraph/test/models/onnx/random_uniform.prototxt create mode 100644 ngraph/test/models/onnx/random_uniform_like.prototxt diff --git a/ngraph/frontend/onnx/frontend/src/op/random_uniform.cpp b/ngraph/frontend/onnx/frontend/src/op/random_uniform.cpp new file mode 100644 index 00000000000..cf01a8edef8 --- /dev/null +++ b/ngraph/frontend/onnx/frontend/src/op/random_uniform.cpp @@ -0,0 +1,50 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "op/random_uniform.hpp" + +#include "default_opset.hpp" +#include "exceptions.hpp" +#include "ngraph/op/constant.hpp" +#include "ngraph/opsets/opset8.hpp" +#include "ngraph/shape.hpp" +#include "utils/common.hpp" + +namespace ngraph { +namespace onnx_import { +namespace op { +namespace set_1 { + +OutputVector random_uniform(const Node& node) { + CHECK_VALID_NODE(node, node.has_attribute("shape"), "RandomUniform operator must specify a 'shape' attribute."); + + const auto dtype = + node.get_attribute_value("dtype", static_cast(ONNX_NAMESPACE::TensorProto_DataType_FLOAT)); + const auto high = node.get_attribute_value("high", 1.0f); + const auto low = node.get_attribute_value("low", 0.0f); + const auto seed = node.get_attribute_value("seed", 0); + const auto shape = node.get_attribute_value>("shape"); + + const auto target_shape_const = default_opset::Constant::create(ngraph::element::i64, Shape{shape.size()}, shape); + const auto high_const = default_opset::Constant::create(ngraph::element::f32, Shape{1}, {high}); + const auto low_const = default_opset::Constant::create(ngraph::element::f32, Shape{1}, {low}); + + const auto target_type = common::get_ngraph_element_type(dtype); + const uint64_t global_seed = 0; + + return {std::make_shared(target_shape_const, + low_const, + high_const, + target_type, + global_seed, + seed)}; +} + +} // namespace set_1 + +} // namespace op + +} // namespace onnx_import + +} // namespace ngraph diff --git a/ngraph/frontend/onnx/frontend/src/op/random_uniform.hpp b/ngraph/frontend/onnx/frontend/src/op/random_uniform.hpp new file mode 100644 index 00000000000..e0015bba92e --- /dev/null +++ b/ngraph/frontend/onnx/frontend/src/op/random_uniform.hpp @@ -0,0 +1,20 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +#include "ngraph/node.hpp" +#include "onnx_import/core/node.hpp" + +namespace ngraph { +namespace onnx_import { +namespace op { +namespace set_1 { + +OutputVector random_uniform(const Node& node); + +} // namespace set_1 +} // namespace op +} // namespace onnx_import +} // namespace ngraph diff --git a/ngraph/frontend/onnx/frontend/src/op/random_uniform_like.cpp b/ngraph/frontend/onnx/frontend/src/op/random_uniform_like.cpp new file mode 100644 index 00000000000..0ca67362247 --- /dev/null +++ b/ngraph/frontend/onnx/frontend/src/op/random_uniform_like.cpp @@ -0,0 +1,56 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "op/random_uniform_like.hpp" + +#include "default_opset.hpp" +#include "exceptions.hpp" +#include "ngraph/op/constant.hpp" +#include "ngraph/opsets/opset8.hpp" +#include "ngraph/shape.hpp" +#include "utils/common.hpp" + +namespace ngraph { +namespace onnx_import { +namespace op { +namespace set_1 { + +OutputVector random_uniform_like(const Node& node) { + OutputVector inputs{node.get_ng_inputs()}; + auto input = inputs.at(0); + + ngraph::element::Type target_type; + if (node.has_attribute("dtype")) { + const auto dtype = node.get_attribute_value("dtype"); + target_type = common::get_ngraph_element_type(dtype); + } else { + target_type = input.get_element_type(); + } + + const auto target_shape = std::make_shared(input); + + const auto high = node.get_attribute_value("high", 1.0f); + const auto low = node.get_attribute_value("low", 0.0f); + const auto seed = node.get_attribute_value("seed", 0); + + const auto high_const = default_opset::Constant::create(ngraph::element::f32, Shape{1}, {high}); + const auto low_const = default_opset::Constant::create(ngraph::element::f32, Shape{1}, {low}); + + const uint64_t global_seed = 0; + + return {std::make_shared(target_shape, + low_const, + high_const, + target_type, + global_seed, + seed)}; +} + +} // namespace set_1 + +} // namespace op + +} // namespace onnx_import + +} // namespace ngraph diff --git a/ngraph/frontend/onnx/frontend/src/op/random_uniform_like.hpp b/ngraph/frontend/onnx/frontend/src/op/random_uniform_like.hpp new file mode 100644 index 00000000000..759ae3c2614 --- /dev/null +++ b/ngraph/frontend/onnx/frontend/src/op/random_uniform_like.hpp @@ -0,0 +1,20 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +#include "ngraph/node.hpp" +#include "onnx_import/core/node.hpp" + +namespace ngraph { +namespace onnx_import { +namespace op { +namespace set_1 { + +OutputVector random_uniform_like(const Node& node); + +} // namespace set_1 +} // namespace op +} // namespace onnx_import +} // namespace ngraph diff --git a/ngraph/frontend/onnx/frontend/src/ops_bridge.cpp b/ngraph/frontend/onnx/frontend/src/ops_bridge.cpp index bab0825909c..6d5fd9b3467 100644 --- a/ngraph/frontend/onnx/frontend/src/ops_bridge.cpp +++ b/ngraph/frontend/onnx/frontend/src/ops_bridge.cpp @@ -106,6 +106,8 @@ #include "op/org.openvinotoolkit/prior_box.hpp" #include "op/org.openvinotoolkit/swish.hpp" #include "op/quantize_linear.hpp" +#include "op/random_uniform.hpp" +#include "op/random_uniform_like.hpp" #include "op/range.hpp" #include "op/reciprocal.hpp" #include "op/reduce.hpp" @@ -366,6 +368,8 @@ OperatorsBridge::OperatorsBridge() { REGISTER_OPERATOR("QuantizeLinear", 1, quantize_linear); REGISTER_OPERATOR("QuantizeLinear", 13, quantize_linear); REGISTER_OPERATOR("Range", 1, range); + REGISTER_OPERATOR("RandomUniform", 1, random_uniform); + REGISTER_OPERATOR("RandomUniformLike", 1, random_uniform_like); REGISTER_OPERATOR("Reciprocal", 1, reciprocal); REGISTER_OPERATOR("ReduceLogSum", 1, reduce_log_sum); REGISTER_OPERATOR("ReduceLogSumExp", 1, reduce_log_sum_exp); diff --git a/ngraph/test/models/onnx/random_uniform.prototxt b/ngraph/test/models/onnx/random_uniform.prototxt new file mode 100644 index 00000000000..00b7d8ee3a5 --- /dev/null +++ b/ngraph/test/models/onnx/random_uniform.prototxt @@ -0,0 +1,49 @@ +ir_version: 3 +producer_name: "nGraph ONNX Importer" +graph { + node { + output: "y" + op_type: "RandomUniform" + attribute { + name: "shape" + ints: 2 + ints: 2 + type: INTS + } + attribute { + name: "high" + f: 50 + type: FLOAT + } + attribute { + name: "low" + f: 40 + type: FLOAT + } + attribute { + name: "seed" + i: 100 + type: INT + } + } + name: "test_model" + output { + name: "y" + type { + tensor_type { + elem_type: 1 + shape { + dim { + dim_value: 2 + } + dim { + dim_value: 2 + } + } + } + } + } +} +opset_import { + version: 1 +} diff --git a/ngraph/test/models/onnx/random_uniform_like.prototxt b/ngraph/test/models/onnx/random_uniform_like.prototxt new file mode 100644 index 00000000000..c90a94c7eca --- /dev/null +++ b/ngraph/test/models/onnx/random_uniform_like.prototxt @@ -0,0 +1,60 @@ +ir_version: 3 +producer_name: "nGraph ONNX Importer" +graph { + node { + input: "x" + output: "y" + op_type: "RandomUniformLike" + attribute { + name: "high" + f: 50 + type: FLOAT + } + attribute { + name: "low" + f: 40 + type: FLOAT + } + attribute { + name: "seed" + i: 100 + type: INT + } + } + name: "test_model" + input { + name: "x" + type { + tensor_type { + elem_type: 1 + shape { + dim { + dim_value: 2 + } + dim { + dim_value: 2 + } + } + } + } + } + output { + name: "y" + type { + tensor_type { + elem_type: 1 + shape { + dim { + dim_value: 2 + } + dim { + dim_value: 2 + } + } + } + } + } +} +opset_import { + version: 1 +} diff --git a/ngraph/test/onnx/onnx_import.in.cpp b/ngraph/test/onnx/onnx_import.in.cpp index e1cdd310cc0..ae74c4cbe6d 100644 --- a/ngraph/test/onnx/onnx_import.in.cpp +++ b/ngraph/test/onnx/onnx_import.in.cpp @@ -4022,3 +4022,27 @@ NGRAPH_TEST(${BACKEND_NAME}, onnx_float16_tensor_as_int32) { // clang-format on test_case.run(); } + +NGRAPH_TEST(${BACKEND_NAME}, onnx_model_random_uniform) { + const auto function = + onnx_import::import_onnx_model(file_util::path_join(SERIALIZED_ZOO, "onnx/random_uniform.onnx")); + + auto test_case = test::TestCase(function); + // These output values are unknown at this time as we don't have a reference implementation of random number + // generator + test_case.add_expected_output(Shape{2, 2}, {41, 42, 43, 44}); + test_case.run(); +} + +NGRAPH_TEST(${BACKEND_NAME}, onnx_model_random_uniform_like) { + const auto function = + onnx_import::import_onnx_model(file_util::path_join(SERIALIZED_ZOO, "onnx/random_uniform_like.onnx")); + + auto test_case = test::TestCase(function); + test_case.add_expected_output(Shape{2, 2}, {0, 0, 0, 0}); + + // These output values are unknown at this time as we don't have a reference implementation of random number + // generator + test_case.add_input(Shape{2, 2}, {41, 42, 43, 44}); + test_case.run(); +} diff --git a/ngraph/test/runtime/ie/unit_test.manifest b/ngraph/test/runtime/ie/unit_test.manifest index 625da707551..88ba3166cb6 100644 --- a/ngraph/test/runtime/ie/unit_test.manifest +++ b/ngraph/test/runtime/ie/unit_test.manifest @@ -41,6 +41,10 @@ onnx_model_matmul_integer_4d_no_zero_point onnx_model_qlinear_matmul onnx_model_qlinear_matmul_3d +# No support yet for RandomUniform +onnx_model_random_uniform +onnx_model_random_uniform_like + # Result mismatch onnx_model_shape onnx_model_split_equal_parts_default diff --git a/ngraph/test/runtime/interpreter/unit_test.manifest b/ngraph/test/runtime/interpreter/unit_test.manifest index 97183b4f61b..8ce07a2dcea 100644 --- a/ngraph/test/runtime/interpreter/unit_test.manifest +++ b/ngraph/test/runtime/interpreter/unit_test.manifest @@ -153,3 +153,7 @@ onnx_model_deformable_conv_2d # No support for unsigned types INTERPRETER.zero_sized_negative + +# No support yet for RandomUniform +INTERPRETER.onnx_model_random_uniform +INTERPRETER.onnx_model_random_uniform_like \ No newline at end of file From 192cb26c5ba314f2c0bdfb0da35e97f8bc0c146a Mon Sep 17 00:00:00 2001 From: "mei, yang" Date: Wed, 25 Aug 2021 11:39:59 +0800 Subject: [PATCH 23/76] remove adaptive pool2d shape check in ngraph paddle frontend (#7074) * remove adaptive pool2d shape check in ngraph paddle frontend * add ngraph paddle frontend dynamic pool2d test --- .../frontend/paddlepaddle/src/op/pool2d.cpp | 4 +-- .../frontend/paddlepaddle/convert_model.cpp | 1 + .../gen_scripts/generate_dynamic_pool2d.py | 32 +++++++++++++++++++ 3 files changed, 34 insertions(+), 3 deletions(-) create mode 100644 ngraph/test/frontend/paddlepaddle/test_models/gen_scripts/generate_dynamic_pool2d.py diff --git a/ngraph/frontend/paddlepaddle/src/op/pool2d.cpp b/ngraph/frontend/paddlepaddle/src/op/pool2d.cpp index dcd068434d5..a2c22983f01 100644 --- a/ngraph/frontend/paddlepaddle/src/op/pool2d.cpp +++ b/ngraph/frontend/paddlepaddle/src/op/pool2d.cpp @@ -100,8 +100,6 @@ NamedOutputs pool2d(const NodeContext& node) { {"Out"}); } } else if (adaptive) { - PDPD_ASSERT(input_shape[2].is_static() && input_shape[3].is_static(), - "pool2d: spatial dim must be static when using adaptive pool"); auto pool_size = std::vector(2, 0); if (kernel_shape.size() == 1) { @@ -187,4 +185,4 @@ NamedOutputs pool2d(const NodeContext& node) { } // namespace op } // namespace pdpd } // namespace frontend -} // namespace ngraph \ No newline at end of file +} // namespace ngraph diff --git a/ngraph/test/frontend/paddlepaddle/convert_model.cpp b/ngraph/test/frontend/paddlepaddle/convert_model.cpp index b7b207b755f..d3a68116e39 100644 --- a/ngraph/test/frontend/paddlepaddle/convert_model.cpp +++ b/ngraph/test/frontend/paddlepaddle/convert_model.cpp @@ -18,6 +18,7 @@ static const std::vector models{ std::string("2in_2out/2in_2out.pdmodel"), std::string("multi_tensor_split/multi_tensor_split.pdmodel"), std::string("2in_2out_dynbatch/2in_2out_dynbatch.pdmodel"), + std::string("pool2d_dyn_hw/pool2d_dyn_hw.pdmodel"), }; INSTANTIATE_TEST_SUITE_P(PDPDConvertModelTest, diff --git a/ngraph/test/frontend/paddlepaddle/test_models/gen_scripts/generate_dynamic_pool2d.py b/ngraph/test/frontend/paddlepaddle/test_models/gen_scripts/generate_dynamic_pool2d.py new file mode 100644 index 00000000000..7a10194599b --- /dev/null +++ b/ngraph/test/frontend/paddlepaddle/test_models/gen_scripts/generate_dynamic_pool2d.py @@ -0,0 +1,32 @@ +# +# pool2d paddle dynamic model generator +# + +import paddle +from paddle import fluid +import numpy as np +import sys +import os +from save_model import saveModel + +paddle.enable_static() +inp_blob1 = np.random.randn(1, 1, 224, 224).astype(np.float32) + +x1 = fluid.data(name='inputX1', shape=[1, 1, -1, -1], dtype='float32') + +adative_pool2d = paddle.fluid.layers.adaptive_pool2d( + input=x1, + pool_size=[3,3], + pool_type='avg', + require_index=False) + +cpu = paddle.static.cpu_places(1) +exe = paddle.static.Executor(cpu[0]) +# startup program will call initializer to initialize the parameters. +exe.run(paddle.static.default_startup_program()) + +outs = exe.run( + feed={'inputX1': inp_blob1}, + fetch_list=[adative_pool2d]) + +saveModel("pool2d_dyn_hw", exe, feedkeys=['inputX1'], fetchlist=adative_pool2d, inputs=[inp_blob1], outputs=outs, target_dir=sys.argv[1]) From 4d56803ce7235457343e6be36138fefc348b4d0d Mon Sep 17 00:00:00 2001 From: Gabriele Galiero Casay Date: Wed, 25 Aug 2021 06:09:41 +0200 Subject: [PATCH 24/76] Revise ReverseSequence reference implementation (#7117) * ReverseSequence ngraph op shell revision with type_prop tests * Add attribute count check in visitor test * Refactor backend tests to template plugin test with reference values * Rename cpu SLT instances * Add op to list of trusted operations * Rewrite validation check for input type due to backward compatibility * Reference implementation speed up by replacing index function call of CoordinateTransform by precalculated strides --- .../op_reference/reverse_sequence.cpp | 153 ++++++++ .../single_layer_tests/reverse_sequence.cpp | 2 +- .../layer_tests_summary/utils/constants.py | 1 + .../include/ngraph/op/reverse_sequence.hpp | 5 +- .../runtime/reference/reverse_sequence.hpp | 16 +- ngraph/core/src/op/reverse_sequence.cpp | 58 +-- ngraph/test/CMakeLists.txt | 1 - ngraph/test/backend/reverse_sequence.in.cpp | 179 ---------- ngraph/test/type_prop/reverse_sequence.cpp | 331 +++++++++++------- ngraph/test/visitors/op/reverse_sequence.cpp | 4 + 10 files changed, 408 insertions(+), 342 deletions(-) create mode 100644 docs/template_plugin/tests/functional/op_reference/reverse_sequence.cpp delete mode 100644 ngraph/test/backend/reverse_sequence.in.cpp diff --git a/docs/template_plugin/tests/functional/op_reference/reverse_sequence.cpp b/docs/template_plugin/tests/functional/op_reference/reverse_sequence.cpp new file mode 100644 index 00000000000..26e2289a528 --- /dev/null +++ b/docs/template_plugin/tests/functional/op_reference/reverse_sequence.cpp @@ -0,0 +1,153 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include + +#include +#include +#include +#include +#include +#include + +#include "base_reference_test.hpp" + +using namespace reference_tests; +using namespace ngraph; +using namespace InferenceEngine; + +namespace { +struct ReverseSequenceParams { + ReverseSequenceParams(const int64_t batchAxis, const int64_t seqAxis, const Tensor& dataTensor, const Tensor& seqLengthsTensor, + const Tensor& expectedTensor) : mBatchAxis(batchAxis), mSeqAxis(seqAxis), mDataTensor(dataTensor), + mSeqLengthsTensor(seqLengthsTensor), mExpectedTensor(expectedTensor) {} +int64_t mBatchAxis; +int64_t mSeqAxis; +Tensor mDataTensor; +Tensor mSeqLengthsTensor; +Tensor mExpectedTensor; +}; +class ReferenceReverseSequenceTest : public testing::TestWithParam, public CommonReferenceTest { +public: + void SetUp() override { + auto params = GetParam(); + function = CreateFunction(params); + inputData = {params.mDataTensor.data, params.mSeqLengthsTensor.data}; + refOutData = {params.mExpectedTensor.data}; + } + static std::string getTestCaseName(const testing::TestParamInfo& obj) { + auto param = obj.param; + std::ostringstream result; + result << "dataType=" << param.mDataTensor.type << "_"; + result << "dataShape=" << param.mDataTensor.shape << "_"; + result << "seqLenType=" << param.mSeqLengthsTensor.type << "_"; + result << "seqLenShape=" << param.mSeqLengthsTensor.shape << "_"; + result << "batchAxis=" << param.mBatchAxis << "_"; + result << "seqAxis=" << param.mSeqAxis; + return result.str(); + } + +private: + static std::shared_ptr CreateFunction(const ReverseSequenceParams& params) { + const auto data = std::make_shared(params.mDataTensor.type, params.mDataTensor.shape); + const auto seqLengths = std::make_shared(params.mSeqLengthsTensor.type, params.mSeqLengthsTensor.shape); + const auto reverseSequence = std::make_shared(data, seqLengths, params.mBatchAxis, params.mSeqAxis); + return std::make_shared(NodeVector {reverseSequence}, ParameterVector {data, seqLengths}); + } +}; + +TEST_P(ReferenceReverseSequenceTest, CompareWithRefs) { + Exec(); +} + +template +std::vector generateReverseSeqParams() { + using T = typename element_type_traits::value_type; + std::vector reverseSeqParams { + // 2D + ReverseSequenceParams(1, 0, + Tensor({4, 4}, IN_ET, std::vector{0, 4, 8, 12, + 1, 5, 9, 13, + 2, 6, 10, 14, + 3, 7, 11, 15}), + Tensor({4}, element::i32, std::vector{4, 3, 2, 1}), + Tensor({4, 4}, IN_ET, std::vector{3, 6, 9, 12, + 2, 5, 8, 13, + 1, 4, 10, 14, + 0, 7, 11, 15})), + ReverseSequenceParams(0, 1, + Tensor({4, 4}, IN_ET, std::vector{0, 1, 2, 3, + 4, 5, 6, 7, + 8, 9, 10, 11, + 12, 13, 14, 15}), + Tensor({4}, element::i32, std::vector{1, 2, 3, 4}), + Tensor({4, 4}, IN_ET, std::vector{0, 1, 2, 3, + 5, 4, 6, 7, + 10, 9, 8, 11, + 15, 14, 13, 12})), + // 4D + ReverseSequenceParams(2, 1, + Tensor({2, 3, 4, 2}, IN_ET, std::vector{ + 0, 0, 3, 0, 6, 0, 9, 0, 1, 0, 4, 0, 7, 0, 10, 0, 2, 0, 5, 0, 8, 0, 11, 0, + 12, 0, 15, 0, 18, 0, 21, 0, 13, 0, 16, 0, 19, 0, 22, 0, 14, 0, 17, 0, 20, 0, 23, 0}), + Tensor({4}, element::i32, std::vector{1, 2, 1, 2}), + Tensor({2, 3, 4, 2}, IN_ET, std::vector{ + 0, 0, 4, 0, 6, 0, 10, 0, 1, 0, 3, 0, 7, 0, 9, 0, 2, 0, 5, 0, 8, 0, 11, 0, + 12, 0, 16, 0, 18, 0, 22, 0, 13, 0, 15, 0, 19, 0, 21, 0, 14, 0, 17, 0, 20, 0, 23, 0})), + ReverseSequenceParams(-2, -3, + Tensor({2, 3, 4, 2}, IN_ET, std::vector{ + 0, 0, 3, 0, 6, 0, 9, 0, 1, 0, 4, 0, 7, 0, 10, 0, 2, 0, 5, 0, 8, 0, 11, 0, + 12, 0, 15, 0, 18, 0, 21, 0, 13, 0, 16, 0, 19, 0, 22, 0, 14, 0, 17, 0, 20, 0, 23, 0}), + Tensor({4}, element::i32, std::vector{1, 2, 1, 2}), + Tensor({2, 3, 4, 2}, IN_ET, std::vector{ + 0, 0, 4, 0, 6, 0, 10, 0, 1, 0, 3, 0, 7, 0, 9, 0, 2, 0, 5, 0, 8, 0, 11, 0, + 12, 0, 16, 0, 18, 0, 22, 0, 13, 0, 15, 0, 19, 0, 21, 0, 14, 0, 17, 0, 20, 0, 23, 0})), + ReverseSequenceParams(0, 1, + Tensor({4, 3, 2, 2}, IN_ET, std::vector{ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47}), + Tensor({4}, element::i32, std::vector{1, 2, 3, 3}), + Tensor({4, 3, 2, 2}, IN_ET, std::vector{ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 16, 17, 18, 19, + 12, 13, 14, 15, 20, 21, 22, 23, 32, 33, 34, 35, 28, 29, 30, 31, + 24, 25, 26, 27, 44, 45, 46, 47, 40, 41, 42, 43, 36, 37, 38, 39})), + // 5D + ReverseSequenceParams(0, 2, + Tensor({4, 2, 3, 2, 2}, IN_ET, std::vector{ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, + 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, + 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, + 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95}), + Tensor({4}, element::i32, std::vector{1, 2, 1, 2}), + Tensor({4, 3, 2, 2}, IN_ET, std::vector{ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 23, 28, 29, 30, 31, 24, 25, 26, 27, 32, 33, 34, 35, 40, 41, 42, 43, + 36, 37, 38, 39, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, + 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 76, 77, 78, 79, 72, 73, 74, 75, + 80, 81, 82, 83, 88, 89, 90, 91, 84, 85, 86, 87, 92, 93, 94, 95})) + }; + return reverseSeqParams; +} + +std::vector generateReverseSeqCombinedParams() { + const std::vector> reverseSeqTypeParams { + generateReverseSeqParams(), + generateReverseSeqParams(), + generateReverseSeqParams(), + generateReverseSeqParams(), + generateReverseSeqParams(), + generateReverseSeqParams()}; + std::vector combinedParams; + + for (const auto& params : reverseSeqTypeParams) { + combinedParams.insert(combinedParams.end(), params.begin(), params.end()); + } + return combinedParams; +} + +INSTANTIATE_TEST_SUITE_P(smoke_ReverseSequence_With_Hardcoded_Refs, ReferenceReverseSequenceTest, + testing::ValuesIn(generateReverseSeqCombinedParams()), ReferenceReverseSequenceTest::getTestCaseName); +} // namespace \ No newline at end of file diff --git a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/single_layer_tests/reverse_sequence.cpp b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/single_layer_tests/reverse_sequence.cpp index b1f864d12ae..b95660e3349 100644 --- a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/single_layer_tests/reverse_sequence.cpp +++ b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/single_layer_tests/reverse_sequence.cpp @@ -33,7 +33,7 @@ const std::vector secondaryInputTypes = { ngraph::helpers::InputLayerType::PARAMETER }; -INSTANTIATE_TEST_SUITE_P(Basic_smoke, ReverseSequenceLayerTest, +INSTANTIATE_TEST_SUITE_P(smoke_ReverseSequence, ReverseSequenceLayerTest, ::testing::Combine( ::testing::ValuesIn(batchAxisIndices), ::testing::ValuesIn(seqAxisIndices), diff --git a/inference-engine/tests/ie_test_utils/functional_test_utils/layer_tests_summary/utils/constants.py b/inference-engine/tests/ie_test_utils/functional_test_utils/layer_tests_summary/utils/constants.py index e3693da7e53..515e768ecb3 100644 --- a/inference-engine/tests/ie_test_utils/functional_test_utils/layer_tests_summary/utils/constants.py +++ b/inference-engine/tests/ie_test_utils/functional_test_utils/layer_tests_summary/utils/constants.py @@ -100,6 +100,7 @@ VERIFIED_OP_REFERENCES = [ 'Relu-1', 'ReorgYOLO-2', 'Result-1' + 'ReverseSequence-1', 'Round-5', 'SpaceToDepth-1', 'ScatterNDUpdate-4', diff --git a/ngraph/core/include/ngraph/op/reverse_sequence.hpp b/ngraph/core/include/ngraph/op/reverse_sequence.hpp index 5c8b37f41ad..836c89e11ea 100644 --- a/ngraph/core/include/ngraph/op/reverse_sequence.hpp +++ b/ngraph/core/include/ngraph/op/reverse_sequence.hpp @@ -21,7 +21,10 @@ public: /// tensor. /// \param batch_axis index of the batch dimension. /// \param seq_axis index of the sequence dimension. - ReverseSequence(const Output& arg, const Output& seq_lengths, int64_t batch_axis, int64_t seq_axis); + ReverseSequence(const Output& arg, + const Output& seq_lengths, + int64_t batch_axis = 0, + int64_t seq_axis = 1); bool visit_attributes(AttributeVisitor& visitor) override; void validate_and_infer_types() override; diff --git a/ngraph/core/reference/include/ngraph/runtime/reference/reverse_sequence.hpp b/ngraph/core/reference/include/ngraph/runtime/reference/reverse_sequence.hpp index b84fe400120..e9762132283 100644 --- a/ngraph/core/reference/include/ngraph/runtime/reference/reverse_sequence.hpp +++ b/ngraph/core/reference/include/ngraph/runtime/reference/reverse_sequence.hpp @@ -20,16 +20,14 @@ void reverse_sequence(const T* arg, size_t batch_axis, size_t sequence_axis, const U* sequence_lengths) { - NGRAPH_SUPPRESS_DEPRECATED_START - CoordinateTransform input_transform(arg_shape); + const auto strides = row_major_strides(arg_shape); + CoordinateTransformBasic input_transform(arg_shape); for (const Coordinate& in_coord : input_transform) { size_t batch_index = in_coord[batch_axis]; auto orig_seq_index = static_cast(sequence_lengths[batch_index]); - if (orig_seq_index > arg_shape.at(sequence_axis)) { - throw ngraph_error("One of the elements of sequence lengths is greater than sequence axis " - "dimension"); - } + NGRAPH_CHECK(orig_seq_index <= arg_shape.at(sequence_axis), + "One of the elements of sequence lengths is greater than sequence axis dimension"); if (orig_seq_index == 0) { orig_seq_index = 1; @@ -41,9 +39,11 @@ void reverse_sequence(const T* arg, // make a copy of in_coord and update sequence_index Coordinate out_coord = in_coord; out_coord[sequence_axis] = sequence_index; - out[input_transform.index(out_coord)] = arg[input_transform.index(in_coord)]; + + const size_t in_idx = std::inner_product(in_coord.begin(), in_coord.end(), strides.begin(), 0); + const size_t out_idx = std::inner_product(out_coord.begin(), out_coord.end(), strides.begin(), 0); + out[out_idx] = arg[in_idx]; } - NGRAPH_SUPPRESS_DEPRECATED_END } } // namespace reference } // namespace runtime diff --git a/ngraph/core/src/op/reverse_sequence.cpp b/ngraph/core/src/op/reverse_sequence.cpp index 711180e7db0..1eda1f50b1c 100644 --- a/ngraph/core/src/op/reverse_sequence.cpp +++ b/ngraph/core/src/op/reverse_sequence.cpp @@ -38,43 +38,49 @@ bool ngraph::op::v0::ReverseSequence::visit_attributes(AttributeVisitor& visitor void op::ReverseSequence::validate_and_infer_types() { NGRAPH_OP_SCOPE(v0_ReverseSequence_validate_and_infer_types); - auto input_shape = get_input_partial_shape(0); - auto input_rank = input_shape.rank(); - - m_normalized_batch_axis = ngraph::normalize_axis(this, m_batch_axis, input_rank); - m_normalized_seq_axis = ngraph::normalize_axis(this, m_seq_axis, input_rank); - - auto indices_shape = get_input_partial_shape(1); - auto indices_rank = indices_shape.rank(); + const auto& data_pshape = get_input_partial_shape(0); + const auto& data_rank = data_pshape.rank(); NODE_VALIDATION_CHECK(this, - indices_rank.is_dynamic() || indices_rank.get_length() == 1, - "Sequence indices must be a 1-dimensional tensor (sequence indices shape: ", - indices_shape, - ")."); + data_rank.is_dynamic() || data_rank.get_length() >= 2, + "Data input rank should be equal or greater than 2. Got: ", + data_pshape); - PartialShape output_shape{input_shape}; + m_normalized_batch_axis = ngraph::normalize_axis(this, m_batch_axis, data_rank); + m_normalized_seq_axis = ngraph::normalize_axis(this, m_seq_axis, data_rank); - if (input_rank.is_static() && indices_rank.is_static()) { + const auto& seq_lengths_et = get_input_element_type(1); + const auto& seq_lengths_pshape = get_input_partial_shape(1); + const auto& seq_lengths_rank = seq_lengths_pshape.rank(); + + NODE_VALIDATION_CHECK(this, + seq_lengths_et.is_real() || seq_lengths_et.is_integral_number(), + "Sequence lengths element type must be numeric type. Got: ", + seq_lengths_et); + + NODE_VALIDATION_CHECK(this, + seq_lengths_rank.compatible(1), + "Sequence lengths rank must be equal to 1. Got: ", + seq_lengths_pshape); + + PartialShape output_pshape{data_pshape}; + if (data_rank.is_static() && seq_lengths_rank.is_static()) { Dimension merged_sequence_length; - NODE_VALIDATION_CHECK( this, - Dimension::merge(merged_sequence_length, input_shape[m_normalized_batch_axis], indices_shape[0]), - "Sequence length (", - indices_shape[0], - ") is not equal to batch axis ", - "dimension (", - input_shape[m_normalized_batch_axis], + Dimension::merge(merged_sequence_length, data_pshape[m_normalized_batch_axis], seq_lengths_pshape[0]), + "Sequence lengths input size (", + seq_lengths_pshape[0], + ") is not equal to batch axis dimension of data input (", + data_pshape[m_normalized_batch_axis], ") (argument shape: ", - input_shape, + data_pshape, ", sequence indices shape: ", - indices_shape, + seq_lengths_pshape, ")."); - output_shape[m_normalized_batch_axis] = merged_sequence_length; + output_pshape[m_normalized_batch_axis] = merged_sequence_length; } - - set_output_type(0, get_input_element_type(0), output_shape); + set_output_type(0, get_input_element_type(0), output_pshape); } shared_ptr op::ReverseSequence::clone_with_new_inputs(const OutputVector& new_args) const { diff --git a/ngraph/test/CMakeLists.txt b/ngraph/test/CMakeLists.txt index 28017824f22..20fc2a0a184 100644 --- a/ngraph/test/CMakeLists.txt +++ b/ngraph/test/CMakeLists.txt @@ -501,7 +501,6 @@ set(MULTI_TEST_SRC backend/reorg_yolo.in.cpp backend/reshape.in.cpp backend/result.in.cpp - backend/reverse_sequence.in.cpp backend/reverse.in.cpp backend/roll.in.cpp backend/round.in.cpp diff --git a/ngraph/test/backend/reverse_sequence.in.cpp b/ngraph/test/backend/reverse_sequence.in.cpp deleted file mode 100644 index 75cf47ff127..00000000000 --- a/ngraph/test/backend/reverse_sequence.in.cpp +++ /dev/null @@ -1,179 +0,0 @@ -// Copyright (C) 2018-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#include "gtest/gtest.h" -#include "ngraph/ngraph.hpp" -#include "ngraph/runtime/tensor.hpp" -#include "runtime/backend.hpp" -#include "util/all_close.hpp" -#include "util/all_close_f.hpp" -#include "util/known_element_types.hpp" -#include "util/ndarray.hpp" -#include "util/test_control.hpp" -#include "util/test_tools.hpp" - -using namespace std; -using namespace ngraph; - -static string s_manifest = "${MANIFEST}"; - -NGRAPH_TEST(${BACKEND_NAME}, reverse_sequence_n2c3h4w2) { - Shape shape{2, 3, 4, 2}; - Shape seq_len_shape{4}; - auto A = make_shared(element::i32, shape); - auto B = make_shared(element::i32, seq_len_shape); - - size_t batch_axis = 2; - size_t sequence_axis = 1; - auto rs = std::make_shared(A, B, batch_axis, sequence_axis); - - auto f = make_shared(rs, ParameterVector{A, B}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}"); - - // Create some tensors for input/output - shared_ptr a = backend->create_tensor(element::i32, shape); - shared_ptr b = backend->create_tensor(element::i32, seq_len_shape); - - shared_ptr result = backend->create_tensor(element::i32, shape); - - std::vector input{ - 0, 0, 3, 0, 6, 0, 9, 0, 1, 0, 4, 0, 7, 0, 10, 0, 2, 0, 5, 0, 8, 0, 11, 0, - 12, 0, 15, 0, 18, 0, 21, 0, 13, 0, 16, 0, 19, 0, 22, 0, 14, 0, 17, 0, 20, 0, 23, 0, - }; - - std::vector seq_lengths{1, 2, 1, 2}; - copy_data(b, seq_lengths); - - std::vector expected{0, 0, 4, 0, 6, 0, 10, 0, 1, 0, 3, 0, 7, 0, 9, 0, 2, 0, 5, 0, 8, 0, 11, 0, - - 12, 0, 16, 0, 18, 0, 22, 0, 13, 0, 15, 0, 19, 0, 21, 0, 14, 0, 17, 0, 20, 0, 23, 0}; - - copy_data(a, input); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a, b}); - EXPECT_EQ(read_vector(result), expected); -} - -NGRAPH_TEST(${BACKEND_NAME}, reverse_sequence_n4c3h2w2) { - Shape shape{4, 3, 2, 2}; - auto A = make_shared(element::i32, shape); - Shape seq_len_shape{4}; - auto B = make_shared(element::i32, seq_len_shape); - - size_t batch_axis = 0; - size_t sequence_axis = 1; - - auto rs = std::make_shared(A, B, batch_axis, sequence_axis); - - auto f = make_shared(rs, ParameterVector{A, B}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}"); - - // Create some tensors for input/output - shared_ptr a = backend->create_tensor(element::i32, shape); - shared_ptr b = backend->create_tensor(element::i32, seq_len_shape); - - shared_ptr result = backend->create_tensor(element::i32, shape); - - std::vector seq_lengths{1, 2, 3, 3}; - copy_data(b, seq_lengths); - - std::vector input{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, - 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47}; - - std::vector expected{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 16, 17, 18, 19, - 12, 13, 14, 15, 20, 21, 22, 23, 32, 33, 34, 35, 28, 29, 30, 31, - 24, 25, 26, 27, 44, 45, 46, 47, 40, 41, 42, 43, 36, 37, 38, 39}; - - copy_data(a, input); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a, b}); - EXPECT_EQ(read_vector(result), expected); -} - -NGRAPH_TEST(${BACKEND_NAME}, reverse_sequence_n4d2c3h2w2) { - Shape shape{4, 2, 3, 2, 2}; - auto A = make_shared(element::i32, shape); - Shape seq_len_shape{4}; - auto B = make_shared(element::i32, seq_len_shape); - - size_t batch_axis = 0; - size_t sequence_axis = 2; - - auto rs = std::make_shared(A, B, batch_axis, sequence_axis); - - auto f = make_shared(rs, ParameterVector{A, B}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}"); - - // Create some tensors for input/output - shared_ptr a = backend->create_tensor(element::i32, shape); - shared_ptr b = backend->create_tensor(element::i32, seq_len_shape); - - shared_ptr result = backend->create_tensor(element::i32, shape); - - std::vector input{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, - 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, - 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, - 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, - 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95}; - - std::vector expected{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, - 20, 21, 22, 23, 28, 29, 30, 31, 24, 25, 26, 27, 32, 33, 34, 35, 40, 41, 42, 43, - 36, 37, 38, 39, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, - 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 76, 77, 78, 79, 72, 73, 74, 75, - 80, 81, 82, 83, 88, 89, 90, 91, 84, 85, 86, 87, 92, 93, 94, 95}; - - copy_data(a, input); - - std::vector seq_lengths{1, 2, 1, 2}; - copy_data(b, seq_lengths); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a, b}); - EXPECT_EQ(read_vector(result), expected); -} - -NGRAPH_TEST(${BACKEND_NAME}, reverse_sequence_negative_axes) { - Shape shape{2, 3, 4, 2}; - Shape seq_len_shape{4}; - auto A = make_shared(element::i32, shape); - auto B = make_shared(element::i32, seq_len_shape); - - int64_t batch_axis = -2; - int64_t sequence_axis = -3; - auto rs = std::make_shared(A, B, batch_axis, sequence_axis); - - auto f = make_shared(rs, ParameterVector{A, B}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}"); - - // Create some tensors for input/output - shared_ptr a = backend->create_tensor(element::i32, shape); - shared_ptr b = backend->create_tensor(element::i32, seq_len_shape); - - shared_ptr result = backend->create_tensor(element::i32, shape); - - std::vector input{ - 0, 0, 3, 0, 6, 0, 9, 0, 1, 0, 4, 0, 7, 0, 10, 0, 2, 0, 5, 0, 8, 0, 11, 0, - 12, 0, 15, 0, 18, 0, 21, 0, 13, 0, 16, 0, 19, 0, 22, 0, 14, 0, 17, 0, 20, 0, 23, 0, - }; - - std::vector seq_lengths{1, 2, 1, 2}; - copy_data(b, seq_lengths); - - std::vector expected{0, 0, 4, 0, 6, 0, 10, 0, 1, 0, 3, 0, 7, 0, 9, 0, 2, 0, 5, 0, 8, 0, 11, 0, - - 12, 0, 16, 0, 18, 0, 22, 0, 13, 0, 15, 0, 19, 0, 21, 0, 14, 0, 17, 0, 20, 0, 23, 0}; - - copy_data(a, input); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a, b}); - EXPECT_EQ(read_vector(result), expected); -} diff --git a/ngraph/test/type_prop/reverse_sequence.cpp b/ngraph/test/type_prop/reverse_sequence.cpp index 6b470d3d0e4..9f88013506b 100644 --- a/ngraph/test/type_prop/reverse_sequence.cpp +++ b/ngraph/test/type_prop/reverse_sequence.cpp @@ -9,232 +9,311 @@ using namespace std; using namespace ngraph; -TEST(type_prop, reverse_sequence_1_dim) { - auto data = make_shared(element::f32, Shape{4, 3, 2}); - auto seq_lengths = make_shared(element::f32, Shape{4, 4}); - try { - size_t batch_axis = 0; - size_t seq_axis = 1; - auto bc = make_shared(data, seq_lengths, batch_axis, seq_axis); - FAIL() << "ReverseSequence c-tor should throw for seq_lengths whose rank isn't equal to 1"; - } catch (const NodeValidationFailure& error) { - EXPECT_HAS_SUBSTRING(error.what(), std::string("Sequence indices must be a 1-dimensional tensor")); - } catch (...) { - FAIL() << "Deduced type check failed for unexpected reason"; +TEST(type_prop, reverse_sequence_default_attributes) { + auto data = make_shared(element::f32, PartialShape{4, 3, 2}); + auto seq_lengths = make_shared(element::i32, PartialShape{4}); + auto reverse_seq = make_shared(data, seq_lengths); + + EXPECT_EQ(reverse_seq->get_batch_axis(), 0); + EXPECT_EQ(reverse_seq->get_sequence_axis(), 1); + EXPECT_EQ(reverse_seq->get_input_size(), 2); + EXPECT_EQ(reverse_seq->get_output_size(), 1); + EXPECT_EQ(reverse_seq->get_output_element_type(0), (element::f32)); + EXPECT_EQ(reverse_seq->get_output_partial_shape(0), (PartialShape{4, 3, 2})); +} + +TEST(type_prop, reverse_sequence_negative_attribute_axes) { + int64_t batch_axis = -3; + int64_t seq_axis = -2; + auto data = make_shared(element::f32, PartialShape{1, 2, 3, 4, 5}); + auto seq_lengths = make_shared(element::i32, PartialShape{3}); + auto reverse_seq = make_shared(data, seq_lengths, batch_axis, seq_axis); + + EXPECT_EQ(reverse_seq->get_batch_axis(), 2); + EXPECT_EQ(reverse_seq->get_sequence_axis(), 3); + EXPECT_EQ(reverse_seq->get_input_size(), 2); + EXPECT_EQ(reverse_seq->get_output_size(), 1); + EXPECT_EQ(reverse_seq->get_output_element_type(0), (element::f32)); + EXPECT_EQ(reverse_seq->get_output_partial_shape(0), (PartialShape{1, 2, 3, 4, 5})); +} + +TEST(type_prop, reverse_sequence_data_et) { + std::vector element_types{element::u4, + element::u8, + element::u16, + element::u32, + element::i8, + element::i16, + element::i32, + element::i64, + element::f16, + element::f32, + element::boolean}; + for (auto& et : element_types) { + try { + auto data = std::make_shared(et, PartialShape{4, 4}); + auto seq_lengths = std::make_shared(element::i32, PartialShape{4}); + + EXPECT_NO_THROW(std::make_shared(data, seq_lengths)); + } catch (...) { + FAIL() << "Data input element type validation check failed for unexpected reason"; + } } } -TEST(type_prop, reverse_sequence_batch_index_oob) { - auto data = make_shared(element::f32, Shape{4, 3, 2}); - auto seq_lengths = make_shared(element::f32, Shape{3}); +TEST(type_prop, reverse_sequence_invalid_seq_lengths_et) { + int64_t batch_axis = 0; + int64_t seq_axis = 1; + std::vector invalid_et{element::bf16, element::f16, element::f32, element::boolean}; + auto data = make_shared(element::f32, PartialShape{4, 3, 2}); + auto seq_lengths = make_shared(element::boolean, PartialShape{4}); try { - size_t batch_axis = 3; - size_t seq_axis = 1; - auto bc = make_shared(data, seq_lengths, batch_axis, seq_axis); - FAIL() << "ReverseSequence c-tor should throw for out-of-bounds batch axis index"; + auto reverse_seq = make_shared(data, seq_lengths, batch_axis, seq_axis); + FAIL() << "Invalid element type of seq_lengths input not detected"; + } catch (const NodeValidationFailure& error) { + EXPECT_HAS_SUBSTRING(error.what(), std::string("Sequence lengths element type must be numeric type.")); + } catch (...) { + FAIL() << "Element type validation check of seq_lengths input failed for unexpected reason"; + } +} + +TEST(type_prop, reverse_sequence_invalid_data_rank) { + std::vector invalid_pshapes = {{}, {4}}; + for (auto& pshape : invalid_pshapes) { + try { + auto data = make_shared(element::f32, pshape); + auto seq_lengths = make_shared(element::i32, PartialShape{1}); + auto reverse_seq = make_shared(data, seq_lengths); + FAIL() << "Invalid rank of data input not detected"; + } catch (const NodeValidationFailure& error) { + EXPECT_HAS_SUBSTRING(error.what(), std::string("Data input rank should be equal or greater than 2.")); + } catch (...) { + FAIL() << "Rank check of data input failed for unexpected reason"; + } + } +} + +TEST(type_prop, reverse_sequence_invalid_seq_lengths_rank) { + std::vector invalid_pshapes = {{}, {4, 1}, {1, 1, 4}}; + int64_t batch_axis = 0; + int64_t seq_axis = 1; + auto data = make_shared(element::f32, PartialShape{4, 3, 2}); + for (auto& pshape : invalid_pshapes) { + try { + auto seq_lengths = make_shared(element::i32, pshape); + auto reverse_seq = make_shared(data, seq_lengths, batch_axis, seq_axis); + FAIL() << "Invalid rank of seq_lengths input not detected"; + } catch (const NodeValidationFailure& error) { + EXPECT_HAS_SUBSTRING(error.what(), std::string("Sequence lengths rank must be equal to 1.")); + } catch (...) { + FAIL() << "Rank check of seq_lengths input failed for unexpected reason"; + } + } +} + +TEST(type_prop, reverse_sequence_invalid_batch_axis_value) { + int64_t batch_axis = 3; + int64_t seq_axis = 1; + auto data = make_shared(element::f32, PartialShape{4, 3, 2}); + auto seq_lengths = make_shared(element::i32, PartialShape{3}); + try { + auto reverse_seq = make_shared(data, seq_lengths, batch_axis, seq_axis); + FAIL() << "Invalid value of batch_axis attribute not detected"; } catch (const ngraph_error& error) { EXPECT_HAS_SUBSTRING(error.what(), std::string("Parameter axis 3 out of the tensor rank")); } catch (...) { - FAIL() << "Deduced type check failed for unexpected reason"; + FAIL() << "Out of bounds check of batch_axis attribute failed for unexpected reason"; } } -TEST(type_prop, reverse_sequence_sequence_index_oob) { - auto data = make_shared(element::f32, Shape{4, 3, 2}); - auto seq_lengths = make_shared(element::f32, Shape{3}); +TEST(type_prop, reverse_sequence_invalid_seq_axis_value) { + int64_t batch_axis = 1; + int64_t seq_axis = 3; + auto data = make_shared(element::f32, PartialShape{4, 3, 2}); + auto seq_lengths = make_shared(element::i32, PartialShape{3}); try { - size_t batch_axis = 1; - size_t seq_axis = 3; - auto bc = make_shared(data, seq_lengths, batch_axis, seq_axis); - FAIL() << "ReverseSequence c-tor should throw for out-of-bounds sequence axis index"; + auto reverse_seq = make_shared(data, seq_lengths, batch_axis, seq_axis); + FAIL() << "Invalid value of seq_axis attribute not detected"; } catch (const ngraph_error& error) { EXPECT_HAS_SUBSTRING(error.what(), std::string("Parameter axis 3 out of the tensor rank")); } catch (...) { - FAIL() << "Deduced type check failed for unexpected reason"; + FAIL() << "Out of bounds check of seq_axis attribute failed for unexpected reason"; } } -TEST(type_prop, reverse_sequence_seq_len_size_equal_to_batch_dim) { - auto data = make_shared(element::f32, Shape{4, 3, 2}); - auto seq_lengths = make_shared(element::f32, Shape{3}); +TEST(type_prop, reverse_sequence_incompatible_seq_len_size_with_batch_dim) { + auto data = make_shared(element::f32, PartialShape{4, 3, 2}); + auto seq_lengths = make_shared(element::i32, PartialShape{3}); try { - size_t batch_axis = 0; - size_t seq_axis = 1; - auto bc = make_shared(data, seq_lengths, batch_axis, seq_axis); - FAIL() << "ReverseSequence c-tor should throw when sequence length size isn't equal to " - "batch dimension"; + auto reverse_seq = make_shared(data, seq_lengths); + FAIL() << "Incompatible number of elements between seq_lengths and batch dimension of data input not detected"; } catch (const NodeValidationFailure& error) { - EXPECT_HAS_SUBSTRING(error.what(), std::string("Sequence length (3) is not equal to batch axis dimension (4)")); + EXPECT_HAS_SUBSTRING( + error.what(), + std::string("Sequence lengths input size (3) is not equal to batch axis dimension of data input (4)")); } catch (...) { - FAIL() << "Deduced type check failed for unexpected reason"; + FAIL() << "Number of elements of input seq_lengths check with respect batch dimension of input failed for " + "unexpected reason"; } } -TEST(type_prop, reverse_sequence_partial_both_rank_dynamic) { +TEST(type_prop, reverse_sequence_dynamic_inputs_with_dynamic_rank) { auto data = make_shared(element::f32, PartialShape::dynamic()); - auto seq_lengths = make_shared(element::f32, PartialShape::dynamic()); + auto seq_lengths = make_shared(element::i32, PartialShape::dynamic()); // Unrealistic values, but they don't matter here. - size_t batch_axis = 202; - size_t seq_axis = 909; - auto rs = make_shared(data, seq_lengths, batch_axis, seq_axis); + int64_t batch_axis = 202; + int64_t seq_axis = 909; + auto reverse_seq = make_shared(data, seq_lengths, batch_axis, seq_axis); - EXPECT_TRUE(rs->get_output_partial_shape(0).is_dynamic()); - EXPECT_EQ(rs->get_output_element_type(0), element::f32); + EXPECT_EQ(reverse_seq->get_output_partial_shape(0), (PartialShape::dynamic())); + EXPECT_EQ(reverse_seq->get_output_element_type(0), element::f32); } -TEST(type_prop, reverse_sequence_partial_left_rank_dynamic) { +TEST(type_prop, reverse_sequence_dynamic_data_input_dynamic_rank) { auto data = make_shared(element::f32, PartialShape::dynamic()); - auto seq_lengths = make_shared(element::f32, PartialShape{3}); + auto seq_lengths = make_shared(element::i32, PartialShape{3}); // Unrealistic values, but they don't matter here. - size_t batch_axis = 202; - size_t seq_axis = 909; - auto rs = make_shared(data, seq_lengths, batch_axis, seq_axis); + int64_t batch_axis = 202; + int64_t seq_axis = 909; + auto reverse_seq = make_shared(data, seq_lengths, batch_axis, seq_axis); - EXPECT_TRUE(rs->get_output_partial_shape(0).is_dynamic()); - EXPECT_EQ(rs->get_output_element_type(0), element::f32); + EXPECT_EQ(reverse_seq->get_output_partial_shape(0), (PartialShape::dynamic())); + EXPECT_EQ(reverse_seq->get_output_element_type(0), element::f32); } -TEST(type_prop, reverse_sequence_partial_right_rank_dynamic) { +TEST(type_prop, reverse_sequence_dynamic_seq_lenghts_input_dynamic_rank) { auto data = make_shared(element::f32, PartialShape{2, 4, 6, 8}); - auto seq_lengths = make_shared(element::f32, PartialShape::dynamic()); - size_t batch_axis = 0; - size_t seq_axis = 1; - auto rs = make_shared(data, seq_lengths, batch_axis, seq_axis); + auto seq_lengths = make_shared(element::i32, PartialShape::dynamic()); + int64_t batch_axis = 0; + int64_t seq_axis = 1; + auto reverse_seq = make_shared(data, seq_lengths, batch_axis, seq_axis); - EXPECT_TRUE(rs->get_output_partial_shape(0).same_scheme(PartialShape{2, 4, 6, 8})); - EXPECT_EQ(rs->get_output_element_type(0), element::f32); + EXPECT_TRUE(reverse_seq->get_output_partial_shape(0).same_scheme(PartialShape{2, 4, 6, 8})); + EXPECT_EQ(reverse_seq->get_output_element_type(0), element::f32); } -TEST(type_prop, reverse_sequence_partial_both_rank_static_dynamic) { +TEST(type_prop, reverse_sequence_dynamic_data_input_static_rank_and_seq_lengths_dynamic_rank) { auto data = make_shared( element::f32, PartialShape{Dimension::dynamic(), Dimension::dynamic(), Dimension::dynamic(), Dimension::dynamic()}); - auto seq_lengths = make_shared(element::f32, PartialShape::dynamic()); - size_t batch_axis = 0; - size_t seq_axis = 1; - auto rs = make_shared(data, seq_lengths, batch_axis, seq_axis); + auto seq_lengths = make_shared(element::i32, PartialShape::dynamic()); + int64_t batch_axis = 0; + int64_t seq_axis = 1; + auto reverse_seq = make_shared(data, seq_lengths, batch_axis, seq_axis); - EXPECT_TRUE(rs->get_output_partial_shape(0).same_scheme( + EXPECT_TRUE(reverse_seq->get_output_partial_shape(0).same_scheme( PartialShape{Dimension::dynamic(), Dimension::dynamic(), Dimension::dynamic(), Dimension::dynamic()})); - EXPECT_EQ(rs->get_output_element_type(0), element::f32); + EXPECT_EQ(reverse_seq->get_output_element_type(0), element::f32); } -TEST(type_prop, reverse_sequence_partial_both_rank_static_dynamic_batch_axis_oob) { +TEST(type_prop, reverse_sequence_dynamic_invalid_batch_axis) { auto data = make_shared( element::f32, PartialShape{Dimension::dynamic(), Dimension::dynamic(), Dimension::dynamic(), Dimension::dynamic()}); - auto seq_lengths = make_shared(element::f32, PartialShape{Dimension::dynamic()}); - size_t batch_axis = 4; - size_t seq_axis = 1; + auto seq_lengths = make_shared(element::i32, PartialShape{Dimension::dynamic()}); + int64_t batch_axis = 4; + int64_t seq_axis = 1; try { - auto rs = make_shared(data, seq_lengths, batch_axis, seq_axis); - FAIL() << "Batch axis out of bounds not detected (rank-static dynamic shape)"; + auto reverse_seq = make_shared(data, seq_lengths, batch_axis, seq_axis); + FAIL() << "Invalid batch_axis attribute value not detected (rank-static dynamic shape)"; } catch (const ngraph_error& error) { EXPECT_HAS_SUBSTRING(error.what(), std::string("Parameter axis 4 out of the tensor rank")); } catch (...) { - FAIL() << "Deduced type check failed for unexpected reason"; + FAIL() << "Out of bounds check of batch_axis attribute failed for unexpected reason"; } } -TEST(type_prop, reverse_sequence_partial_both_rank_static_dynamic_sequence_axis_oob) { +TEST(type_prop, reverse_sequence_dynamic_invalid_seq_axis) { auto data = make_shared( element::f32, PartialShape{Dimension::dynamic(), Dimension::dynamic(), Dimension::dynamic(), Dimension::dynamic()}); - auto seq_lengths = make_shared(element::f32, PartialShape{Dimension::dynamic()}); - size_t batch_axis = 1; - size_t seq_axis = 4; + auto seq_lengths = make_shared(element::i32, PartialShape{Dimension::dynamic()}); + int64_t batch_axis = 1; + int64_t seq_axis = 4; try { - auto rs = make_shared(data, seq_lengths, batch_axis, seq_axis); - FAIL() << "Sequence axis out of bounds not detected (rank-static dynamic shape)"; + auto reverse_seq = make_shared(data, seq_lengths, batch_axis, seq_axis); + FAIL() << "Invalid seq_axis attribute value not detected (rank-static dynamic shape)"; } catch (const ngraph_error& error) { EXPECT_HAS_SUBSTRING(error.what(), std::string("Parameter axis 4 out of the tensor rank")); } catch (...) { - FAIL() << "Deduced type check failed for unexpected reason"; + FAIL() << "Out of bounds check of seq_axis attribute failed for unexpected reason"; } } -TEST(type_prop, reverse_sequence_partial_left_rank_static_dynamic_right_static_left_seq_length_dynamic) { +TEST(type_prop, reverse_sequence_dynamic_data_input_static_rank) { auto data = make_shared( element::f32, PartialShape{Dimension::dynamic(), Dimension::dynamic(), Dimension::dynamic(), Dimension::dynamic()}); - auto seq_lengths = make_shared(element::f32, PartialShape{3}); - size_t batch_axis = 2; - size_t seq_axis = 1; - auto rs = make_shared(data, seq_lengths, batch_axis, seq_axis); + auto seq_lengths = make_shared(element::i32, PartialShape{3}); + int64_t batch_axis = 2; + int64_t seq_axis = 1; + auto reverse_seq = make_shared(data, seq_lengths, batch_axis, seq_axis); - EXPECT_TRUE(rs->get_output_partial_shape(0).same_scheme( + EXPECT_TRUE(reverse_seq->get_output_partial_shape(0).same_scheme( PartialShape{Dimension::dynamic(), Dimension::dynamic(), 3, Dimension::dynamic()})); - EXPECT_EQ(rs->get_output_element_type(0), element::f32); + EXPECT_EQ(reverse_seq->get_output_element_type(0), element::f32); } -TEST(type_prop, reverse_sequence_partial_both_rank_static_dynamic_right_seq_length_dynamic) { +TEST(type_prop, reverse_sequence_dynamic_data_input_static_rank_seq_lengths_input_dynamic_rank) { auto data = make_shared(element::f32, PartialShape{Dimension::dynamic(), Dimension::dynamic(), 3, Dimension::dynamic()}); - auto seq_lengths = make_shared(element::f32, PartialShape{Dimension::dynamic()}); - size_t batch_axis = 2; - size_t seq_axis = 1; - auto rs = make_shared(data, seq_lengths, batch_axis, seq_axis); + auto seq_lengths = make_shared(element::i32, PartialShape{Dimension::dynamic()}); + int64_t batch_axis = 2; + int64_t seq_axis = 1; + auto reverse_seq = make_shared(data, seq_lengths, batch_axis, seq_axis); - EXPECT_TRUE(rs->get_output_partial_shape(0).same_scheme( + EXPECT_TRUE(reverse_seq->get_output_partial_shape(0).same_scheme( PartialShape{Dimension::dynamic(), Dimension::dynamic(), 3, Dimension::dynamic()})); - EXPECT_EQ(rs->get_output_element_type(0), element::f32); + EXPECT_EQ(reverse_seq->get_output_element_type(0), element::f32); } -TEST(type_prop, reverse_sequence_partial_left_rank_static_dynamic_right_static_left_seq_length_static) { +TEST(type_prop, reverse_sequence_dynamic_data_input_static_rank_with_static_batch_dim) { auto data = make_shared(element::f32, PartialShape{Dimension::dynamic(), Dimension::dynamic(), 3, Dimension::dynamic()}); - auto seq_lengths = make_shared(element::f32, PartialShape{3}); - size_t batch_axis = 2; - size_t seq_axis = 1; - auto rs = make_shared(data, seq_lengths, batch_axis, seq_axis); + auto seq_lengths = make_shared(element::i32, PartialShape{3}); + int64_t batch_axis = 2; + int64_t seq_axis = 1; + auto reverse_seq = make_shared(data, seq_lengths, batch_axis, seq_axis); - EXPECT_TRUE(rs->get_output_partial_shape(0).same_scheme( + EXPECT_TRUE(reverse_seq->get_output_partial_shape(0).same_scheme( PartialShape{Dimension::dynamic(), Dimension::dynamic(), 3, Dimension::dynamic()})); - EXPECT_EQ(rs->get_output_element_type(0), element::f32); + EXPECT_EQ(reverse_seq->get_output_element_type(0), element::f32); } -TEST(type_prop, reverse_sequence_partial_left_rank_static_dynamic_right_static_left_seq_length_static_inconsistent) { +TEST(type_prop, reverse_sequence_dynamic_incompatible_data_input_static_rank_with_static_batch_dim) { auto data = make_shared(element::f32, PartialShape{Dimension::dynamic(), Dimension::dynamic(), 3, Dimension::dynamic()}); - auto seq_lengths = make_shared(element::f32, PartialShape{4}); - size_t batch_axis = 2; - size_t seq_axis = 1; + auto seq_lengths = make_shared(element::i32, PartialShape{4}); + int64_t batch_axis = 2; + int64_t seq_axis = 1; try { - auto rs = make_shared(data, seq_lengths, batch_axis, seq_axis); - FAIL() << "Inconsistent sequence length not detected (rank-static dynamic shape)"; + auto reverse_seq = make_shared(data, seq_lengths, batch_axis, seq_axis); + FAIL() << "Incompatible number of elements between seq_lengths and batch dimension of data input not detected " + "(rank-static dynamic shape)"; } catch (const NodeValidationFailure& error) { - EXPECT_HAS_SUBSTRING(error.what(), std::string("Sequence length (4) is not equal to batch axis dimension (3)")); + EXPECT_HAS_SUBSTRING( + error.what(), + std::string("Sequence lengths input size (4) is not equal to batch axis dimension of data input (3)")); } catch (...) { - FAIL() << "Deduced type check failed for unexpected reason"; + FAIL() << "Number of elements of input seq_lengths check with respect batch dimension of input failed for " + "unexpected reason"; } } -TEST(type_prop, reverse_sequence_negative_axis_dynamic_input_rank) { +TEST(type_prop, reverse_sequence_dynamic_invalid_negative_axis_and_data_input_dynamic_rank) { auto data = make_shared(element::f32, PartialShape::dynamic()); - auto seq_lengths = make_shared(element::f32, PartialShape{1}); + auto seq_lengths = make_shared(element::i32, PartialShape{1}); int64_t batch_axis = 1; int64_t seq_axis = -2; try { - auto rs = make_shared(data, seq_lengths, batch_axis, seq_axis); - FAIL() << "Dynamic input rank for negative axis not detected"; + auto reverse_seq = make_shared(data, seq_lengths, batch_axis, seq_axis); + FAIL() << "Dynamic rank of data input for negative axis not detected"; } catch (const CheckFailure& error) { EXPECT_HAS_SUBSTRING(error.what(), std::string("Rank must be static in order to normalize negative axis=-2")); } catch (...) { - FAIL() << "Deduced type check failed for unexpected reason"; + FAIL() << "Static rank of data input for negative axis validation check failed for unexpected reason"; } } - -TEST(type_prop, reverse_sequence_negative_axes_support) { - auto data = make_shared(element::f32, PartialShape{1, 2, 3, 4, 5}); - auto seq_lengths = make_shared(element::f32, PartialShape{3}); - int64_t batch_axis = -3; - int64_t seq_axis = -2; - - auto rs = make_shared(data, seq_lengths, batch_axis, seq_axis); - - EXPECT_EQ(rs->get_batch_axis(), 2); - EXPECT_EQ(rs->get_sequence_axis(), 3); -} diff --git a/ngraph/test/visitors/op/reverse_sequence.cpp b/ngraph/test/visitors/op/reverse_sequence.cpp index 75613e26a6c..22318779f22 100644 --- a/ngraph/test/visitors/op/reverse_sequence.cpp +++ b/ngraph/test/visitors/op/reverse_sequence.cpp @@ -25,7 +25,11 @@ TEST(attributes, reverse_sequence_op) { auto seq_axis = 1; auto reverse_sequence = make_shared(data, seq_indices, batch_axis, seq_axis); + NodeBuilder builder(reverse_sequence); + const auto expected_attr_count = 2; + EXPECT_EQ(builder.get_value_map_size(), expected_attr_count); + auto g_reverse_sequence = ov::as_type_ptr(builder.create()); EXPECT_EQ(g_reverse_sequence->get_origin_batch_axis(), reverse_sequence->get_origin_batch_axis()); From 4297253589477737886a7f797c8433db9e690aea Mon Sep 17 00:00:00 2001 From: Ilya Churaev Date: Wed, 25 Aug 2021 07:13:01 +0300 Subject: [PATCH 25/76] Moved attribute_adapter, attribute_visitor files to ov namespave (#7179) * Fixed nGraph build * Fixed nGraph unit tests * Fixed func tests * Fix some operators * Fixed build * Try to fix specialization in different namespace * Try to fix build * Fixed element_type --- .../include/legacy/ngraph_ops/eltwise.hpp | 6 +- .../src/legacy_api/src/ngraph_ops/eltwise.cpp | 10 +- .../include/ngraph_ops/framework_node.hpp | 12 +- .../src/ngraph_ops/framework_node.cpp | 4 +- .../compare_functions_test.cpp | 6 +- .../core/include/ngraph/attribute_adapter.hpp | 455 +---------------- .../core/include/ngraph/attribute_visitor.hpp | 124 +---- ngraph/core/include/ngraph/axis_set.hpp | 18 +- ngraph/core/include/ngraph/axis_vector.hpp | 16 +- ngraph/core/include/ngraph/coordinate.hpp | 16 +- .../core/include/ngraph/coordinate_diff.hpp | 18 +- ngraph/core/include/ngraph/distributed.hpp | 11 +- ngraph/core/include/ngraph/enum_names.hpp | 55 +- ngraph/core/include/ngraph/node.hpp | 68 +-- .../include/ngraph/op/binary_convolution.hpp | 14 +- .../core/include/ngraph/op/depth_to_space.hpp | 15 +- ngraph/core/include/ngraph/op/gelu.hpp | 15 +- ngraph/core/include/ngraph/op/interpolate.hpp | 75 +-- ngraph/core/include/ngraph/op/loop.hpp | 14 +- ngraph/core/include/ngraph/op/lstm_cell.hpp | 16 +- ngraph/core/include/ngraph/op/matrix_nms.hpp | 14 +- ngraph/core/include/ngraph/op/mvn.hpp | 14 +- .../include/ngraph/op/non_max_suppression.hpp | 42 +- ngraph/core/include/ngraph/op/parameter.hpp | 12 +- ngraph/core/include/ngraph/op/result.hpp | 14 +- ngraph/core/include/ngraph/op/reverse.hpp | 14 +- ngraph/core/include/ngraph/op/roi_align.hpp | 18 +- ngraph/core/include/ngraph/op/round.hpp | 15 +- .../core/include/ngraph/op/space_to_depth.hpp | 16 +- .../include/ngraph/op/util/attr_types.hpp | 273 +++++----- .../ngraph/op/util/multi_subgraph_base.hpp | 6 +- .../core/include/ngraph/op/util/nms_base.hpp | 14 +- .../core/include/ngraph/op/util/variable.hpp | 13 +- .../include/ngraph/runtime/aligned_buffer.hpp | 12 +- ngraph/core/include/ngraph/shape.hpp | 28 +- ngraph/core/include/ngraph/strides.hpp | 16 +- .../openvino/core/attribute_adapter.hpp | 474 ++++++++++++++++++ .../openvino/core/attribute_visitor.hpp | 140 ++++++ .../core/include/openvino/core/enum_names.hpp | 70 +++ .../core/include/openvino/core/function.hpp | 4 +- .../include/openvino/core/partial_shape.hpp | 5 +- .../openvino/core/type/element_type.hpp | 6 +- ngraph/core/src/attribute_adapter.cpp | 4 +- ngraph/core/src/attribute_visitor.cpp | 72 +-- ngraph/core/src/axis_set.cpp | 8 +- ngraph/core/src/axis_vector.cpp | 2 +- ngraph/core/src/coordinate.cpp | 3 +- ngraph/core/src/coordinate_diff.cpp | 2 +- ngraph/core/src/distributed.cpp | 23 +- ngraph/core/src/node.cpp | 2 + ngraph/core/src/op/binary_convolution.cpp | 4 +- ngraph/core/src/op/depth_to_space.cpp | 12 +- ngraph/core/src/op/gelu.cpp | 5 +- ngraph/core/src/op/interpolate.cpp | 47 +- ngraph/core/src/op/loop.cpp | 2 +- ngraph/core/src/op/lstm_cell.cpp | 5 +- ngraph/core/src/op/matrix_nms.cpp | 11 +- ngraph/core/src/op/mvn.cpp | 5 +- ngraph/core/src/op/non_max_suppression.cpp | 25 +- ngraph/core/src/op/parameter.cpp | 6 +- ngraph/core/src/op/result.cpp | 6 +- ngraph/core/src/op/reverse.cpp | 12 +- ngraph/core/src/op/roi_align.cpp | 5 +- ngraph/core/src/op/round.cpp | 12 +- ngraph/core/src/op/space_to_depth.cpp | 12 +- ngraph/core/src/op/util/attr_types.cpp | 265 +++++----- .../core/src/op/util/multi_subgraph_base.cpp | 4 +- ngraph/core/src/op/util/nms_base.cpp | 12 +- ngraph/core/src/op/util/variable.cpp | 4 +- ngraph/core/src/partial_shape.cpp | 44 +- ngraph/core/src/runtime/aligned_buffer.cpp | 4 +- ngraph/core/src/shape.cpp | 2 +- ngraph/core/src/strides.cpp | 2 +- ngraph/core/src/type/element_type.cpp | 60 +-- ngraph/test/visitors/user_op.cpp | 12 +- 75 files changed, 1536 insertions(+), 1346 deletions(-) create mode 100644 ngraph/core/include/openvino/core/attribute_adapter.hpp create mode 100644 ngraph/core/include/openvino/core/attribute_visitor.hpp create mode 100644 ngraph/core/include/openvino/core/enum_names.hpp diff --git a/inference-engine/src/legacy_api/include/legacy/ngraph_ops/eltwise.hpp b/inference-engine/src/legacy_api/include/legacy/ngraph_ops/eltwise.hpp index e9b7e04cc41..706d554980c 100644 --- a/inference-engine/src/legacy_api/include/legacy/ngraph_ops/eltwise.hpp +++ b/inference-engine/src/legacy_api/include/legacy/ngraph_ops/eltwise.hpp @@ -40,6 +40,9 @@ private: } // namespace op std::ostream &operator<<(std::ostream &s, const ELTWISE_TYPE &type); +} // namespace ngraph + +namespace ov { template <> class AttributeAdapter @@ -52,4 +55,5 @@ public: 1}; const DiscreteTypeInfo &get_type_info() const override { return type_info; } }; -} // namespace ngraph + +} // namespace ov diff --git a/inference-engine/src/legacy_api/src/ngraph_ops/eltwise.cpp b/inference-engine/src/legacy_api/src/ngraph_ops/eltwise.cpp index ed10c659895..fbc7546dacd 100644 --- a/inference-engine/src/legacy_api/src/ngraph_ops/eltwise.cpp +++ b/inference-engine/src/legacy_api/src/ngraph_ops/eltwise.cpp @@ -80,8 +80,11 @@ bool op::Eltwise::visit_attributes(AttributeVisitor &visitor) { visitor.on_attribute("operation", eltwise_type); return true; } +std::ostream &operator<<(std::ostream &s, const ELTWISE_TYPE &type) { + return s << as_string(type); +} -namespace ngraph { +namespace ov { template <> EnumNames &EnumNames::get() { static auto enum_names = EnumNames("ELTWISE_TYPE", {{"sum", ELTWISE_TYPE::Sum}, @@ -95,7 +98,4 @@ template <> EnumNames &EnumNames::get() { constexpr DiscreteTypeInfo AttributeAdapter::type_info; -std::ostream &operator<<(std::ostream &s, const ELTWISE_TYPE &type) { - return s << as_string(type); -} -} // namespace ngraph +} // namespace ov diff --git a/inference-engine/src/transformations/include/ngraph_ops/framework_node.hpp b/inference-engine/src/transformations/include/ngraph_ops/framework_node.hpp index 8abda399c9c..fdc0060846d 100644 --- a/inference-engine/src/transformations/include/ngraph_ops/framework_node.hpp +++ b/inference-engine/src/transformations/include/ngraph_ops/framework_node.hpp @@ -80,14 +80,18 @@ private: FrameworkNodeAttrs m_attrs; }; } // namespace op +} // namespace ngraph + +namespace ov { template <> -class TRANSFORMATIONS_API AttributeAdapter - : public DirectValueAccessor { +class TRANSFORMATIONS_API AttributeAdapter + : public DirectValueAccessor { public: - AttributeAdapter(op::FrameworkNodeAttrs& value); + AttributeAdapter(ngraph::op::FrameworkNodeAttrs& value); static constexpr DiscreteTypeInfo type_info{"AttributeAdapter", 0}; const DiscreteTypeInfo& get_type_info() const override { return type_info; } }; -} // namespace ngraph + +} // namespace ov diff --git a/inference-engine/src/transformations/src/ngraph_ops/framework_node.cpp b/inference-engine/src/transformations/src/ngraph_ops/framework_node.cpp index 94d0008c110..75d7faa0dd9 100644 --- a/inference-engine/src/transformations/src/ngraph_ops/framework_node.cpp +++ b/inference-engine/src/transformations/src/ngraph_ops/framework_node.cpp @@ -95,8 +95,8 @@ void op::FrameworkNode::validate_and_infer_types() { } } -constexpr DiscreteTypeInfo AttributeAdapter::type_info; +constexpr ov::DiscreteTypeInfo ov::AttributeAdapter::type_info; -AttributeAdapter::AttributeAdapter( +ov::AttributeAdapter::AttributeAdapter( op::FrameworkNodeAttrs& value) : DirectValueAccessor(value) {} diff --git a/inference-engine/tests/functional/inference_engine/transformations/compare_functions_test.cpp b/inference-engine/tests/functional/inference_engine/transformations/compare_functions_test.cpp index 8a0660f199b..a886bc35972 100644 --- a/inference-engine/tests/functional/inference_engine/transformations/compare_functions_test.cpp +++ b/inference-engine/tests/functional/inference_engine/transformations/compare_functions_test.cpp @@ -620,7 +620,7 @@ TEST(TransformationTests, DummyOpNegativeDifferentStringVector) { EXPECT_THAT(res.message, HasSubstr(" mismatch in value: 'member' : [a, ba] vs [b, ab]")); } -namespace ngraph { +namespace ov { struct TestDummyDataTypeTransformationTests_NO_NGRAPH_NAME_COLISION {}; @@ -643,10 +643,10 @@ public: constexpr DiscreteTypeInfo AttributeAdapter::type_info; -} // namespace ngraph +} // namespace ov TEST(TransformationTests, DummyOpNegativeNotSupportedType) { - TestDummyDataTypeTransformationTests_NO_NGRAPH_NAME_COLISION m{}; + ov::TestDummyDataTypeTransformationTests_NO_NGRAPH_NAME_COLISION m{}; const auto& f1 = createDummyFunc(m); const auto& f2 = createDummyFunc(m); diff --git a/ngraph/core/include/ngraph/attribute_adapter.hpp b/ngraph/core/include/ngraph/attribute_adapter.hpp index b2e78548808..075738a3449 100644 --- a/ngraph/core/include/ngraph/attribute_adapter.hpp +++ b/ngraph/core/include/ngraph/attribute_adapter.hpp @@ -10,464 +10,27 @@ #include "ngraph/enum_names.hpp" #include "ngraph/type.hpp" +#include "openvino/core/attribute_adapter.hpp" /// namespace ngraph { -class AttributeVisitor; -/// \brief Provides access to an attribute of type AT as a value accessor type VAT -template -class ValueAccessor; +using ov::ValueAccessor; -/// \brief ValueAccessor provides an accessor for values that do not have get/set methonds -/// via AttributeVistor.on_adapter. -/// -/// All ValueAccessors must be derived from ValueAccessor so that an AttributeVisitor -/// only needs to implement a subset of the on_adapter methods. -template <> -class NGRAPH_API ValueAccessor { -public: - /// \brief type info enables identification of the value accessor, as well as is_type and - /// as_type. - virtual const DiscreteTypeInfo& get_type_info() const = 0; - virtual ~ValueAccessor() {} -}; +using ov::DirectValueAccessor; -/// \brief Provides access to values via get/set methods from an m_value, typically from -/// ValueReference -/// -/// The m_buffer holds a VAT, which may be wider than the attribute AT. For example, serializers -/// that only -/// support int64_t integers would use a ValueAccessor> to reference a -/// vector attribute. Destruction moves the value back to the attribute if it was -/// changed. -/// \tparam VAT The adapter value type; may be wider than the value being accessed. -template -class ValueAccessor : public ValueAccessor { -public: - /// Returns the value - virtual const VAT& get() = 0; - /// Sets the value - virtual void set(const VAT& value) = 0; -}; - -template <> -class ValueAccessor : public ValueAccessor { -public: - virtual void* get_ptr() = 0; - virtual size_t size() = 0; -}; - -template -class DirectValueAccessor : public ValueAccessor { -public: - DirectValueAccessor(AT& ref) : m_ref(ref) {} - const AT& get() override { - return m_ref; - } - void set(const AT& value) override { - m_ref = value; - } - -protected: - AT& m_ref; -}; - -template -class IndirectScalarValueAccessor : public ValueAccessor { -public: - IndirectScalarValueAccessor(AT& ref) : m_ref(ref), m_buffer() {} - - const VAT& get() override { - if (!m_buffer_valid) { - m_buffer = static_cast(m_ref); - m_buffer_valid = true; - } - return m_buffer; - } - - void set(const VAT& value) override { - m_ref = static_cast(value); - m_buffer_valid = false; - } - -protected: - AT& m_ref; - VAT m_buffer; - bool m_buffer_valid{false}; -}; +using ov::IndirectScalarValueAccessor; template A copy_from(B& b) { - A result(b.size()); - for (size_t i = 0; i < b.size(); ++i) { - result[i] = static_cast::type>(b[i]); - } - return result; + return ov::copy_from(b); } -template -class IndirectVectorValueAccessor : public ValueAccessor { -public: - IndirectVectorValueAccessor(AT& ref) : m_ref(ref) {} +using ov::IndirectVectorValueAccessor; - const VAT& get() override { - if (!m_buffer_valid) { - m_buffer = copy_from::type>(m_ref); - m_buffer_valid = true; - } - return m_buffer; - } +using ov::AttributeAdapter; +using ov::EnumAttributeAdapterBase; - void set(const VAT& value) override { - m_ref = copy_from(value); - m_buffer_valid = false; - } +using ov::VisitorAdapter; - operator AT&() { - return m_ref; - } - -protected: - AT& m_ref; - VAT m_buffer; - bool m_buffer_valid{false}; -}; - -/// \brief An AttributeAdapter "captures" an attribute as an AT& and makes it available as a -/// ValueAccessor. -template -class AttributeAdapter {}; - -/// \brief Access an enum via a string -/// \tparam AT The attribute type enum class -template -class EnumAttributeAdapterBase : public ValueAccessor { -public: - EnumAttributeAdapterBase(AT& value) : m_ref(value) {} - - const std::string& get() override { - return as_string(m_ref); - } - void set(const std::string& value) override { - m_ref = as_enum(value); - } - operator AT&() { - return m_ref; - } - -protected: - AT& m_ref; -}; - -/// Adapters will see visitor -class VisitorAdapter : public ValueAccessor { -public: - virtual bool visit_attributes(AttributeVisitor& visitor) = 0; -}; - -template <> -class NGRAPH_API AttributeAdapter : public IndirectScalarValueAccessor { -public: - AttributeAdapter(float& value) : IndirectScalarValueAccessor(value) {} - - static constexpr DiscreteTypeInfo type_info{"AttributeAdapter", 0}; - const DiscreteTypeInfo& get_type_info() const override { - return type_info; - } -}; - -/// \brief Access a double as a double -template <> -class NGRAPH_API AttributeAdapter : public DirectValueAccessor { -public: - AttributeAdapter(double& value) : DirectValueAccessor(value) {} - - static constexpr DiscreteTypeInfo type_info{"AttributeAdapter", 0}; - const DiscreteTypeInfo& get_type_info() const override { - return type_info; - } -}; - -/// \brief Access a string as a string -template <> -class NGRAPH_API AttributeAdapter : public DirectValueAccessor { -public: - AttributeAdapter(std::string& value) : DirectValueAccessor(value) {} - - static constexpr DiscreteTypeInfo type_info{"AttributeAdapter", 0}; - const DiscreteTypeInfo& get_type_info() const override { - return type_info; - } -}; - -/// \brief Access a bool as a bool -template <> -class NGRAPH_API AttributeAdapter : public DirectValueAccessor { -public: - AttributeAdapter(bool& value) : DirectValueAccessor(value) {} - - static constexpr DiscreteTypeInfo type_info{"AttributeAdapter", 0}; - const DiscreteTypeInfo& get_type_info() const override { - return type_info; - } -}; - -/// \brief Access an int8_t and an int64_t -template <> -class NGRAPH_API AttributeAdapter : public IndirectScalarValueAccessor { -public: - AttributeAdapter(int8_t& value) : IndirectScalarValueAccessor(value) {} - - static constexpr DiscreteTypeInfo type_info{"AttributeAdapter", 0}; - const DiscreteTypeInfo& get_type_info() const override { - return type_info; - } -}; - -/// \brief Access an int16_t as an int64_t -template <> -class NGRAPH_API AttributeAdapter : public IndirectScalarValueAccessor { -public: - AttributeAdapter(int16_t& value) : IndirectScalarValueAccessor(value) {} - - static constexpr DiscreteTypeInfo type_info{"AttributeAdapter", 0}; - const DiscreteTypeInfo& get_type_info() const override { - return type_info; - } -}; - -/// \brief Access an int32_t as an int64_t -template <> -class NGRAPH_API AttributeAdapter : public IndirectScalarValueAccessor { -public: - AttributeAdapter(int32_t& value) : IndirectScalarValueAccessor(value) {} - - static constexpr DiscreteTypeInfo type_info{"AttributeAdapter", 0}; - const DiscreteTypeInfo& get_type_info() const override { - return type_info; - } -}; - -/// \brief Access an int64_t as an int64_t -template <> -class NGRAPH_API AttributeAdapter : public DirectValueAccessor { -public: - AttributeAdapter(int64_t& value) : DirectValueAccessor(value) {} - - static constexpr DiscreteTypeInfo type_info{"AttributeAdapter", 0}; - const DiscreteTypeInfo& get_type_info() const override { - return type_info; - } -}; - -/// \brief Access a uint8_t as an int64_t -template <> -class NGRAPH_API AttributeAdapter : public IndirectScalarValueAccessor { -public: - AttributeAdapter(uint8_t& value) : IndirectScalarValueAccessor(value) {} - - static constexpr DiscreteTypeInfo type_info{"AttributeAdapter", 0}; - const DiscreteTypeInfo& get_type_info() const override { - return type_info; - } -}; - -/// \brief Access a uint16_t as an int64_t -template <> -class NGRAPH_API AttributeAdapter : public IndirectScalarValueAccessor { -public: - AttributeAdapter(uint16_t& value) : IndirectScalarValueAccessor(value) {} - - static constexpr DiscreteTypeInfo type_info{"AttributeAdapter", 0}; - const DiscreteTypeInfo& get_type_info() const override { - return type_info; - } -}; - -/// \brief Access a uint32_t as an int64_t -template <> -class NGRAPH_API AttributeAdapter : public IndirectScalarValueAccessor { -public: - AttributeAdapter(uint32_t& value) : IndirectScalarValueAccessor(value) {} - - static constexpr DiscreteTypeInfo type_info{"AttributeAdapter", 0}; - const DiscreteTypeInfo& get_type_info() const override { - return type_info; - } -}; - -/// \brief Access a uint64_t as an int64_t -template <> -class NGRAPH_API AttributeAdapter : public IndirectScalarValueAccessor { -public: - AttributeAdapter(uint64_t& value) : IndirectScalarValueAccessor(value) {} - - static constexpr DiscreteTypeInfo type_info{"AttributeAdapter", 0}; - const DiscreteTypeInfo& get_type_info() const override { - return type_info; - } -}; - -#ifdef __APPLE__ -// size_t is one of the uint types on _WIN32 -template <> -class NGRAPH_API AttributeAdapter : public IndirectScalarValueAccessor { -public: - AttributeAdapter(size_t& value) : IndirectScalarValueAccessor(value) {} - - static constexpr DiscreteTypeInfo type_info{"AttributeAdapter", 0}; - const DiscreteTypeInfo& get_type_info() const override { - return type_info; - } -}; - -template <> -class NGRAPH_API AttributeAdapter> - : public IndirectVectorValueAccessor, std::vector> { -public: - AttributeAdapter(std::vector& value) - : IndirectVectorValueAccessor, std::vector>(value) {} - - static constexpr DiscreteTypeInfo type_info{"AttributeAdapter>", 0}; - const DiscreteTypeInfo& get_type_info() const override { - return type_info; - } -}; -#endif - -/// Note: These class bodies cannot be defined with templates because of interactions -/// between dllexport and templates on Windows. - -/// \brief Access a vector -template <> -class NGRAPH_API AttributeAdapter> : public DirectValueAccessor> { -public: - AttributeAdapter(std::vector& value) : DirectValueAccessor>(value) {} - - static constexpr DiscreteTypeInfo type_info{"AttributeAdapter>", 0}; - const DiscreteTypeInfo& get_type_info() const override { - return type_info; - } -}; - -/// \brief Access a vector -template <> -class NGRAPH_API AttributeAdapter> : public DirectValueAccessor> { -public: - AttributeAdapter(std::vector& value) : DirectValueAccessor>(value) {} - - static constexpr DiscreteTypeInfo type_info{"AttributeAdapter>", 0}; - const DiscreteTypeInfo& get_type_info() const override { - return type_info; - } -}; - -/// \brief Access a vector -template <> -class NGRAPH_API AttributeAdapter> : public DirectValueAccessor> { -public: - AttributeAdapter(std::vector& value) : DirectValueAccessor>(value) {} - - static constexpr DiscreteTypeInfo type_info{"AttributeAdapter>", 0}; - const DiscreteTypeInfo& get_type_info() const override { - return type_info; - } -}; - -/// \brief Access a vector -template <> -class NGRAPH_API AttributeAdapter> : public DirectValueAccessor> { -public: - AttributeAdapter(std::vector& value) : DirectValueAccessor>(value) {} - - static constexpr DiscreteTypeInfo type_info{"AttributeAdapter>", 0}; - const DiscreteTypeInfo& get_type_info() const override { - return type_info; - } -}; - -/// \brief Access a vector -template <> -class NGRAPH_API AttributeAdapter> : public DirectValueAccessor> { -public: - AttributeAdapter(std::vector& value) : DirectValueAccessor>(value) {} - - static constexpr DiscreteTypeInfo type_info{"AttributeAdapter>", 0}; - const DiscreteTypeInfo& get_type_info() const override { - return type_info; - } -}; - -/// \brief Access a vector -template <> -class NGRAPH_API AttributeAdapter> : public DirectValueAccessor> { -public: - AttributeAdapter(std::vector& value) : DirectValueAccessor>(value) {} - - static constexpr DiscreteTypeInfo type_info{"AttributeAdapter>", 0}; - const DiscreteTypeInfo& get_type_info() const override { - return type_info; - } -}; - -/// \brief Access a vector -template <> -class NGRAPH_API AttributeAdapter> : public DirectValueAccessor> { -public: - AttributeAdapter(std::vector& value) : DirectValueAccessor>(value) {} - - static constexpr DiscreteTypeInfo type_info{"AttributeAdapter>", 0}; - const DiscreteTypeInfo& get_type_info() const override { - return type_info; - } -}; - -/// \brief Access a vector -template <> -class NGRAPH_API AttributeAdapter> : public DirectValueAccessor> { -public: - AttributeAdapter(std::vector& value) : DirectValueAccessor>(value) {} - - static constexpr DiscreteTypeInfo type_info{"AttributeAdapter>", 0}; - const DiscreteTypeInfo& get_type_info() const override { - return type_info; - } -}; - -/// \brief Access a vector -template <> -class NGRAPH_API AttributeAdapter> : public DirectValueAccessor> { -public: - AttributeAdapter(std::vector& value) : DirectValueAccessor>(value) {} - - static constexpr DiscreteTypeInfo type_info{"AttributeAdapter>", 0}; - const DiscreteTypeInfo& get_type_info() const override { - return type_info; - } -}; - -/// \brief Access a vector -template <> -class NGRAPH_API AttributeAdapter> : public DirectValueAccessor> { -public: - AttributeAdapter(std::vector& value) : DirectValueAccessor>(value) {} - - static constexpr DiscreteTypeInfo type_info{"AttributeAdapter>", 0}; - const DiscreteTypeInfo& get_type_info() const override { - return type_info; - } -}; - -/// \brief Access a vector -template <> -class NGRAPH_API AttributeAdapter> : public DirectValueAccessor> { -public: - AttributeAdapter(std::vector& value) : DirectValueAccessor>(value) {} - - static constexpr DiscreteTypeInfo type_info{"AttributeAdapter>", 0}; - const DiscreteTypeInfo& get_type_info() const override { - return type_info; - } -}; } // namespace ngraph diff --git a/ngraph/core/include/ngraph/attribute_visitor.hpp b/ngraph/core/include/ngraph/attribute_visitor.hpp index 5fd9a62a2ef..267d1c3a98c 100644 --- a/ngraph/core/include/ngraph/attribute_visitor.hpp +++ b/ngraph/core/include/ngraph/attribute_visitor.hpp @@ -11,128 +11,8 @@ #include "ngraph/partial_shape.hpp" #include "ngraph/type.hpp" #include "ngraph/type/element_type.hpp" +#include "openvino/core/attribute_visitor.hpp" -namespace ov { -class Function; -} namespace ngraph { -template -class ValueAccessor; -class VisitorAdapter; -class Node; - -/// \brief Visits the attributes of a node, primarily for serialization-like tasks. -/// -/// Attributes are the node parameters that are always compile-time constants. -/// Values computed from the graph topology and attributes during compilation are not -/// attributes. -/// -/// Attributes have a wide variety of types, but serialization formats are more restricted. -/// We asume serialation easily supports scalar types of bool 64-bit signed, string, and double, -/// and has specialized ways to support numeric arrays and raw data+size. The visitor and -/// adapter convert between the limited serialization types and the unlimited attribute types. -/// -/// A visitor is passed to an op's visit_attributes method. The visit_attributes method calls -/// the template method visitor.on_attribute(const std::string& name, AT& value) on each -/// attribute. The visitor can read or write the attribute's value. The on_attribute -/// method creates an AttributeAdapter for the value and passes it to one of the visitors -/// on_adapter methods. The on_adapter methods expect a reference to a ValueAccessor or a -/// VisitorAdapter. A ValueAccessor has get/set methods that can be used to read/write the -/// attribute value as type VAT. These methods are triggered by deriving AttributeAdapter -/// from ValueAccessor. For more complex cases, such as structs, the on_adapter method for -/// VisitorAdapter passes the name and visitor to the adapter, so that the adapter can perform -/// additional work such as visiting struct members or sequence values. -/// -/// When a node visits an attribute with structure, the node's on_attribute passes a name for -/// the entire attribute, but the struct will have its own methods to be visited. Similarly, a -/// vector will have a sequence of members to be visited. The adapter may use the visitor -/// methods start_struct/finish_struct and start_vector/next_vector/finish_vector to inidicate -/// nexted members. -/// -/// The visitor method get_name_with_context creates a generic nested version of the name. -/// Visitors can override according to their serialization requirements. -/// -/// Attributes that are shared_ptr are special. They must have been already been -/// registered with the visitor using register_node, which needs a shared pointer to a node and -/// a string ID. The ID string will be used to serialize the node or find the node during -/// deserialization. -class NGRAPH_API AttributeVisitor { -public: - virtual ~AttributeVisitor() {} - // Must implement these methods - /// \brief handles all specialized on_adapter methods implemented by the visitor. - /// - /// The adapter implements get_type_info(), which can be used to determine the adapter - /// directly - /// or via is_type and as_type on any platform - virtual void on_adapter(const std::string& name, ValueAccessor& adapter) = 0; - // The remaining adapter methods fall back on the void adapter if not implemented - virtual void on_adapter(const std::string& name, ValueAccessor& adapter); - virtual void on_adapter(const std::string& name, ValueAccessor& adapter); - virtual void on_adapter(const std::string& name, ValueAccessor& adapter); - virtual void on_adapter(const std::string& name, ValueAccessor& adapter); - virtual void on_adapter(const std::string& name, ValueAccessor& adapter); - virtual void on_adapter(const std::string& name, ValueAccessor& adapter); - virtual void on_adapter(const std::string& name, ValueAccessor& adapter); - virtual void on_adapter(const std::string& name, ValueAccessor& adapter); - virtual void on_adapter(const std::string& name, ValueAccessor& adapter); - virtual void on_adapter(const std::string& name, ValueAccessor& adapter); - virtual void on_adapter(const std::string& name, ValueAccessor& adapter); - virtual void on_adapter(const std::string& name, ValueAccessor& adapter); - virtual void on_adapter(const std::string& name, ValueAccessor& adapter); - virtual void on_adapter(const std::string& name, ValueAccessor>& adapter); - virtual void on_adapter(const std::string& name, ValueAccessor>& adapter); - virtual void on_adapter(const std::string& name, ValueAccessor>& adapter); - virtual void on_adapter(const std::string& name, ValueAccessor>& adapter); - virtual void on_adapter(const std::string& name, ValueAccessor>& adapter); - virtual void on_adapter(const std::string& name, ValueAccessor>& adapter); - virtual void on_adapter(const std::string& name, ValueAccessor>& adapter); - virtual void on_adapter(const std::string& name, ValueAccessor>& adapter); - virtual void on_adapter(const std::string& name, ValueAccessor>& adapter); - virtual void on_adapter(const std::string& name, ValueAccessor>& adapter); - virtual void on_adapter(const std::string& name, ValueAccessor>& adapter); - /// \brief Hook for adapters that need visitor access - virtual void on_adapter(const std::string& name, VisitorAdapter& adapter); - - /// \brief Provides API to handle nGraph Function attribute type, accessed as ValueAccessor - /// \param name attribute name - /// \param adapter reference to a Function ValueAccessor - virtual void on_adapter(const std::string& name, ValueAccessor>& adapter); - - /// The generic visitor. There must be a definition of AttributeAdapter that can convert - /// to a ValueAccessor for one of the on_adpater methods. - template - void on_attribute(const std::string& name, AT& value) { - AttributeAdapter adapter(value); - start_structure(name); - on_adapter(get_name_with_context(), adapter); - finish_structure(); - } - /// \returns The nested context of visits - const std::vector& get_context() const { - return m_context; - } - /// \returns context prepended to names - virtual std::string get_name_with_context(); - /// \brief Start visiting a nested structure - virtual void start_structure(const std::string& name); - /// \brief Finish visiting a nested structure - virtual std::string finish_structure(); - using node_id_t = std::string; - static const node_id_t invalid_node_id; - /// \brief Associate a node with an id. - /// - /// No node may be used as an attribute unless it has already been registered with an ID. - /// References to nodes are visited with a ValueAccessor of their ID. - virtual void register_node(const std::shared_ptr& node, node_id_t id = invalid_node_id); - /// Returns the node with the given id, or nullptr if there is no registered node - virtual std::shared_ptr get_registered_node(node_id_t id); - /// Returns the id for the node, or -1 if the node is not registered - virtual node_id_t get_registered_node_id(const std::shared_ptr& node); - -protected: - std::vector m_context; - std::unordered_map, node_id_t> m_node_id_map; - std::unordered_map> m_id_node_map; -}; +using ov::AttributeVisitor; } // namespace ngraph diff --git a/ngraph/core/include/ngraph/axis_set.hpp b/ngraph/core/include/ngraph/axis_set.hpp index 03bf736e0ef..9a1c72b8abe 100644 --- a/ngraph/core/include/ngraph/axis_set.hpp +++ b/ngraph/core/include/ngraph/axis_set.hpp @@ -33,10 +33,16 @@ public: NGRAPH_API std::vector to_vector() const; }; +NGRAPH_API +std::ostream& operator<<(std::ostream& s, const AxisSet& axis_set); +} // namespace ngraph + +namespace ov { + template <> -class NGRAPH_API AttributeAdapter : public ValueAccessor> { +class NGRAPH_API AttributeAdapter : public ValueAccessor> { public: - AttributeAdapter(AxisSet& value) : m_ref(value) {} + AttributeAdapter(ngraph::AxisSet& value) : m_ref(value) {} const std::vector& get() override; void set(const std::vector& value) override; @@ -44,16 +50,14 @@ public: const DiscreteTypeInfo& get_type_info() const override { return type_info; } - operator AxisSet&() { + operator ngraph::AxisSet&() { return m_ref; } protected: - AxisSet& m_ref; + ngraph::AxisSet& m_ref; std::vector m_buffer; bool m_buffer_valid{false}; }; -NGRAPH_API -std::ostream& operator<<(std::ostream& s, const AxisSet& axis_set); -} // namespace ngraph +} // namespace ov diff --git a/ngraph/core/include/ngraph/axis_vector.hpp b/ngraph/core/include/ngraph/axis_vector.hpp index ac98561145d..f7215d0c88f 100644 --- a/ngraph/core/include/ngraph/axis_vector.hpp +++ b/ngraph/core/include/ngraph/axis_vector.hpp @@ -35,10 +35,18 @@ public: NGRAPH_API AxisVector& operator=(AxisVector&& v) noexcept; }; +NGRAPH_API +std::ostream& operator<<(std::ostream& s, const AxisVector& axis_vector); +} // namespace ngraph + +namespace ov { + template <> -class NGRAPH_API AttributeAdapter : public IndirectVectorValueAccessor> { +class NGRAPH_API AttributeAdapter + : public IndirectVectorValueAccessor> { public: - AttributeAdapter(AxisVector& value) : IndirectVectorValueAccessor>(value) {} + AttributeAdapter(ngraph::AxisVector& value) + : IndirectVectorValueAccessor>(value) {} static constexpr DiscreteTypeInfo type_info{"AttributeAdapter", 0}; const DiscreteTypeInfo& get_type_info() const override { @@ -46,6 +54,4 @@ public: } }; -NGRAPH_API -std::ostream& operator<<(std::ostream& s, const AxisVector& axis_vector); -} // namespace ngraph +} // namespace ov diff --git a/ngraph/core/include/ngraph/coordinate.hpp b/ngraph/core/include/ngraph/coordinate.hpp index 3d26523ea7b..56535fdeb18 100644 --- a/ngraph/core/include/ngraph/coordinate.hpp +++ b/ngraph/core/include/ngraph/coordinate.hpp @@ -36,17 +36,21 @@ public: NGRAPH_API Coordinate& operator=(Coordinate&& v) noexcept; }; +NGRAPH_API +std::ostream& operator<<(std::ostream& s, const Coordinate& coordinate); +} // namespace ngraph + +namespace ov { template <> -class NGRAPH_API AttributeAdapter : public IndirectVectorValueAccessor> { +class NGRAPH_API AttributeAdapter + : public IndirectVectorValueAccessor> { public: - AttributeAdapter(Coordinate& value) : IndirectVectorValueAccessor>(value) {} + AttributeAdapter(ngraph::Coordinate& value) + : IndirectVectorValueAccessor>(value) {} static constexpr DiscreteTypeInfo type_info{"AttributeAdapter", 0}; const DiscreteTypeInfo& get_type_info() const override { return type_info; } }; - -NGRAPH_API -std::ostream& operator<<(std::ostream& s, const Coordinate& coordinate); -} // namespace ngraph +} // namespace ov diff --git a/ngraph/core/include/ngraph/coordinate_diff.hpp b/ngraph/core/include/ngraph/coordinate_diff.hpp index 2f51c0e8400..77fb5c365ff 100644 --- a/ngraph/core/include/ngraph/coordinate_diff.hpp +++ b/ngraph/core/include/ngraph/coordinate_diff.hpp @@ -35,14 +35,20 @@ public: NGRAPH_API CoordinateDiff& operator=(CoordinateDiff&& v) noexcept; }; +NGRAPH_API +std::ostream& operator<<(std::ostream& s, const CoordinateDiff& coordinate_diff); +} // namespace ngraph + +namespace ov { + template <> -class NGRAPH_API AttributeAdapter - : public IndirectVectorValueAccessor> +class NGRAPH_API AttributeAdapter + : public IndirectVectorValueAccessor> { public: - AttributeAdapter(CoordinateDiff& value) - : IndirectVectorValueAccessor>(value) {} + AttributeAdapter(ngraph::CoordinateDiff& value) + : IndirectVectorValueAccessor>(value) {} static constexpr DiscreteTypeInfo type_info{"AttributeAdapter", 0}; const DiscreteTypeInfo& get_type_info() const override { @@ -50,6 +56,4 @@ public: } }; -NGRAPH_API -std::ostream& operator<<(std::ostream& s, const CoordinateDiff& coordinate_diff); -} // namespace ngraph +} // namespace ov diff --git a/ngraph/core/include/ngraph/distributed.hpp b/ngraph/core/include/ngraph/distributed.hpp index c67e72a408b..f36c318cf05 100644 --- a/ngraph/core/include/ngraph/distributed.hpp +++ b/ngraph/core/include/ngraph/distributed.hpp @@ -25,14 +25,19 @@ NGRAPH_API std::ostream& operator<<(std::ostream& out, const Type& obj); } // namespace reduction +} // namespace ngraph + +namespace ov { + template <> -class NGRAPH_API AttributeAdapter : public EnumAttributeAdapterBase { +class NGRAPH_API AttributeAdapter : public EnumAttributeAdapterBase { public: - AttributeAdapter(reduction::Type& value) : EnumAttributeAdapterBase(value) {} + AttributeAdapter(ngraph::reduction::Type& value) : EnumAttributeAdapterBase(value) {} static constexpr DiscreteTypeInfo type_info{"AttributeAdapter", 0}; const DiscreteTypeInfo& get_type_info() const override { return type_info; } }; -} // namespace ngraph + +} // namespace ov diff --git a/ngraph/core/include/ngraph/enum_names.hpp b/ngraph/core/include/ngraph/enum_names.hpp index 13c9d487ce0..91b95745cd0 100644 --- a/ngraph/core/include/ngraph/enum_names.hpp +++ b/ngraph/core/include/ngraph/enum_names.hpp @@ -4,67 +4,20 @@ #pragma once -#include -#include -#include - #include "ngraph/check.hpp" +#include "openvino/core/enum_names.hpp" namespace ngraph { -/// Uses a pairings defined by EnumTypes::get() to convert between strings -/// and enum values. -template -class EnumNames { -public: - /// Converts strings to enum values - static EnumType as_enum(const std::string& name) { - auto to_lower = [](const std::string& s) { - std::string rc = s; - std::transform(rc.begin(), rc.end(), rc.begin(), [](char c) { - return static_cast(::tolower(static_cast(c))); - }); - return rc; - }; - for (const auto& p : get().m_string_enums) { - if (to_lower(p.first) == to_lower(name)) { - return p.second; - } - } - NGRAPH_CHECK(false, "\"", name, "\"", " is not a member of enum ", get().m_enum_name); - } - - /// Converts enum values to strings - static const std::string& as_string(EnumType e) { - for (const auto& p : get().m_string_enums) { - if (p.second == e) { - return p.first; - } - } - NGRAPH_CHECK(false, " invalid member of enum ", get().m_enum_name); - } - -private: - /// Creates the mapping. - EnumNames(const std::string& enum_name, const std::vector> string_enums) - : m_enum_name(enum_name), - m_string_enums(string_enums) {} - - /// Must be defined to returns a singleton for each supported enum class - static EnumNames& get(); - - const std::string m_enum_name; - std::vector> m_string_enums; -}; - +using ov::EnumNames; /// Returns the enum value matching the string template typename std::enable_if::value, Type>::type as_enum(const Value& value) { - return EnumNames::as_enum(value); + return ov::as_enum(value); } /// Returns the string matching the enum value template const std::string& as_string(Value value) { - return EnumNames::as_string(value); + return ov::as_string(value); } } // namespace ngraph diff --git a/ngraph/core/include/ngraph/node.hpp b/ngraph/core/include/ngraph/node.hpp index e3c4b1a39e4..e72e1e8e1b1 100644 --- a/ngraph/core/include/ngraph/node.hpp +++ b/ngraph/core/include/ngraph/node.hpp @@ -44,7 +44,6 @@ class Input; template class Output; -class AttributeVisitor; class Node; namespace runtime { @@ -649,38 +648,6 @@ struct RawNodeOutput { } }; -/// \brief Visits a reference to a node that has been registered with the visitor. -template <> -class NGRAPH_API AttributeAdapter> : public VisitorAdapter { -public: - AttributeAdapter(std::shared_ptr& value); - - bool visit_attributes(AttributeVisitor& visitor) override; - static constexpr DiscreteTypeInfo type_info{"AttributeAdapter>", 0}; - const DiscreteTypeInfo& get_type_info() const override { - return type_info; - } - -protected: - std::shared_ptr& m_ref; -}; - -template <> -class NGRAPH_API AttributeAdapter : public VisitorAdapter { -public: - AttributeAdapter(NodeVector& ref); - - bool visit_attributes(AttributeVisitor& visitor) override; - - static constexpr DiscreteTypeInfo type_info{"AttributeAdapter", 0}; - const DiscreteTypeInfo& get_type_info() const override { - return type_info; - } - -protected: - NodeVector& m_ref; -}; - using RawNodeOutputMap = std::map>; class NGRAPH_API NodeValidationFailure : public CheckFailure { @@ -705,3 +672,38 @@ void check_new_args_count(const Node* node, T new_args) { } } // namespace ngraph + +namespace ov { +/// \brief Visits a reference to a node that has been registered with the visitor. +template <> +class NGRAPH_API AttributeAdapter> : public VisitorAdapter { +public: + AttributeAdapter(std::shared_ptr& value); + + bool visit_attributes(AttributeVisitor& visitor) override; + static constexpr DiscreteTypeInfo type_info{"AttributeAdapter>", 0}; + const DiscreteTypeInfo& get_type_info() const override { + return type_info; + } + +protected: + std::shared_ptr& m_ref; +}; + +template <> +class NGRAPH_API AttributeAdapter : public VisitorAdapter { +public: + AttributeAdapter(ngraph::NodeVector& ref); + + bool visit_attributes(AttributeVisitor& visitor) override; + + static constexpr DiscreteTypeInfo type_info{"AttributeAdapter", 0}; + const DiscreteTypeInfo& get_type_info() const override { + return type_info; + } + +protected: + ngraph::NodeVector& m_ref; +}; + +} // namespace ov diff --git a/ngraph/core/include/ngraph/op/binary_convolution.hpp b/ngraph/core/include/ngraph/op/binary_convolution.hpp index fbe02f9fbb7..14f7ccf6c05 100644 --- a/ngraph/core/include/ngraph/op/binary_convolution.hpp +++ b/ngraph/core/include/ngraph/op/binary_convolution.hpp @@ -126,12 +126,16 @@ protected: NGRAPH_API std::ostream& operator<<(std::ostream& s, const op::v1::BinaryConvolution::BinaryConvolutionMode& type); +} // namespace ngraph + +namespace ov { + template <> -class NGRAPH_API AttributeAdapter - : public EnumAttributeAdapterBase { +class NGRAPH_API AttributeAdapter + : public EnumAttributeAdapterBase { public: - AttributeAdapter(op::v1::BinaryConvolution::BinaryConvolutionMode& value) - : EnumAttributeAdapterBase(value) {} + AttributeAdapter(ngraph::op::v1::BinaryConvolution::BinaryConvolutionMode& value) + : EnumAttributeAdapterBase(value) {} static constexpr DiscreteTypeInfo type_info{"AttributeAdapter", 0}; @@ -140,4 +144,4 @@ public: } }; -} // namespace ngraph +} // namespace ov diff --git a/ngraph/core/include/ngraph/op/depth_to_space.hpp b/ngraph/core/include/ngraph/op/depth_to_space.hpp index 324982d23ee..0b57d0476db 100644 --- a/ngraph/core/include/ngraph/op/depth_to_space.hpp +++ b/ngraph/core/include/ngraph/op/depth_to_space.hpp @@ -47,7 +47,7 @@ public: DepthToSpaceMode get_mode() const { return m_mode; } - virtual std::shared_ptr clone_with_new_inputs(const OutputVector& new_args) const override; + std::shared_ptr clone_with_new_inputs(const OutputVector& new_args) const override; void validate_and_infer_types() override; bool evaluate(const HostTensorVector& outputs, const HostTensorVector& inputs) const override; bool has_evaluate() const override; @@ -62,17 +62,20 @@ using v0::DepthToSpace; NGRAPH_API std::ostream& operator<<(std::ostream& s, const op::v0::DepthToSpace::DepthToSpaceMode& type); +} // namespace ngraph +namespace ov { template <> -class NGRAPH_API AttributeAdapter - : public EnumAttributeAdapterBase { +class NGRAPH_API AttributeAdapter + : public EnumAttributeAdapterBase { public: - AttributeAdapter(op::v0::DepthToSpace::DepthToSpaceMode& value) - : EnumAttributeAdapterBase(value) {} + AttributeAdapter(ngraph::op::v0::DepthToSpace::DepthToSpaceMode& value) + : EnumAttributeAdapterBase(value) {} static constexpr DiscreteTypeInfo type_info{"AttributeAdapter", 0}; const DiscreteTypeInfo& get_type_info() const override { return type_info; } }; -} // namespace ngraph + +} // namespace ov diff --git a/ngraph/core/include/ngraph/op/gelu.hpp b/ngraph/core/include/ngraph/op/gelu.hpp index 78f683120c2..e662bada82f 100644 --- a/ngraph/core/include/ngraph/op/gelu.hpp +++ b/ngraph/core/include/ngraph/op/gelu.hpp @@ -27,7 +27,7 @@ public: void validate_and_infer_types() override; - virtual std::shared_ptr clone_with_new_inputs(const OutputVector& new_args) const override; + std::shared_ptr clone_with_new_inputs(const OutputVector& new_args) const override; }; } // namespace v0 using v0::Gelu; @@ -68,15 +68,20 @@ private: }; } // namespace v7 } // namespace op +} // namespace ngraph + +namespace ov { template <> -class NGRAPH_API AttributeAdapter - : public EnumAttributeAdapterBase { +class NGRAPH_API AttributeAdapter + : public EnumAttributeAdapterBase { public: - AttributeAdapter(op::GeluApproximationMode& value) : EnumAttributeAdapterBase(value) {} + AttributeAdapter(ngraph::op::GeluApproximationMode& value) + : EnumAttributeAdapterBase(value) {} static constexpr DiscreteTypeInfo type_info{"AttributeAdapter", 0}; const DiscreteTypeInfo& get_type_info() const override { return type_info; } }; -} // namespace ngraph + +} // namespace ov diff --git a/ngraph/core/include/ngraph/op/interpolate.hpp b/ngraph/core/include/ngraph/op/interpolate.hpp index c4a84dee8e0..e2104a8dda7 100644 --- a/ngraph/core/include/ngraph/op/interpolate.hpp +++ b/ngraph/core/include/ngraph/op/interpolate.hpp @@ -283,30 +283,42 @@ using v0::InterpolateAttrs; NGRAPH_API std::ostream& operator<<(std::ostream& s, const op::v0::Interpolate::InterpolateMode& type); +//---------------------------------------- v4 -------------------------------------------------- + +NGRAPH_API +std::ostream& operator<<(std::ostream& s, const op::v4::Interpolate::InterpolateMode& type); + +NGRAPH_API +std::ostream& operator<<(std::ostream& s, const op::v4::Interpolate::CoordinateTransformMode& type); + +NGRAPH_API +std::ostream& operator<<(std::ostream& s, const op::v4::Interpolate::NearestMode& type); + +NGRAPH_API +std::ostream& operator<<(std::ostream& s, const op::v4::Interpolate::ShapeCalcMode& type); + +} // namespace ngraph + +namespace ov { + template <> -class NGRAPH_API AttributeAdapter - : public EnumAttributeAdapterBase { +class NGRAPH_API AttributeAdapter + : public EnumAttributeAdapterBase { public: - AttributeAdapter(op::v0::Interpolate::InterpolateMode& value) - : EnumAttributeAdapterBase(value) {} + AttributeAdapter(ngraph::op::v0::Interpolate::InterpolateMode& value) + : EnumAttributeAdapterBase(value) {} static constexpr DiscreteTypeInfo type_info{"AttributeAdapter", 0}; const DiscreteTypeInfo& get_type_info() const override { return type_info; } }; - -//---------------------------------------- v4 -------------------------------------------------- - -NGRAPH_API -std::ostream& operator<<(std::ostream& s, const op::v4::Interpolate::InterpolateMode& type); - template <> -class NGRAPH_API AttributeAdapter - : public EnumAttributeAdapterBase { +class NGRAPH_API AttributeAdapter + : public EnumAttributeAdapterBase { public: - AttributeAdapter(op::v4::Interpolate::InterpolateMode& value) - : EnumAttributeAdapterBase(value) {} + AttributeAdapter(ngraph::op::v4::Interpolate::InterpolateMode& value) + : EnumAttributeAdapterBase(value) {} static constexpr DiscreteTypeInfo type_info{"AttributeAdapter", 4}; const DiscreteTypeInfo& get_type_info() const override { @@ -314,15 +326,12 @@ public: } }; -NGRAPH_API -std::ostream& operator<<(std::ostream& s, const op::v4::Interpolate::CoordinateTransformMode& type); - template <> -class NGRAPH_API AttributeAdapter - : public EnumAttributeAdapterBase { +class NGRAPH_API AttributeAdapter + : public EnumAttributeAdapterBase { public: - AttributeAdapter(op::v4::Interpolate::CoordinateTransformMode& value) - : EnumAttributeAdapterBase(value) {} + AttributeAdapter(ngraph::op::v4::Interpolate::CoordinateTransformMode& value) + : EnumAttributeAdapterBase(value) {} static constexpr DiscreteTypeInfo type_info{"AttributeAdapter", 4}; const DiscreteTypeInfo& get_type_info() const override { @@ -330,15 +339,12 @@ public: } }; -NGRAPH_API -std::ostream& operator<<(std::ostream& s, const op::v4::Interpolate::NearestMode& type); - template <> -class NGRAPH_API AttributeAdapter - : public EnumAttributeAdapterBase { +class NGRAPH_API AttributeAdapter + : public EnumAttributeAdapterBase { public: - AttributeAdapter(op::v4::Interpolate::NearestMode& value) - : EnumAttributeAdapterBase(value) {} + AttributeAdapter(ngraph::op::v4::Interpolate::NearestMode& value) + : EnumAttributeAdapterBase(value) {} static constexpr DiscreteTypeInfo type_info{"AttributeAdapter", 4}; const DiscreteTypeInfo& get_type_info() const override { @@ -346,19 +352,16 @@ public: } }; -NGRAPH_API -std::ostream& operator<<(std::ostream& s, const op::v4::Interpolate::ShapeCalcMode& type); - template <> -class NGRAPH_API AttributeAdapter - : public EnumAttributeAdapterBase { +class NGRAPH_API AttributeAdapter + : public EnumAttributeAdapterBase { public: - AttributeAdapter(op::v4::Interpolate::ShapeCalcMode& value) - : EnumAttributeAdapterBase(value) {} + AttributeAdapter(ngraph::op::v4::Interpolate::ShapeCalcMode& value) + : EnumAttributeAdapterBase(value) {} static constexpr DiscreteTypeInfo type_info{"AttributeAdapter", 4}; const DiscreteTypeInfo& get_type_info() const override { return type_info; } }; -} // namespace ngraph +} // namespace ov diff --git a/ngraph/core/include/ngraph/op/loop.hpp b/ngraph/core/include/ngraph/op/loop.hpp index a90e150a43f..8d037c9bd37 100644 --- a/ngraph/core/include/ngraph/op/loop.hpp +++ b/ngraph/core/include/ngraph/op/loop.hpp @@ -75,17 +75,21 @@ private: }; } // namespace v5 } // namespace op +} // namespace ngraph + +namespace ov { template <> -class NGRAPH_API AttributeAdapter - : public DirectValueAccessor { +class NGRAPH_API AttributeAdapter + : public DirectValueAccessor { public: - AttributeAdapter(op::v5::Loop::SpecialBodyPorts& value) - : DirectValueAccessor(value) {} + AttributeAdapter(ngraph::op::v5::Loop::SpecialBodyPorts& value) + : DirectValueAccessor(value) {} static constexpr DiscreteTypeInfo type_info{"AttributeAdapter", 0}; const DiscreteTypeInfo& get_type_info() const override { return type_info; } }; -} // namespace ngraph + +} // namespace ov diff --git a/ngraph/core/include/ngraph/op/lstm_cell.hpp b/ngraph/core/include/ngraph/op/lstm_cell.hpp index eabcd319bf7..b6d9a4f16de 100644 --- a/ngraph/core/include/ngraph/op/lstm_cell.hpp +++ b/ngraph/core/include/ngraph/op/lstm_cell.hpp @@ -192,9 +192,9 @@ public: float clip = 0.f, bool input_forget = false); - virtual void validate_and_infer_types() override; + void validate_and_infer_types() override; bool visit_attributes(AttributeVisitor& visitor) override; - virtual std::shared_ptr clone_with_new_inputs(const OutputVector& new_args) const override; + std::shared_ptr clone_with_new_inputs(const OutputVector& new_args) const override; bool get_input_forget() const { return m_input_forget; @@ -383,15 +383,21 @@ private: NGRAPH_API std::ostream& operator<<(std::ostream& s, const op::LSTMWeightsFormat& type); +} // namespace ngraph + +namespace ov { template <> -class NGRAPH_API AttributeAdapter : public EnumAttributeAdapterBase { +class NGRAPH_API AttributeAdapter + : public EnumAttributeAdapterBase { public: - AttributeAdapter(op::LSTMWeightsFormat& value) : EnumAttributeAdapterBase(value) {} + AttributeAdapter(ngraph::op::LSTMWeightsFormat& value) + : EnumAttributeAdapterBase(value) {} static constexpr DiscreteTypeInfo type_info{"AttributeAdapter", 1}; const DiscreteTypeInfo& get_type_info() const override { return type_info; } }; -} // namespace ngraph + +} // namespace ov diff --git a/ngraph/core/include/ngraph/op/matrix_nms.hpp b/ngraph/core/include/ngraph/op/matrix_nms.hpp index b3998dc2a3b..e77b7b439c3 100644 --- a/ngraph/core/include/ngraph/op/matrix_nms.hpp +++ b/ngraph/core/include/ngraph/op/matrix_nms.hpp @@ -74,17 +74,21 @@ protected: } // namespace op NGRAPH_API std::ostream& operator<<(std::ostream& s, const op::v8::MatrixNms::DecayFunction& type); +} // namespace ngraph + +namespace ov { template <> -class NGRAPH_API AttributeAdapter - : public EnumAttributeAdapterBase { +class NGRAPH_API AttributeAdapter + : public EnumAttributeAdapterBase { public: - AttributeAdapter(op::v8::MatrixNms::DecayFunction& value) - : EnumAttributeAdapterBase(value) {} + AttributeAdapter(ngraph::op::v8::MatrixNms::DecayFunction& value) + : EnumAttributeAdapterBase(value) {} static constexpr DiscreteTypeInfo type_info{"AttributeAdapter", 1}; const DiscreteTypeInfo& get_type_info() const override { return type_info; } }; -} // namespace ngraph + +} // namespace ov diff --git a/ngraph/core/include/ngraph/op/mvn.hpp b/ngraph/core/include/ngraph/op/mvn.hpp index 4b6cd70c63a..8795a7cbb8f 100644 --- a/ngraph/core/include/ngraph/op/mvn.hpp +++ b/ngraph/core/include/ngraph/op/mvn.hpp @@ -41,11 +41,11 @@ public: /// MVN(const Output& data, AxisSet reduction_axes, bool normalize_variance = true, double eps = 1e-9); - virtual void validate_and_infer_types() override; + void validate_and_infer_types() override; bool visit_attributes(AttributeVisitor& visitor) override; - virtual std::shared_ptr clone_with_new_inputs(const OutputVector& new_args) const override; + std::shared_ptr clone_with_new_inputs(const OutputVector& new_args) const override; double get_eps() const { return m_eps; @@ -129,15 +129,19 @@ private: }; } // namespace v6 } // namespace op +} // namespace ngraph + +namespace ov { template <> -class NGRAPH_API AttributeAdapter : public EnumAttributeAdapterBase { +class NGRAPH_API AttributeAdapter : public EnumAttributeAdapterBase { public: - AttributeAdapter(op::MVNEpsMode& value) : EnumAttributeAdapterBase(value) {} + AttributeAdapter(ngraph::op::MVNEpsMode& value) : EnumAttributeAdapterBase(value) {} static constexpr DiscreteTypeInfo type_info{"AttributeAdapter", 0}; const DiscreteTypeInfo& get_type_info() const override { return type_info; } }; -} // namespace ngraph + +} // namespace ov diff --git a/ngraph/core/include/ngraph/op/non_max_suppression.hpp b/ngraph/core/include/ngraph/op/non_max_suppression.hpp index 0a75980b5ee..ef6e6178139 100644 --- a/ngraph/core/include/ngraph/op/non_max_suppression.hpp +++ b/ngraph/core/include/ngraph/op/non_max_suppression.hpp @@ -366,12 +366,21 @@ protected: NGRAPH_API std::ostream& operator<<(std::ostream& s, const op::v1::NonMaxSuppression::BoxEncodingType& type); +NGRAPH_API +std::ostream& operator<<(std::ostream& s, const op::v3::NonMaxSuppression::BoxEncodingType& type); + +NGRAPH_API +std::ostream& operator<<(std::ostream& s, const op::v5::NonMaxSuppression::BoxEncodingType& type); +} // namespace ngraph + +namespace ov { + template <> -class NGRAPH_API AttributeAdapter - : public EnumAttributeAdapterBase { +class NGRAPH_API AttributeAdapter + : public EnumAttributeAdapterBase { public: - AttributeAdapter(op::v1::NonMaxSuppression::BoxEncodingType& value) - : EnumAttributeAdapterBase(value) {} + AttributeAdapter(ngraph::op::v1::NonMaxSuppression::BoxEncodingType& value) + : EnumAttributeAdapterBase(value) {} static constexpr DiscreteTypeInfo type_info{"AttributeAdapter", 1}; const DiscreteTypeInfo& get_type_info() const override { @@ -379,15 +388,12 @@ public: } }; -NGRAPH_API -std::ostream& operator<<(std::ostream& s, const op::v3::NonMaxSuppression::BoxEncodingType& type); - template <> -class NGRAPH_API AttributeAdapter - : public EnumAttributeAdapterBase { +class NGRAPH_API AttributeAdapter + : public EnumAttributeAdapterBase { public: - AttributeAdapter(op::v3::NonMaxSuppression::BoxEncodingType& value) - : EnumAttributeAdapterBase(value) {} + AttributeAdapter(ngraph::op::v3::NonMaxSuppression::BoxEncodingType& value) + : EnumAttributeAdapterBase(value) {} static constexpr DiscreteTypeInfo type_info{"AttributeAdapter", 1}; const DiscreteTypeInfo& get_type_info() const override { @@ -395,19 +401,17 @@ public: } }; -NGRAPH_API -std::ostream& operator<<(std::ostream& s, const op::v5::NonMaxSuppression::BoxEncodingType& type); - template <> -class NGRAPH_API AttributeAdapter - : public EnumAttributeAdapterBase { +class NGRAPH_API AttributeAdapter + : public EnumAttributeAdapterBase { public: - AttributeAdapter(op::v5::NonMaxSuppression::BoxEncodingType& value) - : EnumAttributeAdapterBase(value) {} + AttributeAdapter(ngraph::op::v5::NonMaxSuppression::BoxEncodingType& value) + : EnumAttributeAdapterBase(value) {} static constexpr DiscreteTypeInfo type_info{"AttributeAdapter", 1}; const DiscreteTypeInfo& get_type_info() const override { return type_info; } }; -} // namespace ngraph + +} // namespace ov diff --git a/ngraph/core/include/ngraph/op/parameter.hpp b/ngraph/core/include/ngraph/op/parameter.hpp index 0795cc5cc7f..9ac3feb7b8f 100644 --- a/ngraph/core/include/ngraph/op/parameter.hpp +++ b/ngraph/core/include/ngraph/op/parameter.hpp @@ -59,11 +59,14 @@ protected: using v0::Parameter; } // namespace op using ParameterVector = std::vector>; +} // namespace ngraph + +namespace ov { template <> -class NGRAPH_API AttributeAdapter : public VisitorAdapter { +class NGRAPH_API AttributeAdapter : public VisitorAdapter { public: - AttributeAdapter(ParameterVector& ref); + AttributeAdapter(ngraph::ParameterVector& ref); bool visit_attributes(AttributeVisitor& visitor) override; @@ -73,6 +76,7 @@ public: } protected: - ParameterVector& m_ref; + ngraph::ParameterVector& m_ref; }; -} // namespace ngraph + +} // namespace ov diff --git a/ngraph/core/include/ngraph/op/result.hpp b/ngraph/core/include/ngraph/op/result.hpp index 3f63ac07efe..da47ff4b83f 100644 --- a/ngraph/core/include/ngraph/op/result.hpp +++ b/ngraph/core/include/ngraph/op/result.hpp @@ -25,7 +25,7 @@ public: bool visit_attributes(AttributeVisitor& visitor) override; void validate_and_infer_types() override; - virtual std::shared_ptr clone_with_new_inputs(const OutputVector& new_args) const override; + std::shared_ptr clone_with_new_inputs(const OutputVector& new_args) const override; void set_needs_default_layout(bool val) { m_needs_default_layout = val; @@ -45,11 +45,14 @@ private: using v0::Result; } // namespace op using ResultVector = std::vector>; +} // namespace ngraph + +namespace ov { template <> -class NGRAPH_API AttributeAdapter : public VisitorAdapter { +class NGRAPH_API AttributeAdapter : public VisitorAdapter { public: - AttributeAdapter(ResultVector& ref); + AttributeAdapter(ngraph::ResultVector& ref); bool visit_attributes(AttributeVisitor& visitor) override; @@ -59,6 +62,7 @@ public: } protected: - ResultVector& m_ref; + ngraph::ResultVector& m_ref; }; -} // namespace ngraph + +} // namespace ov diff --git a/ngraph/core/include/ngraph/op/reverse.hpp b/ngraph/core/include/ngraph/op/reverse.hpp index 1acff71b394..cbbdb750013 100644 --- a/ngraph/core/include/ngraph/op/reverse.hpp +++ b/ngraph/core/include/ngraph/op/reverse.hpp @@ -29,7 +29,7 @@ public: bool visit_attributes(AttributeVisitor& visitor) override; void validate_and_infer_types() override; - virtual std::shared_ptr clone_with_new_inputs(const OutputVector& new_args) const override; + std::shared_ptr clone_with_new_inputs(const OutputVector& new_args) const override; /// \return The second input data interpretation mode. Mode get_mode() const { @@ -60,15 +60,21 @@ private: NGRAPH_API std::ostream& operator<<(std::ostream& s, const op::v1::Reverse::Mode& type); +} // namespace ngraph + +namespace ov { template <> -class NGRAPH_API AttributeAdapter : public EnumAttributeAdapterBase { +class NGRAPH_API AttributeAdapter + : public EnumAttributeAdapterBase { public: - AttributeAdapter(op::v1::Reverse::Mode& value) : EnumAttributeAdapterBase(value) {} + AttributeAdapter(ngraph::op::v1::Reverse::Mode& value) + : EnumAttributeAdapterBase(value) {} static constexpr DiscreteTypeInfo type_info{"AttributeAdapter", 1}; const DiscreteTypeInfo& get_type_info() const override { return type_info; } }; -} // namespace ngraph + +} // namespace ov diff --git a/ngraph/core/include/ngraph/op/roi_align.hpp b/ngraph/core/include/ngraph/op/roi_align.hpp index ae4656a9d53..03f333c98a1 100644 --- a/ngraph/core/include/ngraph/op/roi_align.hpp +++ b/ngraph/core/include/ngraph/op/roi_align.hpp @@ -48,9 +48,9 @@ public: const float spatial_scale, const PoolingMode mode); - virtual void validate_and_infer_types() override; + void validate_and_infer_types() override; bool visit_attributes(AttributeVisitor& visitor) override; - virtual std::shared_ptr clone_with_new_inputs(const OutputVector& new_args) const override; + std::shared_ptr clone_with_new_inputs(const OutputVector& new_args) const override; int get_pooled_h() const { return m_pooled_h; @@ -85,17 +85,21 @@ using v3::ROIAlign; } // namespace op std::ostream& operator<<(std::ostream& s, const op::v3::ROIAlign::PoolingMode& mode); +} // namespace ngraph + +namespace ov { template <> -class NGRAPH_API AttributeAdapter - : public EnumAttributeAdapterBase { +class NGRAPH_API AttributeAdapter + : public EnumAttributeAdapterBase { public: - AttributeAdapter(op::v3::ROIAlign::PoolingMode& value) - : EnumAttributeAdapterBase(value) {} + AttributeAdapter(ngraph::op::v3::ROIAlign::PoolingMode& value) + : EnumAttributeAdapterBase(value) {} static constexpr DiscreteTypeInfo type_info{"AttributeAdapter", 3}; const DiscreteTypeInfo& get_type_info() const override { return type_info; } }; -} // namespace ngraph + +} // namespace ov diff --git a/ngraph/core/include/ngraph/op/round.hpp b/ngraph/core/include/ngraph/op/round.hpp index 5efed5aa9cf..38a462132f0 100644 --- a/ngraph/core/include/ngraph/op/round.hpp +++ b/ngraph/core/include/ngraph/op/round.hpp @@ -34,7 +34,7 @@ public: bool visit_attributes(AttributeVisitor& visitor) override; void validate_and_infer_types() override; - virtual std::shared_ptr clone_with_new_inputs(const OutputVector& new_args) const override; + std::shared_ptr clone_with_new_inputs(const OutputVector& new_args) const override; bool evaluate(const HostTensorVector& outputs, const HostTensorVector& inputs) const override; bool has_evaluate() const override; @@ -50,16 +50,21 @@ private: } // namespace op NGRAPH_API std::ostream& operator<<(std::ostream& s, const op::v5::Round::RoundMode& type); +} // namespace ngraph + +namespace ov { template <> -class NGRAPH_API AttributeAdapter - : public EnumAttributeAdapterBase { +class NGRAPH_API AttributeAdapter + : public EnumAttributeAdapterBase { public: - AttributeAdapter(op::v5::Round::RoundMode& value) : EnumAttributeAdapterBase(value) {} + AttributeAdapter(ngraph::op::v5::Round::RoundMode& value) + : EnumAttributeAdapterBase(value) {} static constexpr DiscreteTypeInfo type_info{"AttributeAdapter", 5}; const DiscreteTypeInfo& get_type_info() const override { return type_info; } }; -} // namespace ngraph + +} // namespace ov diff --git a/ngraph/core/include/ngraph/op/space_to_depth.hpp b/ngraph/core/include/ngraph/op/space_to_depth.hpp index 4037faa1e5b..d72c725f60e 100644 --- a/ngraph/core/include/ngraph/op/space_to_depth.hpp +++ b/ngraph/core/include/ngraph/op/space_to_depth.hpp @@ -46,7 +46,7 @@ public: return m_mode; } void validate_and_infer_types() override; - virtual std::shared_ptr clone_with_new_inputs(const OutputVector& new_args) const override; + std::shared_ptr clone_with_new_inputs(const OutputVector& new_args) const override; bool evaluate(const HostTensorVector& outputs, const HostTensorVector& inputs) const override; bool has_evaluate() const override; @@ -61,17 +61,21 @@ using v0::SpaceToDepth; NGRAPH_API std::ostream& operator<<(std::ostream& s, const op::v0::SpaceToDepth::SpaceToDepthMode& type); +} // namespace ngraph + +namespace ov { template <> -class NGRAPH_API AttributeAdapter - : public EnumAttributeAdapterBase { +class NGRAPH_API AttributeAdapter + : public EnumAttributeAdapterBase { public: - AttributeAdapter(op::v0::SpaceToDepth::SpaceToDepthMode& value) - : EnumAttributeAdapterBase(value) {} + AttributeAdapter(ngraph::op::v0::SpaceToDepth::SpaceToDepthMode& value) + : EnumAttributeAdapterBase(value) {} static constexpr DiscreteTypeInfo type_info{"AttributeAdapter", 0}; const DiscreteTypeInfo& get_type_info() const override { return type_info; } }; -} // namespace ngraph + +} // namespace ov diff --git a/ngraph/core/include/ngraph/op/util/attr_types.hpp b/ngraph/core/include/ngraph/op/util/attr_types.hpp index 679a432ac5c..c14e996e8a5 100644 --- a/ngraph/core/include/ngraph/op/util/attr_types.hpp +++ b/ngraph/core/include/ngraph/op/util/attr_types.hpp @@ -18,20 +18,7 @@ enum class PadMode { CONSTANT = 0, EDGE, REFLECT, SYMMETRIC }; NGRAPH_API std::ostream& operator<<(std::ostream& s, const PadMode& type); -} // namespace op -template <> -class NGRAPH_API AttributeAdapter : public EnumAttributeAdapterBase { -public: - AttributeAdapter(op::PadMode& value) : EnumAttributeAdapterBase(value) {} - - static constexpr DiscreteTypeInfo type_info{"AttributeAdapter", 0}; - const DiscreteTypeInfo& get_type_info() const override { - return type_info; - } -}; - -namespace op { /// \brief Padding Type used for `Convolution` and `Pooling` /// /// Follows ONNX padding type definitions @@ -57,20 +44,7 @@ enum class PadType { NGRAPH_API std::ostream& operator<<(std::ostream& s, const PadType& type); -} // namespace op -template <> -class NGRAPH_API AttributeAdapter : public EnumAttributeAdapterBase { -public: - AttributeAdapter(op::PadType& value) : EnumAttributeAdapterBase(value) {} - - static constexpr DiscreteTypeInfo type_info{"AttributeAdapter", 0}; - const DiscreteTypeInfo& get_type_info() const override { - return type_info; - } -}; - -namespace op { /// \brief Rounding Type used for `Pooling` operators. enum class RoundingType { FLOOR = 0, @@ -79,20 +53,7 @@ enum class RoundingType { NGRAPH_API std::ostream& operator<<(std::ostream& s, const RoundingType& type); -} // namespace op -template <> -class NGRAPH_API AttributeAdapter : public EnumAttributeAdapterBase { -public: - AttributeAdapter(op::RoundingType& value) : EnumAttributeAdapterBase(value) {} - - static constexpr DiscreteTypeInfo type_info{"AttributeAdapter", 0}; - const DiscreteTypeInfo& get_type_info() const override { - return type_info; - } -}; - -namespace op { /// \brief Specifies the algorithm to use for implicit broadcasting of a tensor /// to align with another tensor /// @@ -140,8 +101,6 @@ enum class AutoBroadcastType { NGRAPH_API std::ostream& operator<<(std::ostream& s, const AutoBroadcastType& type); -} // namespace op -namespace op { /// \brief BroadcastType specifies rules used for mapping of input tensor axes to output /// shape axes. /// @@ -162,31 +121,7 @@ enum class BroadcastType { NONE, EXPLICIT = NONE, NUMPY, PDPD, BIDIRECTIONAL }; NGRAPH_API std::ostream& operator<<(std::ostream& s, const BroadcastType& type); -} // namespace op -template <> -class NGRAPH_API AttributeAdapter : public EnumAttributeAdapterBase { -public: - AttributeAdapter(op::AutoBroadcastType& value) : EnumAttributeAdapterBase(value) {} - - static constexpr DiscreteTypeInfo type_info{"AttributeAdapter", 0}; - const DiscreteTypeInfo& get_type_info() const override { - return type_info; - } -}; - -template <> -class NGRAPH_API AttributeAdapter : public EnumAttributeAdapterBase { -public: - AttributeAdapter(op::BroadcastType& value) : EnumAttributeAdapterBase(value) {} - - static constexpr DiscreteTypeInfo type_info{"AttributeAdapter", 0}; - const DiscreteTypeInfo& get_type_info() const override { - return type_info; - } -}; - -namespace op { /// \brief Specifies how eps is combined with L2 value enum class EpsMode { // Add bias to norm @@ -197,20 +132,7 @@ enum class EpsMode { NGRAPH_API std::ostream& operator<<(std::ostream& s, const EpsMode& type); -} // namespace op -template <> -class NGRAPH_API AttributeAdapter : public EnumAttributeAdapterBase { -public: - AttributeAdapter(op::EpsMode& value) : EnumAttributeAdapterBase(value) {} - - static constexpr DiscreteTypeInfo type_info{"AttributeAdapter", 0}; - const DiscreteTypeInfo& get_type_info() const override { - return type_info; - } -}; - -namespace op { enum class TopKSortType { // Returned values are not sorte NONE, @@ -222,20 +144,7 @@ enum class TopKSortType { NGRAPH_API std::ostream& operator<<(std::ostream& s, const TopKSortType& type); -} // namespace op -template <> -class NGRAPH_API AttributeAdapter : public EnumAttributeAdapterBase { -public: - AttributeAdapter(op::TopKSortType& value) : EnumAttributeAdapterBase(value) {} - - static constexpr DiscreteTypeInfo type_info{"AttributeAdapter", 0}; - const DiscreteTypeInfo& get_type_info() const override { - return type_info; - } -}; - -namespace op { enum class TopKMode { MAX, MIN, @@ -243,20 +152,7 @@ enum class TopKMode { NGRAPH_API std::ostream& operator<<(std::ostream& s, const TopKMode& type); -} // namespace op -template <> -class NGRAPH_API AttributeAdapter : public EnumAttributeAdapterBase { -public: - AttributeAdapter(op::TopKMode& value) : EnumAttributeAdapterBase(value) {} - - static constexpr DiscreteTypeInfo type_info{"AttributeAdapter", 1}; - const DiscreteTypeInfo& get_type_info() const override { - return type_info; - } -}; - -namespace op { /// \brief Implicit broadcast specification struct NGRAPH_API AutoBroadcastSpec { AutoBroadcastSpec() : m_type(AutoBroadcastType::NONE), m_axis(0) {} @@ -280,24 +176,7 @@ struct NGRAPH_API AutoBroadcastSpec { private: AutoBroadcastType type_from_string(const std::string& type) const; }; -} // namespace op -template <> -class AttributeAdapter : public VisitorAdapter { -public: - AttributeAdapter(op::AutoBroadcastSpec& value) : m_ref(value) {} - bool visit_attributes(AttributeVisitor& visitor) override; - - static constexpr DiscreteTypeInfo type_info{"AttributeAdapter", 0}; - const DiscreteTypeInfo& get_type_info() const override { - return type_info; - } - -protected: - op::AutoBroadcastSpec& m_ref; -}; - -namespace op { /// \brief Implicit broadcast specification struct NGRAPH_API BroadcastModeSpec { BroadcastModeSpec() : m_type(BroadcastType::NUMPY), m_axis(0) {} @@ -312,24 +191,7 @@ struct NGRAPH_API BroadcastModeSpec { return a.m_type == m_type && a.m_axis == m_axis; } }; -} // namespace op -template <> -class AttributeAdapter : public VisitorAdapter { -public: - AttributeAdapter(op::BroadcastModeSpec& value) : m_ref(value) {} - bool visit_attributes(AttributeVisitor& visitor) override; - - static constexpr DiscreteTypeInfo type_info{"AttributeAdapter", 0}; - const DiscreteTypeInfo& get_type_info() const override { - return type_info; - } - -protected: - op::BroadcastModeSpec& m_ref; -}; - -namespace op { /// /// \brief This class defines possible recurrent sequence directions. /// @@ -338,17 +200,142 @@ enum class RecurrentSequenceDirection { FORWARD, REVERSE, BIDIRECTIONAL }; NGRAPH_API std::ostream& operator<<(std::ostream& s, const RecurrentSequenceDirection& direction); } // namespace op +} // namespace ngraph + +namespace ov { +template <> +class NGRAPH_API AttributeAdapter : public EnumAttributeAdapterBase { +public: + AttributeAdapter(ngraph::op::PadMode& value) : EnumAttributeAdapterBase(value) {} + + static constexpr DiscreteTypeInfo type_info{"AttributeAdapter", 0}; + const DiscreteTypeInfo& get_type_info() const override { + return type_info; + } +}; template <> -class NGRAPH_API AttributeAdapter - : public EnumAttributeAdapterBase { +class NGRAPH_API AttributeAdapter : public EnumAttributeAdapterBase { public: - AttributeAdapter(op::RecurrentSequenceDirection& value) - : EnumAttributeAdapterBase(value) {} + AttributeAdapter(ngraph::op::PadType& value) : EnumAttributeAdapterBase(value) {} + + static constexpr DiscreteTypeInfo type_info{"AttributeAdapter", 0}; + const DiscreteTypeInfo& get_type_info() const override { + return type_info; + } +}; + +template <> +class NGRAPH_API AttributeAdapter + : public EnumAttributeAdapterBase { +public: + AttributeAdapter(ngraph::op::RoundingType& value) : EnumAttributeAdapterBase(value) {} + + static constexpr DiscreteTypeInfo type_info{"AttributeAdapter", 0}; + const DiscreteTypeInfo& get_type_info() const override { + return type_info; + } +}; + +template <> +class NGRAPH_API AttributeAdapter + : public EnumAttributeAdapterBase { +public: + AttributeAdapter(ngraph::op::AutoBroadcastType& value) + : EnumAttributeAdapterBase(value) {} + + static constexpr DiscreteTypeInfo type_info{"AttributeAdapter", 0}; + const DiscreteTypeInfo& get_type_info() const override { + return type_info; + } +}; + +template <> +class NGRAPH_API AttributeAdapter + : public EnumAttributeAdapterBase { +public: + AttributeAdapter(ngraph::op::BroadcastType& value) : EnumAttributeAdapterBase(value) {} + + static constexpr DiscreteTypeInfo type_info{"AttributeAdapter", 0}; + const DiscreteTypeInfo& get_type_info() const override { + return type_info; + } +}; + +template <> +class NGRAPH_API AttributeAdapter : public EnumAttributeAdapterBase { +public: + AttributeAdapter(ngraph::op::EpsMode& value) : EnumAttributeAdapterBase(value) {} + + static constexpr DiscreteTypeInfo type_info{"AttributeAdapter", 0}; + const DiscreteTypeInfo& get_type_info() const override { + return type_info; + } +}; + +template <> +class NGRAPH_API AttributeAdapter + : public EnumAttributeAdapterBase { +public: + AttributeAdapter(ngraph::op::TopKSortType& value) : EnumAttributeAdapterBase(value) {} + + static constexpr DiscreteTypeInfo type_info{"AttributeAdapter", 0}; + const DiscreteTypeInfo& get_type_info() const override { + return type_info; + } +}; + +template <> +class NGRAPH_API AttributeAdapter : public EnumAttributeAdapterBase { +public: + AttributeAdapter(ngraph::op::TopKMode& value) : EnumAttributeAdapterBase(value) {} + + static constexpr DiscreteTypeInfo type_info{"AttributeAdapter", 1}; + const DiscreteTypeInfo& get_type_info() const override { + return type_info; + } +}; + +template <> +class AttributeAdapter : public VisitorAdapter { +public: + AttributeAdapter(ngraph::op::AutoBroadcastSpec& value) : m_ref(value) {} + bool visit_attributes(AttributeVisitor& visitor) override; + + static constexpr DiscreteTypeInfo type_info{"AttributeAdapter", 0}; + const DiscreteTypeInfo& get_type_info() const override { + return type_info; + } + +protected: + ngraph::op::AutoBroadcastSpec& m_ref; +}; + +template <> +class AttributeAdapter : public VisitorAdapter { +public: + AttributeAdapter(ngraph::op::BroadcastModeSpec& value) : m_ref(value) {} + bool visit_attributes(AttributeVisitor& visitor) override; + + static constexpr DiscreteTypeInfo type_info{"AttributeAdapter", 0}; + const DiscreteTypeInfo& get_type_info() const override { + return type_info; + } + +protected: + ngraph::op::BroadcastModeSpec& m_ref; +}; + +template <> +class NGRAPH_API AttributeAdapter + : public EnumAttributeAdapterBase { +public: + AttributeAdapter(ngraph::op::RecurrentSequenceDirection& value) + : EnumAttributeAdapterBase(value) {} static constexpr DiscreteTypeInfo type_info{"AttributeAdapter", 1}; const DiscreteTypeInfo& get_type_info() const override { return type_info; } }; -} // namespace ngraph +} // namespace ov diff --git a/ngraph/core/include/ngraph/op/util/multi_subgraph_base.hpp b/ngraph/core/include/ngraph/op/util/multi_subgraph_base.hpp index 0cc89d9c387..16919a8a21b 100644 --- a/ngraph/core/include/ngraph/op/util/multi_subgraph_base.hpp +++ b/ngraph/core/include/ngraph/op/util/multi_subgraph_base.hpp @@ -295,6 +295,9 @@ using MultiSubgraphOutputDescriptionVector = util::MultiSubGraphOp::MultiSubgrap } // namespace util } // namespace op +} // namespace ngraph + +namespace ov { template <> class NGRAPH_API AttributeAdapter>> @@ -317,4 +320,5 @@ public: NGRAPH_RTTI_DECLARATION; }; -} // namespace ngraph + +} // namespace ov diff --git a/ngraph/core/include/ngraph/op/util/nms_base.hpp b/ngraph/core/include/ngraph/op/util/nms_base.hpp index 877f67304c8..1d551935496 100644 --- a/ngraph/core/include/ngraph/op/util/nms_base.hpp +++ b/ngraph/core/include/ngraph/op/util/nms_base.hpp @@ -75,17 +75,21 @@ protected: NGRAPH_API std::ostream& operator<<(std::ostream& s, const op::util::NmsBase::SortResultType& type); +} // namespace ngraph + +namespace ov { template <> -class NGRAPH_API AttributeAdapter - : public EnumAttributeAdapterBase { +class NGRAPH_API AttributeAdapter + : public EnumAttributeAdapterBase { public: - AttributeAdapter(op::util::NmsBase::SortResultType& value) - : EnumAttributeAdapterBase(value) {} + AttributeAdapter(ngraph::op::util::NmsBase::SortResultType& value) + : EnumAttributeAdapterBase(value) {} static constexpr DiscreteTypeInfo type_info{"AttributeAdapter", 1}; const DiscreteTypeInfo& get_type_info() const override { return type_info; } }; -} // namespace ngraph + +} // namespace ov diff --git a/ngraph/core/include/ngraph/op/util/variable.hpp b/ngraph/core/include/ngraph/op/util/variable.hpp index 3deabe11fea..04c873bb3ab 100644 --- a/ngraph/core/include/ngraph/op/util/variable.hpp +++ b/ngraph/core/include/ngraph/op/util/variable.hpp @@ -40,16 +40,21 @@ private: }; using VariablePtr = std::shared_ptr; using VariableVector = std::vector; +} // namespace ngraph + +namespace ov { template <> -class NGRAPH_API AttributeAdapter> : public DirectValueAccessor> { +class NGRAPH_API AttributeAdapter> + : public DirectValueAccessor> { public: - explicit AttributeAdapter(std::shared_ptr& value) - : DirectValueAccessor>(value) {} + explicit AttributeAdapter(std::shared_ptr& value) + : DirectValueAccessor>(value) {} static constexpr DiscreteTypeInfo type_info{"AttributeAdapter>", 0}; const DiscreteTypeInfo& get_type_info() const override { return type_info; } }; -} // namespace ngraph + +} // namespace ov diff --git a/ngraph/core/include/ngraph/runtime/aligned_buffer.hpp b/ngraph/core/include/ngraph/runtime/aligned_buffer.hpp index 729bb47c217..2dde201c20b 100644 --- a/ngraph/core/include/ngraph/runtime/aligned_buffer.hpp +++ b/ngraph/core/include/ngraph/runtime/aligned_buffer.hpp @@ -63,15 +63,19 @@ protected: size_t m_byte_size; }; } // namespace runtime +} // namespace ngraph + +namespace ov { template <> -class NGRAPH_API AttributeAdapter> - : public DirectValueAccessor> { +class NGRAPH_API AttributeAdapter> + : public DirectValueAccessor> { public: - AttributeAdapter(std::shared_ptr& value); + AttributeAdapter(std::shared_ptr& value); static constexpr DiscreteTypeInfo type_info{"AttributeAdapter>", 0}; const DiscreteTypeInfo& get_type_info() const override { return type_info; } }; -} // namespace ngraph + +} // namespace ov diff --git a/ngraph/core/include/ngraph/shape.hpp b/ngraph/core/include/ngraph/shape.hpp index ffd3fc05faa..ae3b25b261e 100644 --- a/ngraph/core/include/ngraph/shape.hpp +++ b/ngraph/core/include/ngraph/shape.hpp @@ -35,18 +35,6 @@ public: NGRAPH_API Shape& operator=(Shape&& v) noexcept; }; -template <> -class NGRAPH_API AttributeAdapter : public IndirectVectorValueAccessor> - -{ -public: - AttributeAdapter(Shape& value) : IndirectVectorValueAccessor>(value) {} - static constexpr DiscreteTypeInfo type_info{"AttributeAdapter", 0}; - const DiscreteTypeInfo& get_type_info() const override { - return type_info; - } -}; - /// Number of elements in spanned by a shape template size_t shape_size(const SHAPE_TYPE& shape) { @@ -92,3 +80,19 @@ inline bool is_vector(const SHAPE_TYPE& shape) { NGRAPH_API std::ostream& operator<<(std::ostream& s, const Shape& shape); } // namespace ngraph + +namespace ov { + +template <> +class NGRAPH_API AttributeAdapter + : public IndirectVectorValueAccessor> + +{ +public: + AttributeAdapter(ngraph::Shape& value) : IndirectVectorValueAccessor>(value) {} + static constexpr DiscreteTypeInfo type_info{"AttributeAdapter", 0}; + const DiscreteTypeInfo& get_type_info() const override { + return type_info; + } +}; +} // namespace ov diff --git a/ngraph/core/include/ngraph/strides.hpp b/ngraph/core/include/ngraph/strides.hpp index 67f73829110..c07c2d79c8a 100644 --- a/ngraph/core/include/ngraph/strides.hpp +++ b/ngraph/core/include/ngraph/strides.hpp @@ -33,18 +33,24 @@ public: NGRAPH_API Strides& operator=(Strides&& v) noexcept; }; +NGRAPH_API +std::ostream& operator<<(std::ostream& s, const Strides& strides); +} // namespace ngraph + +namespace ov { + template <> -class NGRAPH_API AttributeAdapter : public IndirectVectorValueAccessor> +class NGRAPH_API AttributeAdapter + : public IndirectVectorValueAccessor> { public: - AttributeAdapter(Strides& value) : IndirectVectorValueAccessor>(value) {} + AttributeAdapter(ngraph::Strides& value) + : IndirectVectorValueAccessor>(value) {} static constexpr DiscreteTypeInfo type_info{"AttributeAdapter", 0}; const DiscreteTypeInfo& get_type_info() const override { return type_info; } }; -NGRAPH_API -std::ostream& operator<<(std::ostream& s, const Strides& strides); -} // namespace ngraph +} // namespace ov diff --git a/ngraph/core/include/openvino/core/attribute_adapter.hpp b/ngraph/core/include/openvino/core/attribute_adapter.hpp new file mode 100644 index 00000000000..1cab9a7299d --- /dev/null +++ b/ngraph/core/include/openvino/core/attribute_adapter.hpp @@ -0,0 +1,474 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +#include +#include +#include + +#include "openvino/core/core_visibility.hpp" +#include "openvino/core/enum_names.hpp" +#include "openvino/core/type.hpp" + +/// +namespace ov { +class AttributeVisitor; + +/// \brief Provides access to an attribute of type AT as a value accessor type VAT +template +class ValueAccessor; + +/// \brief ValueAccessor provides an accessor for values that do not have get/set methonds +/// via AttributeVistor.on_adapter. +/// +/// All ValueAccessors must be derived from ValueAccessor so that an AttributeVisitor +/// only needs to implement a subset of the on_adapter methods. +template <> +class OPENVINO_API ValueAccessor { +public: + /// \brief type info enables identification of the value accessor, as well as is_type and + /// as_type. + virtual const DiscreteTypeInfo& get_type_info() const = 0; + virtual ~ValueAccessor() = default; +}; + +/// \brief Provides access to values via get/set methods from an m_value, typically from +/// ValueReference +/// +/// The m_buffer holds a VAT, which may be wider than the attribute AT. For example, serializers +/// that only +/// support int64_t integers would use a ValueAccessor> to reference a +/// vector attribute. Destruction moves the value back to the attribute if it was +/// changed. +/// \tparam VAT The adapter value type; may be wider than the value being accessed. +template +class ValueAccessor : public ValueAccessor { +public: + /// Returns the value + virtual const VAT& get() = 0; + /// Sets the value + virtual void set(const VAT& value) = 0; +}; + +template <> +class ValueAccessor : public ValueAccessor { +public: + virtual void* get_ptr() = 0; + virtual size_t size() = 0; +}; + +template +class DirectValueAccessor : public ValueAccessor { +public: + DirectValueAccessor(AT& ref) : m_ref(ref) {} + const AT& get() override { + return m_ref; + } + void set(const AT& value) override { + m_ref = value; + } + +protected: + AT& m_ref; +}; + +template +class IndirectScalarValueAccessor : public ValueAccessor { +public: + IndirectScalarValueAccessor(AT& ref) : m_ref(ref), m_buffer() {} + + const VAT& get() override { + if (!m_buffer_valid) { + m_buffer = static_cast(m_ref); + m_buffer_valid = true; + } + return m_buffer; + } + + void set(const VAT& value) override { + m_ref = static_cast(value); + m_buffer_valid = false; + } + +protected: + AT& m_ref; + VAT m_buffer; + bool m_buffer_valid{false}; +}; + +template +A copy_from(B& b) { + A result(b.size()); + for (size_t i = 0; i < b.size(); ++i) { + result[i] = static_cast::type>(b[i]); + } + return result; +} + +template +class IndirectVectorValueAccessor : public ValueAccessor { +public: + IndirectVectorValueAccessor(AT& ref) : m_ref(ref) {} + + const VAT& get() override { + if (!m_buffer_valid) { + m_buffer = ov::copy_from::type>(m_ref); + m_buffer_valid = true; + } + return m_buffer; + } + + void set(const VAT& value) override { + m_ref = copy_from(value); + m_buffer_valid = false; + } + + operator AT&() { + return m_ref; + } + +protected: + AT& m_ref; + VAT m_buffer; + bool m_buffer_valid{false}; +}; + +/// \brief An AttributeAdapter "captures" an attribute as an AT& and makes it available as a +/// ValueAccessor. +template +class AttributeAdapter {}; + +/// \brief Access an enum via a string +/// \tparam AT The attribute type enum class +template +class EnumAttributeAdapterBase : public ValueAccessor { +public: + EnumAttributeAdapterBase(AT& value) : m_ref(value) {} + + const std::string& get() override { + return as_string(m_ref); + } + void set(const std::string& value) override { + m_ref = as_enum(value); + } + operator AT&() { + return m_ref; + } + +protected: + AT& m_ref; +}; + +/// Adapters will see visitor +class VisitorAdapter : public ValueAccessor { +public: + virtual bool visit_attributes(AttributeVisitor& visitor) = 0; +}; + +template <> +class OPENVINO_API AttributeAdapter : public IndirectScalarValueAccessor { +public: + AttributeAdapter(float& value) : IndirectScalarValueAccessor(value) {} + + static constexpr DiscreteTypeInfo type_info{"AttributeAdapter", 0}; + const DiscreteTypeInfo& get_type_info() const override { + return type_info; + } +}; + +/// \brief Access a double as a double +template <> +class OPENVINO_API AttributeAdapter : public DirectValueAccessor { +public: + AttributeAdapter(double& value) : DirectValueAccessor(value) {} + + static constexpr DiscreteTypeInfo type_info{"AttributeAdapter", 0}; + const DiscreteTypeInfo& get_type_info() const override { + return type_info; + } +}; + +/// \brief Access a string as a string +template <> +class OPENVINO_API AttributeAdapter : public DirectValueAccessor { +public: + AttributeAdapter(std::string& value) : DirectValueAccessor(value) {} + + static constexpr DiscreteTypeInfo type_info{"AttributeAdapter", 0}; + const DiscreteTypeInfo& get_type_info() const override { + return type_info; + } +}; + +/// \brief Access a bool as a bool +template <> +class OPENVINO_API AttributeAdapter : public DirectValueAccessor { +public: + AttributeAdapter(bool& value) : DirectValueAccessor(value) {} + + static constexpr DiscreteTypeInfo type_info{"AttributeAdapter", 0}; + const DiscreteTypeInfo& get_type_info() const override { + return type_info; + } +}; + +/// \brief Access an int8_t and an int64_t +template <> +class OPENVINO_API AttributeAdapter : public IndirectScalarValueAccessor { +public: + AttributeAdapter(int8_t& value) : IndirectScalarValueAccessor(value) {} + + static constexpr DiscreteTypeInfo type_info{"AttributeAdapter", 0}; + const DiscreteTypeInfo& get_type_info() const override { + return type_info; + } +}; + +/// \brief Access an int16_t as an int64_t +template <> +class OPENVINO_API AttributeAdapter : public IndirectScalarValueAccessor { +public: + AttributeAdapter(int16_t& value) : IndirectScalarValueAccessor(value) {} + + static constexpr DiscreteTypeInfo type_info{"AttributeAdapter", 0}; + const DiscreteTypeInfo& get_type_info() const override { + return type_info; + } +}; + +/// \brief Access an int32_t as an int64_t +template <> +class OPENVINO_API AttributeAdapter : public IndirectScalarValueAccessor { +public: + AttributeAdapter(int32_t& value) : IndirectScalarValueAccessor(value) {} + + static constexpr DiscreteTypeInfo type_info{"AttributeAdapter", 0}; + const DiscreteTypeInfo& get_type_info() const override { + return type_info; + } +}; + +/// \brief Access an int64_t as an int64_t +template <> +class OPENVINO_API AttributeAdapter : public DirectValueAccessor { +public: + AttributeAdapter(int64_t& value) : DirectValueAccessor(value) {} + + static constexpr DiscreteTypeInfo type_info{"AttributeAdapter", 0}; + const DiscreteTypeInfo& get_type_info() const override { + return type_info; + } +}; + +/// \brief Access a uint8_t as an int64_t +template <> +class OPENVINO_API AttributeAdapter : public IndirectScalarValueAccessor { +public: + AttributeAdapter(uint8_t& value) : IndirectScalarValueAccessor(value) {} + + static constexpr DiscreteTypeInfo type_info{"AttributeAdapter", 0}; + const DiscreteTypeInfo& get_type_info() const override { + return type_info; + } +}; + +/// \brief Access a uint16_t as an int64_t +template <> +class OPENVINO_API AttributeAdapter : public IndirectScalarValueAccessor { +public: + AttributeAdapter(uint16_t& value) : IndirectScalarValueAccessor(value) {} + + static constexpr DiscreteTypeInfo type_info{"AttributeAdapter", 0}; + const DiscreteTypeInfo& get_type_info() const override { + return type_info; + } +}; + +/// \brief Access a uint32_t as an int64_t +template <> +class OPENVINO_API AttributeAdapter : public IndirectScalarValueAccessor { +public: + AttributeAdapter(uint32_t& value) : IndirectScalarValueAccessor(value) {} + + static constexpr DiscreteTypeInfo type_info{"AttributeAdapter", 0}; + const DiscreteTypeInfo& get_type_info() const override { + return type_info; + } +}; + +/// \brief Access a uint64_t as an int64_t +template <> +class OPENVINO_API AttributeAdapter : public IndirectScalarValueAccessor { +public: + AttributeAdapter(uint64_t& value) : IndirectScalarValueAccessor(value) {} + + static constexpr DiscreteTypeInfo type_info{"AttributeAdapter", 0}; + const DiscreteTypeInfo& get_type_info() const override { + return type_info; + } +}; + +#ifdef __APPLE__ +// size_t is one of the uint types on _WIN32 +template <> +class OPENVINO_API AttributeAdapter : public IndirectScalarValueAccessor { +public: + AttributeAdapter(size_t& value) : IndirectScalarValueAccessor(value) {} + + static constexpr DiscreteTypeInfo type_info{"AttributeAdapter", 0}; + const DiscreteTypeInfo& get_type_info() const override { + return type_info; + } +}; + +template <> +class OPENVINO_API AttributeAdapter> + : public IndirectVectorValueAccessor, std::vector> { +public: + AttributeAdapter(std::vector& value) + : IndirectVectorValueAccessor, std::vector>(value) {} + + static constexpr DiscreteTypeInfo type_info{"AttributeAdapter>", 0}; + const DiscreteTypeInfo& get_type_info() const override { + return type_info; + } +}; +#endif + +/// Note: These class bodies cannot be defined with templates because of interactions +/// between dllexport and templates on Windows. + +/// \brief Access a vector +template <> +class OPENVINO_API AttributeAdapter> : public DirectValueAccessor> { +public: + AttributeAdapter(std::vector& value) : DirectValueAccessor>(value) {} + + static constexpr DiscreteTypeInfo type_info{"AttributeAdapter>", 0}; + const DiscreteTypeInfo& get_type_info() const override { + return type_info; + } +}; + +/// \brief Access a vector +template <> +class OPENVINO_API AttributeAdapter> : public DirectValueAccessor> { +public: + AttributeAdapter(std::vector& value) : DirectValueAccessor>(value) {} + + static constexpr DiscreteTypeInfo type_info{"AttributeAdapter>", 0}; + const DiscreteTypeInfo& get_type_info() const override { + return type_info; + } +}; + +/// \brief Access a vector +template <> +class OPENVINO_API AttributeAdapter> : public DirectValueAccessor> { +public: + AttributeAdapter(std::vector& value) : DirectValueAccessor>(value) {} + + static constexpr DiscreteTypeInfo type_info{"AttributeAdapter>", 0}; + const DiscreteTypeInfo& get_type_info() const override { + return type_info; + } +}; + +/// \brief Access a vector +template <> +class OPENVINO_API AttributeAdapter> : public DirectValueAccessor> { +public: + AttributeAdapter(std::vector& value) : DirectValueAccessor>(value) {} + + static constexpr DiscreteTypeInfo type_info{"AttributeAdapter>", 0}; + const DiscreteTypeInfo& get_type_info() const override { + return type_info; + } +}; + +/// \brief Access a vector +template <> +class OPENVINO_API AttributeAdapter> : public DirectValueAccessor> { +public: + AttributeAdapter(std::vector& value) : DirectValueAccessor>(value) {} + + static constexpr DiscreteTypeInfo type_info{"AttributeAdapter>", 0}; + const DiscreteTypeInfo& get_type_info() const override { + return type_info; + } +}; + +/// \brief Access a vector +template <> +class OPENVINO_API AttributeAdapter> : public DirectValueAccessor> { +public: + AttributeAdapter(std::vector& value) : DirectValueAccessor>(value) {} + + static constexpr DiscreteTypeInfo type_info{"AttributeAdapter>", 0}; + const DiscreteTypeInfo& get_type_info() const override { + return type_info; + } +}; + +/// \brief Access a vector +template <> +class OPENVINO_API AttributeAdapter> : public DirectValueAccessor> { +public: + AttributeAdapter(std::vector& value) : DirectValueAccessor>(value) {} + + static constexpr DiscreteTypeInfo type_info{"AttributeAdapter>", 0}; + const DiscreteTypeInfo& get_type_info() const override { + return type_info; + } +}; + +/// \brief Access a vector +template <> +class OPENVINO_API AttributeAdapter> : public DirectValueAccessor> { +public: + AttributeAdapter(std::vector& value) : DirectValueAccessor>(value) {} + + static constexpr DiscreteTypeInfo type_info{"AttributeAdapter>", 0}; + const DiscreteTypeInfo& get_type_info() const override { + return type_info; + } +}; + +/// \brief Access a vector +template <> +class OPENVINO_API AttributeAdapter> : public DirectValueAccessor> { +public: + AttributeAdapter(std::vector& value) : DirectValueAccessor>(value) {} + + static constexpr DiscreteTypeInfo type_info{"AttributeAdapter>", 0}; + const DiscreteTypeInfo& get_type_info() const override { + return type_info; + } +}; + +/// \brief Access a vector +template <> +class OPENVINO_API AttributeAdapter> : public DirectValueAccessor> { +public: + AttributeAdapter(std::vector& value) : DirectValueAccessor>(value) {} + + static constexpr DiscreteTypeInfo type_info{"AttributeAdapter>", 0}; + const DiscreteTypeInfo& get_type_info() const override { + return type_info; + } +}; + +/// \brief Access a vector +template <> +class OPENVINO_API AttributeAdapter> : public DirectValueAccessor> { +public: + AttributeAdapter(std::vector& value) : DirectValueAccessor>(value) {} + + static constexpr DiscreteTypeInfo type_info{"AttributeAdapter>", 0}; + const DiscreteTypeInfo& get_type_info() const override { + return type_info; + } +}; +} // namespace ov diff --git a/ngraph/core/include/openvino/core/attribute_visitor.hpp b/ngraph/core/include/openvino/core/attribute_visitor.hpp new file mode 100644 index 00000000000..fa23b48901f --- /dev/null +++ b/ngraph/core/include/openvino/core/attribute_visitor.hpp @@ -0,0 +1,140 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +#include +#include +#include + +#include "openvino/core/partial_shape.hpp" +#include "openvino/core/type.hpp" +#include "openvino/core/type/element_type.hpp" + +namespace ngraph { +class Node; +} +namespace ov { +class Function; +template +class ValueAccessor; +template +class AttributeAdapter; +class VisitorAdapter; + +/// \brief Visits the attributes of a node, primarily for serialization-like tasks. +/// +/// Attributes are the node parameters that are always compile-time constants. +/// Values computed from the graph topology and attributes during compilation are not +/// attributes. +/// +/// Attributes have a wide variety of types, but serialization formats are more restricted. +/// We asume serialation easily supports scalar types of bool 64-bit signed, string, and double, +/// and has specialized ways to support numeric arrays and raw data+size. The visitor and +/// adapter convert between the limited serialization types and the unlimited attribute types. +/// +/// A visitor is passed to an op's visit_attributes method. The visit_attributes method calls +/// the template method visitor.on_attribute(const std::string& name, AT& value) on each +/// attribute. The visitor can read or write the attribute's value. The on_attribute +/// method creates an AttributeAdapter for the value and passes it to one of the visitors +/// on_adapter methods. The on_adapter methods expect a reference to a ValueAccessor or a +/// VisitorAdapter. A ValueAccessor has get/set methods that can be used to read/write the +/// attribute value as type VAT. These methods are triggered by deriving AttributeAdapter +/// from ValueAccessor. For more complex cases, such as structs, the on_adapter method for +/// VisitorAdapter passes the name and visitor to the adapter, so that the adapter can perform +/// additional work such as visiting struct members or sequence values. +/// +/// When a node visits an attribute with structure, the node's on_attribute passes a name for +/// the entire attribute, but the struct will have its own methods to be visited. Similarly, a +/// vector will have a sequence of members to be visited. The adapter may use the visitor +/// methods start_struct/finish_struct and start_vector/next_vector/finish_vector to inidicate +/// nexted members. +/// +/// The visitor method get_name_with_context creates a generic nested version of the name. +/// Visitors can override according to their serialization requirements. +/// +/// Attributes that are shared_ptr are special. They must have been already been +/// registered with the visitor using register_node, which needs a shared pointer to a node and +/// a string ID. The ID string will be used to serialize the node or find the node during +/// deserialization. +class OPENVINO_API AttributeVisitor { +public: + virtual ~AttributeVisitor() = default; + // Must implement these methods + /// \brief handles all specialized on_adapter methods implemented by the visitor. + /// + /// The adapter implements get_type_info(), which can be used to determine the adapter + /// directly + /// or via is_type and as_type on any platform + virtual void on_adapter(const std::string& name, ValueAccessor& adapter) = 0; + // The remaining adapter methods fall back on the void adapter if not implemented + virtual void on_adapter(const std::string& name, ValueAccessor& adapter); + virtual void on_adapter(const std::string& name, ValueAccessor& adapter); + virtual void on_adapter(const std::string& name, ValueAccessor& adapter); + virtual void on_adapter(const std::string& name, ValueAccessor& adapter); + virtual void on_adapter(const std::string& name, ValueAccessor& adapter); + virtual void on_adapter(const std::string& name, ValueAccessor& adapter); + virtual void on_adapter(const std::string& name, ValueAccessor& adapter); + virtual void on_adapter(const std::string& name, ValueAccessor& adapter); + virtual void on_adapter(const std::string& name, ValueAccessor& adapter); + virtual void on_adapter(const std::string& name, ValueAccessor& adapter); + virtual void on_adapter(const std::string& name, ValueAccessor& adapter); + virtual void on_adapter(const std::string& name, ValueAccessor& adapter); + virtual void on_adapter(const std::string& name, ValueAccessor& adapter); + virtual void on_adapter(const std::string& name, ValueAccessor>& adapter); + virtual void on_adapter(const std::string& name, ValueAccessor>& adapter); + virtual void on_adapter(const std::string& name, ValueAccessor>& adapter); + virtual void on_adapter(const std::string& name, ValueAccessor>& adapter); + virtual void on_adapter(const std::string& name, ValueAccessor>& adapter); + virtual void on_adapter(const std::string& name, ValueAccessor>& adapter); + virtual void on_adapter(const std::string& name, ValueAccessor>& adapter); + virtual void on_adapter(const std::string& name, ValueAccessor>& adapter); + virtual void on_adapter(const std::string& name, ValueAccessor>& adapter); + virtual void on_adapter(const std::string& name, ValueAccessor>& adapter); + virtual void on_adapter(const std::string& name, ValueAccessor>& adapter); + /// \brief Hook for adapters that need visitor access + virtual void on_adapter(const std::string& name, VisitorAdapter& adapter); + + /// \brief Provides API to handle nGraph Function attribute type, accessed as ValueAccessor + /// \param name attribute name + /// \param adapter reference to a Function ValueAccessor + virtual void on_adapter(const std::string& name, ValueAccessor>& adapter); + + /// The generic visitor. There must be a definition of AttributeAdapter that can convert + /// to a ValueAccessor for one of the on_adpater methods. + template + void on_attribute(const std::string& name, AT& value) { + AttributeAdapter adapter(value); + start_structure(name); + on_adapter(get_name_with_context(), adapter); + finish_structure(); + } + /// \returns The nested context of visits + const std::vector& get_context() const { + return m_context; + } + /// \returns context prepended to names + virtual std::string get_name_with_context(); + /// \brief Start visiting a nested structure + virtual void start_structure(const std::string& name); + /// \brief Finish visiting a nested structure + virtual std::string finish_structure(); + using node_id_t = std::string; + static const node_id_t invalid_node_id; + /// \brief Associate a node with an id. + /// + /// No node may be used as an attribute unless it has already been registered with an ID. + /// References to nodes are visited with a ValueAccessor of their ID. + virtual void register_node(const std::shared_ptr& node, node_id_t id = invalid_node_id); + /// Returns the node with the given id, or nullptr if there is no registered node + virtual std::shared_ptr get_registered_node(node_id_t id); + /// Returns the id for the node, or -1 if the node is not registered + virtual node_id_t get_registered_node_id(const std::shared_ptr& node); + +protected: + std::vector m_context; + std::unordered_map, node_id_t> m_node_id_map; + std::unordered_map> m_id_node_map; +}; +} // namespace ov diff --git a/ngraph/core/include/openvino/core/enum_names.hpp b/ngraph/core/include/openvino/core/enum_names.hpp new file mode 100644 index 00000000000..be32a7bdea8 --- /dev/null +++ b/ngraph/core/include/openvino/core/enum_names.hpp @@ -0,0 +1,70 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +#include +#include +#include + +#include "ngraph/check.hpp" + +namespace ov { +/// Uses a pairings defined by EnumTypes::get() to convert between strings +/// and enum values. +template +class EnumNames { +public: + /// Converts strings to enum values + static EnumType as_enum(const std::string& name) { + auto to_lower = [](const std::string& s) { + std::string rc = s; + std::transform(rc.begin(), rc.end(), rc.begin(), [](char c) { + return static_cast(::tolower(static_cast(c))); + }); + return rc; + }; + for (const auto& p : get().m_string_enums) { + if (to_lower(p.first) == to_lower(name)) { + return p.second; + } + } + NGRAPH_CHECK(false, "\"", name, "\"", " is not a member of enum ", get().m_enum_name); + } + + /// Converts enum values to strings + static const std::string& as_string(EnumType e) { + for (const auto& p : get().m_string_enums) { + if (p.second == e) { + return p.first; + } + } + NGRAPH_CHECK(false, " invalid member of enum ", get().m_enum_name); + } + +private: + /// Creates the mapping. + EnumNames(const std::string& enum_name, const std::vector> string_enums) + : m_enum_name(enum_name), + m_string_enums(string_enums) {} + + /// Must be defined to returns a singleton for each supported enum class + static EnumNames& get(); + + const std::string m_enum_name; + std::vector> m_string_enums; +}; + +/// Returns the enum value matching the string +template +typename std::enable_if::value, Type>::type as_enum(const Value& value) { + return EnumNames::as_enum(value); +} + +/// Returns the string matching the enum value +template +const std::string& as_string(Value value) { + return EnumNames::as_string(value); +} +} // namespace ov diff --git a/ngraph/core/include/openvino/core/function.hpp b/ngraph/core/include/openvino/core/function.hpp index 81607040dea..76f7a904591 100644 --- a/ngraph/core/include/openvino/core/function.hpp +++ b/ngraph/core/include/openvino/core/function.hpp @@ -272,8 +272,6 @@ private: ngraph::VariableVector m_variables; }; -} // namespace ov -namespace ngraph { template <> class NGRAPH_API AttributeAdapter> : public DirectValueAccessor> { @@ -286,4 +284,4 @@ public: return type_info; } }; -} // namespace ngraph +} // namespace ov diff --git a/ngraph/core/include/openvino/core/partial_shape.hpp b/ngraph/core/include/openvino/core/partial_shape.hpp index 34b59d7ab47..eff5c651d36 100644 --- a/ngraph/core/include/openvino/core/partial_shape.hpp +++ b/ngraph/core/include/openvino/core/partial_shape.hpp @@ -375,9 +375,6 @@ PartialShape operator+(const PartialShape& s1, const PartialShape& s2); OPENVINO_API std::ostream& operator<<(std::ostream& str, const PartialShape& shape); -} // namespace ov -namespace ngraph { - template <> class OPENVINO_API AttributeAdapter : public ValueAccessor> { public: @@ -398,4 +395,4 @@ protected: std::vector m_buffer; bool m_buffer_valid{false}; }; -} // namespace ngraph +} // namespace ov diff --git a/ngraph/core/include/openvino/core/type/element_type.hpp b/ngraph/core/include/openvino/core/type/element_type.hpp index b3ccc0e0219..88fb9d70327 100644 --- a/ngraph/core/include/openvino/core/type/element_type.hpp +++ b/ngraph/core/include/openvino/core/type/element_type.hpp @@ -165,10 +165,6 @@ OPENVINO_API std::ostream& operator<<(std::ostream& out, const ov::element::Type& obj); } // namespace element -} // namespace ov - -namespace ngraph { - template <> class OPENVINO_API AttributeAdapter : public EnumAttributeAdapterBase { public: @@ -199,4 +195,4 @@ public: protected: ov::element::Type& m_ref; }; -} // namespace ngraph +} // namespace ov diff --git a/ngraph/core/src/attribute_adapter.cpp b/ngraph/core/src/attribute_adapter.cpp index 779a03cbdcd..f590769d6b7 100644 --- a/ngraph/core/src/attribute_adapter.cpp +++ b/ngraph/core/src/attribute_adapter.cpp @@ -18,7 +18,7 @@ using namespace std; using namespace ngraph; -namespace ngraph { +namespace ov { constexpr DiscreteTypeInfo AttributeAdapter::type_info; constexpr DiscreteTypeInfo AttributeAdapter::type_info; constexpr DiscreteTypeInfo AttributeAdapter::type_info; @@ -47,4 +47,4 @@ constexpr DiscreteTypeInfo AttributeAdapter>::type_info; constexpr DiscreteTypeInfo AttributeAdapter>::type_info; constexpr DiscreteTypeInfo AttributeAdapter>::type_info; constexpr DiscreteTypeInfo AttributeAdapter>::type_info; -} // namespace ngraph +} // namespace ov diff --git a/ngraph/core/src/attribute_visitor.cpp b/ngraph/core/src/attribute_visitor.cpp index 9beec812c2b..23bc044ae66 100644 --- a/ngraph/core/src/attribute_visitor.cpp +++ b/ngraph/core/src/attribute_visitor.cpp @@ -9,135 +9,134 @@ #include "ngraph/node.hpp" using namespace std; -using namespace ngraph; -void AttributeVisitor::start_structure(const string& name) { +void ov::AttributeVisitor::start_structure(const string& name) { m_context.push_back(name); } -string AttributeVisitor::finish_structure() { +string ov::AttributeVisitor::finish_structure() { string result = m_context.back(); m_context.pop_back(); return result; } -string AttributeVisitor::get_name_with_context() { +string ov::AttributeVisitor::get_name_with_context() { ostringstream result; string sep = ""; - for (auto c : m_context) { + for (const auto& c : m_context) { result << sep << c; sep = "."; } return result.str(); } -void AttributeVisitor::on_adapter(const std::string& name, VisitorAdapter& adapter) { +void ov::AttributeVisitor::on_adapter(const std::string& name, VisitorAdapter& adapter) { adapter.visit_attributes(*this); } -void AttributeVisitor::on_adapter(const std::string& name, ValueAccessor& adapter) { +void ov::AttributeVisitor::on_adapter(const std::string& name, ValueAccessor& adapter) { on_adapter(name, static_cast&>(adapter)); } -void AttributeVisitor::on_adapter(const string& name, ValueAccessor& adapter) { +void ov::AttributeVisitor::on_adapter(const string& name, ValueAccessor& adapter) { on_adapter(name, static_cast&>(adapter)); }; -void AttributeVisitor::on_adapter(const string& name, ValueAccessor& adapter) { +void ov::AttributeVisitor::on_adapter(const string& name, ValueAccessor& adapter) { on_adapter(name, static_cast&>(adapter)); }; -void AttributeVisitor::on_adapter(const string& name, ValueAccessor& adapter) { +void ov::AttributeVisitor::on_adapter(const string& name, ValueAccessor& adapter) { on_adapter(name, static_cast&>(adapter)); } -void AttributeVisitor::on_adapter(const string& name, ValueAccessor& adapter) { +void ov::AttributeVisitor::on_adapter(const string& name, ValueAccessor& adapter) { on_adapter(name, static_cast&>(adapter)); } -void AttributeVisitor::on_adapter(const string& name, ValueAccessor& adapter) { +void ov::AttributeVisitor::on_adapter(const string& name, ValueAccessor& adapter) { on_adapter(name, static_cast&>(adapter)); } -void AttributeVisitor::on_adapter(const string& name, ValueAccessor& adapter) { +void ov::AttributeVisitor::on_adapter(const string& name, ValueAccessor& adapter) { on_adapter(name, static_cast&>(adapter)); } -void AttributeVisitor::on_adapter(const string& name, ValueAccessor& adapter) { +void ov::AttributeVisitor::on_adapter(const string& name, ValueAccessor& adapter) { on_adapter(name, static_cast&>(adapter)); } -void AttributeVisitor::on_adapter(const string& name, ValueAccessor& adapter) { +void ov::AttributeVisitor::on_adapter(const string& name, ValueAccessor& adapter) { on_adapter(name, static_cast&>(adapter)); } -void AttributeVisitor::on_adapter(const string& name, ValueAccessor& adapter) { +void ov::AttributeVisitor::on_adapter(const string& name, ValueAccessor& adapter) { on_adapter(name, static_cast&>(adapter)); } -void AttributeVisitor::on_adapter(const string& name, ValueAccessor& adapter) { +void ov::AttributeVisitor::on_adapter(const string& name, ValueAccessor& adapter) { on_adapter(name, static_cast&>(adapter)); } -void AttributeVisitor::on_adapter(const string& name, ValueAccessor& adapter) { +void ov::AttributeVisitor::on_adapter(const string& name, ValueAccessor& adapter) { on_adapter(name, static_cast&>(adapter)); } -void AttributeVisitor::on_adapter(const string& name, ValueAccessor& adapter) { +void ov::AttributeVisitor::on_adapter(const string& name, ValueAccessor& adapter) { on_adapter(name, static_cast&>(adapter)); } -void AttributeVisitor::on_adapter(const string& name, ValueAccessor>& adapter) { +void ov::AttributeVisitor::on_adapter(const string& name, ValueAccessor>& adapter) { on_adapter(name, static_cast&>(adapter)); } -void AttributeVisitor::on_adapter(const string& name, ValueAccessor>& adapter) { +void ov::AttributeVisitor::on_adapter(const string& name, ValueAccessor>& adapter) { on_adapter(name, static_cast&>(adapter)); } -void AttributeVisitor::on_adapter(const string& name, ValueAccessor>& adapter) { +void ov::AttributeVisitor::on_adapter(const string& name, ValueAccessor>& adapter) { on_adapter(name, static_cast&>(adapter)); } -void AttributeVisitor::on_adapter(const string& name, ValueAccessor>& adapter) { +void ov::AttributeVisitor::on_adapter(const string& name, ValueAccessor>& adapter) { on_adapter(name, static_cast&>(adapter)); } -void AttributeVisitor::on_adapter(const string& name, ValueAccessor>& adapter) { +void ov::AttributeVisitor::on_adapter(const string& name, ValueAccessor>& adapter) { on_adapter(name, static_cast&>(adapter)); } -void AttributeVisitor::on_adapter(const string& name, ValueAccessor>& adapter) { +void ov::AttributeVisitor::on_adapter(const string& name, ValueAccessor>& adapter) { on_adapter(name, static_cast&>(adapter)); } -void AttributeVisitor::on_adapter(const string& name, ValueAccessor>& adapter) { +void ov::AttributeVisitor::on_adapter(const string& name, ValueAccessor>& adapter) { on_adapter(name, static_cast&>(adapter)); } -void AttributeVisitor::on_adapter(const string& name, ValueAccessor>& adapter) { +void ov::AttributeVisitor::on_adapter(const string& name, ValueAccessor>& adapter) { on_adapter(name, static_cast&>(adapter)); } -void AttributeVisitor::on_adapter(const string& name, ValueAccessor>& adapter) { +void ov::AttributeVisitor::on_adapter(const string& name, ValueAccessor>& adapter) { on_adapter(name, static_cast&>(adapter)); } -void AttributeVisitor::on_adapter(const string& name, ValueAccessor>& adapter) { +void ov::AttributeVisitor::on_adapter(const string& name, ValueAccessor>& adapter) { on_adapter(name, static_cast&>(adapter)); } -void AttributeVisitor::on_adapter(const string& name, ValueAccessor>& adapter) { +void ov::AttributeVisitor::on_adapter(const string& name, ValueAccessor>& adapter) { on_adapter(name, static_cast&>(adapter)); } -void AttributeVisitor::on_adapter(const string& name, ValueAccessor>& adapter) { +void ov::AttributeVisitor::on_adapter(const string& name, ValueAccessor>& adapter) { on_adapter(name, static_cast&>(adapter)); } -const AttributeVisitor::node_id_t AttributeVisitor::invalid_node_id = ""; +const ov::AttributeVisitor::node_id_t ov::AttributeVisitor::invalid_node_id = ""; -void AttributeVisitor::register_node(const std::shared_ptr& node, node_id_t id) { +void ov::AttributeVisitor::register_node(const std::shared_ptr& node, node_id_t id) { if (id == invalid_node_id) { id = node->get_friendly_name(); } @@ -145,12 +144,13 @@ void AttributeVisitor::register_node(const std::shared_ptr& node, node_id_ m_node_id_map[node] = id; } -std::shared_ptr AttributeVisitor::get_registered_node(node_id_t id) { +std::shared_ptr ov::AttributeVisitor::get_registered_node(node_id_t id) { auto it = m_id_node_map.find(id); - return it == m_id_node_map.end() ? shared_ptr() : it->second; + return it == m_id_node_map.end() ? shared_ptr() : it->second; } -AttributeVisitor::node_id_t AttributeVisitor::get_registered_node_id(const std::shared_ptr& node) { +ov::AttributeVisitor::node_id_t ov::AttributeVisitor::get_registered_node_id( + const std::shared_ptr& node) { auto it = m_node_id_map.find(node); return it == m_node_id_map.end() ? invalid_node_id : it->second; } diff --git a/ngraph/core/src/axis_set.cpp b/ngraph/core/src/axis_set.cpp index 38dd5e29354..fcc623dc646 100644 --- a/ngraph/core/src/axis_set.cpp +++ b/ngraph/core/src/axis_set.cpp @@ -37,7 +37,7 @@ std::ostream& ngraph::operator<<(std::ostream& s, const AxisSet& axis_set) { return s; } -const std::vector& ngraph::AttributeAdapter::get() { +const std::vector& ov::AttributeAdapter::get() { if (!m_buffer_valid) { m_buffer.clear(); for (auto elt : m_ref) { @@ -48,12 +48,12 @@ const std::vector& ngraph::AttributeAdapter::get() { return m_buffer; } -void ngraph::AttributeAdapter::set(const std::vector& value) { - m_ref = AxisSet(); +void ov::AttributeAdapter::set(const std::vector& value) { + m_ref = ngraph::AxisSet(); for (auto elt : value) { m_ref.insert(elt); } m_buffer_valid = false; } -constexpr ngraph::DiscreteTypeInfo ngraph::AttributeAdapter::type_info; +constexpr ov::DiscreteTypeInfo ov::AttributeAdapter::type_info; diff --git a/ngraph/core/src/axis_vector.cpp b/ngraph/core/src/axis_vector.cpp index 5bf209c5386..33052a96496 100644 --- a/ngraph/core/src/axis_vector.cpp +++ b/ngraph/core/src/axis_vector.cpp @@ -35,4 +35,4 @@ ngraph::AxisVector& ngraph::AxisVector::operator=(AxisVector&& v) noexcept { return *this; } -constexpr ngraph::DiscreteTypeInfo ngraph::AttributeAdapter::type_info; +constexpr ov::DiscreteTypeInfo ov::AttributeAdapter::type_info; diff --git a/ngraph/core/src/coordinate.cpp b/ngraph/core/src/coordinate.cpp index a3353e5461f..f1b9c17feca 100644 --- a/ngraph/core/src/coordinate.cpp +++ b/ngraph/core/src/coordinate.cpp @@ -7,7 +7,6 @@ #include "ngraph/util.hpp" using namespace std; -using namespace ngraph; std::ostream& ngraph::operator<<(std::ostream& s, const Coordinate& coordinate) { s << "Coordinate{"; @@ -41,4 +40,4 @@ ngraph::Coordinate& ngraph::Coordinate::operator=(Coordinate&& v) noexcept { return *this; } -constexpr ngraph::DiscreteTypeInfo ngraph::AttributeAdapter::type_info; +constexpr ov::DiscreteTypeInfo ov::AttributeAdapter::type_info; diff --git a/ngraph/core/src/coordinate_diff.cpp b/ngraph/core/src/coordinate_diff.cpp index 849a9e21ca0..856a4e2ead9 100644 --- a/ngraph/core/src/coordinate_diff.cpp +++ b/ngraph/core/src/coordinate_diff.cpp @@ -40,4 +40,4 @@ ngraph::CoordinateDiff& ngraph::CoordinateDiff::operator=(CoordinateDiff&& v) no return *this; } -constexpr ngraph::DiscreteTypeInfo ngraph::AttributeAdapter::type_info; +constexpr ov::DiscreteTypeInfo ov::AttributeAdapter::type_info; diff --git a/ngraph/core/src/distributed.cpp b/ngraph/core/src/distributed.cpp index ee4d0144575..5849ef9d2b5 100644 --- a/ngraph/core/src/distributed.cpp +++ b/ngraph/core/src/distributed.cpp @@ -7,22 +7,19 @@ #include "ngraph/log.hpp" #include "ngraph/type.hpp" -using namespace ngraph; - -namespace ngraph { +namespace ov { template <> -EnumNames& EnumNames::get() { - static auto enum_names = EnumNames("reduction::Type", - {{"SUM", reduction::Type::SUM}, - {"PROD", reduction::Type::PROD}, - {"MIN", reduction::Type::MIN}, - {"MAX", reduction::Type::MAX}}); +EnumNames& EnumNames::get() { + static auto enum_names = ov::EnumNames("reduction::Type", + {{"SUM", ngraph::reduction::Type::SUM}, + {"PROD", ngraph::reduction::Type::PROD}, + {"MIN", ngraph::reduction::Type::MIN}, + {"MAX", ngraph::reduction::Type::MAX}}); return enum_names; } +constexpr DiscreteTypeInfo AttributeAdapter::type_info; +} // namespace ov -constexpr DiscreteTypeInfo AttributeAdapter::type_info; -} // namespace ngraph - -std::ostream& reduction::operator<<(std::ostream& out, const reduction::Type& obj) { +std::ostream& ngraph::reduction::operator<<(std::ostream& out, const ngraph::reduction::Type& obj) { return out << as_string(obj); } diff --git a/ngraph/core/src/node.cpp b/ngraph/core/src/node.cpp index 87524021306..96253cf4ba0 100644 --- a/ngraph/core/src/node.cpp +++ b/ngraph/core/src/node.cpp @@ -835,6 +835,7 @@ bool Node::constant_fold(OutputVector& output_values, const OutputVector& input_ return false; } +namespace ov { constexpr DiscreteTypeInfo AttributeAdapter>::type_info; AttributeAdapter>::AttributeAdapter(std::shared_ptr& value) : m_ref(value) {} @@ -874,3 +875,4 @@ bool AttributeAdapter::visit_attributes(AttributeVisitor& visitor) { } return true; } +} // namespace ov diff --git a/ngraph/core/src/op/binary_convolution.cpp b/ngraph/core/src/op/binary_convolution.cpp index c8775d6bca4..ff5c804e288 100644 --- a/ngraph/core/src/op/binary_convolution.cpp +++ b/ngraph/core/src/op/binary_convolution.cpp @@ -117,7 +117,7 @@ bool op::v1::BinaryConvolution::visit_attributes(AttributeVisitor& visitor) { return true; } -namespace ngraph { +namespace ov { template <> NGRAPH_API EnumNames& EnumNames::get() { @@ -128,11 +128,11 @@ EnumNames::get() { } constexpr DiscreteTypeInfo AttributeAdapter::type_info; +} // namespace ov std::ostream& operator<<(std::ostream& s, const op::v1::BinaryConvolution::BinaryConvolutionMode& type) { return s << as_string(type); } -} // namespace ngraph op::v1::BinaryConvolution::BinaryConvolutionMode op::v1::BinaryConvolution::mode_from_string( const std::string& mode) const { diff --git a/ngraph/core/src/op/depth_to_space.cpp b/ngraph/core/src/op/depth_to_space.cpp index 8e25c41865d..8b6eee758dd 100644 --- a/ngraph/core/src/op/depth_to_space.cpp +++ b/ngraph/core/src/op/depth_to_space.cpp @@ -113,7 +113,11 @@ bool op::DepthToSpace::has_evaluate() const { return !get_input_partial_shape(0).is_dynamic(); } -namespace ngraph { +std::ostream& ngraph::operator<<(std::ostream& s, const op::DepthToSpace::DepthToSpaceMode& type) { + return s << as_string(type); +} + +namespace ov { template <> NGRAPH_API EnumNames& EnumNames::get() { static auto enum_names = EnumNames( @@ -124,8 +128,4 @@ NGRAPH_API EnumNames& EnumNames::type_info; - -std::ostream& operator<<(std::ostream& s, const op::DepthToSpace::DepthToSpaceMode& type) { - return s << as_string(type); -} -} // namespace ngraph +} // namespace ov diff --git a/ngraph/core/src/op/gelu.cpp b/ngraph/core/src/op/gelu.cpp index 272023cdfe2..27152cedf24 100644 --- a/ngraph/core/src/op/gelu.cpp +++ b/ngraph/core/src/op/gelu.cpp @@ -51,7 +51,7 @@ void op::v0::Gelu::validate_and_infer_types() { // ------------------------------ V7 ------------------------------ -namespace ngraph { +namespace ov { template <> NGRAPH_API EnumNames& EnumNames::get() { static auto enum_names = EnumNames( @@ -61,11 +61,10 @@ NGRAPH_API EnumNames& EnumNames::type_info; - +} // namespace ov std::ostream& op::operator<<(std::ostream& s, const op::GeluApproximationMode& type) { return s << as_string(type); } -} // namespace ngraph NGRAPH_RTTI_DEFINITION(op::v7::Gelu, "Gelu", 7); diff --git a/ngraph/core/src/op/interpolate.cpp b/ngraph/core/src/op/interpolate.cpp index 42359cde32c..8aff95c9b8e 100644 --- a/ngraph/core/src/op/interpolate.cpp +++ b/ngraph/core/src/op/interpolate.cpp @@ -69,7 +69,11 @@ shared_ptr op::v0::Interpolate::clone_with_new_inputs(const OutputVector& return make_shared(new_args.at(0), new_args.at(1), m_attrs); } -namespace ngraph { +std::ostream& ngraph::operator<<(std::ostream& s, const op::v0::Interpolate::InterpolateMode& type) { + return s << as_string(type); +} + +namespace ov { template <> EnumNames& EnumNames::get() { static auto enum_names = @@ -83,10 +87,7 @@ EnumNames& EnumNames::type_info; -std::ostream& operator<<(std::ostream& s, const op::v0::Interpolate::InterpolateMode& type) { - return s << as_string(type); -} -} // namespace ngraph +} // namespace ov // Interpolate v4 @@ -479,7 +480,23 @@ bool op::v4::Interpolate::has_evaluate() const { return false; } -namespace ngraph { +std::ostream& ngraph::operator<<(std::ostream& s, const op::v4::Interpolate::InterpolateMode& type) { + return s << as_string(type); +} + +std::ostream& ngraph::operator<<(std::ostream& s, const op::v4::Interpolate::ShapeCalcMode& type) { + return s << as_string(type); +} + +std::ostream& ngraph::operator<<(std::ostream& s, const op::v4::Interpolate::CoordinateTransformMode& type) { + return s << as_string(type); +} + +std::ostream& ngraph::operator<<(std::ostream& s, const op::v4::Interpolate::NearestMode& type) { + return s << as_string(type); +} + +namespace ov { template <> NGRAPH_API EnumNames& EnumNames::get() { static auto enum_names = EnumNames( @@ -493,10 +510,6 @@ NGRAPH_API EnumNames& EnumNames::type_info; -std::ostream& operator<<(std::ostream& s, const op::v4::Interpolate::InterpolateMode& type) { - return s << as_string(type); -} - template <> NGRAPH_API EnumNames& EnumNames::get() { static auto enum_names = EnumNames( @@ -507,10 +520,6 @@ NGRAPH_API EnumNames& EnumNames::type_info; -std::ostream& operator<<(std::ostream& s, const op::v4::Interpolate::ShapeCalcMode& type) { - return s << as_string(type); -} - template <> NGRAPH_API EnumNames& EnumNames::get() { @@ -526,10 +535,6 @@ EnumNames::get() { constexpr DiscreteTypeInfo AttributeAdapter::type_info; -std::ostream& operator<<(std::ostream& s, const op::v4::Interpolate::CoordinateTransformMode& type) { - return s << as_string(type); -} - template <> NGRAPH_API EnumNames& EnumNames::get() { static auto enum_names = EnumNames( @@ -543,8 +548,4 @@ NGRAPH_API EnumNames& EnumNames::type_info; - -std::ostream& operator<<(std::ostream& s, const op::v4::Interpolate::NearestMode& type) { - return s << as_string(type); -} -} // namespace ngraph +} // namespace ov diff --git a/ngraph/core/src/op/loop.cpp b/ngraph/core/src/op/loop.cpp index ededa0bb74e..3b1b1b2064d 100644 --- a/ngraph/core/src/op/loop.cpp +++ b/ngraph/core/src/op/loop.cpp @@ -306,6 +306,6 @@ op::v5::Loop::Loop(const op::v5::Loop& other) : SubGraphOp() { other.clone_to(*this, other.input_values()); } -namespace ngraph { +namespace ov { constexpr DiscreteTypeInfo AttributeAdapter::type_info; } diff --git a/ngraph/core/src/op/lstm_cell.cpp b/ngraph/core/src/op/lstm_cell.cpp index 39ef9be6732..9dfd9b2a4e7 100644 --- a/ngraph/core/src/op/lstm_cell.cpp +++ b/ngraph/core/src/op/lstm_cell.cpp @@ -333,7 +333,7 @@ shared_ptr op::v0::LSTMCell::clone_with_new_inputs(const OutputVector& new } } -namespace ngraph { +namespace ov { template <> EnumNames& EnumNames::get() { static auto enum_names = EnumNames("op::LSTMWeightsFormat", @@ -347,10 +347,11 @@ EnumNames& EnumNames::get() { constexpr DiscreteTypeInfo AttributeAdapter::type_info; +} // namespace ov + std::ostream& operator<<(std::ostream& s, const op::LSTMWeightsFormat& type) { return s << as_string(type); } -} // namespace ngraph op::v4::LSTMCell::LSTMCell() { m_activations = {"sigmoid", "tanh", "tanh"}; diff --git a/ngraph/core/src/op/matrix_nms.cpp b/ngraph/core/src/op/matrix_nms.cpp index 117ed5e2e12..6a5af0f0d47 100644 --- a/ngraph/core/src/op/matrix_nms.cpp +++ b/ngraph/core/src/op/matrix_nms.cpp @@ -64,7 +64,11 @@ bool ngraph::op::v8::MatrixNms::visit_attributes(AttributeVisitor& visitor) { return true; } -namespace ngraph { +std::ostream& ngraph::operator<<(std::ostream& s, const op::v8::MatrixNms::DecayFunction& type) { + return s << as_string(type); +} + +namespace ov { template <> NGRAPH_API EnumNames& EnumNames::get() { static auto enum_names = @@ -76,7 +80,4 @@ NGRAPH_API EnumNames& EnumNames::type_info; -std::ostream& operator<<(std::ostream& s, const op::v8::MatrixNms::DecayFunction& type) { - return s << as_string(type); -} -} // namespace ngraph +} // namespace ov diff --git a/ngraph/core/src/op/mvn.cpp b/ngraph/core/src/op/mvn.cpp index 6ab313d1583..ed53701375d 100644 --- a/ngraph/core/src/op/mvn.cpp +++ b/ngraph/core/src/op/mvn.cpp @@ -70,7 +70,7 @@ bool op::v0::MVN::visit_attributes(AttributeVisitor& visitor) { // ------------------------------ V6 ------------------------------ -namespace ngraph { +namespace ov { template <> NGRAPH_API EnumNames& EnumNames::get() { static auto enum_names = EnumNames( @@ -81,10 +81,11 @@ NGRAPH_API EnumNames& EnumNames::get() { constexpr DiscreteTypeInfo AttributeAdapter::type_info; +} // namespace ov + std::ostream& op::operator<<(std::ostream& s, const op::MVNEpsMode& type) { return s << as_string(type); } -} // namespace ngraph NGRAPH_RTTI_DEFINITION(op::v6::MVN, "MVN", 6); diff --git a/ngraph/core/src/op/non_max_suppression.cpp b/ngraph/core/src/op/non_max_suppression.cpp index 4a02e7e6add..9a124547051 100644 --- a/ngraph/core/src/op/non_max_suppression.cpp +++ b/ngraph/core/src/op/non_max_suppression.cpp @@ -174,7 +174,7 @@ int64_t op::v1::NonMaxSuppression::max_boxes_output_from_input() const { return max_output_boxes; } -namespace ngraph { +namespace ov { template <> EnumNames& EnumNames::get() { static auto enum_names = EnumNames( @@ -186,10 +186,11 @@ EnumNames& EnumNames::type_info; -std::ostream& operator<<(std::ostream& s, const op::v1::NonMaxSuppression::BoxEncodingType& type) { +} // namespace ov + +std::ostream& ngraph::operator<<(std::ostream& s, const op::v1::NonMaxSuppression::BoxEncodingType& type) { return s << as_string(type); } -} // namespace ngraph // ------------------------------ V3 ------------------------------ @@ -360,7 +361,7 @@ int64_t op::v3::NonMaxSuppression::max_boxes_output_from_input() const { return max_output_boxes; } -namespace ngraph { +namespace ov { template <> EnumNames& EnumNames::get() { static auto enum_names = EnumNames( @@ -372,10 +373,11 @@ EnumNames& EnumNames::type_info; -std::ostream& operator<<(std::ostream& s, const op::v3::NonMaxSuppression::BoxEncodingType& type) { +} // namespace ov + +std::ostream& ngraph::operator<<(std::ostream& s, const op::v3::NonMaxSuppression::BoxEncodingType& type) { return s << as_string(type); } -} // namespace ngraph // ------------------------------ V4 ------------------------------ @@ -813,7 +815,11 @@ void op::v5::NonMaxSuppression::validate_and_infer_types() { set_output_type(2, m_output_type, Shape{1}); } -namespace ngraph { +std::ostream& ngraph::operator<<(std::ostream& s, const op::v5::NonMaxSuppression::BoxEncodingType& type) { + return s << as_string(type); +} + +namespace ov { template <> EnumNames& EnumNames::get() { static auto enum_names = EnumNames( @@ -825,7 +831,4 @@ EnumNames& EnumNames::type_info; -std::ostream& operator<<(std::ostream& s, const op::v5::NonMaxSuppression::BoxEncodingType& type) { - return s << as_string(type); -} -} // namespace ngraph +} // namespace ov diff --git a/ngraph/core/src/op/parameter.cpp b/ngraph/core/src/op/parameter.cpp index 1c3d32ed8fb..5f8ee481704 100644 --- a/ngraph/core/src/op/parameter.cpp +++ b/ngraph/core/src/op/parameter.cpp @@ -48,11 +48,11 @@ void op::Parameter::set_is_relevant_to_shapes(bool is_relevant) { m_is_relevant_to_shapes = is_relevant; } -constexpr DiscreteTypeInfo AttributeAdapter::type_info; +constexpr DiscreteTypeInfo ov::AttributeAdapter::type_info; -AttributeAdapter::AttributeAdapter(ParameterVector& ref) : m_ref(ref) {} +ov::AttributeAdapter::AttributeAdapter(ParameterVector& ref) : m_ref(ref) {} -bool AttributeAdapter::visit_attributes(AttributeVisitor& visitor) { +bool ov::AttributeAdapter::visit_attributes(AttributeVisitor& visitor) { size_t size = m_ref.size(); visitor.on_attribute("size", size); if (size != m_ref.size()) { diff --git a/ngraph/core/src/op/result.cpp b/ngraph/core/src/op/result.cpp index db23b6adbd2..8111965cbc9 100644 --- a/ngraph/core/src/op/result.cpp +++ b/ngraph/core/src/op/result.cpp @@ -62,11 +62,11 @@ bool op::Result::constant_fold(OutputVector& output_values, const OutputVector& return false; } -constexpr DiscreteTypeInfo AttributeAdapter::type_info; +constexpr DiscreteTypeInfo ov::AttributeAdapter::type_info; -AttributeAdapter::AttributeAdapter(ResultVector& ref) : m_ref(ref) {} +ov::AttributeAdapter::AttributeAdapter(ResultVector& ref) : m_ref(ref) {} -bool AttributeAdapter::visit_attributes(AttributeVisitor& visitor) { +bool ov::AttributeAdapter::visit_attributes(AttributeVisitor& visitor) { size_t size = m_ref.size(); visitor.on_attribute("size", size); if (size != m_ref.size()) { diff --git a/ngraph/core/src/op/reverse.cpp b/ngraph/core/src/op/reverse.cpp index 078099e2eec..abb3f1e4bda 100644 --- a/ngraph/core/src/op/reverse.cpp +++ b/ngraph/core/src/op/reverse.cpp @@ -197,7 +197,11 @@ bool op::v1::Reverse::has_evaluate() const { } } -namespace ngraph { +std::ostream& ngraph::operator<<(std::ostream& s, const op::v1::Reverse::Mode& type) { + return s << as_string(type); +} + +namespace ov { template <> EnumNames& EnumNames::get() { static auto enum_names = EnumNames( @@ -207,8 +211,4 @@ EnumNames& EnumNames::get() { } constexpr DiscreteTypeInfo AttributeAdapter::type_info; - -std::ostream& operator<<(std::ostream& s, const op::v1::Reverse::Mode& type) { - return s << as_string(type); -} -} // namespace ngraph +} // namespace ov diff --git a/ngraph/core/src/op/roi_align.cpp b/ngraph/core/src/op/roi_align.cpp index 410b06b8f18..34376a43997 100644 --- a/ngraph/core/src/op/roi_align.cpp +++ b/ngraph/core/src/op/roi_align.cpp @@ -161,7 +161,7 @@ shared_ptr op::v3::ROIAlign::clone_with_new_inputs(const OutputVector& new m_mode); } -namespace ngraph { +namespace ov { constexpr DiscreteTypeInfo AttributeAdapter::type_info; template <> @@ -172,10 +172,11 @@ NGRAPH_API EnumNames& EnumNames diff --git a/ngraph/core/src/op/round.cpp b/ngraph/core/src/op/round.cpp index f06e364bc78..3323ec6596a 100644 --- a/ngraph/core/src/op/round.cpp +++ b/ngraph/core/src/op/round.cpp @@ -113,7 +113,11 @@ bool op::v5::Round::has_evaluate() const { return false; } -namespace ngraph { +std::ostream& ngraph::operator<<(std::ostream& s, const op::v5::Round::RoundMode& type) { + return s << as_string(type); +} + +namespace ov { template <> EnumNames& EnumNames::get() { static auto enum_names = @@ -124,8 +128,4 @@ EnumNames& EnumNames::get() } constexpr DiscreteTypeInfo AttributeAdapter::type_info; - -std::ostream& operator<<(std::ostream& s, const op::v5::Round::RoundMode& type) { - return s << as_string(type); -} -} // namespace ngraph +} // namespace ov diff --git a/ngraph/core/src/op/space_to_depth.cpp b/ngraph/core/src/op/space_to_depth.cpp index 6e5db6a93da..102beee02ed 100644 --- a/ngraph/core/src/op/space_to_depth.cpp +++ b/ngraph/core/src/op/space_to_depth.cpp @@ -116,7 +116,11 @@ bool ngraph::op::v0::SpaceToDepth::has_evaluate() const { return !get_input_partial_shape(0).is_dynamic(); } -namespace ngraph { +std::ostream& ngraph::operator<<(std::ostream& s, const op::v0::SpaceToDepth::SpaceToDepthMode& type) { + return s << as_string(type); +} + +namespace ov { template <> NGRAPH_API EnumNames& EnumNames::get() { static auto enum_names = EnumNames( @@ -127,8 +131,4 @@ NGRAPH_API EnumNames& EnumNames::type_info; - -std::ostream& operator<<(std::ostream& s, const op::v0::SpaceToDepth::SpaceToDepthMode& type) { - return s << as_string(type); -} -} // namespace ngraph +} // namespace ov diff --git a/ngraph/core/src/op/util/attr_types.cpp b/ngraph/core/src/op/util/attr_types.cpp index 2637d443778..36814edc321 100644 --- a/ngraph/core/src/op/util/attr_types.cpp +++ b/ngraph/core/src/op/util/attr_types.cpp @@ -11,127 +11,173 @@ #include "ngraph/check.hpp" #include "ngraph/enum_names.hpp" -using namespace ngraph; +namespace ov { -const op::AutoBroadcastSpec op::AutoBroadcastSpec::NUMPY(AutoBroadcastType::NUMPY, 0); -const op::AutoBroadcastSpec op::AutoBroadcastSpec::NONE{AutoBroadcastType::NONE, 0}; - -namespace ngraph { template <> -NGRAPH_API EnumNames& EnumNames::get() { - static auto enum_names = EnumNames("op::PadMode", - {{"constant", op::PadMode::CONSTANT}, - {"edge", op::PadMode::EDGE}, - {"reflect", op::PadMode::REFLECT}, - {"symmetric", op::PadMode::SYMMETRIC}}); +NGRAPH_API EnumNames& EnumNames::get() { + static auto enum_names = EnumNames("ngraph::op::PadMode", + {{"constant", ngraph::op::PadMode::CONSTANT}, + {"edge", ngraph::op::PadMode::EDGE}, + {"reflect", ngraph::op::PadMode::REFLECT}, + {"symmetric", ngraph::op::PadMode::SYMMETRIC}}); return enum_names; } -constexpr DiscreteTypeInfo AttributeAdapter::type_info; +constexpr DiscreteTypeInfo AttributeAdapter::type_info; -std::ostream& op::operator<<(std::ostream& s, const op::PadMode& type) { - return s << as_string(type); -} template <> -NGRAPH_API EnumNames& EnumNames::get() { - static auto enum_names = EnumNames("op::PadType", - {{"explicit", op::PadType::EXPLICIT}, - {"same_lower", op::PadType::SAME_LOWER}, - {"same_upper", op::PadType::SAME_UPPER}, - {"valid", op::PadType::VALID}}); +NGRAPH_API EnumNames& EnumNames::get() { + static auto enum_names = EnumNames("ngraph::op::PadType", + {{"explicit", ngraph::op::PadType::EXPLICIT}, + {"same_lower", ngraph::op::PadType::SAME_LOWER}, + {"same_upper", ngraph::op::PadType::SAME_UPPER}, + {"valid", ngraph::op::PadType::VALID}}); return enum_names; } -constexpr DiscreteTypeInfo AttributeAdapter::type_info; +constexpr DiscreteTypeInfo AttributeAdapter::type_info; -std::ostream& op::operator<<(std::ostream& s, const op::PadType& type) { - return s << as_string(type); -} template <> -NGRAPH_API EnumNames& EnumNames::get() { +NGRAPH_API EnumNames& EnumNames::get() { + static auto enum_names = EnumNames( + "ngraph::op::RoundingType", + {{"floor", ngraph::op::RoundingType::FLOOR}, {"ceil", ngraph::op::RoundingType::CEIL}}); + return enum_names; +} + +constexpr DiscreteTypeInfo AttributeAdapter::type_info; + +template <> +NGRAPH_API EnumNames& EnumNames::get() { static auto enum_names = - EnumNames("op::RoundingType", - {{"floor", op::RoundingType::FLOOR}, {"ceil", op::RoundingType::CEIL}}); + EnumNames("ngraph::op::AutoBroadcastType", + {{"none", ngraph::op::AutoBroadcastType::NONE}, + {"explicit", ngraph::op::AutoBroadcastType::EXPLICIT}, + {"numpy", ngraph::op::AutoBroadcastType::NUMPY}, + {"pdpd", ngraph::op::AutoBroadcastType::PDPD}}); return enum_names; } - -constexpr DiscreteTypeInfo AttributeAdapter::type_info; - -std::ostream& op::operator<<(std::ostream& s, const op::RoundingType& type) { - return s << as_string(type); -} +constexpr DiscreteTypeInfo AttributeAdapter::type_info; template <> -NGRAPH_API EnumNames& EnumNames::get() { - static auto enum_names = EnumNames("op::AutoBroadcastType", - {{"none", op::AutoBroadcastType::NONE}, - {"explicit", op::AutoBroadcastType::EXPLICIT}, - {"numpy", op::AutoBroadcastType::NUMPY}, - {"pdpd", op::AutoBroadcastType::PDPD}}); - return enum_names; -} -constexpr DiscreteTypeInfo AttributeAdapter::type_info; - -template <> -NGRAPH_API EnumNames& EnumNames::get() { - static auto enum_names = EnumNames("op::BroadcastType", - {{"none", op::BroadcastType::NONE}, - {"numpy", op::BroadcastType::NUMPY}, - {"explicit", op::BroadcastType::EXPLICIT}, - {"pdpd", op::BroadcastType::PDPD}, - {"bidirectional", op::BroadcastType::BIDIRECTIONAL}}); - return enum_names; -} - -std::ostream& op::operator<<(std::ostream& s, const op::BroadcastType& type) { - return s << as_string(type); -} - -constexpr DiscreteTypeInfo AttributeAdapter::type_info; - -std::ostream& op::operator<<(std::ostream& s, const op::AutoBroadcastType& type) { - return s << as_string(type); -} -template <> -NGRAPH_API EnumNames& EnumNames::get() { +NGRAPH_API EnumNames& EnumNames::get() { static auto enum_names = - EnumNames("op::EpsMode", {{"add", op::EpsMode::ADD}, {"max", op::EpsMode::MAX}}); + EnumNames("ngraph::op::BroadcastType", + {{"none", ngraph::op::BroadcastType::NONE}, + {"numpy", ngraph::op::BroadcastType::NUMPY}, + {"explicit", ngraph::op::BroadcastType::EXPLICIT}, + {"pdpd", ngraph::op::BroadcastType::PDPD}, + {"bidirectional", ngraph::op::BroadcastType::BIDIRECTIONAL}}); return enum_names; } -constexpr DiscreteTypeInfo AttributeAdapter::type_info; - -std::ostream& op::operator<<(std::ostream& s, const op::EpsMode& type) { - return s << as_string(type); -} - +constexpr DiscreteTypeInfo AttributeAdapter::type_info; template <> -NGRAPH_API EnumNames& EnumNames::get() { - static auto enum_names = EnumNames("op::TopKSortType", - {{"none", op::TopKSortType::NONE}, - {"index", op::TopKSortType::SORT_INDICES}, - {"value", op::TopKSortType::SORT_VALUES}}); - return enum_names; -} -template <> -NGRAPH_API EnumNames& EnumNames::get() { +NGRAPH_API EnumNames& EnumNames::get() { static auto enum_names = - EnumNames("op::TopKMode", {{"min", op::TopKMode::MIN}, {"max", op::TopKMode::MAX}}); + EnumNames("ngraph::op::EpsMode", + {{"add", ngraph::op::EpsMode::ADD}, {"max", ngraph::op::EpsMode::MAX}}); return enum_names; } -constexpr DiscreteTypeInfo AttributeAdapter::type_info; -constexpr DiscreteTypeInfo AttributeAdapter::type_info; +constexpr DiscreteTypeInfo AttributeAdapter::type_info; -std::ostream& op::operator<<(std::ostream& s, const op::TopKSortType& type) { +template <> +NGRAPH_API EnumNames& EnumNames::get() { + static auto enum_names = EnumNames("ngraph::op::TopKSortType", + {{"none", ngraph::op::TopKSortType::NONE}, + {"index", ngraph::op::TopKSortType::SORT_INDICES}, + {"value", ngraph::op::TopKSortType::SORT_VALUES}}); + return enum_names; +} +template <> +NGRAPH_API EnumNames& EnumNames::get() { + static auto enum_names = + EnumNames("ngraph::op::TopKMode", + {{"min", ngraph::op::TopKMode::MIN}, {"max", ngraph::op::TopKMode::MAX}}); + return enum_names; +} + +constexpr DiscreteTypeInfo AttributeAdapter::type_info; +constexpr DiscreteTypeInfo AttributeAdapter::type_info; + +bool AttributeAdapter::visit_attributes(AttributeVisitor& visitor) { + // Maintain back-compatibility + std::string name = visitor.finish_structure(); + visitor.on_attribute(name, m_ref.m_type); + visitor.start_structure(name); + if (m_ref.m_type == ngraph::op::AutoBroadcastType::PDPD) { + visitor.on_attribute("auto_broadcast_axis", m_ref.m_axis); + } + return true; +} + +constexpr DiscreteTypeInfo AttributeAdapter::type_info; + +bool AttributeAdapter::visit_attributes(AttributeVisitor& visitor) { + // Maintain back-compatibility + std::string name = visitor.finish_structure(); + visitor.on_attribute(name, m_ref.m_type); + visitor.start_structure(name); + if (m_ref.m_type == ngraph::op::BroadcastType::PDPD) { + visitor.start_structure(name); + visitor.on_attribute("axis", m_ref.m_axis); + visitor.finish_structure(); + } + return true; +} + +constexpr DiscreteTypeInfo AttributeAdapter::type_info; + +NGRAPH_API +constexpr DiscreteTypeInfo AttributeAdapter::type_info; +template <> +NGRAPH_API EnumNames& EnumNames::get() { + static auto enum_names = EnumNames( + "ngraph::op::RecurrentSequenceDirection", + {{"forward", ngraph::op::RecurrentSequenceDirection::FORWARD}, + {"reverse", ngraph::op::RecurrentSequenceDirection::REVERSE}, + {"bidirectional", ngraph::op::RecurrentSequenceDirection::BIDIRECTIONAL}}); + return enum_names; +} +} // namespace ov + +const ngraph::op::AutoBroadcastSpec ngraph::op::AutoBroadcastSpec::NUMPY(AutoBroadcastType::NUMPY, 0); +const ngraph::op::AutoBroadcastSpec ngraph::op::AutoBroadcastSpec::NONE{AutoBroadcastType::NONE, 0}; + +std::ostream& ngraph::op::operator<<(std::ostream& s, const ngraph::op::PadMode& type) { return s << as_string(type); } -std::ostream& op::operator<<(std::ostream& s, const op::TopKMode& type) { +std::ostream& ngraph::op::operator<<(std::ostream& s, const ngraph::op::PadType& type) { return s << as_string(type); } -op::AutoBroadcastType op::AutoBroadcastSpec::type_from_string(const std::string& type) const { +std::ostream& ngraph::op::operator<<(std::ostream& s, const ngraph::op::RoundingType& type) { + return s << as_string(type); +} + +std::ostream& ngraph::op::operator<<(std::ostream& s, const ngraph::op::BroadcastType& type) { + return s << as_string(type); +} + +std::ostream& ngraph::op::operator<<(std::ostream& s, const ngraph::op::AutoBroadcastType& type) { + return s << as_string(type); +} + +std::ostream& ngraph::op::operator<<(std::ostream& s, const ngraph::op::EpsMode& type) { + return s << as_string(type); +} + +std::ostream& ngraph::op::operator<<(std::ostream& s, const ngraph::op::TopKSortType& type) { + return s << as_string(type); +} + +std::ostream& ngraph::op::operator<<(std::ostream& s, const ngraph::op::TopKMode& type) { + return s << as_string(type); +} + +ngraph::op::AutoBroadcastType ngraph::op::AutoBroadcastSpec::type_from_string(const std::string& type) const { auto lowercase_type = type; std::transform(lowercase_type.begin(), lowercase_type.end(), lowercase_type.begin(), [](char c) { return std::tolower(c); @@ -147,47 +193,6 @@ op::AutoBroadcastType op::AutoBroadcastSpec::type_from_string(const std::string& return allowed_values.at(lowercase_type); } -bool AttributeAdapter::visit_attributes(AttributeVisitor& visitor) { - // Maintain back-compatibility - std::string name = visitor.finish_structure(); - visitor.on_attribute(name, m_ref.m_type); - visitor.start_structure(name); - if (m_ref.m_type == op::AutoBroadcastType::PDPD) { - visitor.on_attribute("auto_broadcast_axis", m_ref.m_axis); - } - return true; -} - -constexpr DiscreteTypeInfo AttributeAdapter::type_info; - -bool AttributeAdapter::visit_attributes(AttributeVisitor& visitor) { - // Maintain back-compatibility - std::string name = visitor.finish_structure(); - visitor.on_attribute(name, m_ref.m_type); - visitor.start_structure(name); - if (m_ref.m_type == op::BroadcastType::PDPD) { - visitor.start_structure(name); - visitor.on_attribute("axis", m_ref.m_axis); - visitor.finish_structure(); - } - return true; -} - -constexpr DiscreteTypeInfo AttributeAdapter::type_info; - -NGRAPH_API -constexpr DiscreteTypeInfo AttributeAdapter::type_info; - -std::ostream& op::operator<<(std::ostream& s, const op::RecurrentSequenceDirection& direction) { +std::ostream& ngraph::op::operator<<(std::ostream& s, const ngraph::op::RecurrentSequenceDirection& direction) { return s << as_string(direction); } -template <> -NGRAPH_API EnumNames& EnumNames::get() { - static auto enum_names = - EnumNames("op::RecurrentSequenceDirection", - {{"forward", op::RecurrentSequenceDirection::FORWARD}, - {"reverse", op::RecurrentSequenceDirection::REVERSE}, - {"bidirectional", op::RecurrentSequenceDirection::BIDIRECTIONAL}}); - return enum_names; -} -} // namespace ngraph diff --git a/ngraph/core/src/op/util/multi_subgraph_base.cpp b/ngraph/core/src/op/util/multi_subgraph_base.cpp index 9f58fb52707..fea33f2f653 100644 --- a/ngraph/core/src/op/util/multi_subgraph_base.cpp +++ b/ngraph/core/src/op/util/multi_subgraph_base.cpp @@ -153,7 +153,7 @@ Output op::util::MultiSubGraphOp::set_body_outputs(const ResultVector& bod return Output(shared_from_this(), output_index); } -namespace ngraph { +namespace ov { NGRAPH_RTTI_DEFINITION(AttributeAdapter>>, "AttributeAdapter>>", @@ -163,4 +163,4 @@ NGRAPH_RTTI_DEFINITION(AttributeAdapter>>", 0); -} // namespace ngraph +} // namespace ov diff --git a/ngraph/core/src/op/util/nms_base.cpp b/ngraph/core/src/op/util/nms_base.cpp index be9671be970..22b848707ff 100644 --- a/ngraph/core/src/op/util/nms_base.cpp +++ b/ngraph/core/src/op/util/nms_base.cpp @@ -145,7 +145,11 @@ void op::util::NmsBase::validate_and_infer_types() { } } -namespace ngraph { +std::ostream& ngraph::operator<<(std::ostream& s, const op::util::NmsBase::SortResultType& type) { + return s << as_string(type); +} + +namespace ov { template <> NGRAPH_API EnumNames& EnumNames::get() { static auto enum_names = @@ -157,8 +161,4 @@ NGRAPH_API EnumNames& EnumNames::type_info; - -std::ostream& operator<<(std::ostream& s, const op::util::NmsBase::SortResultType& type) { - return s << as_string(type); -} -} // namespace ngraph +} // namespace ov diff --git a/ngraph/core/src/op/util/variable.cpp b/ngraph/core/src/op/util/variable.cpp index ae434cf8f34..3886f94d6c6 100644 --- a/ngraph/core/src/op/util/variable.cpp +++ b/ngraph/core/src/op/util/variable.cpp @@ -4,6 +4,4 @@ #include -namespace ngraph { -constexpr DiscreteTypeInfo AttributeAdapter>::type_info; -} +constexpr ov::DiscreteTypeInfo ov::AttributeAdapter>::type_info; diff --git a/ngraph/core/src/partial_shape.cpp b/ngraph/core/src/partial_shape.cpp index 9803d84e93b..da93eb1ba15 100644 --- a/ngraph/core/src/partial_shape.cpp +++ b/ngraph/core/src/partial_shape.cpp @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 // -#include "ngraph/partial_shape.hpp" +#include "openvino/core/partial_shape.hpp" #include #include @@ -10,7 +10,7 @@ #include "ngraph/check.hpp" -using namespace ngraph; +using namespace ov; PartialShape::PartialShape() : PartialShape(std::initializer_list{}) {} @@ -20,7 +20,7 @@ PartialShape::PartialShape(const std::vector& dimensions) : m_rank_is_static(true), m_dimensions(dimensions.begin(), dimensions.end()) {} -PartialShape::PartialShape(const Shape& shape) +PartialShape::PartialShape(const ngraph::Shape& shape) : m_rank_is_static(true), m_shape_type(ShapeType::SHAPE_IS_STATIC), m_dimensions(shape.begin(), shape.end()) {} @@ -33,7 +33,7 @@ PartialShape::PartialShape(std::vector dimensions) : m_rank_is_static(true), m_dimensions(std::move(dimensions)) {} -bool ngraph::PartialShape::is_static() const { +bool PartialShape::is_static() const { ShapeType shape_type = m_shape_type; if (m_shape_type == ShapeType::SHAPE_IS_UNKNOWN || m_shape_type == ShapeType::SHAPE_IS_UPDATED) { @@ -52,7 +52,7 @@ bool ngraph::PartialShape::is_static() const { return shape_type == ShapeType::SHAPE_IS_STATIC; } -bool ngraph::PartialShape::operator==(const PartialShape& partial_shape) const { +bool PartialShape::operator==(const PartialShape& partial_shape) const { if (rank() != partial_shape.rank()) { return false; } @@ -67,15 +67,15 @@ bool ngraph::PartialShape::operator==(const PartialShape& partial_shape) const { return true; } -bool ngraph::PartialShape::operator!=(const PartialShape& partial_shape) const { +bool PartialShape::operator!=(const PartialShape& partial_shape) const { return !(*this == partial_shape); } -Shape ngraph::PartialShape::get_max_shape() const { +ngraph::Shape PartialShape::get_max_shape() const { if (rank().is_dynamic()) { - return Shape(); + return ngraph::Shape(); } else { - Shape shape; + ngraph::Shape shape; for (auto dimension : m_dimensions) { shape.push_back(dimension.get_interval().get_max_val()); } @@ -83,11 +83,11 @@ Shape ngraph::PartialShape::get_max_shape() const { } } -Shape ngraph::PartialShape::get_min_shape() const { +ngraph::Shape PartialShape::get_min_shape() const { if (rank().is_dynamic()) { - return Shape(); + return ngraph::Shape(); } else { - Shape shape; + ngraph::Shape shape; for (auto dimension : m_dimensions) { shape.push_back(dimension.get_interval().get_min_val()); } @@ -95,9 +95,9 @@ Shape ngraph::PartialShape::get_min_shape() const { } } -Shape ngraph::PartialShape::get_shape() const { +ngraph::Shape PartialShape::get_shape() const { NGRAPH_CHECK(rank().is_static(), "get_shape() must be called on a static shape"); - Shape shape; + ngraph::Shape shape; for (auto dimension : m_dimensions) { auto min_val = dimension.get_interval().get_min_val(); auto max_val = dimension.get_interval().get_max_val(); @@ -234,7 +234,7 @@ bool PartialShape::merge_rank(Rank r) { } } -Shape PartialShape::to_shape() const { +ngraph::Shape PartialShape::to_shape() const { if (is_dynamic()) { throw std::invalid_argument("to_shape was called on a dynamic shape."); } @@ -269,11 +269,11 @@ bool PartialShape::merge_into(PartialShape& dst, const PartialShape& src) { bool PartialShape::broadcast_merge_into(PartialShape& dst, const PartialShape& src, - const op::AutoBroadcastSpec& autob) { + const ngraph::op::AutoBroadcastSpec& autob) { switch (autob.m_type) { - case op::AutoBroadcastType::NONE: + case ngraph::op::AutoBroadcastType::NONE: return true; - case op::AutoBroadcastType::NUMPY: { + case ngraph::op::AutoBroadcastType::NUMPY: { if (dst.rank().is_dynamic() || src.rank().is_dynamic()) { dst = PartialShape::dynamic(); return true; @@ -293,7 +293,7 @@ bool PartialShape::broadcast_merge_into(PartialShape& dst, return success; } } - case op::AutoBroadcastType::PDPD: { + case ngraph::op::AutoBroadcastType::PDPD: { if (dst.rank().is_dynamic() || src.rank().is_dynamic()) { return true; } else { @@ -357,7 +357,7 @@ Dimension& PartialShape::operator[](size_t i) { return m_dimensions[i]; } -const std::vector& ngraph::AttributeAdapter::get() { +const std::vector& ov::AttributeAdapter::get() { if (!m_buffer_valid) { m_buffer.clear(); if (m_ref.rank().is_dynamic()) { @@ -373,7 +373,7 @@ const std::vector& ngraph::AttributeAdapter::get( return m_buffer; } -void ngraph::AttributeAdapter::set(const std::vector& value) { +void ov::AttributeAdapter::set(const std::vector& value) { m_ref = PartialShape(); if (value.size() == 1 && value[0] == -2) { m_ref = PartialShape::dynamic(); @@ -387,4 +387,4 @@ void ngraph::AttributeAdapter::set(const std::vector::type_info; +NGRAPH_API constexpr DiscreteTypeInfo ov::AttributeAdapter::type_info; diff --git a/ngraph/core/src/runtime/aligned_buffer.cpp b/ngraph/core/src/runtime/aligned_buffer.cpp index f11980dc361..b901bc99204 100644 --- a/ngraph/core/src/runtime/aligned_buffer.cpp +++ b/ngraph/core/src/runtime/aligned_buffer.cpp @@ -56,9 +56,9 @@ runtime::AlignedBuffer& runtime::AlignedBuffer::operator=(AlignedBuffer&& other) return *this; } -namespace ngraph { +namespace ov { constexpr DiscreteTypeInfo AttributeAdapter>::type_info; AttributeAdapter>::AttributeAdapter(shared_ptr& value) : DirectValueAccessor>(value) {} -} // namespace ngraph +} // namespace ov diff --git a/ngraph/core/src/shape.cpp b/ngraph/core/src/shape.cpp index 87a2a396a46..3b7b1aab445 100644 --- a/ngraph/core/src/shape.cpp +++ b/ngraph/core/src/shape.cpp @@ -38,4 +38,4 @@ ngraph::Shape& ngraph::Shape::operator=(Shape&& v) noexcept { return *this; } -constexpr DiscreteTypeInfo AttributeAdapter::type_info; +constexpr DiscreteTypeInfo ov::AttributeAdapter::type_info; diff --git a/ngraph/core/src/strides.cpp b/ngraph/core/src/strides.cpp index 946f2928263..123ad53bc8e 100644 --- a/ngraph/core/src/strides.cpp +++ b/ngraph/core/src/strides.cpp @@ -36,4 +36,4 @@ ngraph::Strides& ngraph::Strides::operator=(Strides&& v) noexcept { return *this; } -constexpr DiscreteTypeInfo AttributeAdapter::type_info; +constexpr DiscreteTypeInfo ov::AttributeAdapter::type_info; diff --git a/ngraph/core/src/type/element_type.cpp b/ngraph/core/src/type/element_type.cpp index cc5042a81d6..4dd724832d0 100644 --- a/ngraph/core/src/type/element_type.cpp +++ b/ngraph/core/src/type/element_type.cpp @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 // -#include "ngraph/type/element_type.hpp" +#include "openvino/core/type/element_type.hpp" #include #include @@ -147,7 +147,7 @@ Type from() { return Type_t::boolean; } template <> -Type from() { +Type from() { return Type_t::f16; } template <> @@ -191,7 +191,7 @@ Type from() { return Type_t::u64; } template <> -Type from() { +Type from() { return Type_t::bf16; } } // namespace element @@ -276,38 +276,38 @@ size_t compiler_byte_size(ov::element::Type_t et) { std::to_string(static_cast(et))); } -namespace ngraph { +namespace ov { template <> -NGRAPH_API EnumNames& EnumNames::get() { - static auto enum_names = EnumNames("ov::element::Type_t", - {{"undefined", ov::element::Type_t::undefined}, - {"dynamic", ov::element::Type_t::dynamic}, - {"boolean", ov::element::Type_t::boolean}, - {"bf16", ov::element::Type_t::bf16}, - {"f16", ov::element::Type_t::f16}, - {"f32", ov::element::Type_t::f32}, - {"f64", ov::element::Type_t::f64}, - {"i4", ov::element::Type_t::i4}, - {"i8", ov::element::Type_t::i8}, - {"i16", ov::element::Type_t::i16}, - {"i32", ov::element::Type_t::i32}, - {"i64", ov::element::Type_t::i64}, - {"u1", ov::element::Type_t::u1}, - {"u4", ov::element::Type_t::u4}, - {"u8", ov::element::Type_t::u8}, - {"u16", ov::element::Type_t::u16}, - {"u32", ov::element::Type_t::u32}, - {"u64", ov::element::Type_t::u64}}); +NGRAPH_API EnumNames& EnumNames::get() { + static auto enum_names = EnumNames("element::Type_t", + {{"undefined", element::Type_t::undefined}, + {"dynamic", element::Type_t::dynamic}, + {"boolean", element::Type_t::boolean}, + {"bf16", element::Type_t::bf16}, + {"f16", element::Type_t::f16}, + {"f32", element::Type_t::f32}, + {"f64", element::Type_t::f64}, + {"i4", element::Type_t::i4}, + {"i8", element::Type_t::i8}, + {"i16", element::Type_t::i16}, + {"i32", element::Type_t::i32}, + {"i64", element::Type_t::i64}, + {"u1", element::Type_t::u1}, + {"u4", element::Type_t::u4}, + {"u8", element::Type_t::u8}, + {"u16", element::Type_t::u16}, + {"u32", element::Type_t::u32}, + {"u64", element::Type_t::u64}}); return enum_names; } -} // namespace ngraph -constexpr ngraph::DiscreteTypeInfo ngraph::AttributeAdapter::type_info; +constexpr DiscreteTypeInfo AttributeAdapter::type_info; -const std::string& ngraph::AttributeAdapter::get() { - return as_string(static_cast(m_ref)); +const std::string& AttributeAdapter::get() { + return as_string(static_cast(m_ref)); } -void ngraph::AttributeAdapter::set(const std::string& value) { - m_ref = as_enum(value); +void AttributeAdapter::set(const std::string& value) { + m_ref = as_enum(value); } +} // namespace ov diff --git a/ngraph/test/visitors/user_op.cpp b/ngraph/test/visitors/user_op.cpp index 61290870422..4ccaffd5bf2 100644 --- a/ngraph/test/visitors/user_op.cpp +++ b/ngraph/test/visitors/user_op.cpp @@ -18,7 +18,7 @@ using ngraph::test::ValueMap; enum class TuringModel { XL400, XL1200 }; -namespace ngraph { +namespace ov { template <> EnumNames& EnumNames::get() { static auto enum_names = @@ -74,7 +74,7 @@ protected: }; constexpr DiscreteTypeInfo AttributeAdapter::type_info; -} // namespace ngraph +} // namespace ov // Given a Turing machine program and data, return scalar 1 if the program would // complete, 1 if it would not. @@ -110,7 +110,7 @@ public: const std::vector& vec_int32_t, const std::vector& vec_int64_t, const std::vector& vec_size_t, - const Position& position, + const ov::Position& position, const shared_ptr& node, const NodeVector& node_vector, const ParameterVector& parameter_vector, @@ -240,7 +240,7 @@ public: const vector& get_vec_size_t() const { return m_vec_size_t; } - const Position& get_position() const { + const ov::Position& get_position() const { return m_position; } const shared_ptr& get_node() const { @@ -362,7 +362,7 @@ protected: vector m_vec_int32_t; vector m_vec_int64_t; vector m_vec_size_t; - Position m_position; + ov::Position m_position; shared_ptr m_node; NodeVector m_node_vector; ParameterVector m_parameter_vector; @@ -406,7 +406,7 @@ TEST(attributes, user_op) { vector{1, 2, 4, 8}, vector{1, 2, 4, 8}, vector{1, 3, 8, 4, 2}, - Position{1.3f, 5.1f, 2.3f}, + ov::Position{1.3f, 5.1f, 2.3f}, data, NodeVector{program, result, data}, ParameterVector{data, data, program}, From 3ff6051f551d68dc54dc2eb1d1ae8226f61b82e8 Mon Sep 17 00:00:00 2001 From: Aleksandr Pertovsky Date: Wed, 25 Aug 2021 08:40:55 +0300 Subject: [PATCH 26/76] [CPU] Disable inplace concat if any parent is constant (#7060) --- .../nodes/mkldnn_concat_node.cpp | 6 ++ .../src/concat_const_inplace.cpp | 55 +++++++++++++++++++ 2 files changed, 61 insertions(+) create mode 100644 inference-engine/tests/functional/plugin/cpu/subgraph_tests/src/concat_const_inplace.cpp diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_concat_node.cpp b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_concat_node.cpp index 2907a035788..12567b74c0f 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_concat_node.cpp +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_concat_node.cpp @@ -152,6 +152,12 @@ void MKLDNNConcatNode::initSupportedPrimitiveDescriptors() { } } + // required to prevent incorrect memory sharing of a constant with other tensors on edges + for (size_t i = 0; i < getParentEdges().size(); i++) { + if (getParentEdgeAt(i)->getParent()->isConstant()) { + return; + } + } if (axis != channelAxis) return; diff --git a/inference-engine/tests/functional/plugin/cpu/subgraph_tests/src/concat_const_inplace.cpp b/inference-engine/tests/functional/plugin/cpu/subgraph_tests/src/concat_const_inplace.cpp new file mode 100644 index 00000000000..ca99be789a9 --- /dev/null +++ b/inference-engine/tests/functional/plugin/cpu/subgraph_tests/src/concat_const_inplace.cpp @@ -0,0 +1,55 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "test_utils/cpu_test_utils.hpp" +#include "shared_test_classes/base/layer_test_utils.hpp" +#include "ngraph_functions/utils/ngraph_helpers.hpp" +#include "ngraph_functions/builders.hpp" + +using namespace CPUTestUtils; +using namespace InferenceEngine; + +namespace SubgraphTestsDefinitions { +// Subgraph: +/* + * Parameter Constant + * \ / + * \ / + * Transpose + * Constant / + * \ / + * \ / + * Concat (inPlace) + * | + * | + * Result + */ + +class ConcatConstantInPlaceTest : virtual public LayerTestsUtils::LayerTestsCommon { +public: + void SetUp() override { + targetDevice = CommonTestUtils::DEVICE_CPU; + inPrc = outPrc = Precision::FP32; + const std::vector inputShape = {1, 384, 196}; + auto inputParams = ngraph::builder::makeParams(ngraph::element::f32, {inputShape, inputShape}); + + auto transposeOrder = ngraph::opset8::Constant::create(ngraph::element::i32, {3}, {0, 2, 1}); + auto transpose = std::make_shared(inputParams[0], transposeOrder); + + auto concatConstantInput = ngraph::opset8::Constant::create(ngraph::element::f32, {1, 1, 384}, {10.0f}); + auto concat = ngraph::builder::makeConcat({concatConstantInput, transpose}, 1); + + ngraph::ResultVector results{std::make_shared(concat)}; + function = std::make_shared(results, inputParams, "ConcatConstantInPlace"); + } +}; + +namespace { + TEST_F(ConcatConstantInPlaceTest, smoke_ConcatConstantInPlaceTest_CPU) { + SKIP_IF_CURRENT_TEST_IS_DISABLED() + + Run(); + } +} // namespace +} // namespace SubgraphTestsDefinitions \ No newline at end of file From 05875693694c9eb74ff3aa8d61ea06c3db51fb51 Mon Sep 17 00:00:00 2001 From: Evgeny Lazarev Date: Wed, 25 Aug 2021 09:42:24 +0300 Subject: [PATCH 27/76] Enable TensorFlow Min operation (#7144) * Added extractor for the TF operation Min (reduce min) * Added unit tests for the TF Reduce ops --- .../extensions/front/tf/reduce_ext.py | 12 +++- .../tensorflow_tests/test_tf_Reduce.py | 63 +++++++++++++++++++ 2 files changed, 74 insertions(+), 1 deletion(-) create mode 100644 tests/layer_tests/tensorflow_tests/test_tf_Reduce.py diff --git a/model-optimizer/extensions/front/tf/reduce_ext.py b/model-optimizer/extensions/front/tf/reduce_ext.py index 5ebff5ba6eb..7167fde5b44 100644 --- a/model-optimizer/extensions/front/tf/reduce_ext.py +++ b/model-optimizer/extensions/front/tf/reduce_ext.py @@ -1,7 +1,7 @@ # Copyright (C) 2018-2021 Intel Corporation # SPDX-License-Identifier: Apache-2.0 -from extensions.ops.ReduceOps import ReduceProd, ReduceAnd, ReduceMax, ReduceMean, ReduceSum, ReduceL2 +from extensions.ops.ReduceOps import ReduceProd, ReduceAnd, ReduceMax, ReduceMean, ReduceSum, ReduceL2, ReduceMin from mo.front.extractor import FrontExtractorOp from mo.graph.graph import Node @@ -27,6 +27,16 @@ class MaxFrontExtractor(FrontExtractorOp): return cls.enabled +class MinFrontExtractor(FrontExtractorOp): + op = 'Min' + enabled = True + + @classmethod + def extract(cls, node: Node): + ReduceMin.update_node_stat(node, {'keep_dims': node.pb.attr['keep_dims'].b}) + return cls.enabled + + class MeanExtractor(FrontExtractorOp): op = 'Mean' enabled = True diff --git a/tests/layer_tests/tensorflow_tests/test_tf_Reduce.py b/tests/layer_tests/tensorflow_tests/test_tf_Reduce.py new file mode 100644 index 00000000000..53341943943 --- /dev/null +++ b/tests/layer_tests/tensorflow_tests/test_tf_Reduce.py @@ -0,0 +1,63 @@ +# Copyright (C) 2018-2021 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 + +import pytest +import numpy as np + +from common.tf_layer_test_class import CommonTFLayerTest + + +class TestReduceOps(CommonTFLayerTest): + def _prepare_input(self, inputs_dict): + for input in inputs_dict.keys(): + inputs_dict[input] = np.random.random(inputs_dict[input]) + return inputs_dict + + def create_reduce_net(self, shape, operation, keep_dims, axis, ir_version): + import tensorflow as tf + fn_mapping = {'sum': tf.reduce_sum, + 'max': tf.reduce_max, + 'min': tf.reduce_min, + 'mean': tf.reduce_mean, + 'prod': tf.reduce_prod, + } + tf.compat.v1.reset_default_graph() + with tf.compat.v1.Session() as sess: + shapes = shape.copy() + if len(shapes) >= 4: + shapes.append(shapes.pop(1)) + + x = tf.compat.v1.placeholder(tf.float32, shapes, 'Input') + fn_mapping[operation](x, axis=axis, keepdims=keep_dims, name='Operation') + tf.compat.v1.global_variables_initializer() + tf_net = sess.graph_def + + return tf_net, None + + test_data = [] + for operation in ['sum', 'max', 'prod', 'min', 'mean']: + test_data.extend([ + dict(shape=[2, 3], operation=operation, axis=1), + dict(shape=[2, 3, 5], operation=operation, axis=-2), + dict(shape=[2, 3, 5, 7], operation=operation, axis=2), + dict(shape=[2, 3, 5, 7, 9], operation=operation, axis=[2, -1]), + ]) + + @pytest.mark.parametrize("params", test_data) + @pytest.mark.parametrize("keep_dims", [True, False]) + @pytest.mark.nightly + def test_reduce(self, params, keep_dims, ie_device, precision, ir_version, temp_dir): + self._test(*self.create_reduce_net(**params, keep_dims=keep_dims, ir_version=ir_version), + ie_device, precision, ir_version, temp_dir=temp_dir) + + test_data_pre_commit = [] + for operation in ['sum', 'max', 'prod', 'min', 'mean']: + test_data_pre_commit.extend([dict(shape=[2, 3, 5, 7], operation=operation, axis=-2), + ]) + + @pytest.mark.parametrize("params", test_data_pre_commit) + @pytest.mark.parametrize("keep_dims", [False]) + @pytest.mark.precommit + def test_reduce_precommit(self, params, keep_dims, ie_device, precision, ir_version, temp_dir): + self._test(*self.create_reduce_net(**params, keep_dims=keep_dims, ir_version=ir_version), + ie_device, precision, ir_version, temp_dir=temp_dir) From 1829fc5b8babb3718ed2ae643e35a92cbe569053 Mon Sep 17 00:00:00 2001 From: Sungeun Kim Date: Wed, 25 Aug 2021 15:50:21 +0900 Subject: [PATCH 28/76] [GPU] Optimized ocl nms implementation (#5411) --- .../cldnn_engine/ops/non_max_suppression.cpp | 3 +- .../single_layer/non_max_suppression.hpp | 5 + .../src/single_layer/non_max_suppression.cpp | 217 ++++++- .../cldnn/runtime/engine_configuration.hpp | 4 + .../kernel_selector/common/common_types.h | 9 + .../detection_output_kernel_ref.cpp | 4 +- .../non_max_suppression_kernel_ref.cpp | 298 +++++++++ .../non_max_suppression_kernel_ref.h | 105 ++++ .../non_max_suppression_kernel_selector.cpp | 15 + .../non_max_suppression_kernel_selector.h | 21 + .../cl_kernels/non_max_suppression_gpu_ref.cl | 568 ++++++++++++++++++ .../core/kernel_selector_common.cpp | 2 + .../src/impls/ocl/non_max_suppression.cpp | 183 ++++++ .../clDNN/src/impls/ocl/register.cpp | 1 + .../clDNN/src/impls/ocl/register.hpp | 2 + .../clDNN/src/include/layout_optimizer.h | 1 + .../src/include/non_max_suppression_inst.h | 2 + .../thirdparty/clDNN/src/layout_optimizer.cpp | 8 + .../thirdparty/clDNN/src/program.cpp | 2 +- .../test_cases/non_max_suppression_test.cpp | 172 +++++- 20 files changed, 1587 insertions(+), 35 deletions(-) create mode 100644 inference-engine/thirdparty/clDNN/kernel_selector/core/actual_kernels/non_max_suppression/non_max_suppression_kernel_ref.cpp create mode 100644 inference-engine/thirdparty/clDNN/kernel_selector/core/actual_kernels/non_max_suppression/non_max_suppression_kernel_ref.h create mode 100644 inference-engine/thirdparty/clDNN/kernel_selector/core/actual_kernels/non_max_suppression/non_max_suppression_kernel_selector.cpp create mode 100644 inference-engine/thirdparty/clDNN/kernel_selector/core/actual_kernels/non_max_suppression/non_max_suppression_kernel_selector.h create mode 100644 inference-engine/thirdparty/clDNN/kernel_selector/core/cl_kernels/non_max_suppression_gpu_ref.cl create mode 100644 inference-engine/thirdparty/clDNN/src/impls/ocl/non_max_suppression.cpp diff --git a/inference-engine/src/cldnn_engine/ops/non_max_suppression.cpp b/inference-engine/src/cldnn_engine/ops/non_max_suppression.cpp index a3d4834c51e..8adaa3cfa76 100644 --- a/inference-engine/src/cldnn_engine/ops/non_max_suppression.cpp +++ b/inference-engine/src/cldnn_engine/ops/non_max_suppression.cpp @@ -89,7 +89,7 @@ void CreateNonMaxSuppressionIEInternalOp(Program& p, const std::shared_ptr(outputIndices), 3, 1, 1)); shared_memory.emplace_back(p.GetEngine().allocate_memory(mutableLayoutFirst)); @@ -105,6 +105,7 @@ void CreateNonMaxSuppressionIEInternalOp(Program& p, const std::shared_ptr 1 ? layer_type_name_ID(op) + ".0" : layer_type_name_ID(op); + auto prim = cldnn::non_max_suppression( nonMaxSupressionLayerName, reorderedInputs[0], diff --git a/inference-engine/tests/functional/shared_test_classes/include/shared_test_classes/single_layer/non_max_suppression.hpp b/inference-engine/tests/functional/shared_test_classes/include/shared_test_classes/single_layer/non_max_suppression.hpp index 67b0f595178..0714f0236d8 100644 --- a/inference-engine/tests/functional/shared_test_classes/include/shared_test_classes/single_layer/non_max_suppression.hpp +++ b/inference-engine/tests/functional/shared_test_classes/include/shared_test_classes/single_layer/non_max_suppression.hpp @@ -53,7 +53,12 @@ protected: void SetUp() override; private: + void CompareBuffer(const std::vector>> &expectedOutputs, + const std::vector &actualOutputs); + void CompareBBoxes(const std::vector>> &expectedOutputs, + const std::vector &actualOutputs); size_t numOfSelectedBoxes; + InputShapeParams inShapeParams; }; } // namespace LayerTestsDefinitions diff --git a/inference-engine/tests/functional/shared_test_classes/src/single_layer/non_max_suppression.cpp b/inference-engine/tests/functional/shared_test_classes/src/single_layer/non_max_suppression.cpp index 1bb8792e3da..fd8499e8897 100644 --- a/inference-engine/tests/functional/shared_test_classes/src/single_layer/non_max_suppression.cpp +++ b/inference-engine/tests/functional/shared_test_classes/src/single_layer/non_max_suppression.cpp @@ -2,6 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 // +#include #include "shared_test_classes/single_layer/non_max_suppression.hpp" namespace LayerTestsDefinitions { @@ -56,7 +57,12 @@ void NmsLayerTest::GenerateInputs() { } void NmsLayerTest::Compare(const std::vector>> &expectedOutputs, - const std::vector &actualOutputs) { + const std::vector &actualOutputs) { + CompareBBoxes(expectedOutputs, actualOutputs); +} + +void NmsLayerTest::CompareBuffer(const std::vector>> &expectedOutputs, + const std::vector &actualOutputs) { for (int outputIndex = static_cast(expectedOutputs.size()) - 1; outputIndex >= 0 ; outputIndex--) { const auto& expected = expectedOutputs[outputIndex]; const auto& actual = actualOutputs[outputIndex]; @@ -129,8 +135,215 @@ void NmsLayerTest::Compare(const std::vectorbatchId = batchId; + this->classId = classId; + this->boxId = boxId; + this->rect = rect; + this->score = score; + } + + int32_t batchId; + int32_t classId; + int32_t boxId; + Rect rect; + float score; +}; + +/* + * 1: selected_indices - tensor of type T_IND and shape [number of selected boxes, 3] containing information about selected boxes as triplets + * [batch_index, class_index, box_index]. + * 2: selected_scores - tensor of type T_THRESHOLDS and shape [number of selected boxes, 3] containing information about scores for each selected box as triplets + * [batch_index, class_index, box_score]. + * 3: valid_outputs - 1D tensor with 1 element of type T_IND representing the total number of selected boxes. + */ +void NmsLayerTest::CompareBBoxes(const std::vector>> &expectedOutputs, + const std::vector &actualOutputs) { + size_t numBatches, numBoxes, numClasses; + std::tie(numBatches, numBoxes, numClasses) = inShapeParams; + + auto iouFunc = [](const Box& boxI, const Box& boxJ) { + const Rect& rectI = boxI.rect; + const Rect& rectJ = boxJ.rect; + + float areaI = (rectI.y2 - rectI.y1) * (rectI.x2 - rectI.x1); + float areaJ = (rectJ.y2 - rectJ.y1) * (rectJ.x2 - rectJ.x1); + + if (areaI <= 0.0f || areaJ <= 0.0f) { + return 0.0f; + } + + float intersection_ymin = std::max(rectI.y1, rectJ.y1); + float intersection_xmin = std::max(rectI.x1, rectJ.x1); + float intersection_ymax = std::min(rectI.y2, rectJ.y2); + float intersection_xmax = std::min(rectI.x2, rectJ.x2); + + float intersection_area = + std::max(intersection_ymax - intersection_ymin, 0.0f) * + std::max(intersection_xmax - intersection_xmin, 0.0f); + + return intersection_area / (areaI + areaJ - intersection_area); + }; + + // Get input bboxes' coords + std::vector> coordList(numBatches, std::vector(numBoxes)); + { + const auto &input = inputs[0]; + auto memory = InferenceEngine::as(input); + IE_ASSERT(memory); + const auto lockedMemory = memory->rmap(); + const auto buffer = lockedMemory.as(); + for (size_t i = 0; i < numBatches; ++i) { + for (size_t j = 0; j < numBoxes; ++j) { + const int32_t y1 = static_cast(buffer[(i*numBoxes+j)*4+0]); + const int32_t x1 = static_cast(buffer[(i*numBoxes+j)*4+1]); + const int32_t y2 = static_cast(buffer[(i*numBoxes+j)*4+2]); + const int32_t x2 = static_cast(buffer[(i*numBoxes+j)*4+3]); + + coordList[i][j] = { std::min(y1, y2), + std::min(x1, x2), + std::max(y1, y2), + std::max(x1, x2) }; + } + } + } + + auto compareBox = [](const Box& boxA, const Box& boxB) { + return (boxA.batchId < boxB.batchId) || + (boxA.batchId == boxB.batchId && boxA.classId < boxB.classId) || + (boxA.batchId == boxB.batchId && boxA.classId == boxB.classId && boxA.boxId < boxB.boxId); + }; + + // Get expected bboxes' index/score + std::vector expectedList; + { + size_t selected_indices_size = expectedOutputs[0].second.size() / expectedOutputs[0].first.size(); + size_t selected_scores_size = expectedOutputs[1].second.size() / expectedOutputs[1].first.size(); + ASSERT_TRUE(selected_indices_size == selected_scores_size); + + expectedList.resize(selected_indices_size); + + if (expectedOutputs[0].first.size() == 4) { + auto selected_indices_data = reinterpret_cast(expectedOutputs[0].second.data()); + + for (size_t i = 0; i < selected_indices_size; i += 3) { + expectedList[i/3].batchId = selected_indices_data[i+0]; + expectedList[i/3].classId = selected_indices_data[i+1]; + expectedList[i/3].boxId = selected_indices_data[i+2]; + expectedList[i/3].rect = coordList[expectedList[i/3].batchId][expectedList[i/3].boxId]; + } + } else { + auto selected_indices_data = reinterpret_cast(expectedOutputs[0].second.data()); + + for (size_t i = 0; i < selected_indices_size; i += 3) { + expectedList[i/3].batchId = static_cast(selected_indices_data[i+0]); + expectedList[i/3].classId = static_cast(selected_indices_data[i+1]); + expectedList[i/3].boxId = static_cast(selected_indices_data[i+2]); + expectedList[i/3].rect = coordList[expectedList[i/3].batchId][expectedList[i/3].boxId]; + } + } + + if (expectedOutputs[1].first.size() == 4) { + auto selected_scores_data = reinterpret_cast(expectedOutputs[0].second.data()); + for (size_t i = 0; i < selected_scores_size; i += 3) { + expectedList[i/3].score = selected_scores_data[i+2]; + } + } else { + auto selected_scores_data = reinterpret_cast(expectedOutputs[0].second.data()); + for (size_t i = 0; i < selected_scores_size; i += 3) { + expectedList[i/3].score = static_cast(selected_scores_data[i+2]); + } + } + + std::sort(expectedList.begin(), expectedList.end(), compareBox); + } + + // Get actual bboxes' index/score + std::vector actualList; + { + size_t selected_indices_size = actualOutputs[0]->byteSize() / sizeof(float); + auto selected_indices_memory = as(actualOutputs[0]); + IE_ASSERT(selected_indices_memory); + const auto selected_indices_lockedMemory = selected_indices_memory->rmap(); + const auto selected_indices_data = selected_indices_lockedMemory.as(); + + auto selected_scores_memory = as(actualOutputs[1]); + IE_ASSERT(selected_scores_memory); + const auto selected_scores_lockedMemory = selected_scores_memory->rmap(); + const auto selected_scores_data = selected_scores_lockedMemory.as(); + + for (size_t i = 0; i < selected_indices_size; i += 3) { + const int32_t batchId = selected_indices_data[i+0]; + const int32_t classId = selected_indices_data[i+1]; + const int32_t boxId = selected_indices_data[i+2]; + const float score = selected_scores_data[i+2]; + if (batchId == -1 || classId == -1 || boxId == -1) + break; + + actualList.emplace_back(batchId, classId, boxId, coordList[batchId][boxId], score); + } + std::sort(actualList.begin(), actualList.end(), compareBox); + } + + std::vector intersectionList; + std::vector differenceList; + { + std::list tempExpectedList(expectedList.size()), tempActualList(actualList.size()); + std::copy(expectedList.begin(), expectedList.end(), tempExpectedList.begin()); + std::copy(actualList.begin(), actualList.end(), tempActualList.begin()); + auto sameBox = [](const Box& boxA, const Box& boxB) { + return (boxA.batchId == boxB.batchId) && (boxA.classId == boxB.classId) && (boxA.boxId == boxB.boxId); + }; + + for (auto itA = tempActualList.begin(); itA != tempActualList.end(); ++itA) { + bool found = false; + for (auto itB = tempExpectedList.begin(); itB != tempExpectedList.end(); ++itB) { + if (sameBox(*itA, *itB)) { + intersectionList.emplace_back(*itB); + tempExpectedList.erase(itB); + found = true; + break; + } + } + + if (!found) { + differenceList.emplace_back(*itA); + } + } + differenceList.insert(differenceList.end(), tempExpectedList.begin(), tempExpectedList.end()); + + for (auto& item : differenceList) { + if ((item.rect.x1 == item.rect.x2) || (item.rect.y1 == item.rect.y2)) + continue; + + float maxIou = 0.f; + for (auto& refItem : intersectionList) { + maxIou = std::max(maxIou, iouFunc(item, refItem)); + + if (maxIou > 0.3f) break; + } + + ASSERT_TRUE(maxIou > 0.3f) << "MaxIOU: " << maxIou + << ", expectedList.size(): " << expectedList.size() << ", actualList.size(): " << actualList.size() + << ", intersectionList.size(): " << intersectionList.size() << ", diffList.size(): " << differenceList.size() + << ", batchId: " << item.batchId << ", classId: " << item.classId << ", boxId: " << item.boxId + << ", score: " << item.score << ", coord: " << item.rect.x1 << ", " << item.rect.y1 << ", " << item.rect.x2 << ", " << item.rect.y2; + } + } +} + void NmsLayerTest::SetUp() { - InputShapeParams inShapeParams; InputPrecisions inPrecisions; size_t maxOutBoxesPerClass; float iouThr, scoreThr, softNmsSigma; diff --git a/inference-engine/thirdparty/clDNN/api/cldnn/runtime/engine_configuration.hpp b/inference-engine/thirdparty/clDNN/api/cldnn/runtime/engine_configuration.hpp index 2cbaca414ab..1ee761641d3 100644 --- a/inference-engine/thirdparty/clDNN/api/cldnn/runtime/engine_configuration.hpp +++ b/inference-engine/thirdparty/clDNN/api/cldnn/runtime/engine_configuration.hpp @@ -67,6 +67,7 @@ struct engine_configuration { bool use_unified_shared_memory; ///< Enables USM usage const std::string kernels_cache_path; ///< Path to compiled kernels cache uint16_t n_threads; ///< Max number of host threads used in gpu plugin + uint16_t n_streams; ///< Number of queues executed in parallel const std::string tuning_cache_path; ///< Path to tuning kernel cache /// @brief Constructs engine configuration with specified options. @@ -79,6 +80,7 @@ struct engine_configuration { /// @param use_unified_shared_memory If this option it true and device supports USM, then engine will use USM for all memory allocations /// @param kernels_cache_path Path to existing directory where plugin can cache compiled kernels /// @param n_threads Max number of host threads used in gpu plugin + /// @param n_streams Number of queues executed in parallel /// @param tuning_cache_path Path to tuning kernel cache engine_configuration( bool enable_profiling = false, @@ -90,6 +92,7 @@ struct engine_configuration { bool use_unified_shared_memory = true, const std::string& kernels_cache_path = "", uint16_t n_threads = std::max(static_cast(std::thread::hardware_concurrency()), static_cast(1)), + uint16_t n_streams = 1, const std::string& tuning_cache_path = "cache.json") : enable_profiling(enable_profiling) , queue_type(queue_type) @@ -100,6 +103,7 @@ struct engine_configuration { , use_unified_shared_memory(use_unified_shared_memory) , kernels_cache_path(kernels_cache_path) , n_threads(n_threads) + , n_streams(n_streams) , tuning_cache_path(tuning_cache_path) { } }; diff --git a/inference-engine/thirdparty/clDNN/kernel_selector/common/common_types.h b/inference-engine/thirdparty/clDNN/kernel_selector/common/common_types.h index 5552f9681e8..d079aca28dc 100644 --- a/inference-engine/thirdparty/clDNN/kernel_selector/common/common_types.h +++ b/inference-engine/thirdparty/clDNN/kernel_selector/common/common_types.h @@ -71,6 +71,7 @@ enum class KernelType { EMBEDDING_BAG, EXTRACT_IMAGE_PATCHES, LOOP, + NON_MAX_SUPPRESSION, DETECTION_OUTPUT }; @@ -583,4 +584,12 @@ enum class EmbeddingBagType { OFFSETS_SUM, SEGMENTS_SUM }; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// BoxEncodingType +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +enum class BoxEncodingType { + BOX_ENCODING_CORNER, + BOX_ENCODING_CENTER, +}; } // namespace kernel_selector diff --git a/inference-engine/thirdparty/clDNN/kernel_selector/core/actual_kernels/detection_output/detection_output_kernel_ref.cpp b/inference-engine/thirdparty/clDNN/kernel_selector/core/actual_kernels/detection_output/detection_output_kernel_ref.cpp index aaa51eeccf1..85c98f48a38 100644 --- a/inference-engine/thirdparty/clDNN/kernel_selector/core/actual_kernels/detection_output/detection_output_kernel_ref.cpp +++ b/inference-engine/thirdparty/clDNN/kernel_selector/core/actual_kernels/detection_output/detection_output_kernel_ref.cpp @@ -60,7 +60,7 @@ JitConstants DetectionOutputKernelRef::GetJitConstants(const detection_output_pa return jit; } -int GetPartitionStep(int localWorkItemNum) { +static inline int GetPartitionStep(int localWorkItemNum) { int step_size = 0; for (int temp = localWorkItemNum; temp > 1; temp /= 2) { step_size++; @@ -68,7 +68,7 @@ int GetPartitionStep(int localWorkItemNum) { return step_size; } -size_t GetOptimalLocalClassSize(std::vector gws, const EngineInfo& info) { +static inline size_t GetOptimalLocalClassSize(std::vector gws, const EngineInfo& info) { const size_t optimal_values[] = {16, 8, 7, 6, 5, 4, 2, 1}; const size_t splitNum = gws[2]; const size_t globalClassNum = gws[1]; diff --git a/inference-engine/thirdparty/clDNN/kernel_selector/core/actual_kernels/non_max_suppression/non_max_suppression_kernel_ref.cpp b/inference-engine/thirdparty/clDNN/kernel_selector/core/actual_kernels/non_max_suppression/non_max_suppression_kernel_ref.cpp new file mode 100644 index 00000000000..4f6bc44facd --- /dev/null +++ b/inference-engine/thirdparty/clDNN/kernel_selector/core/actual_kernels/non_max_suppression/non_max_suppression_kernel_ref.cpp @@ -0,0 +1,298 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "non_max_suppression_kernel_ref.h" +#include "kernel_selector_utils.h" +#include + +namespace kernel_selector { + +Datatype NonMaxSuppressionKernelRef::GetAccumulatorType(const non_max_suppression_params& params) const { + auto in_dt = params.inputs[0].GetDType(); + auto out_dt = params.output.GetDType(); + + auto smaller_fp_type = [](const Datatype& current, const Datatype& candidate) -> Datatype { + if (candidate != Datatype::F32 || candidate != Datatype::F16) + return current; + + return BytesPerElement(candidate) < BytesPerElement(current) ? candidate : current; + }; + + Datatype fp_type = Datatype::F32; + fp_type = smaller_fp_type(fp_type, in_dt); + fp_type = smaller_fp_type(fp_type, out_dt); + + return fp_type; +} + +ParamsKey NonMaxSuppressionKernelRef::GetSupportedKey() const { + ParamsKey k; + k.EnableInputDataType(Datatype::INT32); + k.EnableInputDataType(Datatype::F16); + k.EnableInputDataType(Datatype::F32); + k.EnableOutputDataType(Datatype::INT32); + k.EnableOutputDataType(Datatype::INT64); + k.EnableDifferentTypes(); + k.EnableAllInputLayout(); + k.EnableAllOutputLayout(); + k.EnableTensorOffset(); + k.EnableTensorPitches(); + k.EnableBatching(); + return k; +} + +inline std::string GetInputTypeStr(uint32_t idx) { + return "INPUT" + std::to_string(idx) + "_TYPE"; +} + +inline std::string GetToInputTypeStr(uint32_t idx) { + return "TO_" + GetInputTypeStr(idx); +} + +JitConstants NonMaxSuppressionKernelRef::GetJitConstants(const non_max_suppression_params& params) const { + JitConstants jit = MakeBaseParamsJitConstants(params); + + const auto& input0 = params.inputs[0]; + switch (input0.GetDType()) { + case Datatype::F32: + jit.AddConstant(MakeJitConstant("TO_COORD_TYPE_4", "convert_float4")); + jit.AddConstant(MakeJitConstant("COORD_TYPE_4", "float4")); + jit.AddConstant(MakeJitConstant("TO_COORD_TYPE", "convert_float")); + jit.AddConstant(MakeJitConstant("COORD_TYPE", "float")); + break; + + case Datatype::F16: + jit.AddConstant(MakeJitConstant("TO_COORD_TYPE_4", "convert_half4")); + jit.AddConstant(MakeJitConstant("COORD_TYPE_4", "half4")); + jit.AddConstant(MakeJitConstant("TO_COORD_TYPE", "convert_half")); + jit.AddConstant(MakeJitConstant("COORD_TYPE", "half")); + break; + + default: + throw std::invalid_argument("NMS input0 type should be one of F32 or F16."); + } + + jit.AddConstants({MakeJitConstant("SORT_RESULT_DESCENDING", params.sort_result_descending), + MakeJitConstant("BOX_ENCODING", static_cast(params.box_encoding))}); + + jit.AddConstant(MakeJitConstant("OUTPUT_NUM", params.output.Batch().v)); + + if (params.num_select_per_class_type == NmsArgType::Input) { + jit.AddConstant(MakeJitConstant("NUM_SELECT_PER_CLASS_TYPE", GetInputTypeStr(params.GetIndexNumSelectPerClass()))); + jit.AddConstant(MakeJitConstant("NUM_SELECT_PER_CLASS_VAL", "convert_int(num_select_per_class[0])")); + } else { + jit.AddConstant(MakeJitConstant("NUM_SELECT_PER_CLASS_VAL", params.num_select_per_class)); + } + + if (params.iou_threshold_type == NmsArgType::Input) { + jit.AddConstant(MakeJitConstant("IOU_THRESHOLD_TYPE", GetInputTypeStr(params.GetIndexIouThreshold()))); + jit.AddConstant(MakeJitConstant("IOU_THRESHOLD_VAL", "convert_float(iou_threshold[0])")); + } else { + jit.AddConstant(MakeJitConstant("IOU_THRESHOLD_VAL", params.iou_threshold)); + } + + if (params.score_threshold_type == NmsArgType::Input) { + jit.AddConstant(MakeJitConstant("SCORE_THRESHOLD_TYPE", GetInputTypeStr(params.GetIndexScoreThreshold()))); + jit.AddConstant(MakeJitConstant("SCORE_THRESHOLD_VAL", "convert_float(score_threshold[0])")); + } else { + jit.AddConstant(MakeJitConstant("SCORE_THRESHOLD_VAL", params.score_threshold)); + } + + if (params.soft_nms_sigma_type == NmsArgType::Input) { + jit.AddConstant(MakeJitConstant("SOFT_NMS_SIGMA_TYPE", GetInputTypeStr(params.GetIndexSoftNmsSigma()))); + jit.AddConstant(MakeJitConstant("SOFT_NMS_SIGMA_VAL", "convert_float(soft_nms_sigma[0])")); + } else { + jit.AddConstant(MakeJitConstant("SOFT_NMS_SIGMA_VAL", params.soft_nms_sigma)); + } + + if (params.has_second_output) { + jit.AddConstant(MakeJitConstant("SECOND_OUTPUT_TYPE", GetInputTypeStr(params.GetIndexSecondOutput()))); + jit.AddConstant(MakeJitConstant("TO_SECOND_OUTPUT_TYPE", GetToInputTypeStr(params.GetIndexSecondOutput()))); + } + + if (params.has_third_output) { + jit.AddConstant(MakeJitConstant("THIRD_OUTPUT_TYPE", GetInputTypeStr(params.GetIndexThirdOutput()))); + jit.AddConstant(MakeJitConstant("TO_THIRD_OUTPUT_TYPE", GetToInputTypeStr(params.GetIndexThirdOutput()))); + } + + return jit; +} + +static inline int GetPartitionStep(int localWorkItemNum) { + int step_size = 0; + for (int temp = localWorkItemNum; temp > 1; temp /= 2) { + step_size++; + } + return step_size; +} + +static inline size_t GetOptimalLocalClassSize(std::vector gws, const EngineInfo& info) { + const size_t optimal_values[] = {256, 227, 224, 192, 160, 128, 96, 64, 32, 16, 8, 7, 6, 5, 4, 2, 1}; + const size_t splitNum = gws[2]; + const size_t globalClassNum = gws[1]; + const auto rest_lws = info.maxWorkGroupSize / splitNum; + size_t lws_idx = 0; + while (rest_lws < optimal_values[lws_idx]) + lws_idx++; + while (globalClassNum % optimal_values[lws_idx]) + lws_idx++; + + return optimal_values[lws_idx]; +} + +NonMaxSuppressionKernelRef::DispatchData SetDefault(const non_max_suppression_params& params, int idx) { + NonMaxSuppressionKernelRef::DispatchData dispatchData; + + const auto& input = params.inputs[1]; + if (idx == 0) { + dispatchData.gws = {input.Batch().v, input.Feature().v, params.engineInfo.maxWorkGroupSize}; + dispatchData.lws = {1, 1, params.engineInfo.maxWorkGroupSize}; + } else if (idx == 1) { + const size_t kSplitNum = 16; + dispatchData.gws = {input.Batch().v, input.Feature().v, kSplitNum}; + const size_t kClassSize = GetOptimalLocalClassSize(dispatchData.gws, params.engineInfo); + dispatchData.lws = {1, kClassSize, kSplitNum}; + } else if (idx == 2) { + dispatchData.gws = {input.Batch().v, input.Feature().v, 1}; + dispatchData.lws = GetOptimalLocalWorkGroupSizes(dispatchData.gws, params.engineInfo); + } else { + dispatchData.gws = {1, 1, 1}; + dispatchData.lws = {1, 1, 1}; + } + + return dispatchData; +} + +bool NonMaxSuppressionKernelRef::Validate(const Params& p, const optional_params& o) const { + if (p.GetType() != KernelType::NON_MAX_SUPPRESSION || o.GetType() != KernelType::NON_MAX_SUPPRESSION) { + return false; + } + + const non_max_suppression_params& params = static_cast(p); + + for (auto& fused_op : params.fused_ops) { + if (!IsFusedPrimitiveSupported(fused_op)) + return false; + } + + return true; +} + +/* + * INPUT[0]: boxes + * INPUT[1]: scores + * INTERNAL_BUFFER[0]: intermidiate_sorted_box + * INTERNAL_BUFFER[1]: intermidiate_selected_box + * INTERNAL_BUFFER[2]: intermidiate_sorted_box_num + * + */ +void NonMaxSuppressionKernelRef::SetKernelArguments(const non_max_suppression_params& params, + clKernelData& kernel, size_t idx) const { + switch (idx) { + case 0: + kernel.params.arguments.push_back({ ArgumentDescriptor::Types::INPUT, 1 }); + kernel.params.arguments.push_back({ ArgumentDescriptor::Types::INTERNAL_BUFFER, 0 }); + kernel.params.arguments.push_back({ ArgumentDescriptor::Types::INTERNAL_BUFFER, 2 }); + if (params.score_threshold_type == NmsArgType::Input) + kernel.params.arguments.push_back({ ArgumentDescriptor::Types::INPUT, params.GetIndexScoreThreshold() }); + break; + + case 1: + kernel.params.arguments.push_back({ ArgumentDescriptor::Types::INTERNAL_BUFFER, 0 }); + kernel.params.arguments.push_back({ ArgumentDescriptor::Types::INTERNAL_BUFFER, 2 }); + break; + + case 2: + kernel.params.arguments.push_back({ ArgumentDescriptor::Types::INPUT, 0 }); + kernel.params.arguments.push_back({ ArgumentDescriptor::Types::INTERNAL_BUFFER, 0 }); + kernel.params.arguments.push_back({ ArgumentDescriptor::Types::INTERNAL_BUFFER, 1 }); + kernel.params.arguments.push_back({ ArgumentDescriptor::Types::INTERNAL_BUFFER, 2 }); + + if (params.num_select_per_class_type == NmsArgType::Input) + kernel.params.arguments.push_back({ ArgumentDescriptor::Types::INPUT, params.GetIndexNumSelectPerClass() }); + if (params.iou_threshold_type == NmsArgType::Input) + kernel.params.arguments.push_back({ ArgumentDescriptor::Types::INPUT, params.GetIndexIouThreshold() }); + if (params.score_threshold_type == NmsArgType::Input) + kernel.params.arguments.push_back({ ArgumentDescriptor::Types::INPUT, params.GetIndexScoreThreshold() }); + if (params.soft_nms_sigma_type == NmsArgType::Input) + kernel.params.arguments.push_back({ ArgumentDescriptor::Types::INPUT, params.GetIndexSoftNmsSigma() }); + break; + + case 3: + kernel.params.arguments.push_back({ ArgumentDescriptor::Types::OUTPUT, 0 }); + kernel.params.arguments.push_back({ ArgumentDescriptor::Types::INTERNAL_BUFFER, 1 }); + kernel.params.arguments.push_back({ ArgumentDescriptor::Types::INTERNAL_BUFFER, 0 }); + + if (params.has_second_output) + kernel.params.arguments.push_back({ ArgumentDescriptor::Types::INPUT, params.GetIndexSecondOutput() }); + if (params.has_third_output) + kernel.params.arguments.push_back({ ArgumentDescriptor::Types::INPUT, params.GetIndexThirdOutput() }); + break; + + default: + throw std::invalid_argument("NMS has 4 kernels. valid index is 0 ~ 3."); + } +} + +KernelsData NonMaxSuppressionKernelRef::GetKernelsData(const Params& params, const optional_params& options) const { + if (!Validate(params, options)) { + return {}; + } + + constexpr size_t kKernelsNum = 4; + KernelData kd = KernelData::Default(params, kKernelsNum); + const non_max_suppression_params& orgParams = static_cast(params); + + // Assign internel buffer + constexpr size_t intermediate_bytes = 12; // struct size of SortedBoxInfo/BoxInfo in non_max_suppression_gpu_ref.cl + auto batch_num = orgParams.inputs[1].Batch().v; + auto class_num = orgParams.inputs[1].Feature().v; + auto boxes_num = orgParams.inputs[0].Feature().v; + size_t buffer_stride = boxes_num * intermediate_bytes; + size_t buffer_size = batch_num * class_num * buffer_stride; + size_t sel_num_buffer_size = batch_num * class_num * sizeof(int); + + kd.internalBufferSizes.push_back(buffer_size); + kd.internalBufferSizes.push_back(buffer_size); + kd.internalBufferSizes.push_back(sel_num_buffer_size); + kd.internalBufferDataType = Datatype::F32; + + // Build clKernelData. + for (size_t i = 0; i < kKernelsNum; i++) { + DispatchData dispatchData = SetDefault(orgParams, static_cast(i)); + auto entry_point = GetEntryPoint(kernelName, orgParams.layerID, params, options); + auto cldnn_jit = GetJitConstants(orgParams); + cldnn_jit.AddConstant(MakeJitConstant("BUFFER_STRIDE", buffer_stride)); + + if (i == 0) { + size_t num_bit_mask = CeilDiv(boxes_num, 8); + size_t num_score_per_item = RoundUp(CeilDiv(boxes_num, params.engineInfo.maxWorkGroupSize), 8); + size_t num_score_block = CeilDiv(boxes_num, num_score_per_item); + cldnn_jit.AddConstants({ MakeJitConstant("NUM_BIT_MASK", num_bit_mask) + , MakeJitConstant("NUM_SCORE_PER_ITEM", num_score_per_item) + , MakeJitConstant("NUM_SCORE_BLOCK", num_score_block)}); + } else if (i == 1) { + cldnn_jit.AddConstants({ MakeJitConstant("LOCAL_BATCH_NUM", dispatchData.lws[0]) + , MakeJitConstant("LOCAL_CLASS_NUM", dispatchData.lws[1]) + , MakeJitConstant("LOCAL_WORK_NUM", dispatchData.lws[2]) + , MakeJitConstant("PARTITION_STEP", GetPartitionStep(static_cast(dispatchData.lws[2])))}); + } + cldnn_jit.AddConstant(MakeJitConstant("NMS_STAGE_" + std::to_string(i), "true")); + + auto jit = CreateJit(kernelName, cldnn_jit, entry_point); + auto& kernel = kd.kernels[i]; + KernelBase::CheckDispatchData(kernelName, dispatchData); + kernel.params.workGroups.global = dispatchData.gws; + kernel.params.workGroups.local = dispatchData.lws; + kernel.code.kernelString = GetKernelString(kernelName, jit, entry_point, params.engineInfo); + SetKernelArguments(orgParams, kernel, i); + } + + return {kd}; +} + +KernelsPriority NonMaxSuppressionKernelRef::GetKernelsPriority(const Params& /*params*/, const optional_params& /*options*/) const { + return FORCE_PRIORITY_9; +} +} // namespace kernel_selector diff --git a/inference-engine/thirdparty/clDNN/kernel_selector/core/actual_kernels/non_max_suppression/non_max_suppression_kernel_ref.h b/inference-engine/thirdparty/clDNN/kernel_selector/core/actual_kernels/non_max_suppression/non_max_suppression_kernel_ref.h new file mode 100644 index 00000000000..65c40b0a4fb --- /dev/null +++ b/inference-engine/thirdparty/clDNN/kernel_selector/core/actual_kernels/non_max_suppression/non_max_suppression_kernel_ref.h @@ -0,0 +1,105 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +#include "kernel_base_opencl.h" +#include "kernel_selector_params.h" + +namespace kernel_selector { + +enum class NmsArgType { + None, + Input, + Constant +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// non_max_suppression_params +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +struct non_max_suppression_params : public base_params { + non_max_suppression_params() : base_params(KernelType::NON_MAX_SUPPRESSION), + box_encoding(BoxEncodingType::BOX_ENCODING_CORNER), sort_result_descending(true), + num_select_per_class_type(NmsArgType::None), num_select_per_class(0), + iou_threshold_type(NmsArgType::None), iou_threshold(0.0f), + score_threshold_type(NmsArgType::None), score_threshold(0.0f), + soft_nms_sigma_type(NmsArgType::None), soft_nms_sigma(0.0f), + has_second_output(false), has_third_output(false) {} + + BoxEncodingType box_encoding; + bool sort_result_descending; + NmsArgType num_select_per_class_type; + int num_select_per_class; + NmsArgType iou_threshold_type; + float iou_threshold; + NmsArgType score_threshold_type; + float score_threshold; + NmsArgType soft_nms_sigma_type; + float soft_nms_sigma; + bool has_second_output; + bool has_third_output; + + uint32_t GetIndexNumSelectPerClass() const { + uint32_t input_idx = 2; + return input_idx; + } + + uint32_t GetIndexIouThreshold() const { + uint32_t input_idx = GetIndexNumSelectPerClass(); + if (num_select_per_class_type == NmsArgType::Input) input_idx++; + return input_idx; + } + + uint32_t GetIndexScoreThreshold() const { + uint32_t input_idx = GetIndexIouThreshold(); + if (iou_threshold_type == NmsArgType::Input) input_idx++; + return input_idx; + } + + uint32_t GetIndexSoftNmsSigma() const { + uint32_t input_idx = GetIndexScoreThreshold(); + if (score_threshold_type == NmsArgType::Input) input_idx++; + return input_idx; + } + + uint32_t GetIndexSecondOutput() const { + uint32_t input_idx = GetIndexSoftNmsSigma(); + if (soft_nms_sigma_type == NmsArgType::Input) input_idx++; + return input_idx; + } + + uint32_t GetIndexThirdOutput() const { + uint32_t input_idx = GetIndexSecondOutput(); + if (has_second_output) input_idx++; + return input_idx; + } +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// non_max_suppression_optional_params +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +struct non_max_suppression_optional_params : optional_params { + non_max_suppression_optional_params() : optional_params(KernelType::NON_MAX_SUPPRESSION) {} +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// NonMaxSuppressionKernelRef +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +class NonMaxSuppressionKernelRef : public KernelBaseOpenCL { +public: + NonMaxSuppressionKernelRef() : KernelBaseOpenCL("non_max_suppression_gpu_ref") {} + + using DispatchData = CommonDispatchData; + KernelsData GetKernelsData(const Params& params, const optional_params& options) const override; + KernelsPriority GetKernelsPriority(const Params& params, const optional_params& options) const override; + ParamsKey GetSupportedKey() const override; + +protected: + Datatype GetAccumulatorType(const non_max_suppression_params& params) const; + virtual JitConstants GetJitConstants(const non_max_suppression_params& params) const; + bool Validate(const Params& p, const optional_params& o) const override; + void SetKernelArguments(const non_max_suppression_params& params, clKernelData& kernel, size_t idx) const; +}; + +} // namespace kernel_selector diff --git a/inference-engine/thirdparty/clDNN/kernel_selector/core/actual_kernels/non_max_suppression/non_max_suppression_kernel_selector.cpp b/inference-engine/thirdparty/clDNN/kernel_selector/core/actual_kernels/non_max_suppression/non_max_suppression_kernel_selector.cpp new file mode 100644 index 00000000000..423383e16a7 --- /dev/null +++ b/inference-engine/thirdparty/clDNN/kernel_selector/core/actual_kernels/non_max_suppression/non_max_suppression_kernel_selector.cpp @@ -0,0 +1,15 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "non_max_suppression_kernel_selector.h" +#include "non_max_suppression_kernel_ref.h" + +namespace kernel_selector { + +non_max_suppression_kernel_selector::non_max_suppression_kernel_selector() { Attach(); } + +KernelsData non_max_suppression_kernel_selector::GetBestKernels(const Params& params, const optional_params& options) const { + return GetNaiveBestKernel(params, options, KernelType::NON_MAX_SUPPRESSION); +} +} // namespace kernel_selector diff --git a/inference-engine/thirdparty/clDNN/kernel_selector/core/actual_kernels/non_max_suppression/non_max_suppression_kernel_selector.h b/inference-engine/thirdparty/clDNN/kernel_selector/core/actual_kernels/non_max_suppression/non_max_suppression_kernel_selector.h new file mode 100644 index 00000000000..345f17be887 --- /dev/null +++ b/inference-engine/thirdparty/clDNN/kernel_selector/core/actual_kernels/non_max_suppression/non_max_suppression_kernel_selector.h @@ -0,0 +1,21 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +#include "kernel_selector.h" + +namespace kernel_selector { +class non_max_suppression_kernel_selector : public kernel_selector_base { +public: + static non_max_suppression_kernel_selector& Instance() { + static non_max_suppression_kernel_selector instance_; + return instance_; + } + + non_max_suppression_kernel_selector(); + + KernelsData GetBestKernels(const Params& params, const optional_params& options) const override; +}; +} // namespace kernel_selector diff --git a/inference-engine/thirdparty/clDNN/kernel_selector/core/cl_kernels/non_max_suppression_gpu_ref.cl b/inference-engine/thirdparty/clDNN/kernel_selector/core/cl_kernels/non_max_suppression_gpu_ref.cl new file mode 100644 index 00000000000..1352db090f1 --- /dev/null +++ b/inference-engine/thirdparty/clDNN/kernel_selector/core/cl_kernels/non_max_suppression_gpu_ref.cl @@ -0,0 +1,568 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "include/data_types.cl" +#include "include/fetch_data.cl" + +/// Kernels +/// 0: Only boxes exceeding SCORE_THRESHOLD are copied to intermediate-buffer0. +/// Set copied box number to intermediate-buffer2 +/// 1: Sort the boxes in buffer0 by class. +/// 2: Remove boxes what are over IOU_THRESHOLD. +/// 3: Copy the boxes to output. If SORT_RESULT_DESCENDING is 1, all boxes will be sorted without class distinction. + +/// KERNEL_ARGs +/// +/// boxes +/// - shape: {num_batches, num_boxes, 4} +/// scores +/// - shape: {num_batches, num_classes, num_boxes} +/// buffer0 (intermediate buffer) +/// - size: batch_num * class_num * boxes_num * sizeof(SBOX_INFO) +/// - desc: filtered and sorted SBOX_INFO list +/// buffer1 (intermediate buffer) +/// - size: batch_num * class_num * boxes_num * sizeof(BOX_INFO) +/// - desc: selected SBOX_INFO list by iou calucation +/// buffer2 (intermediate buffer) +/// - size: batch_num * class_num * sizeof(int) +/// - desc: sorted box num for batch*class + +/// optional input variables +/// NUM_SELECT_PER_CLASS_VAL TO_UNIT_TYPE(num_select_per_class[0]), default is 0 +/// IOU_THRESHOLD_VAL TO_ACCUMULATOR_TYPE(iou_threshold[0]), default is ACCUMULATOR_VAL_ZERO +/// SCORE_THRESHOLD_VAL TO_ACCUMULATOR_TYPE(score_threshold[0]), default is ACCUMULATOR_VAL_ZERO +/// SOFT_NMS_SIGMA_VAL TO_ACCUMULATOR_TYPE(soft_nms_sigma[0]), default is ACCUMULATOR_VAL_ZERO +/// OUTPUT_NUM Number of outputs. [OUTPUT_NUM, 3, 1, 1] +/// BUFFER_STRIDE sizeof(SBOX_INFO) * NUM_BOXES + +#define unroll_for __attribute__((opencl_unroll_hint)) for + +#define NUM_BATCHES INPUT0_BATCH_NUM +#define NUM_BOXES INPUT0_FEATURE_NUM +#define NUM_CLASSES INPUT1_FEATURE_NUM + +typedef struct { + ushort boxId; + int suppress_begin_index; + INPUT1_TYPE score; +} FUNC(SortedBoxInfo); + +typedef struct { + short batchId; + ushort classId; + ushort boxId; + INPUT1_TYPE score; +} FUNC(BoxInfo); + +#define SBOX_INFO FUNC(SortedBoxInfo) +#define BOX_INFO FUNC(BoxInfo) + +inline COORD_TYPE_4 FUNC(getBoxCoords)(const __global INPUT0_TYPE *boxes, const short batch, const ushort boxId) +{ + COORD_TYPE_4 coords = TO_COORD_TYPE_4(vload4(0, &boxes[INPUT0_GET_INDEX(batch, boxId, 0, 0)])); + +#if BOX_ENCODING == 0 + const COORD_TYPE ax1 = min(coords[1], coords[3]); + const COORD_TYPE ax2 = max(coords[1], coords[3]); + const COORD_TYPE ay1 = min(coords[0], coords[2]); + const COORD_TYPE ay2 = max(coords[0], coords[2]); + coords[1] = ax1; + coords[3] = ax2; + coords[0] = ay1; + coords[2] = ay2; +#endif + + return coords; +} + +inline float FUNC(intersectionOverUnion)(const COORD_TYPE_4 boxA, const COORD_TYPE_4 boxB) +{ +#if BOX_ENCODING == 0 + /// CORNER + const COORD_TYPE areaA = (boxA[3] - boxA[1]) * (boxA[2] - boxA[0]); + const COORD_TYPE areaB = (boxB[3] - boxB[1]) * (boxB[2] - boxB[0]); + + const COORD_TYPE intersection_ymin = max(boxA[0], boxB[0]); + const COORD_TYPE intersection_xmin = max(boxA[1], boxB[1]); + const COORD_TYPE intersection_ymax = min(boxA[2], boxB[2]); + const COORD_TYPE intersection_xmax = min(boxA[3], boxB[3]); +#else + /// CENTER + const COORD_TYPE areaA = boxA[3] * boxA[2]; + const COORD_TYPE areaB = boxB[3] * boxB[2]; + const COORD_TYPE halfWidthA = boxA[2] / 2; + const COORD_TYPE halfHeightA = boxA[3] / 2; + const COORD_TYPE halfWidthB = boxB[2] / 2; + const COORD_TYPE halfHeightB = boxB[3] / 2; + + const COORD_TYPE intersection_ymin = max(boxA[1] - halfHeightA, boxB[1] - halfHeightB); + const COORD_TYPE intersection_xmin = max(boxA[0] - halfWidthA, boxB[0] - halfWidthB); + const COORD_TYPE intersection_ymax = min(boxA[1] + halfHeightA, boxB[1] + halfHeightB); + const COORD_TYPE intersection_xmax = min(boxA[0] + halfWidthA, boxB[0] + halfWidthB); +#endif + + if (areaA <= 0.0f || areaB <= 0.0f) + return 0.0f; + + const COORD_TYPE intersection_area = max(intersection_xmax - intersection_xmin, TO_COORD_TYPE(0.f)) * + max(intersection_ymax - intersection_ymin, TO_COORD_TYPE(0.f)); + const COORD_TYPE union_area = areaA + areaB - intersection_area; + return convert_float(intersection_area / union_area); +} + +inline float FUNC(scaleIOU)(float iou, float iou_threshold, float scale) +{ + if (iou <= iou_threshold) { + return exp(scale * iou * iou); + } else { + return 0.0f; + } +} + +inline void FUNC(swap_sbox_info)(__global SBOX_INFO* a, __global SBOX_INFO* b) +{ + SBOX_INFO temp = *a; + *a = *b; + *b = temp; +} + +inline int FUNC(partition)(__global SBOX_INFO* arr, int l, int h) +{ + const INPUT1_TYPE pivotScore = arr[h].score; + const ushort pivotBoxId = arr[h].boxId; + int i = (l - 1); + for (int j = l; j <= h - 1; j++) { + if ((arr[j].score > pivotScore) || (arr[j].score == pivotScore && arr[j].boxId < pivotBoxId)) { + i++; + FUNC_CALL(swap_sbox_info)(&arr[i], &arr[j]); + } + } + FUNC_CALL(swap_sbox_info)(&arr[i + 1], &arr[h]); + return (i + 1); +} + +inline void FUNC(bubbleSortIterative)(__global SBOX_INFO* arr, int l, int h) +{ + for (int i = 0; i < h-l; i++) { + bool swapped = false; + for (int j = l; j < h-i; j++) { + if ((arr[j].score > arr[j+1].score) || (arr[j].score == arr[j+1].score && arr[j].boxId < arr[j+1].boxId)) { + FUNC_CALL(swap_sbox_info)(&arr[j], &arr[j+1]); + swapped = true; + } + } + + if (!swapped) + break; + } +} + +inline void FUNC(quickSortIterative)(__global SBOX_INFO* arr, int l, int h) +{ + // Create an auxiliary stack + const int kStackSize = 100; + int stack[kStackSize]; + + // initialize top of stack + int top = -1; + + // push initial values of l and h to stack + stack[++top] = l; + stack[++top] = h; + + // Keep popping from stack while is not empty + while (top >= 0) { + // Pop h and l + h = stack[top--]; + l = stack[top--]; + + // Set pivot element at its correct position + // in sorted array + const int p = FUNC_CALL(partition)(arr, l, h); + + // If there are elements on left side of pivot, + // then push left side to stack + if (p - 1 > l) { + if (top >= (kStackSize - 1)) { + FUNC_CALL(bubbleSortIterative)(arr, l, p - 1); + } else { + stack[++top] = l; + stack[++top] = p - 1; + } + } + + // If there are elements on right side of pivot, + // then push right side to stack + if (p + 1 < h) { + if (top >= (kStackSize - 1)) { + FUNC_CALL(bubbleSortIterative)(arr, p + 1, h); + } else { + stack[++top] = p + 1; + stack[++top] = h; + } + } + } +} + +inline int FUNC(initBoxList)(__global SBOX_INFO *outBoxes, int boxNum, const __global INPUT1_TYPE *scores, float score_threshold, short batchId, ushort classId) +{ + int count = 0; + for (ushort i = 0; i < boxNum; ++i) { + const INPUT1_TYPE score = scores[INPUT1_GET_INDEX(batchId, classId, i, 0)]; + if (convert_float(score) < score_threshold) continue; + + SBOX_INFO binfo; + binfo.boxId = i; + binfo.suppress_begin_index = 0; + binfo.score = score; + outBoxes[count] = binfo; + ++count; + } + + return count; +} + +inline void FUNC(initOutputBoxList)(__global BOX_INFO *outBoxes, int boxNum, const __global INPUT1_TYPE *scores, __global OUTPUT_TYPE *output) +{ + for (int i = 0; i < boxNum; ++i) { + const int outputId = i * 3; + outBoxes[i].batchId = output[outputId + 0]; + outBoxes[i].classId = output[outputId + 1]; + outBoxes[i].boxId = output[outputId + 2]; + outBoxes[i].score = scores[INPUT1_GET_INDEX(outBoxes[i].batchId, outBoxes[i].classId, outBoxes[i].boxId, 0)]; + } +} + +inline void FUNC(swap)(__global BOX_INFO* a, __global BOX_INFO* b) +{ + BOX_INFO temp = *a; + *a = *b; + *b = temp; +} + +inline void FUNC(sortOutputBoxList)(__global BOX_INFO *outSortedBoxes, int boxNum) +{ + for (int i = 0; i < boxNum - 1; ++i) { + bool swapped = false; + for (int j = 0; j < boxNum - i - 1; ++j) { + if ((outSortedBoxes[j].score < outSortedBoxes[j+1].score) || + (outSortedBoxes[j].score == outSortedBoxes[j+1].score && outSortedBoxes[j].batchId > outSortedBoxes[j+1].batchId) || + (outSortedBoxes[j].score == outSortedBoxes[j+1].score && outSortedBoxes[j].batchId == outSortedBoxes[j+1].batchId && + outSortedBoxes[j].classId > outSortedBoxes[j+1].classId) || + (outSortedBoxes[j].score == outSortedBoxes[j+1].score && outSortedBoxes[j].batchId == outSortedBoxes[j+1].batchId && + outSortedBoxes[j].classId == outSortedBoxes[j+1].classId && outSortedBoxes[j].boxId > outSortedBoxes[j+1].boxId)) { + FUNC_CALL(swap)(&outSortedBoxes[j], &outSortedBoxes[j+1]); + swapped = true; + } + } + + // IF no two elements were swapped by inner loop, then break + if (swapped == false) + break; + } +} + + +#ifdef NMS_STAGE_0 +KERNEL (non_max_suppression_ref_stage_0)( + const __global INPUT1_TYPE *scores + , __global uchar *buffer0 + , __global int *buffer2 + #ifdef SCORE_THRESHOLD_TYPE + , const __global SCORE_THRESHOLD_TYPE *score_threshold + #endif + ) +{ + const int batchId = get_global_id(0); + const int classId = get_global_id(1); + const int box_gid = get_global_id(2); + const int start_bid = box_gid * NUM_SCORE_PER_ITEM; + const int end_bid = min(start_bid + NUM_SCORE_PER_ITEM, NUM_BOXES); + + __local char bit_mask[NUM_BIT_MASK]; + __local int block_num[NUM_SCORE_BLOCK]; + + block_num[box_gid] = 0; + + { + int mask_id = start_bid / 8; + int total_block_selected_num = 0; + for (int i = start_bid; i < end_bid; i += 8) { + MAKE_VECTOR_TYPE(INPUT1_TYPE, 8) score8 = vload8(0, &scores[INPUT1_GET_INDEX(batchId, classId, i, 0)]); + + char mask = 0; + for (int bi = 0; bi < 8; bi++) { + if ((i + bi) >= NUM_BOXES) + break; + + if (convert_float(score8[bi]) <= SCORE_THRESHOLD_VAL) + continue; + + mask |= (1 << bi); + total_block_selected_num++; + } + bit_mask[mask_id] = mask; + mask_id++; + } + + block_num[box_gid] = total_block_selected_num; + } + + barrier(CLK_LOCAL_MEM_FENCE); + + { + // first item of group + if (box_gid == 0 && get_local_id(2) == 0) { + int acc_num = 0; + int total_sel_num = 0; + for (int i = 0; i < NUM_SCORE_BLOCK; i++) { + int n = block_num[i]; + block_num[i] = acc_num; + acc_num += n; + } + buffer2[batchId * NUM_CLASSES + classId] = acc_num; + } + } + + barrier(CLK_LOCAL_MEM_FENCE); + + { + __global SBOX_INFO *sortedBoxList = (__global SBOX_INFO*)&buffer0[(batchId * NUM_CLASSES + classId) * BUFFER_STRIDE]; + + int write_offset = block_num[box_gid]; + + int mask_id = start_bid / 8; + for (int i = start_bid; i < end_bid; i += 8) { + MAKE_VECTOR_TYPE(INPUT1_TYPE, 8) score8 = vload8(0, &scores[INPUT1_GET_INDEX(batchId, classId, i, 0)]); + const char mask = bit_mask[mask_id]; + + for (int bi = 0; bi < 8; bi++) { + if ((mask & (1 << bi)) && (i + bi) < NUM_BOXES) { + SBOX_INFO binfo; + binfo.boxId = i + bi; + binfo.suppress_begin_index = 0; + binfo.score = score8[bi]; + sortedBoxList[write_offset] = binfo; + + write_offset++; + } + } + mask_id++; + } + } +} +#endif /* NMS_STAGE_0 */ + +#ifdef NMS_STAGE_1 + +#if LOCAL_BATCH_NUM != 1 +#error "The batch number of LWS should be 1." +#endif + +KERNEL (non_max_suppression_ref_stage_1)( + __global uchar *buffer0 + , __global int *buffer2 + ) +{ + const int batchId = get_global_id(0); + const int classId = get_global_id(1); + const int workItemId = get_global_id(2); + const int localClassId = get_local_id(1); + __local int __range[LOCAL_CLASS_NUM][LOCAL_WORK_NUM * 2]; + const int kSortedBoxNum = buffer2[batchId * NUM_CLASSES + classId]; + __global SBOX_INFO *sortedBoxList = (__global SBOX_INFO*)&buffer0[(batchId * NUM_CLASSES + classId) * BUFFER_STRIDE]; + if (workItemId == 0) { + __range[localClassId][0] = 0; + __range[localClassId][1] = kSortedBoxNum - 1; + } else { + __range[localClassId][workItemId * 2] = 0; + __range[localClassId][workItemId * 2 + 1] = 0; + } + barrier(CLK_LOCAL_MEM_FENCE); + + int range_step = 2; + const int first_id = workItemId * 2; + for (int i = 0, maxWorkingNum = 1; i < PARTITION_STEP; ++i, maxWorkingNum *= 2, range_step *= 2) { + if (workItemId < maxWorkingNum) { + const int begin_id = __range[localClassId][first_id]; + const int end_id = __range[localClassId][first_id + 1]; + const int second_id = first_id + range_step; + + if (begin_id < end_id) { + const int pivot = FUNC_CALL(partition)(sortedBoxList, begin_id, end_id); + __range[localClassId][first_id ] = begin_id; + __range[localClassId][first_id + 1 ] = max(pivot - 1, begin_id); + __range[localClassId][second_id ] = min(pivot + 1, end_id); + __range[localClassId][second_id + 1] = end_id; + } + } + + barrier(CLK_GLOBAL_MEM_FENCE | CLK_LOCAL_MEM_FENCE); + } + + const int begin_id = __range[localClassId][first_id]; + const int end_id = __range[localClassId][first_id + 1]; + if (begin_id < end_id) { + FUNC_CALL(quickSortIterative)(sortedBoxList, begin_id, end_id); + } +} +#endif /* NMS_STAGE_1 */ + +#ifdef NMS_STAGE_2 +KERNEL (non_max_suppression_ref_stage_2)( + const __global INPUT0_TYPE *boxes + , __global uchar *buffer0 + , __global uchar *buffer1 + , __global int *buffer2 + #ifdef NUM_SELECT_PER_CLASS_TYPE + , const __global NUM_SELECT_PER_CLASS_TYPE *num_select_per_class + #endif + #ifdef IOU_THRESHOLD_TYPE + , const __global IOU_THRESHOLD_TYPE *iou_threshold + #endif + #ifdef SCORE_THRESHOLD_TYPE + , const __global SCORE_THRESHOLD_TYPE *score_threshold + #endif + #ifdef SOFT_NMS_SIGMA_TYPE + , const __global SOFT_NMS_SIGMA_TYPE *soft_nms_sigma + #endif + ) +{ + const short batchId = get_global_id(0); + const ushort classId = get_global_id(1); + + float scale = 0.0f; + if (SOFT_NMS_SIGMA_VAL > 0.0f) { + scale = -0.5f / SOFT_NMS_SIGMA_VAL; + } + + __global SBOX_INFO *sortedBoxList = (__global SBOX_INFO*)&buffer0[(batchId * NUM_CLASSES + classId) * BUFFER_STRIDE]; + const int kSortedBoxNum = buffer2[batchId * NUM_CLASSES + classId]; + + __global BOX_INFO *selectedBoxList = (__global BOX_INFO*)&buffer1[(batchId * NUM_CLASSES + classId) * BUFFER_STRIDE]; + int selectedBoxNum = 0; + const int kNumSelectPerClass = NUM_SELECT_PER_CLASS_VAL; + int i = 0; + while (i < kSortedBoxNum && selectedBoxNum < kNumSelectPerClass) { + SBOX_INFO next_candidate = sortedBoxList[i]; + INPUT1_TYPE original_score = next_candidate.score; + const COORD_TYPE_4 next_candidate_coord = FUNC_CALL(getBoxCoords)(boxes, batchId, next_candidate.boxId); + ++i; + + bool should_hard_suppress = false; + for (int j = selectedBoxNum - 1; j >= next_candidate.suppress_begin_index; --j) { + const COORD_TYPE_4 selected_box_coord = FUNC_CALL(getBoxCoords)(boxes, batchId, selectedBoxList[j].boxId); + const float iou = FUNC_CALL(intersectionOverUnion)(next_candidate_coord, selected_box_coord); + next_candidate.score *= FUNC_CALL(scaleIOU)(iou, IOU_THRESHOLD_VAL, scale); + + if (iou >= IOU_THRESHOLD_VAL) { + should_hard_suppress = true; + break; + } + + if (convert_float(next_candidate.score) <= SCORE_THRESHOLD_VAL) { + break; + } + } + + next_candidate.suppress_begin_index = selectedBoxNum; + + if (!should_hard_suppress) { + if (next_candidate.score == original_score) { + BOX_INFO binfo; + binfo.batchId = batchId; + binfo.classId = classId; + binfo.boxId = next_candidate.boxId; + binfo.score = next_candidate.score; + selectedBoxList[selectedBoxNum] = binfo; + ++selectedBoxNum; + + continue; + } + + if (convert_float(next_candidate.score) > SCORE_THRESHOLD_VAL) { + --i; + sortedBoxList[i] = next_candidate; + FUNC_CALL(quickSortIterative)(sortedBoxList, i, kSortedBoxNum); + } + } + } + + // Set pad value to indicate the end of selected box list. + if (selectedBoxNum < NUM_BOXES) { + selectedBoxList[selectedBoxNum].batchId = -1; + } +} +#endif /* NMS_STAGE_2 */ + +#ifdef NMS_STAGE_3 +KERNEL (non_max_suppression_ref_stage_3)( + __global OUTPUT_TYPE *output + , __global uchar *buffer1 + , __global uchar *buffer2 + #ifdef SECOND_OUTPUT_TYPE + , __global SECOND_OUTPUT_TYPE *selected_scores + #endif + #ifdef THIRD_OUTPUT_TYPE + , __global THIRD_OUTPUT_TYPE *valid_outputs + #endif + ) +{ + int outputIdx = 0; + __global BOX_INFO *sortedBoxList = (__global BOX_INFO*)&buffer2[0]; + for (short batchId = 0; batchId < NUM_BATCHES; batchId++) { + for (ushort classId = 0; classId < NUM_CLASSES; classId++) { + __global BOX_INFO *selectedBoxList = (__global BOX_INFO*)&buffer1[(batchId * NUM_CLASSES + classId) * BUFFER_STRIDE]; + for (int i = 0; i < NUM_BOXES; i++) { + if (selectedBoxList[i].batchId > -1) { + sortedBoxList[outputIdx] = selectedBoxList[i]; + outputIdx++; + } else { + break; + } + } + } + } + +#if SORT_RESULT_DESCENDING == 1 + FUNC_CALL(sortOutputBoxList)(sortedBoxList, outputIdx); +#endif + + unroll_for (int i = 0; i < outputIdx; i++) { + const int offset = 3 * i; + output[offset + 0] = sortedBoxList[i].batchId; + output[offset + 1] = sortedBoxList[i].classId; + output[offset + 2] = sortedBoxList[i].boxId; + } + + // Padding + unroll_for (int i = outputIdx; i < OUTPUT_NUM; i++) { + const int offset = 3 * i; + output[offset + 0] = -1; + output[offset + 1] = -1; + output[offset + 2] = -1; + } + +#ifdef SECOND_OUTPUT_TYPE + unroll_for (int i = 0; i < outputIdx; i++) { + const int offset = 3 * i; + selected_scores[offset + 0] = TO_SECOND_OUTPUT_TYPE(sortedBoxList[i].batchId); + selected_scores[offset + 1] = TO_SECOND_OUTPUT_TYPE(sortedBoxList[i].classId); + selected_scores[offset + 2] = TO_SECOND_OUTPUT_TYPE(sortedBoxList[i].score); + } + + // Padding + unroll_for (int i = outputIdx; i < OUTPUT_NUM; i++) { + const int offset = 3 * i; + selected_scores[offset + 0] = -1; + selected_scores[offset + 1] = -1; + selected_scores[offset + 2] = -1; + } +#endif + +#ifdef THIRD_OUTPUT_TYPE + valid_outputs[0] = TO_THIRD_OUTPUT_TYPE(outputIdx); +#endif +} +#endif /* NMS_STAGE_3 */ diff --git a/inference-engine/thirdparty/clDNN/kernel_selector/core/kernel_selector_common.cpp b/inference-engine/thirdparty/clDNN/kernel_selector/core/kernel_selector_common.cpp index 35c2115e5ac..1acd05cdc75 100644 --- a/inference-engine/thirdparty/clDNN/kernel_selector/core/kernel_selector_common.cpp +++ b/inference-engine/thirdparty/clDNN/kernel_selector/core/kernel_selector_common.cpp @@ -156,6 +156,8 @@ std::string toString(KernelType kt) { return "FUSED_CONV_ELTWISE"; case KernelType::BINARY_CONVOLUTION: return "BINARY_CONVOLUTION"; + case KernelType::NON_MAX_SUPPRESSION: + return "NON_MAX_SUPPRESSION"; default: return ""; } } diff --git a/inference-engine/thirdparty/clDNN/src/impls/ocl/non_max_suppression.cpp b/inference-engine/thirdparty/clDNN/src/impls/ocl/non_max_suppression.cpp new file mode 100644 index 00000000000..09479f28de0 --- /dev/null +++ b/inference-engine/thirdparty/clDNN/src/impls/ocl/non_max_suppression.cpp @@ -0,0 +1,183 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "data_inst.h" +#include "non_max_suppression_inst.h" +#include "primitive_base.hpp" +#include "impls/implementation_map.hpp" +#include "kernel_selector_helper.h" +#include "non_max_suppression/non_max_suppression_kernel_selector.h" +#include "non_max_suppression/non_max_suppression_kernel_ref.h" + + +namespace cldnn { +namespace ocl { +struct non_max_suppression_impl : typed_primitive_impl_ocl { + using parent = typed_primitive_impl_ocl; + using parent::parent; + + std::unique_ptr clone() const override { + return make_unique(*this); + } + +protected: + kernel_arguments_data get_arguments(typed_primitive_inst& instance, int32_t) const override { + kernel_arguments_data args; + for (size_t i = 0; i < instance.inputs_memory_count(); i++) { + args.inputs.push_back(instance.input_memory_ptr(i)); + } + + if (instance.has_num_select_per_class() && !instance.node.num_select_per_class_node().is_constant()) { + args.inputs.push_back(instance.num_select_per_class_mem()); + } + + if (instance.has_iou_threshold() && !instance.node.iou_threshold_node().is_constant()) { + args.inputs.push_back(instance.iou_threshold_mem()); + } + + if (instance.has_score_threshold() && !instance.node.score_threshold_node().is_constant()) { + args.inputs.push_back(instance.score_threshold_mem()); + } + + if (instance.has_soft_nms_sigma() && !instance.node.soft_nms_sigma_node().is_constant()) { + args.inputs.push_back(instance.soft_nms_sigma_mem()); + } + + args.output = instance.output_memory_ptr(); + if (instance.has_second_output()) + args.inputs.push_back(instance.second_output_mem()); + if (instance.has_third_output()) + args.inputs.push_back(instance.third_output_mem()); + + return args; + } + +public: + static primitive_impl* create(const non_max_suppression_node& arg) { + auto params = get_default_params(arg); + auto optional_params = + get_default_optional_params(arg.get_program()); + + const auto& primitive = arg.get_primitive(); + params.inputs.push_back(convert_data_tensor(arg.input_scores().get_output_layout())); + + if (arg.has_num_select_per_class()) { + cldnn::program_node& node = arg.num_select_per_class_node(); + if (node.is_type()) { + params.num_select_per_class_type = kernel_selector::NmsArgType::Constant; + params.num_select_per_class = get_value(node); + } else { + params.num_select_per_class_type = kernel_selector::NmsArgType::Input; + params.inputs.push_back(convert_data_tensor(node.get_output_layout())); + } + } + + if (arg.has_iou_threshold()) { + cldnn::program_node& node = arg.iou_threshold_node(); + if (node.is_type()) { + params.iou_threshold_type = kernel_selector::NmsArgType::Constant; + params.iou_threshold = get_value(node); + } else { + params.iou_threshold_type = kernel_selector::NmsArgType::Input; + params.inputs.push_back(convert_data_tensor(node.get_output_layout())); + } + } + + if (arg.has_score_threshold()) { + cldnn::program_node& node = arg.score_threshold_node(); + if (node.is_type()) { + params.score_threshold_type = kernel_selector::NmsArgType::Constant; + params.score_threshold = get_value(node); + } else { + params.score_threshold_type = kernel_selector::NmsArgType::Input; + params.inputs.push_back(convert_data_tensor(node.get_output_layout())); + } + } + + if (arg.has_soft_nms_sigma()) { + cldnn::program_node& node = arg.soft_nms_sigma_node(); + if (node.is_type()) { + params.soft_nms_sigma_type = kernel_selector::NmsArgType::Constant; + params.soft_nms_sigma = get_value(node); + } else { + params.soft_nms_sigma_type = kernel_selector::NmsArgType::Input; + params.inputs.push_back(convert_data_tensor(node.get_output_layout())); + } + } + + if (arg.has_second_output()) { + params.inputs.push_back(convert_data_tensor(arg.second_output_node().get_output_layout())); + params.has_second_output = true; + } + + if (arg.has_third_output()) { + params.inputs.push_back(convert_data_tensor(arg.third_output_node().get_output_layout())); + params.has_third_output = true; + } + + params.sort_result_descending = primitive->sort_result_descending; + params.box_encoding = primitive->center_point_box ? + kernel_selector::BoxEncodingType::BOX_ENCODING_CENTER : kernel_selector::BoxEncodingType::BOX_ENCODING_CORNER; + + auto& kernel_selector = kernel_selector::non_max_suppression_kernel_selector::Instance(); + auto best_kernels = kernel_selector.GetBestKernels(params, optional_params); + + CLDNN_ERROR_BOOL(arg.id(), + "Best_kernel.empty()", + best_kernels.empty(), + "Cannot find a proper kernel with this arguments"); + + auto non_max_suppression_node = new non_max_suppression_impl(arg, best_kernels[0]); + + return non_max_suppression_node; + } + +private: + template + static T get_value(cldnn::program_node& node) { + T retValue; + auto mem = node.as().get_attached_memory_ptr(); + auto& stream = node.get_program().get_stream(); + switch (mem->get_layout().data_type) { + case data_types::f16: { + mem_lock lock(mem, stream); + auto mem_value = static_cast(lock.data()); + retValue = static_cast(*mem_value); + } break; + case data_types::f32: { + mem_lock lock(mem, stream); + auto mem_value = static_cast(lock.data()); + retValue = static_cast(*mem_value); + } break; + case data_types::i32: { + mem_lock lock(mem, stream); + auto mem_value = static_cast(lock.data()); + retValue = static_cast(*mem_value); + } break; + case data_types::i64: { + mem_lock lock(mem, stream); + auto mem_value = static_cast(lock.data()); + retValue = static_cast(*mem_value); + } break; + default: + throw std::runtime_error("Not supported data type."); + } + + return retValue; + } +}; + +namespace detail { + +attach_non_max_suppression_impl::attach_non_max_suppression_impl() { + implementation_map::add(impl_types::ocl, non_max_suppression_impl::create, { + std::make_tuple(data_types::i32, format::bfyx), + std::make_tuple(data_types::f16, format::bfyx), + std::make_tuple(data_types::f32, format::bfyx), + }); +} + +} // namespace detail +} // namespace ocl +} // namespace cldnn diff --git a/inference-engine/thirdparty/clDNN/src/impls/ocl/register.cpp b/inference-engine/thirdparty/clDNN/src/impls/ocl/register.cpp index 28ce961755e..c5068a3445d 100644 --- a/inference-engine/thirdparty/clDNN/src/impls/ocl/register.cpp +++ b/inference-engine/thirdparty/clDNN/src/impls/ocl/register.cpp @@ -40,6 +40,7 @@ void register_implementations() { REGISTER_OCL(max_unpooling); REGISTER_OCL(mutable_data); REGISTER_OCL(mvn); + REGISTER_OCL(non_max_suppression); REGISTER_OCL(normalize); REGISTER_OCL(one_hot); REGISTER_OCL(permute); diff --git a/inference-engine/thirdparty/clDNN/src/impls/ocl/register.hpp b/inference-engine/thirdparty/clDNN/src/impls/ocl/register.hpp index f462c37c3a9..ff9dbfc7932 100644 --- a/inference-engine/thirdparty/clDNN/src/impls/ocl/register.hpp +++ b/inference-engine/thirdparty/clDNN/src/impls/ocl/register.hpp @@ -31,6 +31,7 @@ #include "cldnn/primitives/max_unpooling.hpp" #include "cldnn/primitives/mutable_data.hpp" #include "cldnn/primitives/mvn.hpp" +#include "cldnn/primitives/non_max_suppression.hpp" #include "cldnn/primitives/normalize.hpp" #include "cldnn/primitives/one_hot.hpp" #include "cldnn/primitives/permute.hpp" @@ -105,6 +106,7 @@ REGISTER_OCL(lstm_elt); REGISTER_OCL(max_unpooling); REGISTER_OCL(mutable_data); REGISTER_OCL(mvn); +REGISTER_OCL(non_max_suppression); REGISTER_OCL(normalize); REGISTER_OCL(one_hot); REGISTER_OCL(permute); diff --git a/inference-engine/thirdparty/clDNN/src/include/layout_optimizer.h b/inference-engine/thirdparty/clDNN/src/include/layout_optimizer.h index 39ef6fdb1a9..4681df52800 100644 --- a/inference-engine/thirdparty/clDNN/src/include/layout_optimizer.h +++ b/inference-engine/thirdparty/clDNN/src/include/layout_optimizer.h @@ -17,6 +17,7 @@ #include "binary_convolution_inst.h" #include "lstm_gemm_inst.h" #include "generic_layer.hpp" +#include "non_max_suppression_inst.h" #include "region_yolo_inst.h" #include "kernel_selector_common.h" diff --git a/inference-engine/thirdparty/clDNN/src/include/non_max_suppression_inst.h b/inference-engine/thirdparty/clDNN/src/include/non_max_suppression_inst.h index 36345261fe0..537a04b6024 100644 --- a/inference-engine/thirdparty/clDNN/src/include/non_max_suppression_inst.h +++ b/inference-engine/thirdparty/clDNN/src/include/non_max_suppression_inst.h @@ -21,6 +21,8 @@ public: : parent(prim, prog) {} + program_node& input() const { return get_dependency(0); } + program_node& input_boxes() const { return get_dependency(0); } diff --git a/inference-engine/thirdparty/clDNN/src/layout_optimizer.cpp b/inference-engine/thirdparty/clDNN/src/layout_optimizer.cpp index 4e64b6b349b..a6fcbeaa19f 100644 --- a/inference-engine/thirdparty/clDNN/src/layout_optimizer.cpp +++ b/inference-engine/thirdparty/clDNN/src/layout_optimizer.cpp @@ -834,6 +834,14 @@ impl_types layout_optimizer::get_preferred_impl_type(program_node& node) { preferred_impl = impl_types::ocl; else preferred_impl = impl_types::cpu; + } else if (node.is_type()) { + auto& nms_node = node.as(); + auto scoresTensor = convert_data_tensor(nms_node.input_scores().get_output_layout()); + const size_t kBatchNum = scoresTensor.Batch().v; + const size_t kClassNum = scoresTensor.Feature().v; + const size_t kNStreams = static_cast(node.get_program().get_engine().configuration().n_streams); + const size_t kKeyValue = kBatchNum * std::min(kClassNum, static_cast(8)) * kNStreams; + preferred_impl = (kKeyValue > 64) ? impl_types::ocl : impl_types::cpu; } return preferred_impl; diff --git a/inference-engine/thirdparty/clDNN/src/program.cpp b/inference-engine/thirdparty/clDNN/src/program.cpp index 3caf8727407..82b0f9b111f 100644 --- a/inference-engine/thirdparty/clDNN/src/program.cpp +++ b/inference-engine/thirdparty/clDNN/src/program.cpp @@ -506,7 +506,7 @@ void program::pre_optimize_graph(bool is_internal) { apply_opt_pass(lo, options.get()->enabled()); - if (options.get()->enabled()) { + if (options.get()->enabled() && get_engine().configuration().n_streams == 1) { // Fuse conv + eltw after padding preparations apply_opt_pass(lo, lo.get_optimization_attributes().b_fs_yx_fsv16_network); diff --git a/inference-engine/thirdparty/clDNN/tests/test_cases/non_max_suppression_test.cpp b/inference-engine/thirdparty/clDNN/tests/test_cases/non_max_suppression_test.cpp index 9dfabbce5b8..2b42a61450c 100644 --- a/inference-engine/thirdparty/clDNN/tests/test_cases/non_max_suppression_test.cpp +++ b/inference-engine/thirdparty/clDNN/tests/test_cases/non_max_suppression_test.cpp @@ -6,9 +6,10 @@ #include "test_utils.h" -#include -#include #include +#include +#include +#include using namespace cldnn; using namespace ::tests; @@ -49,6 +50,7 @@ struct non_max_suppression_basic : public testing::Test { const int batch_size = 2; const int classes_num = 2; const int boxes_num = 3; + const int selected_indices_num = 6; const std::vector boxes_data = { T(0.f), T(0.f), T(10.f), T(10.f), @@ -69,6 +71,8 @@ struct non_max_suppression_basic : public testing::Test { const layout boxes_layout = layout(type_to_data_type::value, format::bfyx, tensor(batch(batch_size), feature(boxes_num), spatial(1, 4))); const layout scores_layout = layout(type_to_data_type::value, format::bfyx, tensor(batch(batch_size), feature(classes_num), spatial(1, boxes_num))); + const layout selected_scores_layout = layout(type_to_data_type::value, format::bfyx, tensor(batch(selected_indices_num), feature(3))); + const layout valid_outputs_layout = layout(cldnn::data_types::i32, format::bfyx, tensor(batch(1))); memory::ptr get_boxes_memory(engine& engine) { auto mem = engine.allocate_memory(boxes_layout); @@ -82,6 +86,16 @@ struct non_max_suppression_basic : public testing::Test { return mem; } + memory::ptr get_selected_scores_mem(engine& engine) { + auto mem = engine.allocate_memory(selected_scores_layout); + return mem; + } + + memory::ptr get_valid_outputs_mem(engine& engine) { + auto mem = engine.allocate_memory(valid_outputs_layout); + return mem; + } + const int pad = -1; }; @@ -96,10 +110,10 @@ TYPED_TEST(non_max_suppression_basic, basic) { topo.add(input_layout("scores", this->scores_layout)); topo.add(non_max_suppression("nms", "boxes", "scores", 6, false, true)); - build_options build_opts( - build_option::optimize_data(true) - ); - cldnn::network net(engine, topo, build_opts); + build_options bo; + bo.set_option(build_option::optimize_data(true)); + + cldnn::network net{ engine, topo, bo }; auto boxes_mem = this->get_boxes_memory(engine); auto scores_mem = this->get_scores_memory(engine); @@ -137,12 +151,13 @@ TYPED_TEST(non_max_suppression_basic, num_per_class) { topo.add(input_layout("boxes", this->boxes_layout)); topo.add(input_layout("scores", this->scores_layout)); topo.add(data("num_per_class", num_per_class_mem)); - topo.add(non_max_suppression("nms", "boxes", "scores", 6, false, true, "num_per_class")); + topo.add(non_max_suppression("nms", "boxes", "scores", + this->batch_size * this->classes_num * 1, false, true, "num_per_class")); - build_options build_opts( - build_option::optimize_data(true) - ); - cldnn::network net(engine, topo, build_opts); + build_options bo; + bo.set_option(build_option::optimize_data(true)); + + cldnn::network net{ engine, topo, bo }; auto boxes_mem = this->get_boxes_memory(engine); auto scores_mem = this->get_scores_memory(engine); @@ -157,8 +172,6 @@ TYPED_TEST(non_max_suppression_basic, num_per_class) { 0, 1, 0, 1, 0, 2, 1, 1, 2, - this->pad, this->pad, this->pad, - this->pad, this->pad, this->pad, }; auto out_mem = result.at("nms").get_memory(); @@ -170,6 +183,83 @@ TYPED_TEST(non_max_suppression_basic, num_per_class) { } } +TYPED_TEST(non_max_suppression_basic, optional_outputs) { + auto& engine = tests::get_test_engine(); + + auto num_per_class_mem = engine.allocate_memory(layout(data_types::f32, format::bfyx, tensor(batch(1)))); + tests::set_values(num_per_class_mem, { 1.f }); + + topology topo; + topo.add(input_layout("boxes", this->boxes_layout)); + topo.add(input_layout("scores", this->scores_layout)); + topo.add(data("num_per_class", num_per_class_mem)); + + memory::ptr selected_scores_mem = this->get_selected_scores_mem(engine); + memory::ptr valid_outputs_mem = this->get_valid_outputs_mem(engine); + + topo.add(mutable_data("selected_scores", selected_scores_mem)); + topo.add(mutable_data("valid_outputs", valid_outputs_mem)); + + topo.add(non_max_suppression("nms", "boxes", "scores", + this->batch_size * this->classes_num * 1, false, true, + "num_per_class", cldnn::primitive_id(), + cldnn::primitive_id(), cldnn::primitive_id(), + "selected_scores", "valid_outputs")); + + build_options bo; + bo.set_option(build_option::optimize_data(true)); + + cldnn::network net{ engine, topo, bo }; + + auto boxes_mem = this->get_boxes_memory(engine); + auto scores_mem = this->get_scores_memory(engine); + + net.set_input_data("boxes", boxes_mem); + net.set_input_data("scores", scores_mem); + + auto result = net.execute(); + + std::vector expected_out = { + 0, 0, 2, + 0, 1, 0, + 1, 0, 2, + 1, 1, 2, + }; + const int expected_out_num = static_cast(expected_out.size()) / 3; + + std::vector expected_second_out = { + 0.f, 0.f, 0.9f, + 0.f, 1.f, 0.9f, + 1.f, 0.f, 0.8f, + 1.f, 1.f, 0.3f, + }; + + auto out_mem = result.at("nms").get_memory(); + cldnn::mem_lock out_ptr(out_mem, get_test_stream()); + + ASSERT_EQ(expected_out.size(), out_ptr.size()); + for (size_t i = 0; i < expected_out.size(); ++i) { + EXPECT_EQ(expected_out[i], out_ptr[i]) << "at i = " << i; + } + + if (selected_scores_mem->get_layout().data_type == data_types::f32) { + cldnn::mem_lock second_output_ptr(selected_scores_mem, get_test_stream()); + + for (size_t i = 0; i < expected_second_out.size(); ++i) { + EXPECT_FLOAT_EQ(expected_second_out[i], second_output_ptr[i]); + } + } else { + cldnn::mem_lock second_output_ptr(selected_scores_mem, get_test_stream()); + + for (size_t i = 0; i < expected_second_out.size(); ++i) { + EXPECT_NEAR(expected_second_out[i], half_to_float(second_output_ptr[i]), 0.0002f); + } + } + + cldnn::mem_lock third_output_ptr(valid_outputs_mem, get_test_stream()); + ASSERT_EQ(expected_out_num, third_output_ptr[0]); +} + TYPED_TEST(non_max_suppression_basic, iou_threshold) { auto& engine = tests::get_test_engine(); @@ -183,12 +273,14 @@ TYPED_TEST(non_max_suppression_basic, iou_threshold) { topo.add(input_layout("scores", this->scores_layout)); topo.add(data("num_per_class", num_per_class_mem)); topo.add(data("iou_threshold", iou_threshold_mem)); - topo.add(non_max_suppression("nms", "boxes", "scores", 6, false, true, "num_per_class", "iou_threshold")); + topo.add(non_max_suppression("nms", "boxes", "scores", + this->batch_size * this->classes_num * this->boxes_num, + false, true, "num_per_class", "iou_threshold")); - build_options build_opts( - build_option::optimize_data(true) - ); - cldnn::network net(engine, topo, build_opts); + build_options bo; + bo.set_option(build_option::optimize_data(true)); + + cldnn::network net{ engine, topo, bo }; auto boxes_mem = this->get_boxes_memory(engine); auto scores_mem = this->get_scores_memory(engine); @@ -204,7 +296,13 @@ TYPED_TEST(non_max_suppression_basic, iou_threshold) { 1, 0, 2, 0, 0, 1, 1, 0, 1, - 1, 1, 2 + 1, 1, 2, + 1, 1, 1, + this->pad, this->pad, this->pad, + this->pad, this->pad, this->pad, + this->pad, this->pad, this->pad, + this->pad, this->pad, this->pad, + this->pad, this->pad, this->pad }; auto out_mem = result.at("nms").get_memory(); @@ -232,12 +330,14 @@ TYPED_TEST(non_max_suppression_basic, score_threshold) { topo.add(data("num_per_class", num_per_class_mem)); topo.add(data("iou_threshold", iou_threshold_mem)); topo.add(data("score_threshold", score_threshold_mem)); - topo.add(non_max_suppression("nms", "boxes", "scores", 6, false, true, "num_per_class", "iou_threshold", "score_threshold")); + topo.add(non_max_suppression("nms", "boxes", "scores", + this->batch_size * this->classes_num * this->boxes_num, + false, true, "num_per_class", "iou_threshold", "score_threshold")); - build_options build_opts( - build_option::optimize_data(true) - ); - cldnn::network net(engine, topo, build_opts); + build_options bo; + bo.set_option(build_option::optimize_data(true)); + + cldnn::network net{ engine, topo, bo }; auto boxes_mem = this->get_boxes_memory(engine); auto scores_mem = this->get_scores_memory(engine); @@ -254,6 +354,12 @@ TYPED_TEST(non_max_suppression_basic, score_threshold) { 0, 0, 1, 1, 0, 1, this->pad, this->pad, this->pad, + this->pad, this->pad, this->pad, + this->pad, this->pad, this->pad, + this->pad, this->pad, this->pad, + this->pad, this->pad, this->pad, + this->pad, this->pad, this->pad, + this->pad, this->pad, this->pad }; auto out_mem = result.at("nms").get_memory(); @@ -284,12 +390,14 @@ TYPED_TEST(non_max_suppression_basic, soft_nms_sigma) { topo.add(data("iou_threshold", iou_threshold_mem)); topo.add(data("score_threshold", score_threshold_mem)); topo.add(data("soft_nms_sigma", soft_nms_sigma_mem)); - topo.add(non_max_suppression("nms", "boxes", "scores", 6, false, true, "num_per_class", "iou_threshold", "score_threshold", "soft_nms_sigma")); + topo.add(non_max_suppression("nms", "boxes", "scores", + this->batch_size * this->classes_num * this->boxes_num, + false, true, "num_per_class", "iou_threshold", "score_threshold", "soft_nms_sigma")); - build_options build_opts( - build_option::optimize_data(true) - ); - cldnn::network net(engine, topo, build_opts); + build_options bo; + bo.set_option(build_option::optimize_data(true)); + + cldnn::network net{ engine, topo, bo }; auto boxes_mem = this->get_boxes_memory(engine); auto scores_mem = this->get_scores_memory(engine); @@ -305,6 +413,12 @@ TYPED_TEST(non_max_suppression_basic, soft_nms_sigma) { 1, 0, 2, 0, 0, 1, 1, 0, 1, + this->pad, this->pad, this->pad, + this->pad, this->pad, this->pad, + this->pad, this->pad, this->pad, + this->pad, this->pad, this->pad, + this->pad, this->pad, this->pad, + this->pad, this->pad, this->pad, this->pad, this->pad, this->pad }; From fc32769175be12bcdf1c5ef677327072c0ebfb27 Mon Sep 17 00:00:00 2001 From: Ilya Churaev Date: Wed, 25 Aug 2021 10:08:16 +0300 Subject: [PATCH 29/76] Moved Input/Output/Tensor descriptors to ov (#7219) * Moved Input/Output/Tensor descriptors to ov * Fixed build --- .../core/include/ngraph/descriptor/input.hpp | 110 +-------------- .../core/include/ngraph/descriptor/output.hpp | 55 +------- .../core/include/ngraph/descriptor/tensor.hpp | 83 +----------- ngraph/core/include/ngraph/graph_util.hpp | 4 - .../openvino/core/descriptor/input.hpp | 128 ++++++++++++++++++ .../openvino/core/descriptor/output.hpp | 84 ++++++++++++ .../openvino/core/descriptor/tensor.hpp | 108 +++++++++++++++ ngraph/core/src/descriptor/input.cpp | 43 +++--- ngraph/core/src/descriptor/output.cpp | 23 ++-- ngraph/core/src/descriptor/tensor.cpp | 41 +++--- 10 files changed, 377 insertions(+), 302 deletions(-) create mode 100644 ngraph/core/include/openvino/core/descriptor/input.hpp create mode 100644 ngraph/core/include/openvino/core/descriptor/output.hpp create mode 100644 ngraph/core/include/openvino/core/descriptor/tensor.hpp diff --git a/ngraph/core/include/ngraph/descriptor/input.hpp b/ngraph/core/include/ngraph/descriptor/input.hpp index 876bccc50ec..babcd06e84e 100644 --- a/ngraph/core/include/ngraph/descriptor/input.hpp +++ b/ngraph/core/include/ngraph/descriptor/input.hpp @@ -9,120 +9,14 @@ #include "ngraph/descriptor/tensor.hpp" #include "ngraph/variant.hpp" +#include "openvino/core/descriptor/input.hpp" namespace ngraph { class Node; namespace descriptor { -class Output; // Describes a tensor that is an input to an op, directly or indirectly via a tuple -class NGRAPH_API Input { - friend class ngraph::Node; - -public: - /// \param node The node that owns this input - /// \param index The position of this this tensor in all input tensors - /// \param output The output that supplies a value for this input - Input(Node* node, size_t index, Output& output); - /// \brief Create an Input that is not connected to an output - /// \param node The node that owns this input - /// \param index The position of this this tensor in all input tensors - Input(Node* node, size_t index); - ~Input(); - - /// \return the node that this is an input of - std::shared_ptr get_node() const; - - /// \return the raw pointer to the node that this is an input of - Node* get_raw_pointer_node() const { - return m_node; - } - /// \return the position within all supplied tensors of this input - size_t get_index() const { - return m_index; - } - /// \return the connected output - const Output& get_output() const { - return *m_output; - } - /// \return the connected output - Output& get_output() { - return *m_output; - } - /// \return true if an output is connected to the input. - bool has_output() const { - return m_output != nullptr; - } - /// \return the tensor of the connected output - const Tensor& get_tensor() const; - - /// \return the tensor of the connected output - Tensor& get_tensor(); - - RTMap& get_rt_info() { - return m_rt_info; - } - const RTMap& get_rt_info() const { - return m_rt_info; - } - - /// \brief Replace the current output that supplies a value for this input with output i - /// of node - void replace_output(std::shared_ptr node, size_t i); - /// \brief Replace the current output that supplies a value for this input with output - void replace_output(Output& output); - /// \brief Remove the output from this input. The node will not be valid until another - /// output is supplied. - void remove_output(); - - /// \return true if the value of this input is relevant to the output shapes of the - /// corresponding node. (Usually this is false.) - /// - /// See Node::set_input_is_relevant_to_shape for more details. - bool get_is_relevant_to_shape() const { - return m_is_relevant_to_shape; - } - /// \return true if the value of this input is relevant to the output value of the - /// corresponding node. (Usually this is true.) - /// - /// See Node::set_input_is_relevant_to_value for more details. - bool get_is_relevant_to_value() const { - return m_is_relevant_to_value; - } - -protected: - /// \return the tensor for the connected output - std::shared_ptr get_tensor_ptr() const; - - /// \return the tensor for the connected output - std::shared_ptr get_tensor_ptr(); - -public: - /// \return the shape of the connected output - const Shape& get_shape() const; - - /// \return the partial shape of the connected output - const PartialShape& get_partial_shape() const; - - /// \return the element type of the connected output - const element::Type& get_element_type() const; - - Input(const Input&) = default; - Input(Input&&) = default; - Input& operator=(const Input&) = default; - -protected: - // owner of an argument node (in lieu of m_arguments) - std::shared_ptr m_src_node; - Node* m_node; // The node we are an input for - size_t m_index; // Index into all input tensors - Output* m_output; - RTMap m_rt_info; - -private: - bool m_is_relevant_to_shape; - bool m_is_relevant_to_value; -}; +using ov::descriptor::Input; } // namespace descriptor } // namespace ngraph diff --git a/ngraph/core/include/ngraph/descriptor/output.hpp b/ngraph/core/include/ngraph/descriptor/output.hpp index 45321e7fa1f..d4b8bda4394 100644 --- a/ngraph/core/include/ngraph/descriptor/output.hpp +++ b/ngraph/core/include/ngraph/descriptor/output.hpp @@ -14,6 +14,7 @@ #include "ngraph/descriptor/tensor.hpp" #include "ngraph/node_output.hpp" #include "ngraph/variant.hpp" +#include "openvino/core/descriptor/output.hpp" namespace ngraph { // The forward declaration of Node is needed here because Node has a deque of @@ -25,58 +26,6 @@ class Node; namespace descriptor { // Describes an output tensor of an op -class NGRAPH_API Output { -public: - Output() : m_node(nullptr), m_index(0), m_tensor(nullptr), m_inputs() {} - - /// \param node Node that owns this output. - /// \param index Position of the output tensor in all output tensors - /// \param tensor The tensor where the value will be written - Output(Node* node, size_t index, const std::shared_ptr& tensor); - - std::shared_ptr get_node() const; - size_t get_index() const { - return m_index; - } - ngraph::Output get_output() const; - std::shared_ptr get_tensor_ptr() const { - return m_tensor; - } - void set_tensor_ptr(const std::shared_ptr& tensor) { - m_tensor = tensor; - } - void add_input(Input* input); - void remove_input(Input* input); - const std::vector& get_inputs() const { - return m_inputs; - } - Tensor& get_tensor() const; - - RTMap& get_rt_info() { - return m_rt_info; - } - const RTMap& get_rt_info() const { - return m_rt_info; - } - /// \return the shape of the output - const Shape& get_shape() const; - - /// \return the partial shape of the output - const PartialShape& get_partial_shape() const; - - /// \return the element type of the output - const element::Type& get_element_type() const; - - Output(const Output&) = default; - Output(Output&&) = default; - Output& operator=(const Output&) = default; - -protected: - Node* m_node; - size_t m_index; - std::shared_ptr m_tensor; - RTMap m_rt_info; - std::vector m_inputs; -}; +using ov::descriptor::Output; } // namespace descriptor } // namespace ngraph diff --git a/ngraph/core/include/ngraph/descriptor/tensor.hpp b/ngraph/core/include/ngraph/descriptor/tensor.hpp index fdbbcc2427f..0da1e720a60 100644 --- a/ngraph/core/include/ngraph/descriptor/tensor.hpp +++ b/ngraph/core/include/ngraph/descriptor/tensor.hpp @@ -13,90 +13,11 @@ #include "ngraph/partial_shape.hpp" #include "ngraph/shape.hpp" #include "ngraph/type/element_type.hpp" +#include "openvino/core/descriptor/tensor.hpp" namespace ngraph { -class Node; - -namespace runtime { -class HostTensor; -} -using HostTensorPtr = std::shared_ptr; namespace descriptor { /// \brief Compile-time descriptor of a first-class value that is a tensor. -class NGRAPH_API Tensor { - Tensor(const Tensor&) = delete; - Tensor& operator=(const Tensor&) = delete; - -public: - Tensor(const element::Type& element_type, const PartialShape& pshape, const std::string& name); - Tensor(const element::Type& element_type, const PartialShape& pshape, Node* node, size_t node_output_number); - - NGRAPH_DEPRECATED("get_name() is deprecated! Please use get_names() instead.") - const std::string& get_name() const; - NGRAPH_DEPRECATED("set_name() is deprecated! Please use set_names() instead.") - void set_name(const std::string& name); - - const std::unordered_set& get_names() const; - void set_names(const std::unordered_set& names); - void add_names(const std::unordered_set& names); - void set_tensor_type(const element::Type& element_type, const PartialShape& pshape); - void set_element_type(const element::Type& elemenet_type); - void set_partial_shape(const PartialShape& partial_shape); - - /// \brief sets lower bound value description - void set_lower_value(const HostTensorPtr& value); - /// \brief sets upper bound value description - void set_upper_value(const HostTensorPtr& value); - /// \brief unsets bound value descriptions - void invalidate_values(); - - const element::Type& get_element_type() const { - return m_element_type; - } - const Shape& get_shape() const; - const PartialShape& get_partial_shape() const { - return m_partial_shape; - } - /// \brief gets lower bound value description - HostTensorPtr get_lower_value() const { - return m_lower_value; - } - /// \brief gets upper bound value description - HostTensorPtr get_upper_value() const { - return m_upper_value; - } - /// \brief checks if lower and upper bound are set and point to the same HostTensor - bool has_and_set_bound() const { - return m_upper_value != nullptr && m_upper_value == m_lower_value; - } - size_t size() const; - -protected: - element::Type m_element_type; - - // TODO: remove along with get_shape - // Initially there was ngraph::Shape m_shape only available to keep shape information. - // Support for dynamic shapes required transition to ngraph::PartialShape. - // To smoothly transition to ngraph::PartialShape we introduced m_partial_shape - // and kept m_shape in sync with m_partial_shape. Synchronization point was placed - // in set_partial_shape which dramatically affected performance of ngraph::Function - // validation. Since we have started the transition to ngraph::PartialShape and reduced - // ngraph::Shape usage the only user of m_shape was get_shape method with signature: - // const Shape& descriptor::Tensor::get_shape() const - // It was decided to move m_shape and m_partial_shape synchronization point there and - // to keep methods signature backward compatible. - mutable std::mutex shape_mutex; - mutable std::atomic_bool m_shape_changed; - mutable Shape m_shape; - // TODO: end - - PartialShape m_partial_shape; - HostTensorPtr m_lower_value, m_upper_value; - std::string m_name; - std::unordered_set m_names; -}; - -NGRAPH_API -std::ostream& operator<<(std::ostream&, const ngraph::descriptor::Tensor&); +using ov::descriptor::Tensor; } // namespace descriptor } // namespace ngraph diff --git a/ngraph/core/include/ngraph/graph_util.hpp b/ngraph/core/include/ngraph/graph_util.hpp index f017172ca51..c2318f1ed04 100644 --- a/ngraph/core/include/ngraph/graph_util.hpp +++ b/ngraph/core/include/ngraph/graph_util.hpp @@ -19,10 +19,6 @@ #include "ngraph/node.hpp" namespace ngraph { -namespace descriptor { -class Input; -class Output; -} // namespace descriptor namespace op { namespace v0 { diff --git a/ngraph/core/include/openvino/core/descriptor/input.hpp b/ngraph/core/include/openvino/core/descriptor/input.hpp new file mode 100644 index 00000000000..18a126d042c --- /dev/null +++ b/ngraph/core/include/openvino/core/descriptor/input.hpp @@ -0,0 +1,128 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +#include +#include + +#include "openvino/core/descriptor/tensor.hpp" +#include "openvino/core/variant.hpp" + +namespace ngraph { +class Node; +} + +namespace ov { +namespace descriptor { +class Output; + +// Describes a tensor that is an input to an op, directly or indirectly via a tuple +class NGRAPH_API Input { + friend class ngraph::Node; + +public: + /// \param node The node that owns this input + /// \param index The position of this this tensor in all input tensors + /// \param output The output that supplies a value for this input + Input(ngraph::Node* node, size_t index, Output& output); + /// \brief Create an Input that is not connected to an output + /// \param node The node that owns this input + /// \param index The position of this this tensor in all input tensors + Input(ngraph::Node* node, size_t index); + ~Input(); + + /// \return the node that this is an input of + std::shared_ptr get_node() const; + + /// \return the raw pointer to the node that this is an input of + ngraph::Node* get_raw_pointer_node() const { + return m_node; + } + /// \return the position within all supplied tensors of this input + size_t get_index() const { + return m_index; + } + /// \return the connected output + const Output& get_output() const { + return *m_output; + } + /// \return the connected output + Output& get_output() { + return *m_output; + } + /// \return true if an output is connected to the input. + bool has_output() const { + return m_output != nullptr; + } + /// \return the tensor of the connected output + const Tensor& get_tensor() const; + + /// \return the tensor of the connected output + Tensor& get_tensor(); + + RTMap& get_rt_info() { + return m_rt_info; + } + const RTMap& get_rt_info() const { + return m_rt_info; + } + + /// \brief Replace the current output that supplies a value for this input with output i + /// of node + void replace_output(const std::shared_ptr& node, size_t i); + /// \brief Replace the current output that supplies a value for this input with output + void replace_output(Output& output); + /// \brief Remove the output from this input. The node will not be valid until another + /// output is supplied. + void remove_output(); + + /// \return true if the value of this input is relevant to the output shapes of the + /// corresponding node. (Usually this is false.) + /// + /// See Node::set_input_is_relevant_to_shape for more details. + bool get_is_relevant_to_shape() const { + return m_is_relevant_to_shape; + } + /// \return true if the value of this input is relevant to the output value of the + /// corresponding node. (Usually this is true.) + /// + /// See Node::set_input_is_relevant_to_value for more details. + bool get_is_relevant_to_value() const { + return m_is_relevant_to_value; + } + + /// \return the shape of the connected output + const ngraph::Shape& get_shape() const; + + /// \return the partial shape of the connected output + const PartialShape& get_partial_shape() const; + + /// \return the element type of the connected output + const element::Type& get_element_type() const; + + Input(const Input&) = default; + Input(Input&&) = default; + Input& operator=(const Input&) = default; + +protected: + /// \return the tensor for the connected output + std::shared_ptr get_tensor_ptr() const; + + /// \return the tensor for the connected output + std::shared_ptr get_tensor_ptr(); + + // owner of an argument node (in lieu of m_arguments) + std::shared_ptr m_src_node; + ngraph::Node* m_node; // The node we are an input for + size_t m_index; // Index into all input tensors + Output* m_output; + RTMap m_rt_info; + +private: + bool m_is_relevant_to_shape; + bool m_is_relevant_to_value; +}; +} // namespace descriptor +} // namespace ov diff --git a/ngraph/core/include/openvino/core/descriptor/output.hpp b/ngraph/core/include/openvino/core/descriptor/output.hpp new file mode 100644 index 00000000000..46ea1fd5269 --- /dev/null +++ b/ngraph/core/include/openvino/core/descriptor/output.hpp @@ -0,0 +1,84 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +#include +#include +#include +#include +#include + +#include "ngraph/node_output.hpp" +#include "openvino/core/descriptor/input.hpp" +#include "openvino/core/descriptor/tensor.hpp" +#include "openvino/core/variant.hpp" + +namespace ngraph { +// The forward declaration of Node is needed here because Node has a deque of +// Outputs, and Output is an incomplete type at this point. STL containers of +// incomplete type have undefined behavior according to the C++11 standard, and +// in practice including node.hpp here was causing compilation errors on some +// systems (namely macOS). +class Node; +} // namespace ngraph + +namespace ov { +namespace descriptor { +// Describes an output tensor of an op +class NGRAPH_API Output { +public: + Output() : m_node(nullptr), m_index(0), m_tensor(nullptr), m_inputs() {} + + /// \param node Node that owns this output. + /// \param index Position of the output tensor in all output tensors + /// \param tensor The tensor where the value will be written + Output(ngraph::Node* node, size_t index, const std::shared_ptr& tensor); + + std::shared_ptr get_node() const; + size_t get_index() const { + return m_index; + } + ngraph::Output get_output() const; + std::shared_ptr get_tensor_ptr() const { + return m_tensor; + } + void set_tensor_ptr(const std::shared_ptr& tensor) { + m_tensor = tensor; + } + void add_input(Input* input); + void remove_input(Input* input); + const std::vector& get_inputs() const { + return m_inputs; + } + Tensor& get_tensor() const; + + RTMap& get_rt_info() { + return m_rt_info; + } + const RTMap& get_rt_info() const { + return m_rt_info; + } + /// \return the shape of the output + const ngraph::Shape& get_shape() const; + + /// \return the partial shape of the output + const PartialShape& get_partial_shape() const; + + /// \return the element type of the output + const element::Type& get_element_type() const; + + Output(const Output&) = default; + Output(Output&&) = default; + Output& operator=(const Output&) = default; + +protected: + ngraph::Node* m_node; + size_t m_index; + std::shared_ptr m_tensor; + RTMap m_rt_info; + std::vector m_inputs; +}; +} // namespace descriptor +} // namespace ov diff --git a/ngraph/core/include/openvino/core/descriptor/tensor.hpp b/ngraph/core/include/openvino/core/descriptor/tensor.hpp new file mode 100644 index 00000000000..b3db6901d5e --- /dev/null +++ b/ngraph/core/include/openvino/core/descriptor/tensor.hpp @@ -0,0 +1,108 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +#include +#include +#include +#include +#include + +#include "ngraph/shape.hpp" +#include "openvino/core/partial_shape.hpp" +#include "openvino/core/type/element_type.hpp" + +namespace ngraph { +class Node; + +namespace runtime { +class HostTensor; +} +using HostTensorPtr = std::shared_ptr; + +} // namespace ngraph +namespace ov { +namespace descriptor { +/// \brief Compile-time descriptor of a first-class value that is a tensor. +class NGRAPH_API Tensor { +public: + Tensor(const element::Type& element_type, const PartialShape& pshape, const std::string& name); + Tensor(const element::Type& element_type, + const PartialShape& pshape, + ngraph::Node* node, + size_t node_output_number); + + Tensor(const Tensor&) = delete; + Tensor& operator=(const Tensor&) = delete; + + NGRAPH_DEPRECATED("get_name() is deprecated! Please use get_names() instead.") + const std::string& get_name() const; + NGRAPH_DEPRECATED("set_name() is deprecated! Please use set_names() instead.") + void set_name(const std::string& name); + + const std::unordered_set& get_names() const; + void set_names(const std::unordered_set& names); + void add_names(const std::unordered_set& names); + void set_tensor_type(const element::Type& element_type, const PartialShape& pshape); + void set_element_type(const element::Type& elemenet_type); + void set_partial_shape(const PartialShape& partial_shape); + + /// \brief sets lower bound value description + void set_lower_value(const ngraph::HostTensorPtr& value); + /// \brief sets upper bound value description + void set_upper_value(const ngraph::HostTensorPtr& value); + /// \brief unsets bound value descriptions + void invalidate_values(); + + const element::Type& get_element_type() const { + return m_element_type; + } + const ngraph::Shape& get_shape() const; + const PartialShape& get_partial_shape() const { + return m_partial_shape; + } + /// \brief gets lower bound value description + ngraph::HostTensorPtr get_lower_value() const { + return m_lower_value; + } + /// \brief gets upper bound value description + ngraph::HostTensorPtr get_upper_value() const { + return m_upper_value; + } + /// \brief checks if lower and upper bound are set and point to the same HostTensor + bool has_and_set_bound() const { + return m_upper_value != nullptr && m_upper_value == m_lower_value; + } + size_t size() const; + +protected: + element::Type m_element_type; + + // TODO: remove along with get_shape + // Initially there was ngraph::Shape m_shape only available to keep shape information. + // Support for dynamic shapes required transition to ngraph::PartialShape. + // To smoothly transition to ngraph::PartialShape we introduced m_partial_shape + // and kept m_shape in sync with m_partial_shape. Synchronization point was placed + // in set_partial_shape which dramatically affected performance of ngraph::Function + // validation. Since we have started the transition to ngraph::PartialShape and reduced + // ngraph::Shape usage the only user of m_shape was get_shape method with signature: + // const Shape& descriptor::Tensor::get_shape() const + // It was decided to move m_shape and m_partial_shape synchronization point there and + // to keep methods signature backward compatible. + mutable std::mutex shape_mutex; + mutable std::atomic_bool m_shape_changed; + mutable ngraph::Shape m_shape; + // TODO: end + + PartialShape m_partial_shape; + ngraph::HostTensorPtr m_lower_value, m_upper_value; + std::string m_name; + std::unordered_set m_names; +}; + +NGRAPH_API +std::ostream& operator<<(std::ostream&, const ov::descriptor::Tensor&); +} // namespace descriptor +} // namespace ov diff --git a/ngraph/core/src/descriptor/input.cpp b/ngraph/core/src/descriptor/input.cpp index d2cb673265f..1e08d473493 100644 --- a/ngraph/core/src/descriptor/input.cpp +++ b/ngraph/core/src/descriptor/input.cpp @@ -2,46 +2,43 @@ // SPDX-License-Identifier: Apache-2.0 // -#include "ngraph/descriptor/input.hpp" +#include "openvino/core/descriptor/input.hpp" -#include "ngraph/descriptor/output.hpp" #include "ngraph/env_util.hpp" #include "ngraph/node.hpp" -#include "ngraph/type/element_type.hpp" +#include "openvino/core/descriptor/output.hpp" +#include "openvino/core/type/element_type.hpp" -using namespace ngraph; -using namespace descriptor; - -descriptor::Input::Input(Node* node, size_t index, Output& output) +ov::descriptor::Input::Input(ngraph::Node* node, size_t index, Output& output) : m_node(node), m_index(index), m_output(&output), m_is_relevant_to_shape(false), m_is_relevant_to_value(true) { - m_src_node = std::shared_ptr(output.get_node()); + m_src_node = std::shared_ptr(output.get_node()); output.add_input(this); } -descriptor::Input::Input(Node* node, size_t index) +ov::descriptor::Input::Input(ngraph::Node* node, size_t index) : m_node(node), m_index(index), m_output(nullptr), m_is_relevant_to_shape(false), m_is_relevant_to_value(true) {} -descriptor::Input::~Input() { +ov::descriptor::Input::~Input() { remove_output(); } -void descriptor::Input::replace_output(Output& new_output) { +void ov::descriptor::Input::replace_output(Output& new_output) { if (m_output != nullptr) { m_output->remove_input(this); } new_output.add_input(this); m_output = &new_output; - m_src_node = std::shared_ptr(new_output.get_node()); + m_src_node = std::shared_ptr(new_output.get_node()); - if (getenv_bool("NGRAPH_ENABLE_REPLACE_CHECK")) { + if (ngraph::getenv_bool("NGRAPH_ENABLE_REPLACE_CHECK")) { // the result of clone_with_new_inputs will be thrown away or // an exception will be thrown by `m_node`'s class c-tor // if a new input violates one of the type checks in the c-tor. @@ -49,11 +46,11 @@ void descriptor::Input::replace_output(Output& new_output) { } } -void descriptor::Input::replace_output(std::shared_ptr node, size_t i) { +void ov::descriptor::Input::replace_output(const std::shared_ptr& node, size_t i) { replace_output(node->m_outputs.at(i)); } -void descriptor::Input::remove_output() { +void ov::descriptor::Input::remove_output() { if (m_output != nullptr) { m_output->remove_input(this); m_src_node = nullptr; @@ -61,34 +58,34 @@ void descriptor::Input::remove_output() { } } -std::shared_ptr descriptor::Input::get_node() const { +std::shared_ptr ov::descriptor::Input::get_node() const { return m_node->shared_from_this(); } -const Tensor& descriptor::Input::get_tensor() const { +const ov::descriptor::Tensor& ov::descriptor::Input::get_tensor() const { return m_output->get_tensor(); } -Tensor& descriptor::Input::get_tensor() { +ov::descriptor::Tensor& ov::descriptor::Input::get_tensor() { return m_output->get_tensor(); } -std::shared_ptr descriptor::Input::get_tensor_ptr() const { +std::shared_ptr ov::descriptor::Input::get_tensor_ptr() const { return m_output->get_tensor_ptr(); } -std::shared_ptr descriptor::Input::get_tensor_ptr() { +std::shared_ptr ov::descriptor::Input::get_tensor_ptr() { return m_output->get_tensor_ptr(); } -const Shape& descriptor::Input::get_shape() const { +const ngraph::Shape& ov::descriptor::Input::get_shape() const { return m_output->get_shape(); } -const PartialShape& descriptor::Input::get_partial_shape() const { +const ov::PartialShape& ov::descriptor::Input::get_partial_shape() const { return m_output->get_partial_shape(); } -const element::Type& descriptor::Input::get_element_type() const { +const ov::element::Type& ov::descriptor::Input::get_element_type() const { return m_output->get_element_type(); } diff --git a/ngraph/core/src/descriptor/output.cpp b/ngraph/core/src/descriptor/output.cpp index 566ff85e2bc..c90885bc5df 100644 --- a/ngraph/core/src/descriptor/output.cpp +++ b/ngraph/core/src/descriptor/output.cpp @@ -2,56 +2,55 @@ // SPDX-License-Identifier: Apache-2.0 // -#include "ngraph/descriptor/output.hpp" +#include "openvino/core/descriptor/output.hpp" #include -#include "ngraph/descriptor/input.hpp" #include "ngraph/node.hpp" +#include "openvino/core/descriptor/input.hpp" using namespace std; -using namespace ngraph; -descriptor::Output::Output(Node* node, size_t index, const shared_ptr& tensor) +ov::descriptor::Output::Output(ngraph::Node* node, size_t index, const shared_ptr& tensor) : m_node(node), m_index(index), m_tensor(tensor) {} // Add an input to the vector of inputs that use this output. -void descriptor::Output::add_input(Input* input) { +void ov::descriptor::Output::add_input(Input* input) { // Keep the inputs in insertion order to keep sorts deterministic if (find(m_inputs.begin(), m_inputs.end(), input) == m_inputs.end()) { m_inputs.push_back(input); } } -void descriptor::Output::remove_input(Input* input) { +void ov::descriptor::Output::remove_input(Input* input) { auto it = find(m_inputs.begin(), m_inputs.end(), input); if (it != m_inputs.end()) { m_inputs.erase(it); } } -shared_ptr descriptor::Output::get_node() const { +shared_ptr ov::descriptor::Output::get_node() const { return m_node->shared_from_this(); } -ngraph::Output descriptor::Output::get_output() const { +ngraph::Output ov::descriptor::Output::get_output() const { return get_node()->output(m_index); } -descriptor::Tensor& descriptor::Output::get_tensor() const { +ov::descriptor::Tensor& ov::descriptor::Output::get_tensor() const { return *m_tensor; } -const Shape& descriptor::Output::get_shape() const { +const ngraph::Shape& ov::descriptor::Output::get_shape() const { return m_tensor->get_shape(); } -const PartialShape& descriptor::Output::get_partial_shape() const { +const ov::PartialShape& ov::descriptor::Output::get_partial_shape() const { return m_tensor->get_partial_shape(); } -const element::Type& descriptor::Output::get_element_type() const { +const ov::element::Type& ov::descriptor::Output::get_element_type() const { return m_tensor->get_element_type(); } diff --git a/ngraph/core/src/descriptor/tensor.cpp b/ngraph/core/src/descriptor/tensor.cpp index 1ae1aeb635b..2abc343a2b9 100644 --- a/ngraph/core/src/descriptor/tensor.cpp +++ b/ngraph/core/src/descriptor/tensor.cpp @@ -2,61 +2,60 @@ // SPDX-License-Identifier: Apache-2.0 // -#include "ngraph/descriptor/tensor.hpp" +#include "openvino/core/descriptor/tensor.hpp" #include "ngraph/node.hpp" -using namespace ngraph; using namespace std; -descriptor::Tensor::Tensor(const element::Type& element_type, const PartialShape& pshape, const std::string& name) +ov::descriptor::Tensor::Tensor(const element::Type& element_type, const PartialShape& pshape, const std::string& name) : m_element_type(element_type), m_partial_shape(pshape), m_name(name), m_shape_changed(true) {} -descriptor::Tensor::Tensor(const element::Type& element_type, - const PartialShape& pshape, - Node* node, - size_t node_output_number) +ov::descriptor::Tensor::Tensor(const element::Type& element_type, + const PartialShape& pshape, + ngraph::Node* node, + size_t node_output_number) : m_element_type(element_type), m_partial_shape(pshape), m_shape_changed(true) {} -void descriptor::Tensor::set_tensor_type(const element::Type& element_type, const PartialShape& pshape) { +void ov::descriptor::Tensor::set_tensor_type(const element::Type& element_type, const PartialShape& pshape) { set_element_type(element_type); set_partial_shape(pshape); } -void descriptor::Tensor::set_element_type(const element::Type& element_type) { +void ov::descriptor::Tensor::set_element_type(const element::Type& element_type) { m_element_type = element_type; } -void descriptor::Tensor::set_partial_shape(const PartialShape& partial_shape) { +void ov::descriptor::Tensor::set_partial_shape(const PartialShape& partial_shape) { m_partial_shape = partial_shape; m_shape_changed = true; } -void descriptor::Tensor::invalidate_values() { +void ov::descriptor::Tensor::invalidate_values() { m_upper_value = nullptr; m_lower_value = nullptr; } -void descriptor::Tensor::set_lower_value(const HostTensorPtr& value) { +void ov::descriptor::Tensor::set_lower_value(const ngraph::HostTensorPtr& value) { NGRAPH_CHECK(value != nullptr); NGRAPH_CHECK(m_partial_shape.same_scheme(value->get_partial_shape())); NGRAPH_CHECK(m_element_type == value->get_element_type()); m_lower_value = value; } -void descriptor::Tensor::set_upper_value(const HostTensorPtr& value) { +void ov::descriptor::Tensor::set_upper_value(const ngraph::HostTensorPtr& value) { NGRAPH_CHECK(value != nullptr); NGRAPH_CHECK(m_partial_shape.same_scheme(value->get_partial_shape())); NGRAPH_CHECK(m_element_type == value->get_element_type()); m_upper_value = value; } -const Shape& descriptor::Tensor::get_shape() const { +const ngraph::Shape& ov::descriptor::Tensor::get_shape() const { if (m_partial_shape.is_static()) { if (m_shape_changed.load(std::memory_order_relaxed)) { std::lock_guard guard(shape_mutex); @@ -72,7 +71,7 @@ const Shape& descriptor::Tensor::get_shape() const { } } -size_t descriptor::Tensor::size() const { +size_t ov::descriptor::Tensor::size() const { const bool bitwidth_less_than_byte = m_element_type.bitwidth() < 8; if (bitwidth_less_than_byte) { return ceil((1.0 * shape_size(get_shape()) * m_element_type.bitwidth()) / 8); @@ -81,30 +80,30 @@ size_t descriptor::Tensor::size() const { } NGRAPH_SUPPRESS_DEPRECATED_START -void descriptor::Tensor::set_name(const string& name) { +void ov::descriptor::Tensor::set_name(const string& name) { m_name = name; } -const std::string& descriptor::Tensor::get_name() const { +const std::string& ov::descriptor::Tensor::get_name() const { return m_name; } NGRAPH_SUPPRESS_DEPRECATED_END -const std::unordered_set& descriptor::Tensor::get_names() const { +const std::unordered_set& ov::descriptor::Tensor::get_names() const { return m_names; } -void descriptor::Tensor::set_names(const std::unordered_set& names) { +void ov::descriptor::Tensor::set_names(const std::unordered_set& names) { m_names = names; } -void descriptor::Tensor::add_names(const std::unordered_set& names) { +void ov::descriptor::Tensor::add_names(const std::unordered_set& names) { for (const auto& name : names) { m_names.insert(name); } } -ostream& operator<<(ostream& out, const descriptor::Tensor& tensor) { +ostream& operator<<(ostream& out, const ov::descriptor::Tensor& tensor) { std::string names; for (const auto& name : tensor.get_names()) { if (!names.empty()) From 622d177c6242fdb29fdd94b0384471bc35c3e3b9 Mon Sep 17 00:00:00 2001 From: Katarzyna Mitrus Date: Wed, 25 Aug 2021 10:06:32 +0200 Subject: [PATCH 30/76] FusedOp class removal (#7156) * Remove fused_op.hpp includes * Remove fused_op.cpp and .hpp * Remove support decompose util * Remove fused_op.in.cpp from tests CMakeLists * Remove fused_op.in.cpp * Remove supports_decompose from op_types.hpp --- .../legacy/ngraph_ops/fully_connected.hpp | 1 - .../op/fully_connected.hpp | 1 - ngraph/core/include/ngraph/op/group_conv.hpp | 1 - ngraph/core/include/ngraph/op/gru_cell.hpp | 2 +- ngraph/core/include/ngraph/op/lstm_cell.hpp | 2 +- ngraph/core/include/ngraph/op/rnn_cell.hpp | 2 +- .../include/ngraph/op/shuffle_channels.hpp | 2 +- ngraph/core/include/ngraph/op/split.hpp | 2 +- .../core/include/ngraph/op/util/fused_op.hpp | 50 --- .../core/include/ngraph/op/util/op_types.hpp | 6 - ngraph/core/src/op/util/fused_op.cpp | 44 --- ngraph/core/src/op/util/op_types.cpp | 11 - ngraph/test/CMakeLists.txt | 1 - ngraph/test/backend/fused_op.in.cpp | 322 ------------------ 14 files changed, 5 insertions(+), 442 deletions(-) delete mode 100644 ngraph/core/include/ngraph/op/util/fused_op.hpp delete mode 100644 ngraph/core/src/op/util/fused_op.cpp delete mode 100644 ngraph/test/backend/fused_op.in.cpp diff --git a/inference-engine/src/legacy_api/include/legacy/ngraph_ops/fully_connected.hpp b/inference-engine/src/legacy_api/include/legacy/ngraph_ops/fully_connected.hpp index 462654e2467..fa60a594191 100644 --- a/inference-engine/src/legacy_api/include/legacy/ngraph_ops/fully_connected.hpp +++ b/inference-engine/src/legacy_api/include/legacy/ngraph_ops/fully_connected.hpp @@ -10,7 +10,6 @@ #include "ngraph/node.hpp" #include "ngraph/op/op.hpp" -#include "ngraph/op/util/fused_op.hpp" namespace ngraph { namespace op { diff --git a/inference-engine/src/mkldnn_plugin/ngraph_transformations/op/fully_connected.hpp b/inference-engine/src/mkldnn_plugin/ngraph_transformations/op/fully_connected.hpp index 484a0a0ea3f..47c6509db58 100644 --- a/inference-engine/src/mkldnn_plugin/ngraph_transformations/op/fully_connected.hpp +++ b/inference-engine/src/mkldnn_plugin/ngraph_transformations/op/fully_connected.hpp @@ -6,7 +6,6 @@ #include #include -#include namespace MKLDNNPlugin { diff --git a/ngraph/core/include/ngraph/op/group_conv.hpp b/ngraph/core/include/ngraph/op/group_conv.hpp index eba95d59a2c..42d79149c87 100644 --- a/ngraph/core/include/ngraph/op/group_conv.hpp +++ b/ngraph/core/include/ngraph/op/group_conv.hpp @@ -7,7 +7,6 @@ #include "ngraph/op/convolution.hpp" #include "ngraph/op/op.hpp" #include "ngraph/op/util/attr_types.hpp" -#include "ngraph/op/util/fused_op.hpp" namespace ngraph { namespace op { diff --git a/ngraph/core/include/ngraph/op/gru_cell.hpp b/ngraph/core/include/ngraph/op/gru_cell.hpp index 6cb4c680d0f..3fa8e4d6c40 100644 --- a/ngraph/core/include/ngraph/op/gru_cell.hpp +++ b/ngraph/core/include/ngraph/op/gru_cell.hpp @@ -10,8 +10,8 @@ #include #include "ngraph/node.hpp" +#include "ngraph/op/op.hpp" #include "ngraph/op/util/activation_functions.hpp" -#include "ngraph/op/util/fused_op.hpp" #include "ngraph/op/util/rnn_cell_base.hpp" namespace ngraph { diff --git a/ngraph/core/include/ngraph/op/lstm_cell.hpp b/ngraph/core/include/ngraph/op/lstm_cell.hpp index b6d9a4f16de..17c81965e37 100644 --- a/ngraph/core/include/ngraph/op/lstm_cell.hpp +++ b/ngraph/core/include/ngraph/op/lstm_cell.hpp @@ -10,8 +10,8 @@ #include #include "ngraph/node.hpp" +#include "ngraph/op/op.hpp" #include "ngraph/op/util/activation_functions.hpp" -#include "ngraph/op/util/fused_op.hpp" #include "ngraph/op/util/rnn_cell_base.hpp" namespace ngraph { diff --git a/ngraph/core/include/ngraph/op/rnn_cell.hpp b/ngraph/core/include/ngraph/op/rnn_cell.hpp index 24752579270..4a1dbad316b 100644 --- a/ngraph/core/include/ngraph/op/rnn_cell.hpp +++ b/ngraph/core/include/ngraph/op/rnn_cell.hpp @@ -10,8 +10,8 @@ #include #include "ngraph/node.hpp" +#include "ngraph/op/op.hpp" #include "ngraph/op/util/activation_functions.hpp" -#include "ngraph/op/util/fused_op.hpp" #include "ngraph/op/util/rnn_cell_base.hpp" namespace ngraph { diff --git a/ngraph/core/include/ngraph/op/shuffle_channels.hpp b/ngraph/core/include/ngraph/op/shuffle_channels.hpp index 36dcc08f041..f72ba64b45c 100644 --- a/ngraph/core/include/ngraph/op/shuffle_channels.hpp +++ b/ngraph/core/include/ngraph/op/shuffle_channels.hpp @@ -7,7 +7,7 @@ #include #include "ngraph/node.hpp" -#include "ngraph/op/util/fused_op.hpp" +#include "ngraph/op/op.hpp" namespace ngraph { namespace op { diff --git a/ngraph/core/include/ngraph/op/split.hpp b/ngraph/core/include/ngraph/op/split.hpp index b612a3f1f1d..fa3023697d2 100644 --- a/ngraph/core/include/ngraph/op/split.hpp +++ b/ngraph/core/include/ngraph/op/split.hpp @@ -8,7 +8,7 @@ #include #include "ngraph/node.hpp" -#include "ngraph/op/util/fused_op.hpp" +#include "ngraph/op/op.hpp" namespace ngraph { namespace op { diff --git a/ngraph/core/include/ngraph/op/util/fused_op.hpp b/ngraph/core/include/ngraph/op/util/fused_op.hpp deleted file mode 100644 index 8ec008d4c95..00000000000 --- a/ngraph/core/include/ngraph/op/util/fused_op.hpp +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright (C) 2018-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#pragma once - -#include "ngraph/op/op.hpp" - -namespace ngraph { -namespace op { -namespace util { -/// \brief Abstract base class for fused ops, i.e ops that can be broken down into core -/// ngraph ops -/// -class NGRAPH_DEPRECATED("FusedOp approach was deprecated! " - "Please use inheritance from usual Op instead of FusedOp") NGRAPH_API FusedOp : public Op { -public: - NGRAPH_RTTI_DECLARATION; - - // Fused op decomposition can be performed in the presence of - // partial shapes - virtual bool can_decompose_with_partial_shapes() { - return false; - } - // Shape inference that will use fused op decomposition to infer - // shapes and types of output elements. Ops can choose to override - // and provide a more direct implementation. - void validate_and_infer_types() override; - - // Pre-validation hook that will be invoked before op - // decomposition in validate_and_infer_types(). - // Can be used for attribute validation and setting types/shapes - // that can be inferred without requiring op decomposition. - // Can also be used to set shape specialization hints - // (set_input_is_relevant_to_shape()) - virtual void pre_validate_and_infer_types() {} - // Post-validation hook that will be invoked after op decomposition - // in validate_and_infer_types(). - virtual void post_validate_and_infer_types() {} - -protected: - FusedOp(); - - /// \brief Constructs a FusedOp - /// - FusedOp(const OutputVector& args); -}; -} // namespace util -} // namespace op -} // namespace ngraph diff --git a/ngraph/core/include/ngraph/op/util/op_types.hpp b/ngraph/core/include/ngraph/op/util/op_types.hpp index 44370988203..5c875830025 100644 --- a/ngraph/core/include/ngraph/op/util/op_types.hpp +++ b/ngraph/core/include/ngraph/op/util/op_types.hpp @@ -23,9 +23,6 @@ bool is_binary_elementwise_logical(const ngraph::Node* node); NGRAPH_API bool supports_auto_broadcast(const ngraph::Node* node); -NGRAPH_API -bool supports_decompose(const ngraph::Node* node); - NGRAPH_API bool is_op(const ngraph::Node* node); NGRAPH_API @@ -51,9 +48,6 @@ bool is_binary_elementwise_logical(const std::shared_ptr& node); NGRAPH_API bool supports_auto_broadcast(const std::shared_ptr& node); -NGRAPH_API -bool supports_decompose(const std::shared_ptr& node); - NGRAPH_API bool is_op(const std::shared_ptr& node); NGRAPH_API diff --git a/ngraph/core/src/op/util/fused_op.cpp b/ngraph/core/src/op/util/fused_op.cpp deleted file mode 100644 index 60e94575cae..00000000000 --- a/ngraph/core/src/op/util/fused_op.cpp +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright (C) 2018-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#include "ngraph/op/util/fused_op.hpp" - -#include "itt.hpp" -#include "ngraph/graph_util.hpp" - -using namespace ngraph; - -NGRAPH_SUPPRESS_DEPRECATED_START - -NGRAPH_RTTI_DEFINITION(op::util::FusedOp, "FusedOp", 0); - -op::util::FusedOp::FusedOp() : Op() {} - -op::util::FusedOp::FusedOp(const OutputVector& args) : Op(args) {} - -void op::util::FusedOp::validate_and_infer_types() { - NGRAPH_OP_SCOPE(util_FusedOp_validate_and_infer_types); - pre_validate_and_infer_types(); - - if (!can_decompose_with_partial_shapes() && is_dynamic()) { - return; - } - - auto subgraph_outputs = decompose_op(); - NodeVector nodes; - for (auto& val : input_values()) - nodes.emplace_back(val.get_node_shared_ptr()); - auto subgraph = extract_subgraph(ngraph::as_node_vector(subgraph_outputs), nodes); - - size_t i = 0; - for (const auto& output : subgraph_outputs) { - if (i >= get_output_size()) { - set_output_size(i + 1); - } - set_output_type(i, output.get_element_type(), output.get_shape()); - i++; - } - - post_validate_and_infer_types(); -} diff --git a/ngraph/core/src/op/util/op_types.cpp b/ngraph/core/src/op/util/op_types.cpp index 1cf79822dc3..ca5813bf117 100644 --- a/ngraph/core/src/op/util/op_types.cpp +++ b/ngraph/core/src/op/util/op_types.cpp @@ -21,7 +21,6 @@ #include "ngraph/op/util/binary_elementwise_arithmetic.hpp" #include "ngraph/op/util/binary_elementwise_comparison.hpp" #include "ngraph/op/util/binary_elementwise_logical.hpp" -#include "ngraph/op/util/fused_op.hpp" #include "ngraph/op/util/unary_elementwise_arithmetic.hpp" #include "ngraph/op/xor.hpp" #include "ngraph/type.hpp" @@ -50,12 +49,6 @@ bool ngraph::op::supports_auto_broadcast(const ngraph::Node* node) { dynamic_cast(node) != nullptr; } -bool ngraph::op::supports_decompose(const ngraph::Node* node) { - NGRAPH_SUPPRESS_DEPRECATED_START - return dynamic_cast(node) != nullptr; - NGRAPH_SUPPRESS_DEPRECATED_END -} - bool ngraph::op::is_op(const ngraph::Node* node) { return dynamic_cast(node) != nullptr; } @@ -106,10 +99,6 @@ bool ngraph::op::supports_auto_broadcast(const std::shared_ptr& no return supports_auto_broadcast(node.get()); } -bool ngraph::op::supports_decompose(const std::shared_ptr& node) { - return supports_decompose(node.get()); -} - bool ngraph::op::is_op(const std::shared_ptr& node) { return is_op(node.get()); } diff --git a/ngraph/test/CMakeLists.txt b/ngraph/test/CMakeLists.txt index 20fc2a0a184..7eed6dd82b5 100644 --- a/ngraph/test/CMakeLists.txt +++ b/ngraph/test/CMakeLists.txt @@ -448,7 +448,6 @@ set(MULTI_TEST_SRC backend/floor.in.cpp backend/floor_mod.in.cpp backend/function_name.in.cpp - backend/fused_op.in.cpp backend/gather.in.cpp backend/gather_elements.in.cpp backend/gather_nd.in.cpp diff --git a/ngraph/test/backend/fused_op.in.cpp b/ngraph/test/backend/fused_op.in.cpp deleted file mode 100644 index 0110383bd64..00000000000 --- a/ngraph/test/backend/fused_op.in.cpp +++ /dev/null @@ -1,322 +0,0 @@ -// Copyright (C) 2018-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -// clang-format off -#ifdef ${BACKEND_NAME}_FLOAT_TOLERANCE_BITS -#define DEFAULT_FLOAT_TOLERANCE_BITS ${BACKEND_NAME}_FLOAT_TOLERANCE_BITS -#endif -// clang-format on - -#include "gtest/gtest.h" -#include "ngraph/check.hpp" -#include "ngraph/ngraph.hpp" -#include "ngraph/opsets/opset4.hpp" -#include "ngraph/op/util/attr_types.hpp" -#include "util/all_close.hpp" -#include "util/all_close_f.hpp" -#include "util/engine/test_engines.hpp" -#include "util/ndarray.hpp" -#include "util/random.hpp" -#include "util/test_case.hpp" -#include "util/test_control.hpp" -#include "util/test_tools.hpp" - -NGRAPH_SUPPRESS_DEPRECATED_START - -using namespace std; -using namespace ngraph; - -static string s_manifest = "${MANIFEST}"; - -using TestEngine = test::ENGINE_CLASS_NAME(${BACKEND_NAME}); - -NGRAPH_TEST(${BACKEND_NAME}, hardsigmoid) { - const Shape shape{2, 7}; - const float alpha_f = 0.125f; - const float beta_f = 0.642f; - const auto A = make_shared(element::f32, shape); - const auto alpha = op::Constant::create(A->get_element_type(), Shape{}, {alpha_f}); - const auto beta = op::Constant::create(A->get_element_type(), Shape{}, {beta_f}); - auto hardsigmoid = make_shared(A, alpha, beta); - auto f = make_shared(NodeVector{hardsigmoid}, ParameterVector{A}); - vector input{-1.f, - 0.f, - 1.f, - -100.f, - 100.f, - -3.1234567f, - 5.876543f, - 7.13245364f, - numeric_limits::max(), - numeric_limits::lowest(), - numeric_limits::min(), - numeric_limits::infinity(), - numeric_limits::min() / 16.f, - -numeric_limits::min() / 16.f}; - - // Prepare expected output data - auto impl = [alpha_f, beta_f](float val) { - return min(max(alpha_f * val + beta_f, 0.f), 1.f); - }; - vector expected_output; - transform(begin(input), end(input), back_inserter(expected_output), impl); - - auto test_case = test::TestCase(f); - test_case.add_input(input); - test_case.add_expected_output(expected_output); - test_case.run(); -} - -NGRAPH_TEST(${BACKEND_NAME}, mvn_mean_normalization) { - Shape data_shape{1, 2, 5}; - auto data = make_shared(element::f32, data_shape); - - auto mvn_func = make_shared(data, true, false); - auto function = make_shared(NodeVector{mvn_func}, ParameterVector{data}); - auto test_case = test::TestCase(function); - // data - vector data_vector(shape_size(data_shape)); - iota(begin(data_vector), end(data_vector), 0); - test_case.add_input(data_vector); - - // expected result - test_case.add_expected_output(data_shape, - vector{-4.5, -3.5, -2.5, -1.5, -0.5, 0.5, 1.5, 2.5, 3.5, 4.5}); - - test_case.run(); -} - -NGRAPH_TEST(${BACKEND_NAME}, mvn_mean_normalization_split_channels) { - Shape data_shape{1, 2, 5, 1}; - auto data = make_shared(element::f32, data_shape); - - auto mvn_func = make_shared(data, false, false); - auto function = make_shared(NodeVector{mvn_func}, ParameterVector{data}); - auto test_case = test::TestCase(function); - // data - vector data_vector(shape_size(data_shape)); - iota(begin(data_vector), end(data_vector), 0); - test_case.add_input(data_vector); - - // expected result - test_case.add_expected_output({1, 2, 5, 1}, vector{-2, -1, 0, 1, 2, -2, -1, 0, 1, 2}); - - test_case.run(); -} - -NGRAPH_TEST(${BACKEND_NAME}, mvn_mean_variance_normalization) { - Shape data_shape{1, 2, 5}; - auto data = make_shared(element::f32, data_shape); - - auto mvn_func = make_shared(data); - auto function = make_shared(NodeVector{mvn_func}, ParameterVector{data}); - auto test_case = test::TestCase(function); - // data - vector data_vector(shape_size(data_shape)); - iota(begin(data_vector), end(data_vector), 0); - test_case.add_input(data_vector); - - // expected result - test_case.add_expected_output(data_shape, - vector{-1.566698903055826, - -1.2185435912656424, - -0.87038827947545883, - -0.52223296768527527, - -0.17407765589509178, - 0.17407765589509178, - 0.52223296768527527, - 0.87038827947545883, - 1.2185435912656424, - 1.566698903055826}); - - test_case.run(); -} - -NGRAPH_TEST(${BACKEND_NAME}, mvn_mean_variance_normalization_split_channels) { - Shape data_shape{1, 2, 5}; - auto data = make_shared(element::f32, data_shape); - - auto mvn_func = make_shared(data, false); - auto function = make_shared(NodeVector{mvn_func}, ParameterVector{data}); - auto test_case = test::TestCase(function); - // data - vector data_vector(shape_size(data_shape)); - iota(begin(data_vector), end(data_vector), 0); - test_case.add_input(data_vector); - - // expected result - test_case.add_expected_output(data_shape, - vector{-1.4142135613730948, - -0.70710678068654742, - 0.000000000000000, - 0.70710678068654742, - 1.4142135613730948, - -1.4142135613730948, - -0.70710678068654742, - 0.000000000000000, - 0.70710678068654742, - 1.4142135613730948}); - - test_case.run(); -} -NGRAPH_TEST(${BACKEND_NAME}, mvn_mean_variance_normalization_shared_across_channel_batch_size_2) { - Shape data_shape{2, 2, 5}; - auto data = make_shared(element::f32, data_shape); - - auto mvn_func = make_shared(data, true); - auto function = make_shared(NodeVector{mvn_func}, ParameterVector{data}); - auto test_case = test::TestCase(function); - // data - vector data_vector(shape_size(data_shape)); - iota(begin(data_vector), end(data_vector), 0); - test_case.add_input(data_vector); - - // expected result - test_case.add_expected_output(data_shape, {-1.5666989f, -1.2185436f, -0.8703883f, -0.5222329f, -0.1740777f, - 0.1740777f, 0.5222329f, 0.8703883f, 1.2185436f, 1.5666989f, - -1.5666989f, -1.2185436f, -0.8703883f, -0.5222329f, -0.1740777f, - 0.1740777f, 0.5222329f, 0.8703883f, 1.2185436f, 1.5666989f}); - - test_case.run(); -} - -NGRAPH_TEST(${BACKEND_NAME}, mvn_mean_variance_normalization_not_shared_across_channel_batch_size_2) { - Shape data_shape{2, 2, 5}; - auto data = make_shared(element::f32, data_shape); - - auto mvn_func = make_shared(data, false); - auto function = make_shared(NodeVector{mvn_func}, ParameterVector{data}); - auto test_case = test::TestCase(function); - // data - vector data_vector(shape_size(data_shape)); - iota(begin(data_vector), end(data_vector), 0); - test_case.add_input(data_vector); - - // expected result - test_case.add_expected_output(data_shape, {-1.4142135f, -0.7071068f, 0.0000000f, 0.7071068f, 1.4142135f, - -1.4142135f, -0.7071068f, 0.0000000f, 0.7071068f, 1.4142135f, - -1.4142135f, -0.7071068f, 0.0000000f, 0.7071068f, 1.4142135f, - -1.4142135f, -0.7071068f, 0.0000000f, 0.7071068f, 1.4142135f}); - - test_case.run(); -} - -// TODO: Issue: 37534 -NGRAPH_TEST(${BACKEND_NAME}, DISABLED_squared_difference) { - const auto x1 = make_shared(element::f32, Shape{2, 2}); - const auto x2 = make_shared(element::f32, Shape{2, 2}); - - auto tested_op = make_shared(x1, x2); - auto function = make_shared(tested_op, ParameterVector{x1, x2}); - - auto test_case = test::TestCase(function); - test_case.add_input({1.0, 16.0, 0.0, 1.234567}); - test_case.add_input({1.0, 8.0, -3.0, 3.456789}); - - test_case.add_expected_output(Shape{2, 2}, {0.0, 64.0, 9.0, 4.938270617284}); - test_case.run(); -} - -NGRAPH_TEST(${BACKEND_NAME}, DISABLED_squared_difference_broadcast) { - const auto x1 = make_shared(element::i32, Shape{2, 2}); - const auto x2 = make_shared(element::i32, Shape{}); - - auto tested_op = make_shared(x1, x2); - auto function = make_shared(tested_op, ParameterVector{x1, x2}); - - auto test_case = test::TestCase(function); - test_case.add_input({1, 1, 1, 1}); - test_case.add_input({1}); - - test_case.add_expected_output(Shape{2, 2}, {0, 0, 0, 0}); - test_case.run(); -} - -NGRAPH_TEST(${BACKEND_NAME}, depth_to_space_space_to_depth_block_first) { - auto backend = runtime::Backend::create("${BACKEND_NAME}"); - Shape dts_input_shape{2, 32, 2, 4, 2, 4}; - size_t block_size = 2; - - auto dts_input = make_shared(element::f32, dts_input_shape); - auto depth_to_space = - make_shared(dts_input, op::DepthToSpace::DepthToSpaceMode::BLOCKS_FIRST, block_size); - auto dts_func = make_shared(NodeVector{depth_to_space}, ParameterVector{dts_input}); - - auto dts_input_tensor = backend->create_tensor(element::f32, dts_input_shape); - const auto data_size = shape_size(dts_input_shape); - vector data(data_size); - std::iota(data.begin(), data.end(), 0); - copy_data(dts_input_tensor, data); - const auto dts_output_shape = depth_to_space->get_output_shape(0); - auto dts_output_tensor = backend->create_tensor(element::f32, dts_output_shape); - auto handle = backend->compile(dts_func); - handle->call_with_validate({dts_output_tensor}, {dts_input_tensor}); - auto dts_result = read_vector(dts_output_tensor); - - // use depth_to_space output as space_to_depth input - auto std_input = make_shared(element::f32, dts_output_shape); - auto space_to_depth = - make_shared(std_input, op::SpaceToDepth::SpaceToDepthMode::BLOCKS_FIRST, block_size); - auto std_func = make_shared(NodeVector{space_to_depth}, ParameterVector{std_input}); - - auto std_input_tensor = backend->create_tensor(element::f32, dts_output_shape); - copy_data(std_input_tensor, dts_result); - auto std_output_tensor = backend->create_tensor(element::f32, dts_input_shape); - handle = backend->compile(std_func); - handle->call_with_validate({std_output_tensor}, {std_input_tensor}); - auto std_result = read_vector(std_output_tensor); - - // expected output of space_to_depth is input of depth_to_space - ASSERT_EQ(dts_input_shape, space_to_depth->get_output_shape(0)); - EXPECT_TRUE(test::all_close_f(std_result, data, data_size)); -} - -NGRAPH_TEST(${BACKEND_NAME}, depth_to_space_space_to_depth_depth_first) { - auto backend = runtime::Backend::create("${BACKEND_NAME}"); - Shape dts_input_shape{2, 32, 2, 4, 2, 4}; - size_t block_size = 2; - - auto dts_input = make_shared(element::f32, dts_input_shape); - auto depth_to_space = - make_shared(dts_input, op::DepthToSpace::DepthToSpaceMode::DEPTH_FIRST, block_size); - auto dts_func = make_shared(NodeVector{depth_to_space}, ParameterVector{dts_input}); - - auto dts_input_tensor = backend->create_tensor(element::f32, dts_input_shape); - const auto data_size = shape_size(dts_input_shape); - vector data(data_size); - std::iota(data.begin(), data.end(), 0); - copy_data(dts_input_tensor, data); - const auto dts_output_shape = depth_to_space->get_output_shape(0); - auto dts_output_tensor = backend->create_tensor(element::f32, dts_output_shape); - auto handle = backend->compile(dts_func); - handle->call_with_validate({dts_output_tensor}, {dts_input_tensor}); - auto dts_result = read_vector(dts_output_tensor); - - // use depth_to_space output as space_to_depth input - auto std_input = make_shared(element::f32, dts_output_shape); - auto space_to_depth = - make_shared(std_input, op::SpaceToDepth::SpaceToDepthMode::DEPTH_FIRST, block_size); - auto std_func = make_shared(NodeVector{space_to_depth}, ParameterVector{std_input}); - - auto std_input_tensor = backend->create_tensor(element::f32, dts_output_shape); - copy_data(std_input_tensor, dts_result); - auto std_output_tensor = backend->create_tensor(element::f32, dts_input_shape); - handle = backend->compile(std_func); - handle->call_with_validate({std_output_tensor}, {std_input_tensor}); - auto std_result = read_vector(std_output_tensor); - - // expected output of space_to_depth is input of depth_to_space - ASSERT_EQ(dts_input_shape, space_to_depth->get_output_shape(0)); - EXPECT_TRUE(test::all_close_f(std_result, data, data_size)); -} From ac53316f4912aedf518f23ac2764e9bd6f6aa95e Mon Sep 17 00:00:00 2001 From: Piotr Szmelczynski Date: Wed, 25 Aug 2021 10:35:58 +0200 Subject: [PATCH 31/76] Revise greater equal (#7111) * update spec * create op_reference test * add greateEqual to constants.py * add ngraph_check for number of inputs and outputs * add include * fix style * add information about broadcast in examples in spec * Remove redundant reegistration of a new test class * Remove visit_attributes method * update outputs part in Greater and GreaterEqual spec * fix typos in spec --- docs/ops/comparison/GreaterEqual_1.md | 35 ++++---- docs/ops/comparison/Greater_1.md | 2 +- .../functional/op_reference/greater_equal.cpp | 81 +++++++++++++++++++ .../layer_tests_summary/utils/constants.py | 3 +- ngraph/core/include/ngraph/op/greater_eq.hpp | 1 - ngraph/core/src/op/greater_eq.cpp | 8 +- 6 files changed, 104 insertions(+), 26 deletions(-) create mode 100644 docs/template_plugin/tests/functional/op_reference/greater_equal.cpp diff --git a/docs/ops/comparison/GreaterEqual_1.md b/docs/ops/comparison/GreaterEqual_1.md index c072a9c5923..5cc5f2d8b6a 100644 --- a/docs/ops/comparison/GreaterEqual_1.md +++ b/docs/ops/comparison/GreaterEqual_1.md @@ -4,7 +4,16 @@ **Category**: *Comparison binary* -**Short description**: *GreaterEqual* performs element-wise comparison operation with two given tensors applying multi-directional broadcast rules. +**Short description**: *GreaterEqual* performs element-wise comparison operation with two given tensors applying broadcast rules specified in the `auto_broadcast` attribute. + +**Detailed description** +Before performing arithmetic operation, input tensors *a* and *b* are broadcasted if their shapes are different and `auto_broadcast` attribute is not `none`. Broadcasting is performed according to `auto_broadcast` value. + +After broadcasting, *GreaterEqual* does the following with the input tensors *a* and *b*: + +\f[ +o_{i} = a_{i} \geq b_{i} +\f] **Attributes**: @@ -13,36 +22,28 @@ * **Description**: specifies rules used for auto-broadcasting of input tensors. * **Range of values**: * *none* - no auto-broadcasting is allowed, all input shapes should match - * *numpy* - numpy broadcasting rules, aligned with ONNX Broadcasting. Description is available in ONNX docs. + * *numpy* - numpy broadcasting rules, description is available in [Broadcast Rules For Elementwise Operations](../broadcast_rules.md) + * *pdpd* - PaddlePaddle-style implicit broadcasting, description is available in [Broadcast Rules For Elementwise Operations](../broadcast_rules.md) * **Type**: string * **Default value**: "numpy" * **Required**: *no* **Inputs** - -* **1**: A tensor of type *T*. **Required.** -* **2**: A tensor of type *T*. **Required.** +* **1**: A tensor of type *T* and arbitrary shape. **Required.** +* **2**: A tensor of type *T* and arbitrary shape. **Required.** **Outputs** -* **1**: The result of element-wise comparison operation. A tensor of type boolean. +* **1**: The result of element-wise *GreaterEqual* operation applied to the input tensors. A tensor of type *T_BOOL* and shape equal to broadcasted shape of two inputs. **Types** * *T*: arbitrary supported type. - -**Detailed description** -Before performing arithmetic operation, input tensors *a* and *b* are broadcasted if their shapes are different and `auto_broadcast` attributes is not `none`. Broadcasting is performed according to `auto_broadcast` value. - -After broadcasting *GreaterEqual* does the following with the input tensors *a* and *b*: - -\f[ -o_{i} = a_{i} \geq b_{i} -\f] +* *T_BOOL*: `boolean`. **Examples** -*Example 1* +*Example 1: no broadcast* ```xml @@ -65,7 +66,7 @@ o_{i} = a_{i} \geq b_{i} ``` -*Example 2: broadcast* +*Example 2: numpy broadcast* ```xml diff --git a/docs/ops/comparison/Greater_1.md b/docs/ops/comparison/Greater_1.md index 2beb0ce3fd0..4076251fd1a 100644 --- a/docs/ops/comparison/Greater_1.md +++ b/docs/ops/comparison/Greater_1.md @@ -35,7 +35,7 @@ o_{i} = a_{i} > b_{i} **Outputs** -* **1**: The result of element-wise comparison operation applied to the input tensors. A tensor of type *T_BOOL* and shape equal to broadcasted shape of two inputs. +* **1**: The result of element-wise *Greater* operation applied to the input tensors. A tensor of type *T_BOOL* and shape equal to broadcasted shape of two inputs. **Types** diff --git a/docs/template_plugin/tests/functional/op_reference/greater_equal.cpp b/docs/template_plugin/tests/functional/op_reference/greater_equal.cpp new file mode 100644 index 00000000000..0e609fb4f74 --- /dev/null +++ b/docs/template_plugin/tests/functional/op_reference/greater_equal.cpp @@ -0,0 +1,81 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include + +#include +#include +#include +#include + +#include "comparison.hpp" + +using namespace ngraph; +using namespace InferenceEngine; +using ComparisonTypes = ngraph::helpers::ComparisonTypes; + +namespace reference_tests { +namespace ComparisonOpsRefTestDefinitions { +namespace { + +template +std::vector generateComparisonParams(const element::Type& type) { + using T = typename element_type_traits::value_type; + std::vector compParams { + // 1D // 2D // 3D // 4D + Builder {} + .compType(ComparisonTypes::GREATER_EQUAL) + .input1({{2, 2}, type, std::vector {0, 12, 23, 0}}) + .input2({{2, 2}, type, std::vector {0, 12, 23, 0}}) + .expected({{2, 2}, element::boolean, std::vector {1, 1, 1, 1}}), + Builder {} + .compType(ComparisonTypes::GREATER_EQUAL) + .input1({{2, 3}, type, std::vector {0, 6, 45, 1, 21, 21}}) + .input2({{2, 3}, type, std::vector {1, 18, 23, 1, 19, 21}}) + .expected({{2, 3}, element::boolean, std::vector {0, 0, 1, 1, 1, 1}}), + Builder {} + .compType(ComparisonTypes::GREATER_EQUAL) + .input1({{1}, type, std::vector {53}}) + .input2({{1}, type, std::vector {53}}) + .expected({{1}, element::boolean, std::vector {1}}), + Builder {} + .compType(ComparisonTypes::GREATER_EQUAL) + .input1({{2, 4}, type, std::vector {0, 12, 23, 0, 1, 5, 12, 8}}) + .input2({{2, 4}, type, std::vector {0, 12, 23, 0, 10, 5, 11, 8}}) + .expected({{2, 4}, element::boolean, std::vector {1, 1, 1, 1, 0, 1, 1, 1}}), + Builder {} + .compType(ComparisonTypes::GREATER_EQUAL) + .input1({{3, 1, 2}, type, std::vector {2, 1, 4, 1, 3, 1}}) + .input2({{1, 2, 1}, type, std::vector {1, 1}}) + .expected({{3, 2, 2}, element::boolean, std::vector {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}), + Builder {} + .compType(ComparisonTypes::GREATER_EQUAL) + .input1({{2, 1, 2, 1}, type, std::vector {2, 1, 4, 1}}) + .input2({{1, 2, 1}, type, std::vector {1, 1}}) + .expected({{2, 1, 2, 1}, element::boolean, std::vector {1, 1, 1, 1}})}; + return compParams; +} + +std::vector generateComparisonCombinedParams() { + const std::vector> compTypeParams { + generateComparisonParams(element::f32), + generateComparisonParams(element::f16), + generateComparisonParams(element::i64), + generateComparisonParams(element::i32), + generateComparisonParams(element::u64), + generateComparisonParams(element::u32), + generateComparisonParams(element::boolean)}; + std::vector combinedParams; + + for (const auto& params : compTypeParams) { + combinedParams.insert(combinedParams.end(), params.begin(), params.end()); + } + return combinedParams; +} + +} // namespace +INSTANTIATE_TEST_SUITE_P(smoke_Comparison_With_Hardcoded_Refs, ReferenceComparisonLayerTest, ::testing::ValuesIn(generateComparisonCombinedParams()), + ReferenceComparisonLayerTest::getTestCaseName); +} // namespace ComparisonOpsRefTestDefinitions +} // namespace reference_tests diff --git a/inference-engine/tests/ie_test_utils/functional_test_utils/layer_tests_summary/utils/constants.py b/inference-engine/tests/ie_test_utils/functional_test_utils/layer_tests_summary/utils/constants.py index 515e768ecb3..7a79d64fa9e 100644 --- a/inference-engine/tests/ie_test_utils/functional_test_utils/layer_tests_summary/utils/constants.py +++ b/inference-engine/tests/ie_test_utils/functional_test_utils/layer_tests_summary/utils/constants.py @@ -46,7 +46,8 @@ VERIFIED_OP_REFERENCES = [ 'GatherElements-6', 'GatherND-5', 'Gelu-7', - 'Greater-1' + 'Greater-1', + 'GreaterEqual-1', 'GRN-1', 'GroupConvolution-1', 'GroupConvolutionBackpropData-1', diff --git a/ngraph/core/include/ngraph/op/greater_eq.hpp b/ngraph/core/include/ngraph/op/greater_eq.hpp index 382037876db..f9e9fc61a58 100644 --- a/ngraph/core/include/ngraph/op/greater_eq.hpp +++ b/ngraph/core/include/ngraph/op/greater_eq.hpp @@ -24,7 +24,6 @@ public: const Output& arg1, const AutoBroadcastSpec& auto_broadcast = AutoBroadcastSpec(AutoBroadcastType::NUMPY)); - bool visit_attributes(AttributeVisitor& visitor) override; virtual std::shared_ptr clone_with_new_inputs(const OutputVector& new_args) const override; bool evaluate(const HostTensorVector& outputs, const HostTensorVector& inputs) const override; bool has_evaluate() const override; diff --git a/ngraph/core/src/op/greater_eq.cpp b/ngraph/core/src/op/greater_eq.cpp index 12b575e60f1..c42720e5489 100644 --- a/ngraph/core/src/op/greater_eq.cpp +++ b/ngraph/core/src/op/greater_eq.cpp @@ -7,6 +7,7 @@ #include "itt.hpp" #include "ngraph/runtime/host_tensor.hpp" #include "ngraph/runtime/reference/greater_eq.hpp" +#include "ngraph/validation_util.hpp" using namespace std; using namespace ngraph; @@ -67,6 +68,7 @@ shared_ptr op::v1::GreaterEqual::clone_with_new_inputs(const OutputVector& bool op::v1::GreaterEqual::evaluate(const HostTensorVector& outputs, const HostTensorVector& inputs) const { NGRAPH_OP_SCOPE(v1_GreaterEqual_evaluate); + NGRAPH_CHECK(validate_host_tensor_vector(outputs, 1) && validate_host_tensor_vector(inputs, 2)); return greater_equalop::evaluate_greater_equal(inputs[0], inputs[1], outputs[0], get_autob()); } @@ -86,9 +88,3 @@ bool op::v1::GreaterEqual::has_evaluate() const { } return false; } - -bool op::v1::GreaterEqual::visit_attributes(AttributeVisitor& visitor) { - NGRAPH_OP_SCOPE(v1_GreaterEqual_visit_attributes); - BinaryElementwiseComparison::visit_attributes(visitor); - return true; -} From ac6c58f03a22707d2f07626cb5957155a483e3e0 Mon Sep 17 00:00:00 2001 From: Ilya Sharikov Date: Wed, 25 Aug 2021 11:49:42 +0300 Subject: [PATCH 32/76] Updated inter_tool due to IE api was updated (#7217) --- tests/conditional_compilation/test_cc.py | 2 ++ tests/conditional_compilation/tools/infer_tool.py | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/conditional_compilation/test_cc.py b/tests/conditional_compilation/test_cc.py index 423b9524426..50bf71f9d14 100644 --- a/tests/conditional_compilation/test_cc.py +++ b/tests/conditional_compilation/test_cc.py @@ -36,6 +36,8 @@ def test_cc_collect(test_id, models, openvino_ref, test_info, prev_result = glob.glob(f"{out / test_id}.pid*.csv") for path in prev_result: os.remove(path) + # Create a directory for infer results, if it haven't done before + infer_out_dir.mkdir(parents=True, exist_ok=True) # run use case return_code, output = cmd_exec( [ diff --git a/tests/conditional_compilation/tools/infer_tool.py b/tests/conditional_compilation/tools/infer_tool.py index 54bafd78d1e..d6c9fdf4580 100644 --- a/tests/conditional_compilation/tools/infer_tool.py +++ b/tests/conditional_compilation/tools/infer_tool.py @@ -27,8 +27,8 @@ def input_preparation(net): """ feed_dict = {} - for layer_name, layer_data in net.inputs.items(): - feed_dict.update({layer_name: np.ones(shape=layer_data.shape)}) + for layer_name, layer_data in net.input_info.items(): + feed_dict.update({layer_name: np.ones(shape=layer_data.input_data.shape)}) return feed_dict From 059870a3a0bb055b1fa9e84cd0a61cab2c860723 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Karzy=C5=84ski?= Date: Wed, 25 Aug 2021 11:37:44 +0200 Subject: [PATCH 33/76] Update ONNX to version 1.10 (#7186) --- .../onnx/frontend/src/core/transform.cpp | 38 +- .../onnx/frontend/src/core/transform.hpp | 6 +- ngraph/frontend/onnx/frontend/src/op/cast.cpp | 4 +- ngraph/frontend/onnx/frontend/src/op/cast.hpp | 4 +- .../onnx/frontend/src/op/cast_like.cpp | 25 + .../onnx/frontend/src/op/cast_like.hpp | 20 + .../onnx/frontend/src/op/hard_swish.hpp | 24 + .../frontend/onnx/frontend/src/op/shape.cpp | 4 +- .../frontend/onnx/frontend/src/op/shape.hpp | 4 +- .../frontend/onnx/frontend/src/op/slice.cpp | 3 - .../frontend/onnx/frontend/src/ops_bridge.cpp | 4 + ngraph/python/requirements_test.txt | 2 +- ngraph/python/tests/__init__.py | 35 +- .../tests/test_onnx/model_zoo_preprocess.sh | 10 +- ngraph/python/tests/test_onnx/test_backend.py | 814 +++++++++++------- .../python/tests/test_onnx/test_zoo_models.py | 4 +- .../tests/test_onnx/utils/model_importer.py | 1 + ngraph/test/CMakeLists.txt | 4 +- ngraph/test/requirements_test_onnx.txt | 2 +- thirdparty/onnx/onnx | 2 +- 20 files changed, 652 insertions(+), 358 deletions(-) create mode 100644 ngraph/frontend/onnx/frontend/src/op/cast_like.cpp create mode 100644 ngraph/frontend/onnx/frontend/src/op/cast_like.hpp create mode 100644 ngraph/frontend/onnx/frontend/src/op/hard_swish.hpp diff --git a/ngraph/frontend/onnx/frontend/src/core/transform.cpp b/ngraph/frontend/onnx/frontend/src/core/transform.cpp index 758216fed4a..c22157d8452 100644 --- a/ngraph/frontend/onnx/frontend/src/core/transform.cpp +++ b/ngraph/frontend/onnx/frontend/src/core/transform.cpp @@ -6,11 +6,35 @@ #include #include +#include #include "core/model.hpp" #include "ngraph/file_util.hpp" +#include "ngraph/log.hpp" #include "ops_bridge.hpp" +namespace ngraph { +namespace onnx_import { +namespace transform { +namespace detail { +ONNX_NAMESPACE::TypeProto get_input_type(std::string const& name, ONNX_NAMESPACE::GraphProto& graph) { + for (auto& input : graph.input()) { + if (input.name() == name) { + return input.type(); + } + } + for (auto& value_info : graph.value_info()) { + if (value_info.name() == name) { + return value_info.type(); + } + } + return ONNX_NAMESPACE::TypeProto(); +} +} // namespace detail +} // namespace transform +} // namespace onnx_import +} // namespace ngraph + void ngraph::onnx_import::transform::expand_onnx_functions(ONNX_NAMESPACE::ModelProto& model_proto) { auto graph_proto = model_proto.mutable_graph(); @@ -43,7 +67,19 @@ void ngraph::onnx_import::transform::expand_onnx_functions(ONNX_NAMESPACE::Model } else if (node_op_schema->HasContextDependentFunction()) { - ONNX_NAMESPACE::FunctionBodyBuildContextImpl ctx(node); + // In order to expand a context-dependent function, we need to infer types + try { + ONNX_NAMESPACE::shape_inference::InferShapes(model_proto); + } catch (const std::exception& e) { + NGRAPH_WARN << "ONNX Shape inference failed: " << e.what(); + } + + std::vector input_types; + for (const auto& input : node.input()) { + input_types.push_back(ngraph::onnx_import::transform::detail::get_input_type(input, *graph_proto)); + } + + ONNX_NAMESPACE::FunctionBodyBuildContextImpl ctx(node, input_types); ONNX_NAMESPACE::FunctionProto func_proto; node_op_schema->BuildContextDependentFunction(ctx, func_proto); ONNX_NAMESPACE::FunctionExpandHelper(node, func_proto, *graph_proto); diff --git a/ngraph/frontend/onnx/frontend/src/core/transform.hpp b/ngraph/frontend/onnx/frontend/src/core/transform.hpp index 2149f149625..722d95d80fa 100644 --- a/ngraph/frontend/onnx/frontend/src/core/transform.hpp +++ b/ngraph/frontend/onnx/frontend/src/core/transform.hpp @@ -9,6 +9,7 @@ namespace ngraph { namespace onnx_import { namespace transform { + /// \brief Replace external_data path in tensors with full path to data file. /// /// Paths to external data files are stored as relative to model path. @@ -19,7 +20,8 @@ namespace transform { /// \param model_path Filesystem path to the ONNX model file. void update_external_data_paths(ONNX_NAMESPACE::ModelProto& model_proto, const std::string& model_path); -static const std::vector onnx_functions_to_expand = {"Celu", +static const std::vector onnx_functions_to_expand = {"Bernoulli", + "Celu", "DynamicQuantizeLinear", "GreaterOrEqual", "LessOrEqual", @@ -63,7 +65,5 @@ static const std::vector legacy_ops_to_fixup = {"DeformableConv2D", void fixup_legacy_operators(ONNX_NAMESPACE::ModelProto& model_proto); } // namespace transform - } // namespace onnx_import - } // namespace ngraph diff --git a/ngraph/frontend/onnx/frontend/src/op/cast.cpp b/ngraph/frontend/onnx/frontend/src/op/cast.cpp index 82b252c63a6..6c083877497 100644 --- a/ngraph/frontend/onnx/frontend/src/op/cast.cpp +++ b/ngraph/frontend/onnx/frontend/src/op/cast.cpp @@ -14,6 +14,7 @@ namespace ngraph { namespace onnx_import { namespace op { namespace set_1 { + OutputVector cast(const Node& node) { auto data = node.get_ng_inputs().at(0); int64_t target_type = node.get_attribute_value("to"); @@ -23,9 +24,6 @@ OutputVector cast(const Node& node) { } } // namespace set_1 - } // namespace op - } // namespace onnx_import - } // namespace ngraph diff --git a/ngraph/frontend/onnx/frontend/src/op/cast.hpp b/ngraph/frontend/onnx/frontend/src/op/cast.hpp index eed57d51f9a..e712e7f5034 100644 --- a/ngraph/frontend/onnx/frontend/src/op/cast.hpp +++ b/ngraph/frontend/onnx/frontend/src/op/cast.hpp @@ -11,12 +11,10 @@ namespace ngraph { namespace onnx_import { namespace op { namespace set_1 { + OutputVector cast(const Node& node); } // namespace set_1 - } // namespace op - } // namespace onnx_import - } // namespace ngraph diff --git a/ngraph/frontend/onnx/frontend/src/op/cast_like.cpp b/ngraph/frontend/onnx/frontend/src/op/cast_like.cpp new file mode 100644 index 00000000000..112b55749e4 --- /dev/null +++ b/ngraph/frontend/onnx/frontend/src/op/cast_like.cpp @@ -0,0 +1,25 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include + +#include "default_opset.hpp" +#include "ngraph/type/element_type.hpp" +#include "op/cast.hpp" +#include "utils/common.hpp" + +namespace ngraph { +namespace onnx_import { +namespace op { +namespace set_1 { + +OutputVector cast_like(const Node& node) { + auto inputs = node.get_ng_inputs(); + return {std::make_shared(inputs.at(0), inputs.at(1))}; +} + +} // namespace set_1 +} // namespace op +} // namespace onnx_import +} // namespace ngraph diff --git a/ngraph/frontend/onnx/frontend/src/op/cast_like.hpp b/ngraph/frontend/onnx/frontend/src/op/cast_like.hpp new file mode 100644 index 00000000000..fb197b244ca --- /dev/null +++ b/ngraph/frontend/onnx/frontend/src/op/cast_like.hpp @@ -0,0 +1,20 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +#include "ngraph/node.hpp" +#include "onnx_import/core/node.hpp" + +namespace ngraph { +namespace onnx_import { +namespace op { +namespace set_1 { + +OutputVector cast_like(const Node& node); + +} // namespace set_1 +} // namespace op +} // namespace onnx_import +} // namespace ngraph diff --git a/ngraph/frontend/onnx/frontend/src/op/hard_swish.hpp b/ngraph/frontend/onnx/frontend/src/op/hard_swish.hpp new file mode 100644 index 00000000000..68b2c403026 --- /dev/null +++ b/ngraph/frontend/onnx/frontend/src/op/hard_swish.hpp @@ -0,0 +1,24 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +#include "default_opset.hpp" +#include "ngraph/node.hpp" +#include "onnx_import/core/node.hpp" + +namespace ngraph { +namespace onnx_import { +namespace op { +namespace set_1 { +inline OutputVector hard_swish(const Node& node) { + return {std::make_shared(node.get_ng_inputs().at(0))}; +} +} // namespace set_1 + +} // namespace op + +} // namespace onnx_import + +} // namespace ngraph diff --git a/ngraph/frontend/onnx/frontend/src/op/shape.cpp b/ngraph/frontend/onnx/frontend/src/op/shape.cpp index a35bbb235a1..04f99516c1d 100644 --- a/ngraph/frontend/onnx/frontend/src/op/shape.cpp +++ b/ngraph/frontend/onnx/frontend/src/op/shape.cpp @@ -15,15 +15,13 @@ namespace ngraph { namespace onnx_import { namespace op { namespace set_1 { + OutputVector shape(const Node& node) { const auto data = node.get_ng_inputs().at(0); return {std::make_shared(data)}; } } // namespace set_1 - } // namespace op - } // namespace onnx_import - } // namespace ngraph diff --git a/ngraph/frontend/onnx/frontend/src/op/shape.hpp b/ngraph/frontend/onnx/frontend/src/op/shape.hpp index c73465f9328..9124aa6f48f 100644 --- a/ngraph/frontend/onnx/frontend/src/op/shape.hpp +++ b/ngraph/frontend/onnx/frontend/src/op/shape.hpp @@ -11,12 +11,10 @@ namespace ngraph { namespace onnx_import { namespace op { namespace set_1 { + OutputVector shape(const Node& node); } // namespace set_1 - } // namespace op - } // namespace onnx_import - } // namespace ngraph diff --git a/ngraph/frontend/onnx/frontend/src/op/slice.cpp b/ngraph/frontend/onnx/frontend/src/op/slice.cpp index ce5d8240e63..13c08449cab 100644 --- a/ngraph/frontend/onnx/frontend/src/op/slice.cpp +++ b/ngraph/frontend/onnx/frontend/src/op/slice.cpp @@ -217,9 +217,6 @@ OutputVector slice(const Node& node) { } } // namespace set_1 - } // namespace op - } // namespace onnx_import - } // namespace ngraph diff --git a/ngraph/frontend/onnx/frontend/src/ops_bridge.cpp b/ngraph/frontend/onnx/frontend/src/ops_bridge.cpp index 6d5fd9b3467..ed759c1b5ea 100644 --- a/ngraph/frontend/onnx/frontend/src/ops_bridge.cpp +++ b/ngraph/frontend/onnx/frontend/src/ops_bridge.cpp @@ -26,6 +26,7 @@ #include "op/batch_norm.hpp" #include "op/bitshift.hpp" #include "op/cast.hpp" +#include "op/cast_like.hpp" #include "op/ceil.hpp" #include "op/clip.hpp" #include "op/compress.hpp" @@ -62,6 +63,7 @@ #include "op/greater.hpp" #include "op/gru.hpp" #include "op/hard_sigmoid.hpp" +#include "op/hard_swish.hpp" #include "op/hardmax.hpp" #include "op/identity.hpp" #include "op/image_scaler.hpp" @@ -285,6 +287,7 @@ OperatorsBridge::OperatorsBridge() { REGISTER_OPERATOR("BatchNormalization", 7, batch_norm); REGISTER_OPERATOR("BitShift", 1, bitshift); REGISTER_OPERATOR("Cast", 1, cast); + REGISTER_OPERATOR("CastLike", 1, cast_like); REGISTER_OPERATOR("Ceil", 1, ceil); REGISTER_OPERATOR("Clip", 1, clip); REGISTER_OPERATOR("Clip", 11, clip); @@ -330,6 +333,7 @@ OperatorsBridge::OperatorsBridge() { REGISTER_OPERATOR("Hardmax", 1, hardmax); REGISTER_OPERATOR("Hardmax", 13, hardmax); REGISTER_OPERATOR("HardSigmoid", 1, hard_sigmoid); + REGISTER_OPERATOR("HardSwish", 1, hard_swish); REGISTER_OPERATOR("Identity", 1, identity); REGISTER_OPERATOR("ImageScaler", 1, image_scaler); REGISTER_OPERATOR("InstanceNormalization", 1, instance_norm); diff --git a/ngraph/python/requirements_test.txt b/ngraph/python/requirements_test.txt index 0a63e05497a..595f3e4f75d 100644 --- a/ngraph/python/requirements_test.txt +++ b/ngraph/python/requirements_test.txt @@ -4,7 +4,7 @@ flake8-comprehensions==3.3.0 flake8-docstrings==1.6.0 flake8-quotes==3.2.0 mypy==0.812 -onnx==1.8.1 +onnx==1.10.1 pydocstyle==5.1.1 pytest-xdist==2.2.1 pytest==6.1.2 diff --git a/ngraph/python/tests/__init__.py b/ngraph/python/tests/__init__.py index a132f6fad53..929eb41658b 100644 --- a/ngraph/python/tests/__init__.py +++ b/ngraph/python/tests/__init__.py @@ -62,7 +62,7 @@ xfail_issue_38701 = xfail_test(reason="RuntimeError: unsupported element type: S xfail_issue_38706 = xfail_test(reason="RuntimeError: output_3.0 has zero dimension which is not allowed") xfail_issue_38708 = xfail_test(reason="RuntimeError: While validating ONNX node '': " "Axes input must be constant") -xfail_issue_38710 = xfail_test(reason="RuntimeError: roi has zero dimension which is not allowed") +xfail_issue_38710 = xfail_test(reason="RuntimeError: data has zero dimension which is not allowed") xfail_issue_38713 = xfail_test(reason="RuntimeError: nGraph does not support the following ONNX operations:" "ai.onnx.preview.training.Momentum") xfail_issue_43742 = xfail_test(reason="RuntimeError: nGraph does not support the following ONNX operations:" @@ -91,16 +91,16 @@ xfail_issue_38735 = xfail_test(reason="RuntimeError: nGraph does not support the "ai.onnx.preview.training.Adagrad") xfail_issue_48052 = xfail_test(reason="Dropout op is not supported in traning mode") xfail_issue_45180 = xfail_test(reason="RuntimeError: Unsupported dynamic op: ReduceSum") -xfail_issue_44848 = xfail_test(reason="E Unsupported dynamic op: Range") -xfail_issue_44851 = xfail_test(reason="E Unsupported dynamic op: Broadcast") -xfail_issue_44854 = xfail_test(reason="E Unsupported dynamic op: VariadicSplit") -xfail_issue_44858 = xfail_test(reason="E Unsupported dynamic op: Unsqueeze") -xfail_issue_44956 = xfail_test(reason="E Unsupported dynamic op: Loop") -xfail_issue_44957 = xfail_test(reason="E Unsupported dynamic op: NonZero") -xfail_issue_44958 = xfail_test(reason="E Unsupported dynamic op: Interpolate") -xfail_issue_44965 = xfail_test(reason="E RuntimeError: value info has no element") -xfail_issue_44968 = xfail_test(reason="E Unsupported dynamic op: Squeeze") -xfail_issue_44976 = xfail_test(reason="E RuntimeError: Quantize layer with name:" +xfail_issue_44848 = xfail_test(reason="Expected: Unsupported dynamic op: Range") +xfail_issue_44851 = xfail_test(reason="Expected: Unsupported dynamic op: Broadcast") +xfail_issue_44854 = xfail_test(reason="Expected: Unsupported dynamic op: VariadicSplit") +xfail_issue_44858 = xfail_test(reason="Expected: Unsupported dynamic op: Unsqueeze") +xfail_issue_44956 = xfail_test(reason="Expected: Unsupported dynamic op: Loop") +xfail_issue_44957 = xfail_test(reason="Expected: Unsupported dynamic op: NonZero") +xfail_issue_44958 = xfail_test(reason="Expected: Unsupported dynamic op: Interpolate") +xfail_issue_44965 = xfail_test(reason="Expected: RuntimeError: value info has no element") +xfail_issue_44968 = xfail_test(reason="Expected: Unsupported dynamic op: Squeeze") +xfail_issue_44976 = xfail_test(reason="Expected: RuntimeError: Quantize layer with name:" "FakeQuantize_xxx has non const input on 1 port") xfail_issue_46762 = xfail_test(reason="Incorrect result of Minimum op if uint data type is used") xfail_issue_47323 = xfail_test(reason="RuntimeError: The plugin does not support FP64") @@ -145,5 +145,16 @@ xfail_issue_52463 = xfail_test(reason="test_operator_add_size1_singleton_broadca xfail_issue_58033 = xfail_test(reason="Einsum operation misses support for complex ellipsis equations") xfail_issue_58676 = xfail_test(reason="AssertionError: Not equal to tolerance rtol=0.001, atol=1e-07") xfail_issue_onnx_models_140 = xfail_test(reason="https://github.com/onnx/models/issues/140") - xfail_issue_54630 = xfail_test(reason="Gather with negative indices is not yet implemented on CPU") + +xfail_issue_63033 = xfail_test(reason="BatchNormalization: Training mode is not supported") +xfail_issue_63036 = xfail_test(reason="Changes in ConvTranspose padding") +xfail_issue_63039 = xfail_test(reason="Result mismatches with UINT8 operations") +xfail_issue_63043 = xfail_test(reason="Recurrent node expects constants as W, R, B inputs.") +xfail_issue_63044 = xfail_test(reason="ONNX opset 14 operation: Trilu") +xfail_issue_63045 = xfail_test(reason="Maxpool with strides, padding and dilations fail") + +skip_rng_tests = pytest.mark.skip(reason="Tests use random number generator with no seed.") +xfail_issue_63136 = xfail_test(reason="Unsupported operation: CastLike") +xfail_issue_63137 = xfail_test(reason="Unsupported operations: OptionalHasElement, OptionalGetElement") +xfail_issue_63138 = xfail_test(reason="Missing ONNX Shape-15 support") diff --git a/ngraph/python/tests/test_onnx/model_zoo_preprocess.sh b/ngraph/python/tests/test_onnx/model_zoo_preprocess.sh index dd35ed340eb..e7b5a891cf1 100755 --- a/ngraph/python/tests/test_onnx/model_zoo_preprocess.sh +++ b/ngraph/python/tests/test_onnx/model_zoo_preprocess.sh @@ -23,6 +23,8 @@ function print_help { echo " -s Onnx Model Zoo commit SHA" echo " -m update MSFT models" echo " -f force update of a chosen model" + echo "" + echo "Note: This script requires wget, GNU tar (not bsdtar) and git with LFS support." } while getopts "homfd:s:" opt; do @@ -70,7 +72,9 @@ function pull_and_postprocess_onnx_model_zoo() { find "$ONNX_MODELS_DIR" -name "*.onnx" | while read filename; do rm "$filename"; done; printf "Extracting tar.gz archives into %s\n" "$ONNX_MODELS_DIR" - find "$ONNX_MODELS_DIR" -name '*.tar.gz' -execdir sh -c 'BASEDIR=$(basename "{}" .tar.gz) && rm -rf $BASEDIR && mkdir -p $BASEDIR' \; -execdir sh -c 'BASEDIR=$(basename "{}" .tar.gz) && tar --warning=no-unknown-keyword -xvzf "{}" -C $BASEDIR' \; + find "$ONNX_MODELS_DIR" -name '*.tar.gz' \ + -execdir sh -c 'BASEDIR=$(basename "{}" .tar.gz) && rm -rf $BASEDIR && mkdir -p $BASEDIR' \; \ + -execdir sh -c 'BASEDIR=$(basename "{}" .tar.gz) && tar --warning=no-unknown-keyword -xvzf "{}" -C $BASEDIR' \; echo "Postprocessing of ONNX Model Zoo models:" @@ -129,7 +133,7 @@ function postprocess_msft_models() { } if [[ $ENABLE_ONNX_MODELS_ZOO = false ]] && [[ $ENABLE_MSFT_MODELS = false ]] ; then - printf "Please choose an option to update chosen model: + echo "Please choose an option to update chosen model: -o to update ONNX Model ZOO -m to update MSFT models" exit 170 @@ -144,7 +148,7 @@ fi # check if general model zoo directory exists (directory to store ONNX model zoo and MSFT models) if [[ ! -d $MODEL_ZOO_DIR ]] ; then - printf "The general model directory: %s doesn't exist on your filesystem then will be created \n" "$MODEL_ZOO_DIR" + printf "The general model directory: %s doesn't exist on your filesystem, it will be created \n" "$MODEL_ZOO_DIR" mkdir -p $MODEL_ZOO_DIR else printf "The general model directory: %s found\n" "$MODEL_ZOO_DIR" diff --git a/ngraph/python/tests/test_onnx/test_backend.py b/ngraph/python/tests/test_onnx/test_backend.py index f8a1d99c900..367e9a04dd5 100644 --- a/ngraph/python/tests/test_onnx/test_backend.py +++ b/ngraph/python/tests/test_onnx/test_backend.py @@ -4,64 +4,74 @@ import logging import onnx.backend.test - +from tests import ( + BACKEND_NAME, + skip_rng_tests, + xfail_issue_33488, + xfail_issue_33535, + xfail_issue_33538, + xfail_issue_33581, + xfail_issue_33589, + xfail_issue_33593, + xfail_issue_33595, + xfail_issue_33596, + xfail_issue_33606, + xfail_issue_33633, + xfail_issue_33651, + xfail_issue_38091, + xfail_issue_38699, + xfail_issue_38701, + xfail_issue_38706, + xfail_issue_38708, + xfail_issue_38710, + xfail_issue_38713, + xfail_issue_38722, + xfail_issue_38723, + xfail_issue_38724, + xfail_issue_38732, + xfail_issue_38734, + xfail_issue_38735, + xfail_issue_39656, + xfail_issue_39658, + xfail_issue_39659, + xfail_issue_39662, + xfail_issue_43742, + xfail_issue_44848, + xfail_issue_44851, + xfail_issue_44854, + xfail_issue_44858, + xfail_issue_44956, + xfail_issue_44957, + xfail_issue_44958, + xfail_issue_44965, + xfail_issue_44968, + xfail_issue_44976, + xfail_issue_45180, + xfail_issue_45344, + xfail_issue_46762, + xfail_issue_47323, + xfail_issue_47337, + xfail_issue_48052, + xfail_issue_49207, + xfail_issue_49750, + xfail_issue_49752, + xfail_issue_49753, + xfail_issue_49754, + xfail_issue_52463, + xfail_issue_55760, + xfail_issue_58033, + xfail_issue_63033, + xfail_issue_63036, + xfail_issue_63039, + xfail_issue_63043, + xfail_issue_63044, + xfail_issue_63045, + xfail_issue_63136, + xfail_issue_63137, + xfail_issue_63138, +) from tests.test_onnx.utils.onnx_backend import OpenVinoTestBackend -from tests import (BACKEND_NAME, - xfail_issue_33488, - xfail_issue_33535, - xfail_issue_33538, - xfail_issue_33581, - xfail_issue_33589, - xfail_issue_33593, - xfail_issue_33595, - xfail_issue_33596, - xfail_issue_33606, - xfail_issue_33633, - xfail_issue_33651, - xfail_issue_38091, - xfail_issue_38699, - xfail_issue_38701, - xfail_issue_38706, - xfail_issue_38708, - xfail_issue_38713, - xfail_issue_38722, - xfail_issue_38723, - xfail_issue_38724, - xfail_issue_38732, - xfail_issue_38734, - xfail_issue_38735, - xfail_issue_39656, - xfail_issue_39658, - xfail_issue_39659, - xfail_issue_39662, - xfail_issue_43742, - xfail_issue_44848, - xfail_issue_44851, - xfail_issue_44854, - xfail_issue_44858, - xfail_issue_44956, - xfail_issue_44957, - xfail_issue_44958, - xfail_issue_44965, - xfail_issue_44968, - xfail_issue_44976, - xfail_issue_45180, - xfail_issue_45344, - xfail_issue_46762, - xfail_issue_47323, - xfail_issue_47337, - xfail_issue_48052, - xfail_issue_49207, - xfail_issue_49750, - xfail_issue_49752, - xfail_issue_49753, - xfail_issue_49754, - xfail_issue_52463, - xfail_issue_55760, - xfail_issue_58033, - ) - def expect_fail(test_case_path, xfail): # type: (str) -> None """Mark the test as expected to fail.""" @@ -70,7 +80,9 @@ def expect_fail(test_case_path, xfail): # type: (str) -> None if hasattr(module, test_name): xfail(getattr(module, test_name)) else: - logging.getLogger().warning("Could not mark test as XFAIL, not found: %s", test_case_path) + logging.getLogger().warning( + "Could not mark test as XFAIL, not found: %s", test_case_path + ) OpenVinoTestBackend.backend_name = BACKEND_NAME @@ -107,265 +119,435 @@ OnnxBackendPyTorchConvertedModelTest = None globals().update(backend_test.enable_report().test_cases) tests_expected_to_fail = [ - (xfail_issue_49207, - "OnnxBackendNodeModelTest.test_rnn_seq_length_cpu", - "OnnxBackendNodeModelTest.test_simple_rnn_defaults_cpu", - "OnnxBackendNodeModelTest.test_simple_rnn_with_initial_bias_cpu", - "OnnxBackendNodeModelTest.test_gru_defaults_cpu", - "OnnxBackendNodeModelTest.test_gru_seq_length_cpu", - "OnnxBackendNodeModelTest.test_gru_with_initial_bias_cpu", - "OnnxBackendNodeModelTest.test_lstm_defaults_cpu", - "OnnxBackendNodeModelTest.test_lstm_with_initial_bias_cpu", - "OnnxBackendNodeModelTest.test_lstm_with_peepholes_cpu"), - (xfail_issue_49752, - "OnnxBackendNodeModelTest.test_constant_pad_cpu", - "OnnxBackendNodeModelTest.test_edge_pad_cpu", - "OnnxBackendNodeModelTest.test_reflect_pad_cpu"), - (xfail_issue_39656, - "OnnxBackendNodeModelTest.test_reshape_extended_dims_cpu", - "OnnxBackendNodeModelTest.test_reshape_negative_dim_cpu", - "OnnxBackendNodeModelTest.test_reshape_one_dim_cpu", - "OnnxBackendNodeModelTest.test_reshape_reduced_dims_cpu", - "OnnxBackendNodeModelTest.test_reshape_negative_extended_dims_cpu", - "OnnxBackendNodeModelTest.test_reshape_reordered_all_dims_cpu", - "OnnxBackendNodeModelTest.test_reshape_reordered_last_dims_cpu", - "OnnxBackendNodeModelTest.test_reshape_zero_and_negative_dim_cpu", - "OnnxBackendNodeModelTest.test_reshape_zero_dim_cpu"), - (xfail_issue_39658, - "OnnxBackendNodeModelTest.test_tile_cpu", - "OnnxBackendNodeModelTest.test_tile_precomputed_cpu"), - (xfail_issue_39659, - "OnnxBackendNodeModelTest.test_constantofshape_float_ones_cpu", - "OnnxBackendNodeModelTest.test_constantofshape_int_zeros_cpu", - "OnnxBackendNodeModelTest.test_constantofshape_int_shape_zero_cpu"), - (xfail_issue_45344, - "OnnxBackendNodeModelTest.test_nonmaxsuppression_center_point_box_format_cpu", - "OnnxBackendNodeModelTest.test_nonmaxsuppression_flipped_coordinates_cpu", - "OnnxBackendNodeModelTest.test_nonmaxsuppression_identical_boxes_cpu", - "OnnxBackendNodeModelTest.test_nonmaxsuppression_limit_output_size_cpu", - "OnnxBackendNodeModelTest.test_nonmaxsuppression_single_box_cpu", - "OnnxBackendNodeModelTest.test_nonmaxsuppression_suppress_by_IOU_and_scores_cpu", - "OnnxBackendNodeModelTest.test_nonmaxsuppression_suppress_by_IOU_cpu", - "OnnxBackendNodeModelTest.test_nonmaxsuppression_two_batches_cpu", - "OnnxBackendNodeModelTest.test_nonmaxsuppression_two_classes_cpu"), - (xfail_issue_39662, - "OnnxBackendNodeModelTest.test_nonmaxsuppression_two_classes_cpu", - "OnnxBackendNodeModelTest.test_scatter_elements_with_negative_indices_cpu", - "OnnxBackendNodeModelTest.test_gather_negative_indices_cpu"), - (xfail_issue_49753, - "OnnxBackendNodeModelTest.test_slice_default_axes_cpu"), - (xfail_issue_49754, - "OnnxBackendNodeModelTest.test_top_k_cpu", - "OnnxBackendNodeModelTest.test_top_k_negative_axis_cpu", - "OnnxBackendNodeModelTest.test_top_k_smallest_cpu"), - (xfail_issue_33633, - "OnnxBackendNodeModelTest.test_maxpool_2d_dilations_cpu"), - (xfail_issue_46762, - "OnnxBackendNodeModelTest.test_min_uint8_cpu", - "OnnxBackendNodeModelTest.test_min_uint16_cpu", - "OnnxBackendNodeModelTest.test_min_uint32_cpu", - "OnnxBackendNodeModelTest.test_min_uint64_cpu"), - (xfail_issue_55760, - "OnnxBackendNodeModelTest.test_argmax_negative_axis_keepdims_example_select_last_index_cpu", - "OnnxBackendNodeModelTest.test_argmin_negative_axis_keepdims_example_select_last_index_cpu", - "OnnxBackendNodeModelTest.test_argmax_negative_axis_keepdims_random_select_last_index_cpu", - "OnnxBackendNodeModelTest.test_argmin_negative_axis_keepdims_random_select_last_index_cpu"), - (xfail_issue_38091, - "OnnxBackendNodeModelTest.test_gather_negative_indices_cpu"), - (xfail_issue_52463, - "OnnxBackendPyTorchOperatorModelTest.test_operator_add_size1_singleton_broadcast_cpu"), - (xfail_issue_47323, - "OnnxBackendPyTorchOperatorModelTest.test_operator_add_broadcast_cpu", - "OnnxBackendPyTorchOperatorModelTest.test_operator_addconstant_cpu", - "OnnxBackendPyTorchOperatorModelTest.test_operator_add_size1_right_broadcast_cpu"), - (xfail_issue_38699, - "OnnxBackendSimpleModelTest.test_gradient_of_add_and_mul_cpu", - "OnnxBackendSimpleModelTest.test_gradient_of_add_cpu"), - (xfail_issue_33596, - "OnnxBackendSimpleModelTest.test_sequence_model5_cpu", - "OnnxBackendSimpleModelTest.test_sequence_model7_cpu", - "OnnxBackendSimpleModelTest.test_sequence_model1_cpu", - "OnnxBackendSimpleModelTest.test_sequence_model3_cpu", - "OnnxBackendSimpleModelTest.test_sequence_model6_cpu", - "OnnxBackendSimpleModelTest.test_sequence_model8_cpu", - "OnnxBackendSimpleModelTest.test_sequence_model4_cpu", - "OnnxBackendSimpleModelTest.test_sequence_model2_cpu"), - (xfail_issue_38701, - "OnnxBackendSimpleModelTest.test_strnorm_model_monday_casesensintive_nochangecase_cpu", - "OnnxBackendSimpleModelTest.test_strnorm_model_nostopwords_nochangecase_cpu", - "OnnxBackendSimpleModelTest.test_strnorm_model_monday_empty_output_cpu", - "OnnxBackendSimpleModelTest.test_strnorm_model_monday_insensintive_upper_twodim_cpu", - "OnnxBackendSimpleModelTest.test_strnorm_model_monday_casesensintive_lower_cpu", - "OnnxBackendSimpleModelTest.test_strnorm_model_monday_casesensintive_upper_cpu", - "OnnxBackendNodeModelTest.test_strnormalizer_nostopwords_nochangecase_cpu", - "OnnxBackendNodeModelTest.test_strnormalizer_export_monday_casesensintive_nochangecase_cpu", - "OnnxBackendNodeModelTest.test_strnormalizer_export_monday_insensintive_upper_twodim_cpu", - "OnnxBackendNodeModelTest.test_strnormalizer_export_monday_casesensintive_lower_cpu", - "OnnxBackendNodeModelTest.test_strnormalizer_export_monday_empty_output_cpu", - "OnnxBackendNodeModelTest.test_strnormalizer_export_monday_casesensintive_upper_cpu", - "OnnxBackendNodeModelTest.test_cast_STRING_to_FLOAT_cpu", - "OnnxBackendNodeModelTest.test_cast_FLOAT_to_STRING_cpu"), - (xfail_issue_33595, - "OnnxBackendNodeModelTest.test_unique_not_sorted_without_axis_cpu", - "OnnxBackendNodeModelTest.test_unique_sorted_with_negative_axis_cpu", - "OnnxBackendNodeModelTest.test_unique_sorted_with_axis_cpu", - "OnnxBackendNodeModelTest.test_unique_sorted_with_axis_3d_cpu", - "OnnxBackendNodeModelTest.test_unique_sorted_without_axis_cpu"), - (xfail_issue_33651, - "OnnxBackendNodeModelTest.test_tfidfvectorizer_tf_batch_onlybigrams_skip5_cpu", - "OnnxBackendNodeModelTest.test_tfidfvectorizer_tf_onlybigrams_levelempty_cpu", - "OnnxBackendNodeModelTest.test_tfidfvectorizer_tf_batch_onlybigrams_skip0_cpu", - "OnnxBackendNodeModelTest.test_tfidfvectorizer_tf_uniandbigrams_skip5_cpu", - "OnnxBackendNodeModelTest.test_tfidfvectorizer_tf_only_bigrams_skip0_cpu", - "OnnxBackendNodeModelTest.test_tfidfvectorizer_tf_batch_uniandbigrams_skip5_cpu", - "OnnxBackendNodeModelTest.test_tfidfvectorizer_tf_onlybigrams_skip5_cpu"), - (xfail_issue_38706, - "OnnxBackendNodeModelTest.test_split_zero_size_splits_cpu"), - (xfail_issue_38708, - "OnnxBackendNodeModelTest.test_slice_default_steps_cpu", - "OnnxBackendNodeModelTest.test_slice_negative_axes_cpu", - "OnnxBackendNodeModelTest.test_slice_neg_steps_cpu", - "OnnxBackendNodeModelTest.test_slice_neg_cpu", - "OnnxBackendNodeModelTest.test_slice_cpu", - "OnnxBackendNodeModelTest.test_slice_end_out_of_bounds_cpu", - "OnnxBackendNodeModelTest.test_slice_start_out_of_bounds_cpu"), - (xfail_issue_33538, - "OnnxBackendNodeModelTest.test_scan_sum_cpu", - "OnnxBackendNodeModelTest.test_scan9_sum_cpu"), - (xfail_issue_49750, - "OnnxBackendNodeModelTest.test_resize_downsample_scales_linear_align_corners_cpu", - "OnnxBackendNodeModelTest.test_resize_upsample_scales_cubic_cpu", - "OnnxBackendNodeModelTest.test_resize_downsample_scales_cubic_cpu", - "OnnxBackendNodeModelTest.test_resize_downsample_scales_cubic_align_corners_cpu", - "OnnxBackendNodeModelTest.test_resize_upsample_scales_nearest_cpu", - "OnnxBackendNodeModelTest.test_resize_upsample_scales_cubic_asymmetric_cpu", - "OnnxBackendNodeModelTest.test_resize_downsample_scales_cubic_A_n0p5_exclude_outside_cpu", - "OnnxBackendNodeModelTest.test_resize_upsample_scales_linear_cpu", - "OnnxBackendNodeModelTest.test_resize_upsample_scales_cubic_align_corners_cpu", - "OnnxBackendNodeModelTest.test_resize_upsample_scales_linear_align_corners_cpu", - "OnnxBackendNodeModelTest.test_resize_upsample_scales_cubic_A_n0p5_exclude_outside_cpu", - "OnnxBackendNodeModelTest.test_resize_downsample_scales_nearest_cpu", - "OnnxBackendNodeModelTest.test_resize_downsample_scales_linear_cpu", - "OnnxBackendNodeModelTest.test_resize_downsample_sizes_cubic_cpu", - "OnnxBackendNodeModelTest.test_resize_upsample_sizes_nearest_round_prefer_ceil_asymmetric_cpu", - "OnnxBackendNodeModelTest.test_resize_upsample_sizes_nearest_floor_align_corners_cpu", - "OnnxBackendNodeModelTest.test_resize_upsample_sizes_nearest_cpu", - "OnnxBackendNodeModelTest.test_resize_upsample_sizes_nearest_ceil_half_pixel_cpu", - "OnnxBackendNodeModelTest.test_resize_upsample_sizes_cubic_cpu", - "OnnxBackendNodeModelTest.test_resize_downsample_sizes_linear_pytorch_half_pixel_cpu", - "OnnxBackendNodeModelTest.test_resize_downsample_sizes_nearest_cpu", - "OnnxBackendNodeModelTest.test_resize_downsample_sizes_nearest_tf_half_pixel_for_nn_cpu"), - (xfail_issue_33581, - "OnnxBackendNodeModelTest.test_gather_elements_negative_indices_cpu"), - (xfail_issue_38713, - "OnnxBackendNodeModelTest.test_momentum_cpu", - "OnnxBackendNodeModelTest.test_nesterov_momentum_cpu", - "OnnxBackendNodeModelTest.test_momentum_multiple_cpu"), - (xfail_issue_47337, - "OnnxBackendNodeModelTest.test_onehot_without_axis_cpu", - "OnnxBackendNodeModelTest.test_onehot_with_negative_axis_cpu", - "OnnxBackendNodeModelTest.test_onehot_with_axis_cpu", - "OnnxBackendNodeModelTest.test_onehot_negative_indices_cpu"), - (xfail_issue_33488, - "OnnxBackendNodeModelTest.test_maxunpool_export_with_output_shape_cpu", - "OnnxBackendNodeModelTest.test_maxunpool_export_without_output_shape_cpu"), - (xfail_issue_33589, - "OnnxBackendNodeModelTest.test_isnan_cpu", - "OnnxBackendNodeModelTest.test_isinf_positive_cpu", - "OnnxBackendNodeModelTest.test_isinf_negative_cpu", - "OnnxBackendNodeModelTest.test_isinf_cpu"), - (xfail_issue_33535, - "OnnxBackendNodeModelTest.test_dynamicquantizelinear_min_adjusted_cpu", - "OnnxBackendNodeModelTest.test_dynamicquantizelinear_cpu", - "OnnxBackendNodeModelTest.test_dynamicquantizelinear_max_adjusted_cpu"), - (xfail_issue_38722, - "OnnxBackendNodeModelTest.test_matmulinteger_cpu", - "OnnxBackendNodeModelTest.test_qlinearmatmul_2D_cpu", - "OnnxBackendNodeModelTest.test_qlinearmatmul_3D_cpu"), - (xfail_issue_38723, - "OnnxBackendNodeModelTest.test_qlinearconv_cpu"), - (xfail_issue_38724, - "OnnxBackendNodeModelTest.test_resize_tf_crop_and_resize_cpu"), - (xfail_issue_33606, - "OnnxBackendNodeModelTest.test_det_2d_cpu", - "OnnxBackendNodeModelTest.test_det_nd_cpu"), - (xfail_issue_38732, - "OnnxBackendNodeModelTest.test_convinteger_with_padding_cpu", - "OnnxBackendNodeModelTest.test_basic_convinteger_cpu"), - (xfail_issue_38734, - "OnnxBackendNodeModelTest.test_adam_multiple_cpu", - "OnnxBackendNodeModelTest.test_adam_cpu"), - (xfail_issue_38735, - "OnnxBackendNodeModelTest.test_adagrad_multiple_cpu", - "OnnxBackendNodeModelTest.test_adagrad_cpu"), - (xfail_issue_48052, - "OnnxBackendNodeModelTest.test_training_dropout_cpu", - "OnnxBackendNodeModelTest.test_training_dropout_mask_cpu", - "OnnxBackendNodeModelTest.test_training_dropout_default_cpu", - "OnnxBackendNodeModelTest.test_training_dropout_zero_ratio_cpu", - "OnnxBackendNodeModelTest.test_training_dropout_default_mask_cpu", - "OnnxBackendNodeModelTest.test_training_dropout_zero_ratio_mask_cpu"), - (xfail_issue_45180, - "OnnxBackendNodeModelTest.test_reduce_sum_do_not_keepdims_example_cpu", - "OnnxBackendNodeModelTest.test_reduce_sum_do_not_keepdims_random_cpu", - "OnnxBackendNodeModelTest.test_reduce_sum_keepdims_example_cpu", - "OnnxBackendNodeModelTest.test_reduce_sum_keepdims_random_cpu", - "OnnxBackendNodeModelTest.test_reduce_sum_negative_axes_keepdims_example_cpu"), - (xfail_issue_43742, - "OnnxBackendNodeModelTest.test_if_cpu", - "OnnxBackendNodeModelTest.test_if_seq_cpu"), - (xfail_issue_44848, - "OnnxBackendNodeModelTest.test_range_float_type_positive_delta_cpu", - "OnnxBackendNodeModelTest.test_range_int32_type_negative_delta_cpu",), - (xfail_issue_44851, - "OnnxBackendNodeModelTest.test_expand_dim_changed_cpu", - "OnnxBackendNodeModelTest.test_expand_dim_unchanged_cpu", - "OnnxBackendSimpleModelTest.test_expand_shape_model1_cpu", - "OnnxBackendSimpleModelTest.test_expand_shape_model2_cpu", - "OnnxBackendSimpleModelTest.test_expand_shape_model3_cpu", - "OnnxBackendSimpleModelTest.test_expand_shape_model4_cpu",), - (xfail_issue_44854, - "OnnxBackendNodeModelTest.test_split_variable_parts_1d_cpu", - "OnnxBackendNodeModelTest.test_split_variable_parts_2d_cpu", - "OnnxBackendNodeModelTest.test_split_variable_parts_default_axis_cpu",), - (xfail_issue_44858, - "OnnxBackendNodeModelTest.test_unsqueeze_axis_0_cpu", - "OnnxBackendNodeModelTest.test_unsqueeze_axis_1_cpu", - "OnnxBackendNodeModelTest.test_unsqueeze_axis_2_cpu", - "OnnxBackendNodeModelTest.test_unsqueeze_negative_axes_cpu", - "OnnxBackendNodeModelTest.test_unsqueeze_three_axes_cpu", - "OnnxBackendNodeModelTest.test_unsqueeze_two_axes_cpu", - "OnnxBackendNodeModelTest.test_unsqueeze_unsorted_axes_cpu",), - (xfail_issue_44956, - "OnnxBackendNodeModelTest.test_loop11_cpu", - "OnnxBackendNodeModelTest.test_range_int32_type_negative_delta_expanded_cpu", - "OnnxBackendNodeModelTest.test_range_float_type_positive_delta_expanded_cpu"), - (xfail_issue_44957, - "OnnxBackendNodeModelTest.test_compress_0_cpu", - "OnnxBackendNodeModelTest.test_compress_1_cpu", - "OnnxBackendNodeModelTest.test_compress_default_axis_cpu", - "OnnxBackendNodeModelTest.test_compress_negative_axis_cpu", - "OnnxBackendNodeModelTest.test_nonzero_example_cpu"), - (xfail_issue_44958, - "OnnxBackendNodeModelTest.test_upsample_nearest_cpu"), - (xfail_issue_44965, - "OnnxBackendNodeModelTest.test_loop13_seq_cpu", - "OnnxBackendNodeModelTest.test_sequence_insert_at_back_cpu", - "OnnxBackendNodeModelTest.test_sequence_insert_at_front_cpu",), - (xfail_issue_44968, - "OnnxBackendNodeModelTest.test_squeeze_cpu", - "OnnxBackendNodeModelTest.test_squeeze_negative_axes_cpu",), - (xfail_issue_44976, - "OnnxBackendNodeModelTest.test_quantizelinear_axis_cpu", - "OnnxBackendNodeModelTest.test_dynamicquantizelinear_min_adjusted_expanded_cpu", - "OnnxBackendNodeModelTest.test_dynamicquantizelinear_expanded_cpu", - "OnnxBackendNodeModelTest.test_dynamicquantizelinear_max_adjusted_expanded_cpu", - "OnnxBackendNodeModelTest.test_quantizelinear_cpu"), - (xfail_issue_33593, - "OnnxBackendNodeModelTest.test_maxpool_with_argmax_2d_precomputed_strides_cpu", - "OnnxBackendNodeModelTest.test_maxpool_with_argmax_2d_precomputed_pads_cpu",), - (xfail_issue_58033, - "OnnxBackendNodeModelTest.test_einsum_batch_diagonal_cpu"), + ( + xfail_issue_49207, + "OnnxBackendNodeModelTest.test_rnn_seq_length_cpu", + "OnnxBackendNodeModelTest.test_simple_rnn_defaults_cpu", + "OnnxBackendNodeModelTest.test_simple_rnn_with_initial_bias_cpu", + "OnnxBackendNodeModelTest.test_gru_defaults_cpu", + "OnnxBackendNodeModelTest.test_gru_seq_length_cpu", + "OnnxBackendNodeModelTest.test_gru_with_initial_bias_cpu", + "OnnxBackendNodeModelTest.test_lstm_defaults_cpu", + "OnnxBackendNodeModelTest.test_lstm_with_initial_bias_cpu", + "OnnxBackendNodeModelTest.test_lstm_with_peepholes_cpu", + ), + ( + xfail_issue_49752, + "OnnxBackendNodeModelTest.test_constant_pad_cpu", + "OnnxBackendNodeModelTest.test_edge_pad_cpu", + "OnnxBackendNodeModelTest.test_reflect_pad_cpu", + ), + ( + xfail_issue_39656, + "OnnxBackendNodeModelTest.test_reshape_extended_dims_cpu", + "OnnxBackendNodeModelTest.test_reshape_negative_dim_cpu", + "OnnxBackendNodeModelTest.test_reshape_one_dim_cpu", + "OnnxBackendNodeModelTest.test_reshape_reduced_dims_cpu", + "OnnxBackendNodeModelTest.test_reshape_negative_extended_dims_cpu", + "OnnxBackendNodeModelTest.test_reshape_reordered_all_dims_cpu", + "OnnxBackendNodeModelTest.test_reshape_reordered_last_dims_cpu", + "OnnxBackendNodeModelTest.test_reshape_zero_and_negative_dim_cpu", + "OnnxBackendNodeModelTest.test_reshape_zero_dim_cpu", + ), + ( + xfail_issue_39658, + "OnnxBackendNodeModelTest.test_tile_cpu", + "OnnxBackendNodeModelTest.test_tile_precomputed_cpu", + ), + ( + xfail_issue_39659, + "OnnxBackendNodeModelTest.test_constantofshape_float_ones_cpu", + "OnnxBackendNodeModelTest.test_constantofshape_int_zeros_cpu", + "OnnxBackendNodeModelTest.test_constantofshape_int_shape_zero_cpu", + ), + ( + xfail_issue_45344, + "OnnxBackendNodeModelTest.test_nonmaxsuppression_center_point_box_format_cpu", + "OnnxBackendNodeModelTest.test_nonmaxsuppression_flipped_coordinates_cpu", + "OnnxBackendNodeModelTest.test_nonmaxsuppression_identical_boxes_cpu", + "OnnxBackendNodeModelTest.test_nonmaxsuppression_limit_output_size_cpu", + "OnnxBackendNodeModelTest.test_nonmaxsuppression_single_box_cpu", + "OnnxBackendNodeModelTest.test_nonmaxsuppression_suppress_by_IOU_and_scores_cpu", + "OnnxBackendNodeModelTest.test_nonmaxsuppression_suppress_by_IOU_cpu", + "OnnxBackendNodeModelTest.test_nonmaxsuppression_two_batches_cpu", + "OnnxBackendNodeModelTest.test_nonmaxsuppression_two_classes_cpu", + ), + ( + xfail_issue_39662, + "OnnxBackendNodeModelTest.test_nonmaxsuppression_two_classes_cpu", + "OnnxBackendNodeModelTest.test_scatter_elements_with_negative_indices_cpu", + "OnnxBackendNodeModelTest.test_gather_negative_indices_cpu", + ), + (xfail_issue_49753, "OnnxBackendNodeModelTest.test_slice_default_axes_cpu"), + ( + xfail_issue_49754, + "OnnxBackendNodeModelTest.test_top_k_cpu", + "OnnxBackendNodeModelTest.test_top_k_negative_axis_cpu", + "OnnxBackendNodeModelTest.test_top_k_smallest_cpu", + ), + (xfail_issue_33633, "OnnxBackendNodeModelTest.test_maxpool_2d_dilations_cpu"), + ( + xfail_issue_46762, + "OnnxBackendNodeModelTest.test_min_uint8_cpu", + "OnnxBackendNodeModelTest.test_min_uint16_cpu", + "OnnxBackendNodeModelTest.test_min_uint32_cpu", + "OnnxBackendNodeModelTest.test_min_uint64_cpu", + ), + ( + xfail_issue_55760, + "OnnxBackendNodeModelTest.test_argmax_negative_axis_keepdims_example_select_last_index_cpu", + "OnnxBackendNodeModelTest.test_argmin_negative_axis_keepdims_example_select_last_index_cpu", + "OnnxBackendNodeModelTest.test_argmax_negative_axis_keepdims_random_select_last_index_cpu", + "OnnxBackendNodeModelTest.test_argmin_negative_axis_keepdims_random_select_last_index_cpu", + ), + (xfail_issue_38091, "OnnxBackendNodeModelTest.test_gather_negative_indices_cpu"), + ( + xfail_issue_52463, + "OnnxBackendPyTorchOperatorModelTest.test_operator_add_size1_singleton_broadcast_cpu", + ), + ( + xfail_issue_47323, + "OnnxBackendPyTorchOperatorModelTest.test_operator_add_broadcast_cpu", + "OnnxBackendPyTorchOperatorModelTest.test_operator_addconstant_cpu", + "OnnxBackendPyTorchOperatorModelTest.test_operator_add_size1_right_broadcast_cpu", + ), + ( + xfail_issue_38699, + "OnnxBackendSimpleModelTest.test_gradient_of_add_and_mul_cpu", + "OnnxBackendSimpleModelTest.test_gradient_of_add_cpu", + ), + ( + xfail_issue_33596, + "OnnxBackendSimpleModelTest.test_sequence_model5_cpu", + "OnnxBackendSimpleModelTest.test_sequence_model7_cpu", + "OnnxBackendSimpleModelTest.test_sequence_model1_cpu", + "OnnxBackendSimpleModelTest.test_sequence_model3_cpu", + "OnnxBackendSimpleModelTest.test_sequence_model6_cpu", + "OnnxBackendSimpleModelTest.test_sequence_model8_cpu", + "OnnxBackendSimpleModelTest.test_sequence_model4_cpu", + "OnnxBackendSimpleModelTest.test_sequence_model2_cpu", + "OnnxBackendNodeModelTest.test_identity_sequence_cpu", + ), + ( + xfail_issue_38701, + "OnnxBackendSimpleModelTest.test_strnorm_model_monday_casesensintive_nochangecase_cpu", + "OnnxBackendSimpleModelTest.test_strnorm_model_nostopwords_nochangecase_cpu", + "OnnxBackendSimpleModelTest.test_strnorm_model_monday_empty_output_cpu", + "OnnxBackendSimpleModelTest.test_strnorm_model_monday_insensintive_upper_twodim_cpu", + "OnnxBackendSimpleModelTest.test_strnorm_model_monday_casesensintive_lower_cpu", + "OnnxBackendSimpleModelTest.test_strnorm_model_monday_casesensintive_upper_cpu", + "OnnxBackendNodeModelTest.test_strnormalizer_nostopwords_nochangecase_cpu", + "OnnxBackendNodeModelTest.test_strnormalizer_export_monday_casesensintive_nochangecase_cpu", + "OnnxBackendNodeModelTest.test_strnormalizer_export_monday_insensintive_upper_twodim_cpu", + "OnnxBackendNodeModelTest.test_strnormalizer_export_monday_casesensintive_lower_cpu", + "OnnxBackendNodeModelTest.test_strnormalizer_export_monday_empty_output_cpu", + "OnnxBackendNodeModelTest.test_strnormalizer_export_monday_casesensintive_upper_cpu", + "OnnxBackendNodeModelTest.test_cast_STRING_to_FLOAT_cpu", + "OnnxBackendNodeModelTest.test_cast_FLOAT_to_STRING_cpu", + "OnnxBackendNodeModelTest.test_castlike_FLOAT_to_STRING_cpu", + "OnnxBackendNodeModelTest.test_castlike_FLOAT_to_STRING_expanded_cpu", + "OnnxBackendNodeModelTest.test_castlike_STRING_to_FLOAT_cpu", + "OnnxBackendNodeModelTest.test_castlike_STRING_to_FLOAT_expanded_cpu", + ), + ( + xfail_issue_33595, + "OnnxBackendNodeModelTest.test_unique_not_sorted_without_axis_cpu", + "OnnxBackendNodeModelTest.test_unique_sorted_with_negative_axis_cpu", + "OnnxBackendNodeModelTest.test_unique_sorted_with_axis_cpu", + "OnnxBackendNodeModelTest.test_unique_sorted_with_axis_3d_cpu", + "OnnxBackendNodeModelTest.test_unique_sorted_without_axis_cpu", + ), + ( + xfail_issue_33651, + "OnnxBackendNodeModelTest.test_tfidfvectorizer_tf_batch_onlybigrams_skip5_cpu", + "OnnxBackendNodeModelTest.test_tfidfvectorizer_tf_onlybigrams_levelempty_cpu", + "OnnxBackendNodeModelTest.test_tfidfvectorizer_tf_batch_onlybigrams_skip0_cpu", + "OnnxBackendNodeModelTest.test_tfidfvectorizer_tf_uniandbigrams_skip5_cpu", + "OnnxBackendNodeModelTest.test_tfidfvectorizer_tf_only_bigrams_skip0_cpu", + "OnnxBackendNodeModelTest.test_tfidfvectorizer_tf_batch_uniandbigrams_skip5_cpu", + "OnnxBackendNodeModelTest.test_tfidfvectorizer_tf_onlybigrams_skip5_cpu", + ), + (xfail_issue_38706, "OnnxBackendNodeModelTest.test_split_zero_size_splits_cpu"), + ( + xfail_issue_38708, + "OnnxBackendNodeModelTest.test_slice_default_steps_cpu", + "OnnxBackendNodeModelTest.test_slice_negative_axes_cpu", + "OnnxBackendNodeModelTest.test_slice_neg_steps_cpu", + "OnnxBackendNodeModelTest.test_slice_neg_cpu", + "OnnxBackendNodeModelTest.test_slice_cpu", + "OnnxBackendNodeModelTest.test_slice_end_out_of_bounds_cpu", + "OnnxBackendNodeModelTest.test_slice_start_out_of_bounds_cpu", + ), + ( + xfail_issue_33538, + "OnnxBackendNodeModelTest.test_scan_sum_cpu", + "OnnxBackendNodeModelTest.test_scan9_sum_cpu", + ), + ( + xfail_issue_49750, + "OnnxBackendNodeModelTest.test_resize_downsample_scales_linear_align_corners_cpu", + "OnnxBackendNodeModelTest.test_resize_upsample_scales_cubic_cpu", + "OnnxBackendNodeModelTest.test_resize_downsample_scales_cubic_cpu", + "OnnxBackendNodeModelTest.test_resize_downsample_scales_cubic_align_corners_cpu", + "OnnxBackendNodeModelTest.test_resize_upsample_scales_nearest_cpu", + "OnnxBackendNodeModelTest.test_resize_upsample_scales_cubic_asymmetric_cpu", + "OnnxBackendNodeModelTest.test_resize_downsample_scales_cubic_A_n0p5_exclude_outside_cpu", + "OnnxBackendNodeModelTest.test_resize_upsample_scales_linear_cpu", + "OnnxBackendNodeModelTest.test_resize_upsample_scales_cubic_align_corners_cpu", + "OnnxBackendNodeModelTest.test_resize_upsample_scales_linear_align_corners_cpu", + "OnnxBackendNodeModelTest.test_resize_upsample_scales_cubic_A_n0p5_exclude_outside_cpu", + "OnnxBackendNodeModelTest.test_resize_downsample_scales_nearest_cpu", + "OnnxBackendNodeModelTest.test_resize_downsample_scales_linear_cpu", + "OnnxBackendNodeModelTest.test_resize_downsample_sizes_cubic_cpu", + "OnnxBackendNodeModelTest.test_resize_upsample_sizes_nearest_round_prefer_ceil_asymmetric_cpu", + "OnnxBackendNodeModelTest.test_resize_upsample_sizes_nearest_floor_align_corners_cpu", + "OnnxBackendNodeModelTest.test_resize_upsample_sizes_nearest_cpu", + "OnnxBackendNodeModelTest.test_resize_upsample_sizes_nearest_ceil_half_pixel_cpu", + "OnnxBackendNodeModelTest.test_resize_upsample_sizes_cubic_cpu", + "OnnxBackendNodeModelTest.test_resize_downsample_sizes_linear_pytorch_half_pixel_cpu", + "OnnxBackendNodeModelTest.test_resize_downsample_sizes_nearest_cpu", + "OnnxBackendNodeModelTest.test_resize_downsample_sizes_nearest_tf_half_pixel_for_nn_cpu", + ), + ( + xfail_issue_33581, + "OnnxBackendNodeModelTest.test_gather_elements_negative_indices_cpu", + ), + ( + xfail_issue_38713, + "OnnxBackendNodeModelTest.test_momentum_cpu", + "OnnxBackendNodeModelTest.test_nesterov_momentum_cpu", + "OnnxBackendNodeModelTest.test_momentum_multiple_cpu", + ), + ( + xfail_issue_47337, + "OnnxBackendNodeModelTest.test_onehot_without_axis_cpu", + "OnnxBackendNodeModelTest.test_onehot_with_negative_axis_cpu", + "OnnxBackendNodeModelTest.test_onehot_with_axis_cpu", + "OnnxBackendNodeModelTest.test_onehot_negative_indices_cpu", + ), + ( + xfail_issue_33488, + "OnnxBackendNodeModelTest.test_maxunpool_export_with_output_shape_cpu", + "OnnxBackendNodeModelTest.test_maxunpool_export_without_output_shape_cpu", + ), + ( + xfail_issue_33589, + "OnnxBackendNodeModelTest.test_isnan_cpu", + "OnnxBackendNodeModelTest.test_isinf_positive_cpu", + "OnnxBackendNodeModelTest.test_isinf_negative_cpu", + "OnnxBackendNodeModelTest.test_isinf_cpu", + ), + ( + xfail_issue_33535, + "OnnxBackendNodeModelTest.test_dynamicquantizelinear_min_adjusted_cpu", + "OnnxBackendNodeModelTest.test_dynamicquantizelinear_cpu", + "OnnxBackendNodeModelTest.test_dynamicquantizelinear_max_adjusted_cpu", + ), + ( + xfail_issue_38722, + "OnnxBackendNodeModelTest.test_matmulinteger_cpu", + "OnnxBackendNodeModelTest.test_qlinearmatmul_2D_cpu", + "OnnxBackendNodeModelTest.test_qlinearmatmul_3D_cpu", + ), + (xfail_issue_38723, "OnnxBackendNodeModelTest.test_qlinearconv_cpu"), + (xfail_issue_38724, "OnnxBackendNodeModelTest.test_resize_tf_crop_and_resize_cpu"), + ( + xfail_issue_33606, + "OnnxBackendNodeModelTest.test_det_2d_cpu", + "OnnxBackendNodeModelTest.test_det_nd_cpu", + ), + ( + xfail_issue_38732, + "OnnxBackendNodeModelTest.test_convinteger_without_padding_cpu", + "OnnxBackendNodeModelTest.test_convinteger_with_padding_cpu", + "OnnxBackendNodeModelTest.test_basic_convinteger_cpu", + ), + ( + xfail_issue_38734, + "OnnxBackendNodeModelTest.test_adam_multiple_cpu", + "OnnxBackendNodeModelTest.test_adam_cpu", + ), + ( + xfail_issue_38735, + "OnnxBackendNodeModelTest.test_adagrad_multiple_cpu", + "OnnxBackendNodeModelTest.test_adagrad_cpu", + ), + ( + xfail_issue_48052, + "OnnxBackendNodeModelTest.test_training_dropout_cpu", + "OnnxBackendNodeModelTest.test_training_dropout_mask_cpu", + "OnnxBackendNodeModelTest.test_training_dropout_default_cpu", + "OnnxBackendNodeModelTest.test_training_dropout_zero_ratio_cpu", + "OnnxBackendNodeModelTest.test_training_dropout_default_mask_cpu", + "OnnxBackendNodeModelTest.test_training_dropout_zero_ratio_mask_cpu", + ), + ( + xfail_issue_45180, + "OnnxBackendNodeModelTest.test_reduce_sum_do_not_keepdims_example_cpu", + "OnnxBackendNodeModelTest.test_reduce_sum_do_not_keepdims_random_cpu", + "OnnxBackendNodeModelTest.test_reduce_sum_keepdims_example_cpu", + "OnnxBackendNodeModelTest.test_reduce_sum_keepdims_random_cpu", + "OnnxBackendNodeModelTest.test_reduce_sum_negative_axes_keepdims_example_cpu", + ), + ( + xfail_issue_43742, + "OnnxBackendNodeModelTest.test_if_cpu", + "OnnxBackendNodeModelTest.test_if_seq_cpu", + ), + ( + xfail_issue_44848, + "OnnxBackendNodeModelTest.test_range_float_type_positive_delta_cpu", + "OnnxBackendNodeModelTest.test_range_int32_type_negative_delta_cpu", + ), + ( + xfail_issue_44851, + "OnnxBackendNodeModelTest.test_expand_dim_changed_cpu", + "OnnxBackendNodeModelTest.test_expand_dim_unchanged_cpu", + "OnnxBackendSimpleModelTest.test_expand_shape_model1_cpu", + "OnnxBackendSimpleModelTest.test_expand_shape_model2_cpu", + "OnnxBackendSimpleModelTest.test_expand_shape_model3_cpu", + "OnnxBackendSimpleModelTest.test_expand_shape_model4_cpu", + ), + ( + xfail_issue_44854, + "OnnxBackendNodeModelTest.test_split_variable_parts_1d_cpu", + "OnnxBackendNodeModelTest.test_split_variable_parts_2d_cpu", + "OnnxBackendNodeModelTest.test_split_variable_parts_default_axis_cpu", + ), + ( + xfail_issue_44858, + "OnnxBackendNodeModelTest.test_unsqueeze_axis_0_cpu", + "OnnxBackendNodeModelTest.test_unsqueeze_axis_1_cpu", + "OnnxBackendNodeModelTest.test_unsqueeze_axis_2_cpu", + "OnnxBackendNodeModelTest.test_unsqueeze_negative_axes_cpu", + "OnnxBackendNodeModelTest.test_unsqueeze_three_axes_cpu", + "OnnxBackendNodeModelTest.test_unsqueeze_two_axes_cpu", + "OnnxBackendNodeModelTest.test_unsqueeze_unsorted_axes_cpu", + ), + ( + xfail_issue_44956, + "OnnxBackendNodeModelTest.test_loop11_cpu", + "OnnxBackendNodeModelTest.test_range_int32_type_negative_delta_expanded_cpu", + "OnnxBackendNodeModelTest.test_range_float_type_positive_delta_expanded_cpu", + ), + ( + xfail_issue_44957, + "OnnxBackendNodeModelTest.test_compress_0_cpu", + "OnnxBackendNodeModelTest.test_compress_1_cpu", + "OnnxBackendNodeModelTest.test_compress_default_axis_cpu", + "OnnxBackendNodeModelTest.test_compress_negative_axis_cpu", + "OnnxBackendNodeModelTest.test_nonzero_example_cpu", + ), + (xfail_issue_44958, "OnnxBackendNodeModelTest.test_upsample_nearest_cpu"), + ( + xfail_issue_44965, + "OnnxBackendNodeModelTest.test_loop13_seq_cpu", + "OnnxBackendNodeModelTest.test_sequence_insert_at_back_cpu", + "OnnxBackendNodeModelTest.test_sequence_insert_at_front_cpu", + ), + ( + xfail_issue_44968, + "OnnxBackendNodeModelTest.test_squeeze_cpu", + "OnnxBackendNodeModelTest.test_squeeze_negative_axes_cpu", + ), + ( + xfail_issue_44976, + "OnnxBackendNodeModelTest.test_quantizelinear_axis_cpu", + "OnnxBackendNodeModelTest.test_dynamicquantizelinear_min_adjusted_expanded_cpu", + "OnnxBackendNodeModelTest.test_dynamicquantizelinear_expanded_cpu", + "OnnxBackendNodeModelTest.test_dynamicquantizelinear_max_adjusted_expanded_cpu", + "OnnxBackendNodeModelTest.test_quantizelinear_cpu", + ), + ( + xfail_issue_33593, + "OnnxBackendNodeModelTest.test_maxpool_with_argmax_2d_precomputed_strides_cpu", + "OnnxBackendNodeModelTest.test_maxpool_with_argmax_2d_precomputed_pads_cpu", + ), + (xfail_issue_58033, "OnnxBackendNodeModelTest.test_einsum_batch_diagonal_cpu"), + ( + xfail_issue_63033, + "OnnxBackendNodeModelTest.test_batchnorm_epsilon_training_mode_cpu", + "OnnxBackendNodeModelTest.test_batchnorm_example_training_mode_cpu", + ), + (xfail_issue_63036, "OnnxBackendNodeModelTest.test_convtranspose_autopad_same_cpu"), + ( + xfail_issue_63039, + "OnnxBackendNodeModelTest.test_div_uint8_cpu", + "OnnxBackendNodeModelTest.test_mul_uint8_cpu", + "OnnxBackendNodeModelTest.test_sub_uint8_cpu", + ), + ( + xfail_issue_63043, + "OnnxBackendNodeModelTest.test_gru_batchwise_cpu", + "OnnxBackendNodeModelTest.test_lstm_batchwise_cpu", + "OnnxBackendNodeModelTest.test_simple_rnn_batchwise_cpu", + ), + ( + xfail_issue_38710, + "OnnxBackendNodeModelTest.test_reshape_allowzero_reordered_cpu", + ), + ( + xfail_issue_63044, + "OnnxBackendNodeModelTest.test_tril_cpu", + "OnnxBackendNodeModelTest.test_tril_neg_cpu", + "OnnxBackendNodeModelTest.test_tril_one_row_neg_cpu", + "OnnxBackendNodeModelTest.test_tril_out_neg_cpu", + "OnnxBackendNodeModelTest.test_tril_out_pos_cpu", + "OnnxBackendNodeModelTest.test_tril_pos_cpu", + "OnnxBackendNodeModelTest.test_tril_square_cpu", + "OnnxBackendNodeModelTest.test_tril_square_neg_cpu", + "OnnxBackendNodeModelTest.test_tril_zero_cpu", + "OnnxBackendNodeModelTest.test_triu_cpu", + "OnnxBackendNodeModelTest.test_triu_neg_cpu", + "OnnxBackendNodeModelTest.test_triu_one_row_cpu", + "OnnxBackendNodeModelTest.test_triu_out_neg_out_cpu", + "OnnxBackendNodeModelTest.test_triu_out_pos_cpu", + "OnnxBackendNodeModelTest.test_triu_pos_cpu", + "OnnxBackendNodeModelTest.test_triu_square_cpu", + "OnnxBackendNodeModelTest.test_triu_square_neg_cpu", + "OnnxBackendNodeModelTest.test_triu_zero_cpu", + ), + ( + xfail_issue_63045, + "OnnxBackendPyTorchConvertedModelTest.test_MaxPool1d_stride_padding_dilation_cpu", + "OnnxBackendPyTorchConvertedModelTest.test_MaxPool2d_stride_padding_dilation_cpu", + ), + ( + skip_rng_tests, + "OnnxBackendNodeModelTest.test_bernoulli_cpu", + "OnnxBackendNodeModelTest.test_bernoulli_double_cpu", + "OnnxBackendNodeModelTest.test_bernoulli_double_expanded_cpu", + "OnnxBackendNodeModelTest.test_bernoulli_expanded_cpu", + "OnnxBackendNodeModelTest.test_bernoulli_seed_cpu", + "OnnxBackendNodeModelTest.test_bernoulli_seed_expanded_cpu", + ), + ( + xfail_issue_63136, + "OnnxBackendNodeModelTest.test_castlike_BFLOAT16_to_FLOAT_cpu", + "OnnxBackendNodeModelTest.test_castlike_DOUBLE_to_FLOAT16_cpu", + "OnnxBackendNodeModelTest.test_castlike_DOUBLE_to_FLOAT_cpu", + "OnnxBackendNodeModelTest.test_castlike_FLOAT16_to_DOUBLE_cpu", + "OnnxBackendNodeModelTest.test_castlike_FLOAT16_to_FLOAT_cpu", + "OnnxBackendNodeModelTest.test_castlike_FLOAT_to_BFLOAT16_cpu", + "OnnxBackendNodeModelTest.test_castlike_FLOAT_to_DOUBLE_cpu", + "OnnxBackendNodeModelTest.test_castlike_FLOAT_to_FLOAT16_cpu", + ), + ( + xfail_issue_63137, + "OnnxBackendNodeModelTest.test_optional_get_element_cpu", + "OnnxBackendNodeModelTest.test_optional_get_element_sequence_cpu", + "OnnxBackendNodeModelTest.test_optional_has_element_cpu", + "OnnxBackendNodeModelTest.test_optional_has_element_empty_cpu", + ), + ( + xfail_issue_63138, + "OnnxBackendNodeModelTest.test_shape_end_1_cpu", + "OnnxBackendNodeModelTest.test_shape_end_negative_1_cpu", + "OnnxBackendNodeModelTest.test_shape_start_1_cpu", + "OnnxBackendNodeModelTest.test_shape_start_1_end_2_cpu", + "OnnxBackendNodeModelTest.test_shape_start_1_end_negative_1_cpu", + "OnnxBackendNodeModelTest.test_shape_start_negative_1_cpu", + ), ] for test_group in tests_expected_to_fail: diff --git a/ngraph/python/tests/test_onnx/test_zoo_models.py b/ngraph/python/tests/test_onnx/test_zoo_models.py index 720659a19f3..dd253460044 100644 --- a/ngraph/python/tests/test_onnx/test_zoo_models.py +++ b/ngraph/python/tests/test_onnx/test_zoo_models.py @@ -1,11 +1,9 @@ # Copyright (C) 2018-2021 Intel Corporation # SPDX-License-Identifier: Apache-2.0 -import pytest import tests from operator import itemgetter from pathlib import Path -import os from typing import Sequence, Any import numpy as np @@ -134,7 +132,7 @@ for path in Path(MODELS_ROOT_DIR).rglob("*.onnx"): zoo_models.append(model) if len(zoo_models) > 0: - sorted(zoo_models, key=itemgetter("model_name")) + zoo_models = sorted(zoo_models, key=itemgetter("model_name")) # Set backend device name to be used instead of hardcoded by ONNX BackendTest class ones. OpenVinoOnnxBackend.backend_name = tests.BACKEND_NAME diff --git a/ngraph/python/tests/test_onnx/utils/model_importer.py b/ngraph/python/tests/test_onnx/utils/model_importer.py index 44e09e4860f..4979a5cf5bd 100644 --- a/ngraph/python/tests/test_onnx/utils/model_importer.py +++ b/ngraph/python/tests/test_onnx/utils/model_importer.py @@ -33,6 +33,7 @@ class ModelImportRunner(onnx.backend.test.BackendTest): self._include_patterns = set() # type: Set[Pattern[Text]] self._exclude_patterns = set() # type: Set[Pattern[Text]] self._test_items = defaultdict(dict) # type: Dict[Text, Dict[Text, TestItem]] + self._xfail_patterns = set() # type: Set[Pattern[Text]] for model in models: test_name = "test{}".format(model["model_name"]) \ diff --git a/ngraph/test/CMakeLists.txt b/ngraph/test/CMakeLists.txt index 7eed6dd82b5..a851e199d73 100644 --- a/ngraph/test/CMakeLists.txt +++ b/ngraph/test/CMakeLists.txt @@ -8,11 +8,11 @@ set(NGRAPH_ONNX_NAMESPACE ngraph_onnx) add_subdirectory(runtime) if(NOT NGRAPH_UNIT_TEST_ENABLE) - message(STATUS "unit tests disabled") + message(STATUS "nGraph unit tests disabled") return() endif() -message(STATUS "unit tests enabled") +message(STATUS "nGraph unit tests enabled") if(LINUX) set(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE) diff --git a/ngraph/test/requirements_test_onnx.txt b/ngraph/test/requirements_test_onnx.txt index 4e7803c987b..86e1f720c0d 100644 --- a/ngraph/test/requirements_test_onnx.txt +++ b/ngraph/test/requirements_test_onnx.txt @@ -1,4 +1,4 @@ # ONNX - generate test models docopt~=0.6.2 -onnx~=1.9.0 +onnx~=1.10.0 protobuf>=3.9 \ No newline at end of file diff --git a/thirdparty/onnx/onnx b/thirdparty/onnx/onnx index 685898bc6f3..1089b9e8045 160000 --- a/thirdparty/onnx/onnx +++ b/thirdparty/onnx/onnx @@ -1 +1 @@ -Subproject commit 685898bc6f3fd6eb16ba129ea990f96330537e38 +Subproject commit 1089b9e8045a3a2882d7bb6a1dbaeaf9cae131da From 158b630354f11bd4ebf85cdbe85b0960650ae8fc Mon Sep 17 00:00:00 2001 From: Mikhail Ryzhov Date: Wed, 25 Aug 2021 12:57:44 +0300 Subject: [PATCH 34/76] [Samples] Enabled oname for imported models (#7227) --- inference-engine/samples/speech_sample/main.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/inference-engine/samples/speech_sample/main.cpp b/inference-engine/samples/speech_sample/main.cpp index d236fc84833..640081a876b 100644 --- a/inference-engine/samples/speech_sample/main.cpp +++ b/inference-engine/samples/speech_sample/main.cpp @@ -719,8 +719,10 @@ int main(int argc, char* argv[]) { } } - for (size_t i = 0; i < outputs.size(); i++) { - network.addOutput(outputs[i], ports[i]); + if (!FLAGS_m.empty()) { + for (size_t i = 0; i < outputs.size(); i++) { + network.addOutput(outputs[i], ports[i]); + } } } if (!FLAGS_m.empty()) { From 8e476c5fedb84705db2cc26a84b0fed9add94eee Mon Sep 17 00:00:00 2001 From: Mateusz Tabaka Date: Wed, 25 Aug 2021 12:07:00 +0200 Subject: [PATCH 35/76] StridesPropagation - retain original padding when setting Convolution strides (#6943) When propagating strides to Convolution node, make sure that setting strides does not change padding in cases when auto_pad is not EXPLICIT. When padding type is not EXPLICIT, strides make a role in paddings calculation. Changes in paddings, result in change in an image position that filter is applied, so we may end up with unwanted results after that. --- .../strides_optimization.cpp | 6 +++ .../subgraph_tests/conv_strides_opt.cpp | 29 ++++++++++++ .../subgraph_tests/conv_strides_opt.hpp | 14 ++++++ .../subgraph/conv_strides_opt.hpp | 32 ++++++++++++++ .../src/subgraph/conv_strides_opt.cpp | 44 +++++++++++++++++++ 5 files changed, 125 insertions(+) create mode 100644 inference-engine/tests/functional/plugin/cpu/shared_tests_instances/subgraph_tests/conv_strides_opt.cpp create mode 100644 inference-engine/tests/functional/plugin/shared/include/subgraph_tests/conv_strides_opt.hpp create mode 100644 inference-engine/tests/functional/shared_test_classes/include/shared_test_classes/subgraph/conv_strides_opt.hpp create mode 100644 inference-engine/tests/functional/shared_test_classes/src/subgraph/conv_strides_opt.cpp diff --git a/inference-engine/src/transformations/src/transformations/common_optimizations/strides_optimization.cpp b/inference-engine/src/transformations/src/transformations/common_optimizations/strides_optimization.cpp index a490cf361cf..bb93ed831af 100644 --- a/inference-engine/src/transformations/src/transformations/common_optimizations/strides_optimization.cpp +++ b/inference-engine/src/transformations/src/transformations/common_optimizations/strides_optimization.cpp @@ -118,6 +118,12 @@ ngraph::pass::ConvStridesPropagation::ConvStridesPropagation() { auto conv_input = conv->input(0); insert_strides_prop(conv_input, conv_strides); } else { + // Retain original padding + // Make sure that setting strides does not change padding in cases when auto_pad is not EXPLICIT. + // When padding type is not EXPLICIT, strides make a role to paddings calculation. + // Change in padding, results in change in image position that filter is applied, + // so we may end up with unwanted results after that. + conv->set_auto_pad(op::PadType::EXPLICIT); conv->set_strides(conv_strides); } diff --git a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/subgraph_tests/conv_strides_opt.cpp b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/subgraph_tests/conv_strides_opt.cpp new file mode 100644 index 00000000000..6a433a9175c --- /dev/null +++ b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/subgraph_tests/conv_strides_opt.cpp @@ -0,0 +1,29 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include + +#include "subgraph_tests/conv_strides_opt.hpp" +#include "common_test_utils/test_constants.hpp" + +using namespace SubgraphTestsDefinitions; + +namespace { + std::vector input_shapes{ + ngraph::Shape{1, 1, 4, 4}, + ngraph::Shape{1, 64, 56, 56}, + }; + std::vector pads{ + ngraph::op::PadType::SAME_UPPER, + ngraph::op::PadType::SAME_LOWER, + ngraph::op::PadType::EXPLICIT, + }; + INSTANTIATE_TEST_SUITE_P(smoke_Convolution_StridesOpt, ConvStridesOpt, + ::testing::Combine( + ::testing::ValuesIn(input_shapes), + ::testing::ValuesIn(pads), + ::testing::Values(CommonTestUtils::DEVICE_CPU)), + ConvStridesOpt::getTestCaseName); + +} // namespace diff --git a/inference-engine/tests/functional/plugin/shared/include/subgraph_tests/conv_strides_opt.hpp b/inference-engine/tests/functional/plugin/shared/include/subgraph_tests/conv_strides_opt.hpp new file mode 100644 index 00000000000..d2a68107823 --- /dev/null +++ b/inference-engine/tests/functional/plugin/shared/include/subgraph_tests/conv_strides_opt.hpp @@ -0,0 +1,14 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +#include "shared_test_classes/subgraph/conv_strides_opt.hpp" + +namespace SubgraphTestsDefinitions { + +TEST_P(ConvStridesOpt, CompareWithRefs) { + Run(); +} +} // namespace SubgraphTestsDefinitions diff --git a/inference-engine/tests/functional/shared_test_classes/include/shared_test_classes/subgraph/conv_strides_opt.hpp b/inference-engine/tests/functional/shared_test_classes/include/shared_test_classes/subgraph/conv_strides_opt.hpp new file mode 100644 index 00000000000..a5c262740b8 --- /dev/null +++ b/inference-engine/tests/functional/shared_test_classes/include/shared_test_classes/subgraph/conv_strides_opt.hpp @@ -0,0 +1,32 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +#include +#include +#include +#include "shared_test_classes/base/layer_test_utils.hpp" +#include "ngraph_functions/builders.hpp" +#include +#include + +namespace SubgraphTestsDefinitions { + +typedef std::tuple< + ngraph::Shape, // input shape + ngraph::op::PadType, + std::string // Device name + > ConvStridesOptParams; + +class ConvStridesOpt + : public testing::WithParamInterface, + public LayerTestsUtils::LayerTestsCommon { +public: + static std::string getTestCaseName(const testing::TestParamInfo &obj); + +protected: + void SetUp() override; +}; +} // namespace SubgraphTestsDefinitions diff --git a/inference-engine/tests/functional/shared_test_classes/src/subgraph/conv_strides_opt.cpp b/inference-engine/tests/functional/shared_test_classes/src/subgraph/conv_strides_opt.cpp new file mode 100644 index 00000000000..9ac09308e70 --- /dev/null +++ b/inference-engine/tests/functional/shared_test_classes/src/subgraph/conv_strides_opt.cpp @@ -0,0 +1,44 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "shared_test_classes/subgraph/conv_strides_opt.hpp" + +namespace SubgraphTestsDefinitions { + +using namespace ngraph; + +std::string ConvStridesOpt::getTestCaseName(const testing::TestParamInfo &obj) { + Shape input_shape; + op::PadType pad; + std::string targetName; + std::tie(input_shape, pad, targetName) = obj.param; + std::ostringstream results; + + results << "inputShape=" << input_shape << "_"; + results << "padType=" << pad << "_"; + results << "targetDevice=" << targetName; + return results.str(); +} + +void ConvStridesOpt::SetUp() { + Shape input_shape; + op::PadType pad_type; + std::tie(input_shape, pad_type, targetDevice) = this->GetParam(); + auto param = std::make_shared(element::f32, input_shape); + auto C = input_shape[1]; + auto weights1 = ngraph::builder::makeConstant(element::f32, {C, C, 3, 3}, {}, true); + auto spatial_dims = input_shape.size() - 2; + Strides strides1(spatial_dims, 1); + Strides dilations(spatial_dims, 1); + CoordinateDiff pad_begin1(spatial_dims, 1), pad_end1(spatial_dims, 1); + auto conv1 = std::make_shared(param, weights1, strides1, pad_begin1, pad_end1, + dilations, pad_type); + auto weights2 = ngraph::builder::makeConstant(element::f32, {C, C, 1, 1}, {}, true); + CoordinateDiff pad_begin2(spatial_dims, 0), pad_end2(spatial_dims, 0); + Strides strides2(spatial_dims, 2); + auto conv2 = std::make_shared(conv1, weights2, strides2, pad_begin2, pad_end2, + dilations); + function = std::make_shared(OutputVector{conv2}, ParameterVector{param}); +} +} // namespace SubgraphTestsDefinitions From 841c3531fbf610ac7544665cdcfc2e3c2449af0d Mon Sep 17 00:00:00 2001 From: Irina Efode Date: Wed, 25 Aug 2021 14:43:19 +0300 Subject: [PATCH 36/76] [IE TESTS] Behavior2.0 -> InferRequest() (#6559) * Need to remove * Preprocessing + InferRequest * infer_request_callback * tmp commit * InferRequest * tst * tetet * Fix template * SetBlobType * InferRequest Conformance * Add prc * Remove prc * Fix paths * commit * Fixes for review * Dynamic Batch * fix * fiz * Try * fkf * Fix azure * Centos * skip * conformance fix * fix template * Small fix * small fix in print * Fixes --- .../behavior/{ => caching}/caching_tests.cpp | 4 +- .../callback.cpp} | 13 +- .../config.cpp} | 13 +- .../io_blob.cpp} | 15 +- .../multithreading.cpp} | 12 +- .../wait.cpp} | 15 +- .../behavior/layout.cpp | 38 - .../{ => preprocessing}/preprocessing.cpp | 10 +- .../{ => preprocessing}/set_preprocess.cpp | 22 +- .../tests/functional/skip_tests_config.cpp | 10 +- .../src/behavior/infer_request/callback.cpp | 41 ++ .../behavior/infer_request/cancellation.cpp | 21 + .../src/behavior/infer_request/io_blob.cpp | 44 ++ .../behavior/infer_request/multitheading.cpp | 47 ++ .../behavior/infer_request/perf_counters.cpp | 33 + .../infer_request/set_blob_by_type.cpp | 52 ++ .../src/behavior/infer_request/wait.cpp | 46 ++ .../behavior/preprocessing/set_preprocess.cpp | 189 +++++ .../test_runner/src/read_ir/read_ir.cpp | 1 + .../behavior/caching_tests.cpp | 2 +- .../callback.cpp} | 22 +- .../cancellation.cpp} | 12 +- .../config.cpp} | 52 +- .../infer_request}/dynamic_batch.cpp | 2 +- .../behavior/infer_request/io_blob.cpp | 125 ++++ .../multitheading.cpp} | 22 +- .../behavior/infer_request/perf_counters.cpp | 51 ++ .../infer_request/set_blob_by_type.cpp | 48 ++ .../behavior/infer_request/wait.cpp | 44 ++ .../behavior/infer_request_input.cpp | 49 -- .../behavior/infer_request_output.cpp | 45 -- .../behavior/layout.cpp | 37 - .../behavior/perf_counters.cpp | 31 - .../{ => preprocessing}/preprocessing.cpp | 2 +- .../{ => preprocessing}/set_preprocess.cpp | 52 +- .../behavior/set_blob_of_kind.cpp | 44 -- .../skip_tests_config.cpp | 18 +- .../behavior/{ => caching}/caching_tests.cpp | 2 +- .../behavior/infer_request.cpp | 27 - .../callback.cpp} | 17 +- .../config.cpp} | 21 +- .../behavior/infer_request/io_blob.cpp | 16 + .../{ => infer_request}/memory_states.cpp | 13 +- .../behavior/infer_request/multitheading.cpp | 14 + .../behavior/infer_request/wait.cpp | 16 + .../behavior/infer_request_input.cpp | 25 - .../behavior/infer_request_output.cpp | 24 - .../behavior/layout.cpp | 34 - .../skip_tests_config.cpp | 8 +- .../behavior/caching_tests.cpp | 2 +- .../callback.cpp} | 22 +- .../behavior/infer_request/config.cpp | 30 + .../infer_request}/dynamic_batch.cpp | 2 +- .../behavior/infer_request/io_blob.cpp | 120 ++++ .../behavior/infer_request/multithreading.cpp | 39 ++ .../{ => infer_request}/perf_counters.cpp | 12 +- .../infer_request/set_blob_by_type.cpp | 48 ++ .../wait.cpp} | 22 +- .../behavior/infer_request_config.cpp | 36 - .../behavior/infer_request_input.cpp | 49 -- .../behavior/infer_request_output.cpp | 44 -- .../behavior/layout.cpp | 32 - .../{ => preprocessing}/set_preprocess.cpp | 22 +- .../behavior/set_blob_of_kind.cpp | 24 - .../skip_tests_config.cpp | 15 +- .../behavior/{ => caching}/caching_tests.cpp | 2 +- .../callback.cpp} | 16 +- .../config.cpp} | 32 +- .../io_blob.cpp} | 21 +- .../behavior/infer_request/multithreading.cpp | 27 + .../behavior/infer_request/wait.cpp | 27 + .../behavior/infer_request_input.cpp | 36 - .../behavior/infer_request_output.cpp | 36 - .../behavior/layout.cpp | 36 - .../{ => preprocessing}/set_preprocess.cpp | 18 +- .../skip_tests_config.cpp | 6 +- .../include/base/behavior_test_utils.hpp | 62 +- .../behavior/{ => caching}/caching_tests.hpp | 0 .../plugin/shared/include/behavior/config.hpp | 2 +- .../include/behavior/exec_graph_info.hpp | 38 +- .../shared/include/behavior/infer_request.hpp | 657 ------------------ .../callback.hpp} | 130 ++-- .../cancellation.hpp} | 60 +- .../include/behavior/infer_request/config.hpp | 96 +++ .../infer_request}/dynamic_batch.hpp | 0 .../behavior/infer_request/io_blob.hpp | 501 +++++++++++++ .../{ => infer_request}/memory_states.hpp | 10 +- .../behavior/infer_request/multithreading.hpp | 78 +++ .../behavior/infer_request/perf_counters.hpp | 50 ++ .../infer_request/set_blob_by_type.hpp | 94 +++ .../include/behavior/infer_request/wait.hpp | 103 +++ .../include/behavior/infer_request_config.hpp | 100 --- .../include/behavior/infer_request_input.hpp | 139 ---- .../include/behavior/infer_request_output.hpp | 137 ---- .../plugin/shared/include/behavior/layout.hpp | 55 -- .../shared/include/behavior/perf_counters.hpp | 39 -- .../{ => preprocessing}/preprocessing.hpp | 19 +- .../{ => preprocessing}/set_preprocess.hpp | 66 +- .../include/behavior/set_blob_of_kind.hpp | 32 - .../behavior/{ => caching}/caching_tests.cpp | 2 +- .../infer_request}/dynamic_batch.cpp | 12 +- .../{ => infer_request}/memory_states.cpp | 81 +-- .../plugin/shared/src/behavior/layout.cpp | 111 --- .../plugin/shared/src/behavior/set_blob.cpp | 4 +- .../shared/src/behavior/set_blob_of_kind.cpp | 106 --- .../base/layer_test_utils.hpp | 2 +- .../src/base/layer_test_utils.cpp | 2 +- .../common_test_utils/common_utils.hpp | 8 + .../common_test_utils/test_constants.hpp | 2 + .../functional_test_utils/blob_utils.hpp | 137 +++- .../ie_memory_state_internal_test.cpp | 46 +- 111 files changed, 2612 insertions(+), 2646 deletions(-) rename docs/template_plugin/tests/functional/shared_tests_instances/behavior/{ => caching}/caching_tests.cpp (85%) rename docs/template_plugin/tests/functional/shared_tests_instances/behavior/{infer_request_callback.cpp => infer_request/callback.cpp} (53%) rename docs/template_plugin/tests/functional/shared_tests_instances/behavior/{infer_request.cpp => infer_request/config.cpp} (54%) rename docs/template_plugin/tests/functional/shared_tests_instances/behavior/{infer_request_output.cpp => infer_request/io_blob.cpp} (52%) rename docs/template_plugin/tests/functional/shared_tests_instances/behavior/{infer_request_config.cpp => infer_request/multithreading.cpp} (54%) rename docs/template_plugin/tests/functional/shared_tests_instances/behavior/{infer_request_input.cpp => infer_request/wait.cpp} (52%) delete mode 100644 docs/template_plugin/tests/functional/shared_tests_instances/behavior/layout.cpp rename docs/template_plugin/tests/functional/shared_tests_instances/behavior/{ => preprocessing}/preprocessing.cpp (69%) rename docs/template_plugin/tests/functional/shared_tests_instances/behavior/{ => preprocessing}/set_preprocess.cpp (79%) create mode 100644 inference-engine/tests/functional/plugin/conformance/test_runner/src/behavior/infer_request/callback.cpp create mode 100644 inference-engine/tests/functional/plugin/conformance/test_runner/src/behavior/infer_request/cancellation.cpp create mode 100644 inference-engine/tests/functional/plugin/conformance/test_runner/src/behavior/infer_request/io_blob.cpp create mode 100644 inference-engine/tests/functional/plugin/conformance/test_runner/src/behavior/infer_request/multitheading.cpp create mode 100644 inference-engine/tests/functional/plugin/conformance/test_runner/src/behavior/infer_request/perf_counters.cpp create mode 100644 inference-engine/tests/functional/plugin/conformance/test_runner/src/behavior/infer_request/set_blob_by_type.cpp create mode 100644 inference-engine/tests/functional/plugin/conformance/test_runner/src/behavior/infer_request/wait.cpp create mode 100644 inference-engine/tests/functional/plugin/conformance/test_runner/src/behavior/preprocessing/set_preprocess.cpp rename inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/{infer_request_callback.cpp => infer_request/callback.cpp} (62%) rename inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/{infer_request_cancellation.cpp => infer_request/cancellation.cpp} (50%) rename inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/{infer_request_config.cpp => infer_request/config.cpp} (65%) rename inference-engine/tests/functional/plugin/cpu/shared_tests_instances/{configuration_tests => behavior/infer_request}/dynamic_batch.cpp (95%) create mode 100644 inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/infer_request/io_blob.cpp rename inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/{infer_request.cpp => infer_request/multitheading.cpp} (67%) create mode 100644 inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/infer_request/perf_counters.cpp create mode 100644 inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/infer_request/set_blob_by_type.cpp create mode 100644 inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/infer_request/wait.cpp delete mode 100644 inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/infer_request_input.cpp delete mode 100644 inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/infer_request_output.cpp delete mode 100644 inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/layout.cpp delete mode 100644 inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/perf_counters.cpp rename inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/{ => preprocessing}/preprocessing.cpp (96%) rename inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/{ => preprocessing}/set_preprocess.cpp (78%) delete mode 100644 inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/set_blob_of_kind.cpp rename inference-engine/tests/functional/plugin/gna/shared_tests_instances/behavior/{ => caching}/caching_tests.cpp (95%) delete mode 100644 inference-engine/tests/functional/plugin/gna/shared_tests_instances/behavior/infer_request.cpp rename inference-engine/tests/functional/plugin/gna/shared_tests_instances/behavior/{infer_request_callback.cpp => infer_request/callback.cpp} (57%) rename inference-engine/tests/functional/plugin/gna/shared_tests_instances/behavior/{infer_request_config.cpp => infer_request/config.cpp} (66%) create mode 100644 inference-engine/tests/functional/plugin/gna/shared_tests_instances/behavior/infer_request/io_blob.cpp rename inference-engine/tests/functional/plugin/gna/shared_tests_instances/behavior/{ => infer_request}/memory_states.cpp (92%) create mode 100644 inference-engine/tests/functional/plugin/gna/shared_tests_instances/behavior/infer_request/multitheading.cpp create mode 100644 inference-engine/tests/functional/plugin/gna/shared_tests_instances/behavior/infer_request/wait.cpp delete mode 100644 inference-engine/tests/functional/plugin/gna/shared_tests_instances/behavior/infer_request_input.cpp delete mode 100644 inference-engine/tests/functional/plugin/gna/shared_tests_instances/behavior/infer_request_output.cpp delete mode 100644 inference-engine/tests/functional/plugin/gna/shared_tests_instances/behavior/layout.cpp rename inference-engine/tests/functional/plugin/gpu/shared_tests_instances/behavior/{infer_request_callback.cpp => infer_request/callback.cpp} (55%) create mode 100644 inference-engine/tests/functional/plugin/gpu/shared_tests_instances/behavior/infer_request/config.cpp rename inference-engine/tests/functional/plugin/gpu/shared_tests_instances/{configuration_tests => behavior/infer_request}/dynamic_batch.cpp (95%) create mode 100644 inference-engine/tests/functional/plugin/gpu/shared_tests_instances/behavior/infer_request/io_blob.cpp create mode 100644 inference-engine/tests/functional/plugin/gpu/shared_tests_instances/behavior/infer_request/multithreading.cpp rename inference-engine/tests/functional/plugin/gpu/shared_tests_instances/behavior/{ => infer_request}/perf_counters.cpp (62%) create mode 100644 inference-engine/tests/functional/plugin/gpu/shared_tests_instances/behavior/infer_request/set_blob_by_type.cpp rename inference-engine/tests/functional/plugin/gpu/shared_tests_instances/behavior/{infer_request.cpp => infer_request/wait.cpp} (61%) delete mode 100644 inference-engine/tests/functional/plugin/gpu/shared_tests_instances/behavior/infer_request_config.cpp delete mode 100644 inference-engine/tests/functional/plugin/gpu/shared_tests_instances/behavior/infer_request_input.cpp delete mode 100644 inference-engine/tests/functional/plugin/gpu/shared_tests_instances/behavior/infer_request_output.cpp delete mode 100644 inference-engine/tests/functional/plugin/gpu/shared_tests_instances/behavior/layout.cpp rename inference-engine/tests/functional/plugin/gpu/shared_tests_instances/behavior/{ => preprocessing}/set_preprocess.cpp (79%) delete mode 100644 inference-engine/tests/functional/plugin/gpu/shared_tests_instances/behavior/set_blob_of_kind.cpp rename inference-engine/tests/functional/plugin/myriad/shared_tests_instances/behavior/{ => caching}/caching_tests.cpp (97%) rename inference-engine/tests/functional/plugin/myriad/shared_tests_instances/behavior/{infer_request_callback.cpp => infer_request/callback.cpp} (59%) rename inference-engine/tests/functional/plugin/myriad/shared_tests_instances/behavior/{infer_request_config.cpp => infer_request/config.cpp} (71%) rename inference-engine/tests/functional/plugin/myriad/shared_tests_instances/behavior/{infer_request.cpp => infer_request/io_blob.cpp} (61%) create mode 100644 inference-engine/tests/functional/plugin/myriad/shared_tests_instances/behavior/infer_request/multithreading.cpp create mode 100644 inference-engine/tests/functional/plugin/myriad/shared_tests_instances/behavior/infer_request/wait.cpp delete mode 100644 inference-engine/tests/functional/plugin/myriad/shared_tests_instances/behavior/infer_request_input.cpp delete mode 100644 inference-engine/tests/functional/plugin/myriad/shared_tests_instances/behavior/infer_request_output.cpp delete mode 100644 inference-engine/tests/functional/plugin/myriad/shared_tests_instances/behavior/layout.cpp rename inference-engine/tests/functional/plugin/myriad/shared_tests_instances/behavior/{ => preprocessing}/set_preprocess.cpp (80%) rename inference-engine/tests/functional/plugin/shared/include/behavior/{ => caching}/caching_tests.hpp (100%) delete mode 100644 inference-engine/tests/functional/plugin/shared/include/behavior/infer_request.hpp rename inference-engine/tests/functional/plugin/shared/include/behavior/{infer_request_callback.hpp => infer_request/callback.hpp} (58%) rename inference-engine/tests/functional/plugin/shared/include/behavior/{infer_request_cancellation.hpp => infer_request/cancellation.hpp} (51%) create mode 100644 inference-engine/tests/functional/plugin/shared/include/behavior/infer_request/config.hpp rename inference-engine/tests/functional/plugin/shared/include/{configuration_tests => behavior/infer_request}/dynamic_batch.hpp (100%) create mode 100644 inference-engine/tests/functional/plugin/shared/include/behavior/infer_request/io_blob.hpp rename inference-engine/tests/functional/plugin/shared/include/behavior/{ => infer_request}/memory_states.hpp (72%) create mode 100644 inference-engine/tests/functional/plugin/shared/include/behavior/infer_request/multithreading.hpp create mode 100644 inference-engine/tests/functional/plugin/shared/include/behavior/infer_request/perf_counters.hpp create mode 100644 inference-engine/tests/functional/plugin/shared/include/behavior/infer_request/set_blob_by_type.hpp create mode 100644 inference-engine/tests/functional/plugin/shared/include/behavior/infer_request/wait.hpp delete mode 100644 inference-engine/tests/functional/plugin/shared/include/behavior/infer_request_config.hpp delete mode 100644 inference-engine/tests/functional/plugin/shared/include/behavior/infer_request_input.hpp delete mode 100644 inference-engine/tests/functional/plugin/shared/include/behavior/infer_request_output.hpp delete mode 100644 inference-engine/tests/functional/plugin/shared/include/behavior/layout.hpp delete mode 100644 inference-engine/tests/functional/plugin/shared/include/behavior/perf_counters.hpp rename inference-engine/tests/functional/plugin/shared/include/behavior/{ => preprocessing}/preprocessing.hpp (92%) rename inference-engine/tests/functional/plugin/shared/include/behavior/{ => preprocessing}/set_preprocess.hpp (93%) delete mode 100644 inference-engine/tests/functional/plugin/shared/include/behavior/set_blob_of_kind.hpp rename inference-engine/tests/functional/plugin/shared/src/behavior/{ => caching}/caching_tests.cpp (99%) rename inference-engine/tests/functional/plugin/shared/src/{configuration_tests => behavior/infer_request}/dynamic_batch.cpp (92%) rename inference-engine/tests/functional/plugin/shared/src/behavior/{ => infer_request}/memory_states.cpp (80%) delete mode 100644 inference-engine/tests/functional/plugin/shared/src/behavior/layout.cpp delete mode 100644 inference-engine/tests/functional/plugin/shared/src/behavior/set_blob_of_kind.cpp diff --git a/docs/template_plugin/tests/functional/shared_tests_instances/behavior/caching_tests.cpp b/docs/template_plugin/tests/functional/shared_tests_instances/behavior/caching/caching_tests.cpp similarity index 85% rename from docs/template_plugin/tests/functional/shared_tests_instances/behavior/caching_tests.cpp rename to docs/template_plugin/tests/functional/shared_tests_instances/behavior/caching/caching_tests.cpp index a698d72e526..aa0fae40e2c 100644 --- a/docs/template_plugin/tests/functional/shared_tests_instances/behavior/caching_tests.cpp +++ b/docs/template_plugin/tests/functional/shared_tests_instances/behavior/caching/caching_tests.cpp @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 // -#include "behavior/caching_tests.hpp" +#include "behavior/caching/caching_tests.hpp" using namespace LayerTestsDefinitions; @@ -15,7 +15,7 @@ namespace { 1, 2 }; - INSTANTIATE_TEST_SUITE_P(smoke_CachingSupportCase_Template, LoadNetworkCacheTestBase, + INSTANTIATE_TEST_SUITE_P(smoke_Behavior_CachingSupportCase_Template, LoadNetworkCacheTestBase, ::testing::Combine( ::testing::ValuesIn(LoadNetworkCacheTestBase::getStandardFunctions()), ::testing::ValuesIn(precisionsTemplate), diff --git a/docs/template_plugin/tests/functional/shared_tests_instances/behavior/infer_request_callback.cpp b/docs/template_plugin/tests/functional/shared_tests_instances/behavior/infer_request/callback.cpp similarity index 53% rename from docs/template_plugin/tests/functional/shared_tests_instances/behavior/infer_request_callback.cpp rename to docs/template_plugin/tests/functional/shared_tests_instances/behavior/infer_request/callback.cpp index 3bc9d1f6f02..59e2a0a0429 100644 --- a/docs/template_plugin/tests/functional/shared_tests_instances/behavior/infer_request_callback.cpp +++ b/docs/template_plugin/tests/functional/shared_tests_instances/behavior/infer_request/callback.cpp @@ -4,25 +4,18 @@ #include -#include "behavior/infer_request_callback.hpp" +#include "behavior/infer_request/callback.hpp" using namespace BehaviorTestsDefinitions; namespace { - -const std::vector netPrecisions = { - InferenceEngine::Precision::FP32, - InferenceEngine::Precision::FP16 -}; - const std::vector> configs = { {} }; -INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, CallbackTests, +INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, InferRequestCallbackTests, ::testing::Combine( - ::testing::ValuesIn(netPrecisions), ::testing::Values(CommonTestUtils::DEVICE_TEMPLATE), ::testing::ValuesIn(configs)), - CallbackTests::getTestCaseName); + InferRequestCallbackTests::getTestCaseName); } // namespace diff --git a/docs/template_plugin/tests/functional/shared_tests_instances/behavior/infer_request.cpp b/docs/template_plugin/tests/functional/shared_tests_instances/behavior/infer_request/config.cpp similarity index 54% rename from docs/template_plugin/tests/functional/shared_tests_instances/behavior/infer_request.cpp rename to docs/template_plugin/tests/functional/shared_tests_instances/behavior/infer_request/config.cpp index edb803a614f..dd0795aa775 100644 --- a/docs/template_plugin/tests/functional/shared_tests_instances/behavior/infer_request.cpp +++ b/docs/template_plugin/tests/functional/shared_tests_instances/behavior/infer_request/config.cpp @@ -4,26 +4,21 @@ #include -#include "behavior/infer_request.hpp" +#include "behavior/infer_request/config.hpp" using namespace BehaviorTestsDefinitions; namespace { -const std::vector netPrecisions = { - InferenceEngine::Precision::FP32, - InferenceEngine::Precision::FP16 -}; - const std::vector> configs = { {} }; -INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, InferRequestTests, +INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, InferRequestConfigTest, ::testing::Combine( - ::testing::ValuesIn(netPrecisions), + ::testing::Values(1u), ::testing::Values(CommonTestUtils::DEVICE_TEMPLATE), ::testing::ValuesIn(configs)), - InferRequestTests::getTestCaseName); + InferRequestConfigTest::getTestCaseName); } // namespace diff --git a/docs/template_plugin/tests/functional/shared_tests_instances/behavior/infer_request_output.cpp b/docs/template_plugin/tests/functional/shared_tests_instances/behavior/infer_request/io_blob.cpp similarity index 52% rename from docs/template_plugin/tests/functional/shared_tests_instances/behavior/infer_request_output.cpp rename to docs/template_plugin/tests/functional/shared_tests_instances/behavior/infer_request/io_blob.cpp index eae52cec60c..9ee158dcb01 100644 --- a/docs/template_plugin/tests/functional/shared_tests_instances/behavior/infer_request_output.cpp +++ b/docs/template_plugin/tests/functional/shared_tests_instances/behavior/infer_request/io_blob.cpp @@ -2,26 +2,21 @@ // SPDX-License-Identifier: Apache-2.0 // -#include "behavior/infer_request_output.hpp" +#include + +#include "behavior/infer_request/io_blob.hpp" using namespace BehaviorTestsDefinitions; namespace { - -const std::vector netPrecisions = { - InferenceEngine::Precision::FP32, - InferenceEngine::Precision::FP16 -}; - const std::vector> configs = { {} }; -INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, InferRequestOutputTests, +INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, InferRequestIOBBlobTest, ::testing::Combine( - ::testing::ValuesIn(netPrecisions), ::testing::Values(CommonTestUtils::DEVICE_TEMPLATE), ::testing::ValuesIn(configs)), - InferRequestOutputTests::getTestCaseName); + InferRequestIOBBlobTest::getTestCaseName); } // namespace diff --git a/docs/template_plugin/tests/functional/shared_tests_instances/behavior/infer_request_config.cpp b/docs/template_plugin/tests/functional/shared_tests_instances/behavior/infer_request/multithreading.cpp similarity index 54% rename from docs/template_plugin/tests/functional/shared_tests_instances/behavior/infer_request_config.cpp rename to docs/template_plugin/tests/functional/shared_tests_instances/behavior/infer_request/multithreading.cpp index a6ffbe80bbc..70df22ac1b2 100644 --- a/docs/template_plugin/tests/functional/shared_tests_instances/behavior/infer_request_config.cpp +++ b/docs/template_plugin/tests/functional/shared_tests_instances/behavior/infer_request/multithreading.cpp @@ -4,26 +4,20 @@ #include -#include "behavior/infer_request_config.hpp" +#include "behavior/infer_request/multithreading.hpp" using namespace BehaviorTestsDefinitions; namespace { -const std::vector netPrecisions = { - InferenceEngine::Precision::FP32, - InferenceEngine::Precision::FP16 -}; - const std::vector> configs = { {} }; -INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, InferConfigTests, +INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, InferRequestMultithreadingTests, ::testing::Combine( - ::testing::ValuesIn(netPrecisions), ::testing::Values(CommonTestUtils::DEVICE_TEMPLATE), ::testing::ValuesIn(configs)), - InferConfigTests::getTestCaseName); + InferRequestMultithreadingTests::getTestCaseName); } // namespace diff --git a/docs/template_plugin/tests/functional/shared_tests_instances/behavior/infer_request_input.cpp b/docs/template_plugin/tests/functional/shared_tests_instances/behavior/infer_request/wait.cpp similarity index 52% rename from docs/template_plugin/tests/functional/shared_tests_instances/behavior/infer_request_input.cpp rename to docs/template_plugin/tests/functional/shared_tests_instances/behavior/infer_request/wait.cpp index 23d5cb7136f..dfbab8e995c 100644 --- a/docs/template_plugin/tests/functional/shared_tests_instances/behavior/infer_request_input.cpp +++ b/docs/template_plugin/tests/functional/shared_tests_instances/behavior/infer_request/wait.cpp @@ -2,26 +2,21 @@ // SPDX-License-Identifier: Apache-2.0 // -#include "behavior/infer_request_input.hpp" +#include + +#include "behavior/infer_request/wait.hpp" using namespace BehaviorTestsDefinitions; namespace { - -const std::vector netPrecisions = { - InferenceEngine::Precision::FP32, - InferenceEngine::Precision::FP16 -}; - const std::vector> configs = { {} }; -INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, InferRequestInputTests, +INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, InferRequestWaitTests, ::testing::Combine( - ::testing::ValuesIn(netPrecisions), ::testing::Values(CommonTestUtils::DEVICE_TEMPLATE), ::testing::ValuesIn(configs)), - InferRequestInputTests::getTestCaseName); + InferRequestWaitTests::getTestCaseName); } // namespace diff --git a/docs/template_plugin/tests/functional/shared_tests_instances/behavior/layout.cpp b/docs/template_plugin/tests/functional/shared_tests_instances/behavior/layout.cpp deleted file mode 100644 index f4d8091b20e..00000000000 --- a/docs/template_plugin/tests/functional/shared_tests_instances/behavior/layout.cpp +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (C) 2018-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#include "behavior/layout.hpp" - -using namespace BehaviorTestsDefinitions; - -namespace { - -const std::vector> configs = { - {} -}; - -const std::vector Layout = { - InferenceEngine::Layout::NCHW, - InferenceEngine::Layout::CHW, - InferenceEngine::Layout::NC, - InferenceEngine::Layout::C -}; - -const std::vector> inputShapes = { - { 1, 3, 16, 16 }, - { 3, 32, 16 }, - { 1, 3 }, - { 3 } -}; - -INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, LayoutTest, - ::testing::Combine( - ::testing::Values(InferenceEngine::Precision::FP32), - ::testing::Values(CommonTestUtils::DEVICE_TEMPLATE), - ::testing::ValuesIn(configs), - ::testing::ValuesIn(Layout), - ::testing::ValuesIn(inputShapes)), - LayoutTest::getTestCaseName); - -} // namespace \ No newline at end of file diff --git a/docs/template_plugin/tests/functional/shared_tests_instances/behavior/preprocessing.cpp b/docs/template_plugin/tests/functional/shared_tests_instances/behavior/preprocessing/preprocessing.cpp similarity index 69% rename from docs/template_plugin/tests/functional/shared_tests_instances/behavior/preprocessing.cpp rename to docs/template_plugin/tests/functional/shared_tests_instances/behavior/preprocessing/preprocessing.cpp index 4aa9439b1ad..212d570bcfa 100644 --- a/docs/template_plugin/tests/functional/shared_tests_instances/behavior/preprocessing.cpp +++ b/docs/template_plugin/tests/functional/shared_tests_instances/behavior/preprocessing/preprocessing.cpp @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 // -#include "behavior/preprocessing.hpp" +#include "behavior/preprocessing/preprocessing.hpp" using namespace BehaviorTestsDefinitions; @@ -17,19 +17,19 @@ const std::vector> configs = { {} }; -INSTANTIATE_TEST_SUITE_P(smoke_PreprocessingPrecisionConvertTestsViaSetInput, PreprocessingPrecisionConvertTest, +INSTANTIATE_TEST_SUITE_P(smoke_Behavior_PreprocessingPrecisionConvertTestsViaSetInput, PreprocessingPrecisionConvertTest, ::testing::Combine( ::testing::ValuesIn(inputPrecisions), - ::testing::Values(4), // Number of input tensor channels + ::testing::Values(4), // Number of input tensor channels ::testing::Values(true), // Use SetInput ::testing::Values(CommonTestUtils::DEVICE_TEMPLATE), ::testing::ValuesIn(configs)), PreprocessingPrecisionConvertTest::getTestCaseName); -INSTANTIATE_TEST_SUITE_P(smoke_PreprocessingPrecisionConvertTestsViaGetBlob, PreprocessingPrecisionConvertTest, +INSTANTIATE_TEST_SUITE_P(smoke_Behavior_PreprocessingPrecisionConvertTestsViaGetBlob, PreprocessingPrecisionConvertTest, ::testing::Combine( ::testing::ValuesIn(inputPrecisions), - ::testing::Values(4), // Number of input tensor channels (blob_copy only supports 4d and 5d tensors) + ::testing::Values(4), // Number of input tensor channels (blob_copy only supports 4d and 5d tensors) ::testing::Values(false), // use GetBlob ::testing::Values(CommonTestUtils::DEVICE_TEMPLATE), ::testing::ValuesIn(configs)), diff --git a/docs/template_plugin/tests/functional/shared_tests_instances/behavior/set_preprocess.cpp b/docs/template_plugin/tests/functional/shared_tests_instances/behavior/preprocessing/set_preprocess.cpp similarity index 79% rename from docs/template_plugin/tests/functional/shared_tests_instances/behavior/set_preprocess.cpp rename to docs/template_plugin/tests/functional/shared_tests_instances/behavior/preprocessing/set_preprocess.cpp index 19841bb64da..59c68928a0a 100644 --- a/docs/template_plugin/tests/functional/shared_tests_instances/behavior/set_preprocess.cpp +++ b/docs/template_plugin/tests/functional/shared_tests_instances/behavior/preprocessing/set_preprocess.cpp @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 // -#include "behavior/set_preprocess.hpp" +#include "behavior/preprocessing/set_preprocess.hpp" using namespace BehaviorTestsDefinitions; @@ -26,26 +26,26 @@ const std::vector> heteroConfigs = { {{ "TARGET_FALLBACK", CommonTestUtils::DEVICE_TEMPLATE }} }; -INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, PreprocessTest, +INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, InferRequestPreprocessTest, ::testing::Combine( ::testing::ValuesIn(netPrecisions), ::testing::Values(CommonTestUtils::DEVICE_TEMPLATE), ::testing::ValuesIn(configs)), - PreprocessTest::getTestCaseName); + InferRequestPreprocessTest::getTestCaseName); -INSTANTIATE_TEST_SUITE_P(smoke_Multi_BehaviorTests, PreprocessTest, +INSTANTIATE_TEST_SUITE_P(smoke_Multi_BehaviorTests, InferRequestPreprocessTest, ::testing::Combine( ::testing::ValuesIn(netPrecisions), ::testing::Values(CommonTestUtils::DEVICE_MULTI), ::testing::ValuesIn(multiConfigs)), - PreprocessTest::getTestCaseName); + InferRequestPreprocessTest::getTestCaseName); -INSTANTIATE_TEST_SUITE_P(smoke_Hetero_BehaviorTests, PreprocessTest, +INSTANTIATE_TEST_SUITE_P(smoke_Hetero_BehaviorTests, InferRequestPreprocessTest, ::testing::Combine( ::testing::ValuesIn(netPrecisions), ::testing::Values(CommonTestUtils::DEVICE_HETERO), ::testing::ValuesIn(heteroConfigs)), - PreprocessTest::getTestCaseName); + InferRequestPreprocessTest::getTestCaseName); const std::vector ioPrecisions = { InferenceEngine::Precision::FP32, @@ -61,7 +61,7 @@ const std::vector ioLayouts = { InferenceEngine::Layout::NHWC }; -INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, PreprocessConversionTest, +INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, InferRequestPreprocessConversionTest, ::testing::Combine( ::testing::ValuesIn(netPrecisions), ::testing::ValuesIn(ioPrecisions), @@ -73,9 +73,9 @@ INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, PreprocessConversionTest, ::testing::Bool(), ::testing::Values(CommonTestUtils::DEVICE_TEMPLATE), ::testing::ValuesIn(configs)), - PreprocessConversionTest::getTestCaseName); + InferRequestPreprocessConversionTest::getTestCaseName); -INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, PreprocessDynamicallyInSetBlobTest, +INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, InferRequestPreprocessDynamicallyInSetBlobTest, ::testing::Combine( ::testing::ValuesIn(netPrecisions), ::testing::Bool(), @@ -87,6 +87,6 @@ INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, PreprocessDynamicallyInSetBlobTest ::testing::Values(true), // only SetBlob ::testing::Values(CommonTestUtils::DEVICE_TEMPLATE), ::testing::ValuesIn(configs)), - PreprocessDynamicallyInSetBlobTest::getTestCaseName); + InferRequestPreprocessDynamicallyInSetBlobTest::getTestCaseName); } // namespace \ No newline at end of file diff --git a/docs/template_plugin/tests/functional/skip_tests_config.cpp b/docs/template_plugin/tests/functional/skip_tests_config.cpp index 8d100118a9d..e035511cf8b 100644 --- a/docs/template_plugin/tests/functional/skip_tests_config.cpp +++ b/docs/template_plugin/tests/functional/skip_tests_config.cpp @@ -9,11 +9,13 @@ std::vector disabledTestPatterns() { return { - ".*ExclusiveAsyncRequests.*", - ".*ReusableCPUStreamsExecutor.*", + R"(.*ExclusiveAsyncRequests.*)", + R"(.*ReusableCPUStreamsExecutor.*)", R"(.*SplitLayerTest.*numSplits\=30.*)", // CVS-51758 - ".*PreprocessConversionTest.*oLT=NHWC.*", - ".*PreprocessDynamicallyInSetBlobTest.*oPRC=0.*oLT=1.*", + R"(.*InferRequestPreprocessConversionTest.*oLT=(NHWC|NCHW).*)", + R"(.*InferRequestPreprocessDynamicallyInSetBlobTest.*oPRC=0.*oLT=1.*)", + // CVS-58963: Not implemented yet + R"(.*Behavior.*InferRequest.*OutOfFirstOutIsInputForSecondNetwork.*)", }; } diff --git a/inference-engine/tests/functional/plugin/conformance/test_runner/src/behavior/infer_request/callback.cpp b/inference-engine/tests/functional/plugin/conformance/test_runner/src/behavior/infer_request/callback.cpp new file mode 100644 index 00000000000..92c1cba64a2 --- /dev/null +++ b/inference-engine/tests/functional/plugin/conformance/test_runner/src/behavior/infer_request/callback.cpp @@ -0,0 +1,41 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "behavior/infer_request/callback.hpp" +#include "conformance.hpp" + +namespace { +using namespace BehaviorTestsDefinitions; +using namespace ConformanceTests; + +const std::vector> configsCallback = { + {}, +}; + +const std::vector> multiConfigsCallback = { + {{MULTI_CONFIG_KEY(DEVICE_PRIORITIES), targetDevice}} +}; + +const std::vector> autoConfigsCallback = { + {{AUTO_CONFIG_KEY(DEVICE_LIST), targetDevice}} +}; + +INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, InferRequestCallbackTests, + ::testing::Combine( + ::testing::Values(targetDevice), + ::testing::ValuesIn(configsCallback)), + InferRequestCallbackTests::getTestCaseName); + +INSTANTIATE_TEST_SUITE_P(smoke_Multi_BehaviorTests, InferRequestCallbackTests, + ::testing::Combine( + ::testing::Values(CommonTestUtils::DEVICE_MULTI), + ::testing::ValuesIn(multiConfigsCallback)), + InferRequestCallbackTests::getTestCaseName); + +INSTANTIATE_TEST_SUITE_P(smoke_Auto_BehaviorTests, InferRequestCallbackTests, + ::testing::Combine( + ::testing::Values(CommonTestUtils::DEVICE_AUTO), + ::testing::ValuesIn(autoConfigsCallback)), + InferRequestCallbackTests::getTestCaseName); +} // namespace diff --git a/inference-engine/tests/functional/plugin/conformance/test_runner/src/behavior/infer_request/cancellation.cpp b/inference-engine/tests/functional/plugin/conformance/test_runner/src/behavior/infer_request/cancellation.cpp new file mode 100644 index 00000000000..49a1dbc904d --- /dev/null +++ b/inference-engine/tests/functional/plugin/conformance/test_runner/src/behavior/infer_request/cancellation.cpp @@ -0,0 +1,21 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "behavior/infer_request/cancellation.hpp" +#include "conformance.hpp" + +namespace { +using namespace BehaviorTestsDefinitions; +using namespace ConformanceTests; + +const std::vector> configsCancel = { + {}, +}; + +INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, InferRequestCancellationTests, + ::testing::Combine( + ::testing::Values(targetDevice), + ::testing::ValuesIn(configsCancel)), + InferRequestCancellationTests::getTestCaseName); +} // namespace diff --git a/inference-engine/tests/functional/plugin/conformance/test_runner/src/behavior/infer_request/io_blob.cpp b/inference-engine/tests/functional/plugin/conformance/test_runner/src/behavior/infer_request/io_blob.cpp new file mode 100644 index 00000000000..4e288e5baaa --- /dev/null +++ b/inference-engine/tests/functional/plugin/conformance/test_runner/src/behavior/infer_request/io_blob.cpp @@ -0,0 +1,44 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include + +#include "behavior/infer_request/io_blob.hpp" +#include "ie_plugin_config.hpp" +#include "conformance.hpp" + +namespace { +using namespace BehaviorTestsDefinitions; +using namespace ConformanceTests; + +const std::vector> configsIOBlob = { + {}, +}; + +const std::vector> MulticonfigsIOBlob = { + {{ MULTI_CONFIG_KEY(DEVICE_PRIORITIES), targetDevice }} +}; + +const std::vector> AutoconfigsIOBlob = { + {{ AUTO_CONFIG_KEY(DEVICE_LIST), targetDevice}} +}; + +INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, InferRequestIOBBlobTest, + ::testing::Combine( + ::testing::Values(targetDevice), + ::testing::ValuesIn(configsIOBlob)), + InferRequestIOBBlobTest::getTestCaseName); + +INSTANTIATE_TEST_SUITE_P(smoke_Multi_BehaviorTests, InferRequestIOBBlobTest, + ::testing::Combine( + ::testing::Values(CommonTestUtils::DEVICE_MULTI), + ::testing::ValuesIn(MulticonfigsIOBlob)), + InferRequestIOBBlobTest::getTestCaseName); + +INSTANTIATE_TEST_SUITE_P(smoke_Auto_BehaviorTests, InferRequestIOBBlobTest, + ::testing::Combine( + ::testing::Values(CommonTestUtils::DEVICE_AUTO), + ::testing::ValuesIn(AutoconfigsIOBlob)), + InferRequestIOBBlobTest::getTestCaseName); +} // namespace diff --git a/inference-engine/tests/functional/plugin/conformance/test_runner/src/behavior/infer_request/multitheading.cpp b/inference-engine/tests/functional/plugin/conformance/test_runner/src/behavior/infer_request/multitheading.cpp new file mode 100644 index 00000000000..7e319ed74d0 --- /dev/null +++ b/inference-engine/tests/functional/plugin/conformance/test_runner/src/behavior/infer_request/multitheading.cpp @@ -0,0 +1,47 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include + +#include "behavior/infer_request/multithreading.hpp" +#include "ie_plugin_config.hpp" + +#include "conformance.hpp" + +namespace { + +using namespace ConformanceTests; +using namespace BehaviorTestsDefinitions; + +const std::vector> configsMultithreading = { + {}, +}; + +const std::vector> MulticonfigsMultithreading = { + {{ MULTI_CONFIG_KEY(DEVICE_PRIORITIES), targetDevice }} +}; + +const std::vector> AutoconfigsMultithreading = { + {{ AUTO_CONFIG_KEY(DEVICE_LIST), targetDevice}} +}; + +INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, InferRequestMultithreadingTests, + ::testing::Combine( + ::testing::Values(targetDevice), + ::testing::ValuesIn(configsMultithreading)), + InferRequestMultithreadingTests::getTestCaseName); + +INSTANTIATE_TEST_SUITE_P(smoke_Multi_BehaviorTests, InferRequestMultithreadingTests, + ::testing::Combine( + ::testing::Values(CommonTestUtils::DEVICE_MULTI), + ::testing::ValuesIn(MulticonfigsMultithreading)), + InferRequestMultithreadingTests::getTestCaseName); + +INSTANTIATE_TEST_SUITE_P(smoke_Auto_BehaviorTests, InferRequestMultithreadingTests, + ::testing::Combine( + ::testing::Values(CommonTestUtils::DEVICE_AUTO), + ::testing::ValuesIn(AutoconfigsMultithreading)), + InferRequestMultithreadingTests::getTestCaseName); + +} // namespace diff --git a/inference-engine/tests/functional/plugin/conformance/test_runner/src/behavior/infer_request/perf_counters.cpp b/inference-engine/tests/functional/plugin/conformance/test_runner/src/behavior/infer_request/perf_counters.cpp new file mode 100644 index 00000000000..b7007dd16f3 --- /dev/null +++ b/inference-engine/tests/functional/plugin/conformance/test_runner/src/behavior/infer_request/perf_counters.cpp @@ -0,0 +1,33 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "behavior/infer_request/perf_counters.hpp" +#include "conformance.hpp" + +namespace { + +using namespace ConformanceTests; +using namespace BehaviorTestsDefinitions; + +const std::vector> configsPerfCounters = { + {} +}; + +const std::vector> MulticonfigsPerfCounters = { + {{ MULTI_CONFIG_KEY(DEVICE_PRIORITIES), targetDevice }} +}; + +INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, InferRequestPerfCountersTest, + ::testing::Combine( + ::testing::Values(targetDevice), + ::testing::ValuesIn(configsPerfCounters)), + InferRequestPerfCountersTest::getTestCaseName); + +INSTANTIATE_TEST_SUITE_P(smoke_Multi_BehaviorTests, InferRequestPerfCountersTest, + ::testing::Combine( + ::testing::Values(CommonTestUtils::DEVICE_MULTI), + ::testing::ValuesIn(MulticonfigsPerfCounters)), + InferRequestPerfCountersTest::getTestCaseName); + +} // namespace diff --git a/inference-engine/tests/functional/plugin/conformance/test_runner/src/behavior/infer_request/set_blob_by_type.cpp b/inference-engine/tests/functional/plugin/conformance/test_runner/src/behavior/infer_request/set_blob_by_type.cpp new file mode 100644 index 00000000000..55f31b42328 --- /dev/null +++ b/inference-engine/tests/functional/plugin/conformance/test_runner/src/behavior/infer_request/set_blob_by_type.cpp @@ -0,0 +1,52 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "behavior/infer_request/set_blob_by_type.hpp" +#include "common_test_utils/test_constants.hpp" +#include "conformance.hpp" + +namespace { + +using namespace ConformanceTests; +using namespace BehaviorTestsDefinitions; + +const std::vector BlobTypes = { + FuncTestUtils::BlobType::Compound, + FuncTestUtils::BlobType::Batched, + FuncTestUtils::BlobType::Memory, +// FuncTestUtils::BlobType::Remote, + FuncTestUtils::BlobType::I420, + FuncTestUtils::BlobType::NV12 +}; + +const std::map ConfigBlobType{}; //nothing special +const std::map autoConfigBlobType{}; +const std::map multiConfigBlobType{{MULTI_CONFIG_KEY(DEVICE_PRIORITIES), targetDevice}}; +const std::map heteroConfigBlobType{{"TARGET_FALLBACK", targetDevice}}; + +INSTANTIATE_TEST_SUITE_P(smoke_Behavior, InferRequestSetBlobByType, + ::testing::Combine(::testing::ValuesIn(BlobTypes), + ::testing::Values(targetDevice), + ::testing::Values(ConfigBlobType)), + InferRequestSetBlobByType::getTestCaseName); + + +INSTANTIATE_TEST_SUITE_P(smoke_Behavior_Multi, InferRequestSetBlobByType, + ::testing::Combine(::testing::ValuesIn(BlobTypes), + ::testing::Values(CommonTestUtils::DEVICE_MULTI), + ::testing::Values(multiConfigBlobType)), + InferRequestSetBlobByType::getTestCaseName); + +INSTANTIATE_TEST_SUITE_P(smoke_Behavior_Auto, InferRequestSetBlobByType, + ::testing::Combine(::testing::ValuesIn(BlobTypes), + ::testing::Values(CommonTestUtils::DEVICE_AUTO + std::string(":") + targetDevice), + ::testing::Values(autoConfigBlobType)), + InferRequestSetBlobByType::getTestCaseName); + +INSTANTIATE_TEST_SUITE_P(smoke_Behavior_Hetero, InferRequestSetBlobByType, + ::testing::Combine(::testing::ValuesIn(BlobTypes), + ::testing::Values(CommonTestUtils::DEVICE_HETERO), + ::testing::Values(heteroConfigBlobType)), + InferRequestSetBlobByType::getTestCaseName); +} // namespace diff --git a/inference-engine/tests/functional/plugin/conformance/test_runner/src/behavior/infer_request/wait.cpp b/inference-engine/tests/functional/plugin/conformance/test_runner/src/behavior/infer_request/wait.cpp new file mode 100644 index 00000000000..2496bdf26f2 --- /dev/null +++ b/inference-engine/tests/functional/plugin/conformance/test_runner/src/behavior/infer_request/wait.cpp @@ -0,0 +1,46 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include + +#include "behavior/infer_request/wait.hpp" +#include "ie_plugin_config.hpp" +#include "conformance.hpp" + +namespace { + +using namespace ConformanceTests; +using namespace BehaviorTestsDefinitions; + +const std::vector> configsWait = { + {}, +}; + +const std::vector> MulticonfigsWait = { + {{ MULTI_CONFIG_KEY(DEVICE_PRIORITIES) , targetDevice}} +}; + +const std::vector> AutoconfigsWait = { + {{ AUTO_CONFIG_KEY(DEVICE_LIST) , targetDevice}} +}; + +INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, InferRequestWaitTests, + ::testing::Combine( + ::testing::Values(targetDevice), + ::testing::ValuesIn(configsWait)), + InferRequestWaitTests::getTestCaseName); + +INSTANTIATE_TEST_SUITE_P(smoke_Multi_BehaviorTests, InferRequestWaitTests, + ::testing::Combine( + ::testing::Values(CommonTestUtils::DEVICE_MULTI), + ::testing::ValuesIn(MulticonfigsWait)), + InferRequestWaitTests::getTestCaseName); + +INSTANTIATE_TEST_SUITE_P(smoke_Auto_BehaviorTests, InferRequestWaitTests, + ::testing::Combine( + ::testing::Values(CommonTestUtils::DEVICE_AUTO), + ::testing::ValuesIn(AutoconfigsWait)), + InferRequestWaitTests::getTestCaseName); + +} // namespace diff --git a/inference-engine/tests/functional/plugin/conformance/test_runner/src/behavior/preprocessing/set_preprocess.cpp b/inference-engine/tests/functional/plugin/conformance/test_runner/src/behavior/preprocessing/set_preprocess.cpp new file mode 100644 index 00000000000..1eef28fb789 --- /dev/null +++ b/inference-engine/tests/functional/plugin/conformance/test_runner/src/behavior/preprocessing/set_preprocess.cpp @@ -0,0 +1,189 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "behavior/preprocessing/set_preprocess.hpp" +#include "conformance.hpp" + +namespace { + +using namespace ConformanceTests; +using namespace BehaviorTestsDefinitions; + +const std::vector netPrecisions = { + InferenceEngine::Precision::FP32, + InferenceEngine::Precision::FP16 +}; + +const std::vector> configs = { + {}, +}; + +const std::vector> heteroConfigs = { + {{ "TARGET_FALLBACK" , targetDevice}} +}; + +const std::vector> multiConfigs = { + {{ InferenceEngine::MultiDeviceConfigParams::KEY_MULTI_DEVICE_PRIORITIES , targetDevice}} +}; + +const std::vector> autoConfigs = { + {{ InferenceEngine::KEY_AUTO_DEVICE_LIST , targetDevice}} +}; + +INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, InferRequestPreprocessTest, + ::testing::Combine( + ::testing::ValuesIn(netPrecisions), + ::testing::Values(targetDevice), + ::testing::ValuesIn(configs)), + InferRequestPreprocessTest::getTestCaseName); + +INSTANTIATE_TEST_SUITE_P(smoke_Hetero_BehaviorTests, InferRequestPreprocessTest, + ::testing::Combine( + ::testing::ValuesIn(netPrecisions), + ::testing::Values(CommonTestUtils::DEVICE_HETERO), + ::testing::ValuesIn(heteroConfigs)), + InferRequestPreprocessTest::getTestCaseName); + +INSTANTIATE_TEST_SUITE_P(smoke_Multi_BehaviorTests, InferRequestPreprocessTest, + ::testing::Combine( + ::testing::ValuesIn(netPrecisions), + ::testing::Values(CommonTestUtils::DEVICE_MULTI), + ::testing::ValuesIn(multiConfigs)), + InferRequestPreprocessTest::getTestCaseName); + +INSTANTIATE_TEST_SUITE_P(smoke_Auto_BehaviorTests, InferRequestPreprocessTest, + ::testing::Combine( + ::testing::ValuesIn(netPrecisions), + ::testing::Values(CommonTestUtils::DEVICE_AUTO), + ::testing::ValuesIn(autoConfigs)), + InferRequestPreprocessTest::getTestCaseName); + + +const std::vector ioPrecisions = { + InferenceEngine::Precision::FP32, + InferenceEngine::Precision::U8 +}; +const std::vector netLayouts = { + InferenceEngine::Layout::NCHW, + // InferenceEngine::Layout::NHWC +}; + +const std::vector ioLayouts = { + InferenceEngine::Layout::NCHW, + InferenceEngine::Layout::NHWC +}; + +INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, InferRequestPreprocessConversionTest, + ::testing::Combine( + ::testing::ValuesIn(netPrecisions), + ::testing::ValuesIn(ioPrecisions), + ::testing::ValuesIn(ioPrecisions), + ::testing::ValuesIn(netLayouts), + ::testing::ValuesIn(ioLayouts), + ::testing::ValuesIn(ioLayouts), + ::testing::Bool(), + ::testing::Bool(), + ::testing::Values(targetDevice), + ::testing::ValuesIn(configs)), + InferRequestPreprocessConversionTest::getTestCaseName); + +INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, InferRequestPreprocessDynamicallyInSetBlobTest, + ::testing::Combine( + ::testing::ValuesIn(netPrecisions), + ::testing::Bool(), + ::testing::Bool(), + ::testing::ValuesIn(netLayouts), + ::testing::Bool(), + ::testing::Bool(), + ::testing::Values(true), // only SetBlob + ::testing::Values(true), // only SetBlob + ::testing::Values(targetDevice), + ::testing::ValuesIn(configs)), + InferRequestPreprocessDynamicallyInSetBlobTest::getTestCaseName); + +INSTANTIATE_TEST_SUITE_P(smoke_Hetero_BehaviorTests, InferRequestPreprocessConversionTest, + ::testing::Combine( + ::testing::ValuesIn(netPrecisions), + ::testing::ValuesIn(ioPrecisions), + ::testing::ValuesIn(ioPrecisions), + ::testing::ValuesIn(netLayouts), + ::testing::ValuesIn(ioLayouts), + ::testing::ValuesIn(ioLayouts), + ::testing::Bool(), + ::testing::Bool(), + ::testing::Values(CommonTestUtils::DEVICE_HETERO), + ::testing::ValuesIn(heteroConfigs)), + InferRequestPreprocessConversionTest::getTestCaseName); + +INSTANTIATE_TEST_SUITE_P(smoke_Hetero_BehaviorTests, InferRequestPreprocessDynamicallyInSetBlobTest, + ::testing::Combine( + ::testing::ValuesIn(netPrecisions), + ::testing::Bool(), + ::testing::Bool(), + ::testing::ValuesIn(netLayouts), + ::testing::Bool(), + ::testing::Bool(), + ::testing::Values(true), // only SetBlob + ::testing::Values(true), // only SetBlob + ::testing::Values(CommonTestUtils::DEVICE_HETERO), + ::testing::ValuesIn(heteroConfigs)), + InferRequestPreprocessDynamicallyInSetBlobTest::getTestCaseName); + +INSTANTIATE_TEST_SUITE_P(smoke_Multi_BehaviorTests, InferRequestPreprocessConversionTest, + ::testing::Combine( + ::testing::ValuesIn(netPrecisions), + ::testing::ValuesIn(ioPrecisions), + ::testing::ValuesIn(ioPrecisions), + ::testing::ValuesIn(netLayouts), + ::testing::ValuesIn(ioLayouts), + ::testing::ValuesIn(ioLayouts), + ::testing::Bool(), + ::testing::Bool(), + ::testing::Values(CommonTestUtils::DEVICE_MULTI), + ::testing::ValuesIn(multiConfigs)), + InferRequestPreprocessConversionTest::getTestCaseName); + +INSTANTIATE_TEST_SUITE_P(smoke_Multi_BehaviorTests, InferRequestPreprocessDynamicallyInSetBlobTest, + ::testing::Combine( + ::testing::ValuesIn(netPrecisions), + ::testing::Bool(), + ::testing::Bool(), + ::testing::ValuesIn(netLayouts), + ::testing::Bool(), + ::testing::Bool(), + ::testing::Values(true), // only SetBlob + ::testing::Values(true), // only SetBlob + ::testing::Values(CommonTestUtils::DEVICE_MULTI), + ::testing::ValuesIn(multiConfigs)), + InferRequestPreprocessDynamicallyInSetBlobTest::getTestCaseName); + +INSTANTIATE_TEST_SUITE_P(smoke_Auto_BehaviorTests, InferRequestPreprocessConversionTest, + ::testing::Combine( + ::testing::ValuesIn(netPrecisions), + ::testing::ValuesIn(ioPrecisions), + ::testing::ValuesIn(ioPrecisions), + ::testing::ValuesIn(netLayouts), + ::testing::ValuesIn(ioLayouts), + ::testing::ValuesIn(ioLayouts), + ::testing::Bool(), + ::testing::Bool(), + ::testing::Values(CommonTestUtils::DEVICE_AUTO), + ::testing::ValuesIn(autoConfigs)), + InferRequestPreprocessConversionTest::getTestCaseName); + +INSTANTIATE_TEST_SUITE_P(smoke_Auto_BehaviorTests, InferRequestPreprocessDynamicallyInSetBlobTest, + ::testing::Combine( + ::testing::ValuesIn(netPrecisions), + ::testing::Bool(), + ::testing::Bool(), + ::testing::ValuesIn(netLayouts), + ::testing::Bool(), + ::testing::Bool(), + ::testing::Values(true), // only SetBlob + ::testing::Values(true), // only SetBlob + ::testing::Values(CommonTestUtils::DEVICE_AUTO), + ::testing::ValuesIn(autoConfigs)), + InferRequestPreprocessDynamicallyInSetBlobTest::getTestCaseName); + +} // namespace diff --git a/inference-engine/tests/functional/plugin/conformance/test_runner/src/read_ir/read_ir.cpp b/inference-engine/tests/functional/plugin/conformance/test_runner/src/read_ir/read_ir.cpp index a3e70abb487..c748559fd0b 100644 --- a/inference-engine/tests/functional/plugin/conformance/test_runner/src/read_ir/read_ir.cpp +++ b/inference-engine/tests/functional/plugin/conformance/test_runner/src/read_ir/read_ir.cpp @@ -5,6 +5,7 @@ #include "common_test_utils/file_utils.hpp" #include "read_ir/read_ir.hpp" +#include "conformance.hpp" namespace ConformanceTests { using namespace LayerTestsDefinitions; diff --git a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/caching_tests.cpp b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/caching_tests.cpp index c541f4e21ba..3c0d237b4ad 100644 --- a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/caching_tests.cpp +++ b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/caching_tests.cpp @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 // -#include "behavior/caching_tests.hpp" +#include "behavior/caching/caching_tests.hpp" using namespace LayerTestsDefinitions; diff --git a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/infer_request_callback.cpp b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/infer_request/callback.cpp similarity index 62% rename from inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/infer_request_callback.cpp rename to inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/infer_request/callback.cpp index a22af7eda78..e02e5151c12 100644 --- a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/infer_request_callback.cpp +++ b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/infer_request/callback.cpp @@ -2,15 +2,10 @@ // SPDX-License-Identifier: Apache-2.0 // -#include "behavior/infer_request_callback.hpp" +#include "behavior/infer_request/callback.hpp" using namespace BehaviorTestsDefinitions; namespace { -const std::vector netPrecisions = { - InferenceEngine::Precision::FP32, - InferenceEngine::Precision::FP16 -}; - const std::vector> configs = { {}, {{InferenceEngine::PluginConfigParams::KEY_CPU_THROUGHPUT_STREAMS, InferenceEngine::PluginConfigParams::CPU_THROUGHPUT_AUTO}}, @@ -21,24 +16,21 @@ const std::vector> multiConfigs = { {{ MULTI_CONFIG_KEY(DEVICE_PRIORITIES) , CommonTestUtils::DEVICE_CPU}} }; -INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, CallbackTests, +INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, InferRequestCallbackTests, ::testing::Combine( - ::testing::ValuesIn(netPrecisions), ::testing::Values(CommonTestUtils::DEVICE_CPU), ::testing::ValuesIn(configs)), - CallbackTests::getTestCaseName); + InferRequestCallbackTests::getTestCaseName); -INSTANTIATE_TEST_SUITE_P(smoke_Multi_BehaviorTests, CallbackTests, +INSTANTIATE_TEST_SUITE_P(smoke_Multi_BehaviorTests, InferRequestCallbackTests, ::testing::Combine( - ::testing::ValuesIn(netPrecisions), ::testing::Values(CommonTestUtils::DEVICE_MULTI), ::testing::ValuesIn(multiConfigs)), - CallbackTests::getTestCaseName); + InferRequestCallbackTests::getTestCaseName); -INSTANTIATE_TEST_SUITE_P(smoke_Auto_BehaviorTests, CallbackTests, +INSTANTIATE_TEST_SUITE_P(smoke_Auto_BehaviorTests, InferRequestCallbackTests, ::testing::Combine( - ::testing::ValuesIn(netPrecisions), ::testing::Values(CommonTestUtils::DEVICE_AUTO), ::testing::ValuesIn(multiConfigs)), - CallbackTests::getTestCaseName); + InferRequestCallbackTests::getTestCaseName); } // namespace diff --git a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/infer_request_cancellation.cpp b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/infer_request/cancellation.cpp similarity index 50% rename from inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/infer_request_cancellation.cpp rename to inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/infer_request/cancellation.cpp index 0d2aa9a72fd..fbaaf57bfe8 100644 --- a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/infer_request_cancellation.cpp +++ b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/infer_request/cancellation.cpp @@ -2,23 +2,17 @@ // SPDX-License-Identifier: Apache-2.0 // -#include "behavior/infer_request_cancellation.hpp" +#include "behavior/infer_request/cancellation.hpp" using namespace BehaviorTestsDefinitions; namespace { -const std::vector netPrecisions = { - InferenceEngine::Precision::FP32, - InferenceEngine::Precision::FP16 -}; - const std::vector> configs = { {}, }; -INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, CancellationTests, +INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, InferRequestCancellationTests, ::testing::Combine( - ::testing::ValuesIn(netPrecisions), ::testing::Values(CommonTestUtils::DEVICE_CPU), ::testing::ValuesIn(configs)), - CancellationTests::getTestCaseName); + InferRequestCancellationTests::getTestCaseName); } // namespace diff --git a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/infer_request_config.cpp b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/infer_request/config.cpp similarity index 65% rename from inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/infer_request_config.cpp rename to inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/infer_request/config.cpp index 42c426ca383..7013c3096dd 100644 --- a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/infer_request_config.cpp +++ b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/infer_request/config.cpp @@ -2,15 +2,10 @@ // SPDX-License-Identifier: Apache-2.0 // -#include "behavior/infer_request_config.hpp" +#include "behavior/infer_request/config.hpp" using namespace BehaviorTestsDefinitions; namespace { - const std::vector netPrecisions = { - InferenceEngine::Precision::FP32, - InferenceEngine::Precision::FP16 - }; - const std::vector> configs = { {} }; @@ -46,46 +41,39 @@ namespace { {InferenceEngine::PluginConfigParams::KEY_DYN_BATCH_LIMIT, "10"}} }; - INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, InferConfigTests, + INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, InferRequestConfigTest, ::testing::Combine( - ::testing::ValuesIn(netPrecisions), + ::testing::Values(1u), ::testing::Values(CommonTestUtils::DEVICE_CPU), ::testing::ValuesIn(configs)), - InferConfigTests::getTestCaseName); + InferRequestConfigTest::getTestCaseName); - INSTANTIATE_TEST_SUITE_P(smoke_Multi_BehaviorTests, InferConfigTests, + INSTANTIATE_TEST_SUITE_P(smoke_Multi_BehaviorTests, InferRequestConfigTest, ::testing::Combine( - ::testing::ValuesIn(netPrecisions), + ::testing::Values(1u), ::testing::Values(CommonTestUtils::DEVICE_MULTI), ::testing::ValuesIn(multiConfigs)), - InferConfigTests::getTestCaseName); + InferRequestConfigTest::getTestCaseName); - INSTANTIATE_TEST_SUITE_P(smoke_Auto_BehaviorTests, InferConfigTests, + INSTANTIATE_TEST_SUITE_P(smoke_Multi_BehaviorTests_, InferRequestConfigTest, + ::testing::Combine( + ::testing::Values(1u), + ::testing::Values(CommonTestUtils::DEVICE_MULTI), + ::testing::ValuesIn(MultiInConfigs)), + InferRequestConfigTest::getTestCaseName); + + INSTANTIATE_TEST_SUITE_P(smoke_Auto_BehaviorTests, InferRequestConfigTest, ::testing::Combine( - ::testing::ValuesIn(netPrecisions), + ::testing::Values(1u), ::testing::Values(CommonTestUtils::DEVICE_AUTO), ::testing::ValuesIn(multiConfigs)), - InferConfigTests::getTestCaseName); + InferRequestConfigTest::getTestCaseName); - INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, InferConfigInTests, - ::testing::Combine( - ::testing::ValuesIn(netPrecisions), - ::testing::Values(CommonTestUtils::DEVICE_CPU), - ::testing::ValuesIn(InConfigs)), - InferConfigTests::getTestCaseName); - INSTANTIATE_TEST_SUITE_P(smoke_Multi_BehaviorTests, InferConfigInTests, - ::testing::Combine( - ::testing::ValuesIn(netPrecisions), - ::testing::Values(CommonTestUtils::DEVICE_MULTI), - ::testing::ValuesIn(MultiInConfigs)), - InferConfigInTests::getTestCaseName); - - INSTANTIATE_TEST_SUITE_P(smoke_Auto_BehaviorTests, InferConfigInTests, + INSTANTIATE_TEST_SUITE_P(smoke_Auto_BehaviorTests_, InferRequestConfigTest, ::testing::Combine( - ::testing::ValuesIn(netPrecisions), + ::testing::Values(1u), ::testing::Values(CommonTestUtils::DEVICE_AUTO), ::testing::ValuesIn(MultiInConfigs)), - InferConfigInTests::getTestCaseName); - + InferRequestConfigTest::getTestCaseName); } // namespace diff --git a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/configuration_tests/dynamic_batch.cpp b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/infer_request/dynamic_batch.cpp similarity index 95% rename from inference-engine/tests/functional/plugin/cpu/shared_tests_instances/configuration_tests/dynamic_batch.cpp rename to inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/infer_request/dynamic_batch.cpp index 0b6ff2ae24e..0d2397eb067 100644 --- a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/configuration_tests/dynamic_batch.cpp +++ b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/infer_request/dynamic_batch.cpp @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 // -#include +#include #include "common_test_utils/test_constants.hpp" namespace ConfigurationTestsDefinitions { diff --git a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/infer_request/io_blob.cpp b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/infer_request/io_blob.cpp new file mode 100644 index 00000000000..67acfc8cd2e --- /dev/null +++ b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/infer_request/io_blob.cpp @@ -0,0 +1,125 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include + +#include "behavior/infer_request/io_blob.hpp" +#include "ie_plugin_config.hpp" + +using namespace BehaviorTestsDefinitions; +namespace { + const std::vector> configs = { + {}, + {{InferenceEngine::PluginConfigParams::KEY_CPU_THROUGHPUT_STREAMS, InferenceEngine::PluginConfigParams::CPU_THROUGHPUT_AUTO}}, + {{InferenceEngine::PluginConfigParams::KEY_CPU_THROUGHPUT_STREAMS, "0"}, {InferenceEngine::PluginConfigParams::KEY_CPU_THREADS_NUM, "1"}} + }; + + const std::vector> Multiconfigs = { + {{ MULTI_CONFIG_KEY(DEVICE_PRIORITIES) , CommonTestUtils::DEVICE_CPU}} + }; + + const std::vector> Autoconfigs = { + {{ AUTO_CONFIG_KEY(DEVICE_LIST) , CommonTestUtils::DEVICE_CPU}} + }; + + INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, InferRequestIOBBlobTest, + ::testing::Combine( + ::testing::Values(CommonTestUtils::DEVICE_CPU), + ::testing::ValuesIn(configs)), + InferRequestIOBBlobTest::getTestCaseName); + + INSTANTIATE_TEST_SUITE_P(smoke_Multi_BehaviorTests, InferRequestIOBBlobTest, + ::testing::Combine( + ::testing::Values(CommonTestUtils::DEVICE_MULTI), + ::testing::ValuesIn(Multiconfigs)), + InferRequestIOBBlobTest::getTestCaseName); + + INSTANTIATE_TEST_SUITE_P(smoke_Auto_BehaviorTests, InferRequestIOBBlobTest, + ::testing::Combine( + ::testing::Values(CommonTestUtils::DEVICE_AUTO), + ::testing::ValuesIn(Autoconfigs)), + InferRequestIOBBlobTest::getTestCaseName); + + std::vector prcs = { + InferenceEngine::Precision::FP16, + InferenceEngine::Precision::FP32, + InferenceEngine::Precision::FP64, + InferenceEngine::Precision::I4, + InferenceEngine::Precision::I8, + InferenceEngine::Precision::I16, + InferenceEngine::Precision::I32, + InferenceEngine::Precision::I64, + InferenceEngine::Precision::U4, + InferenceEngine::Precision::U8, + InferenceEngine::Precision::U16, + InferenceEngine::Precision::U32, + InferenceEngine::Precision::U64, + InferenceEngine::Precision::BF16, + InferenceEngine::Precision::BIN, + InferenceEngine::Precision::BOOL, + }; + +INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, InferRequestIOBBlobSetPrecisionTest, + ::testing::Combine( + ::testing::ValuesIn(prcs), + ::testing::Values(CommonTestUtils::DEVICE_CPU), + ::testing::ValuesIn(configs)), + InferRequestIOBBlobSetPrecisionTest::getTestCaseName); + +INSTANTIATE_TEST_SUITE_P(smoke_Multi_BehaviorTests, InferRequestIOBBlobSetPrecisionTest, + ::testing::Combine( + ::testing::ValuesIn(prcs), + ::testing::Values(CommonTestUtils::DEVICE_MULTI), + ::testing::ValuesIn(Multiconfigs)), + InferRequestIOBBlobSetPrecisionTest::getTestCaseName); + +INSTANTIATE_TEST_SUITE_P(smoke_Auto_BehaviorTests, InferRequestIOBBlobSetPrecisionTest, + ::testing::Combine( + ::testing::ValuesIn(prcs), + ::testing::Values(CommonTestUtils::DEVICE_AUTO), + ::testing::ValuesIn(Autoconfigs)), + InferRequestIOBBlobSetPrecisionTest::getTestCaseName); + + std::vector layouts = { + InferenceEngine::Layout::ANY, + InferenceEngine::Layout::NCHW, + InferenceEngine::Layout::NHWC, + InferenceEngine::Layout::NCDHW, + InferenceEngine::Layout::NDHWC, + InferenceEngine::Layout::OIHW, + InferenceEngine::Layout::GOIHW, + InferenceEngine::Layout::OIDHW, + InferenceEngine::Layout::GOIDHW, + InferenceEngine::Layout::SCALAR, + InferenceEngine::Layout::C, + InferenceEngine::Layout::CHW, + InferenceEngine::Layout::HWC, + InferenceEngine::Layout::HW, + InferenceEngine::Layout::NC, + InferenceEngine::Layout::CN, + InferenceEngine::Layout::BLOCKED, + }; + + INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, InferRequestIOBBlobSetLayoutTest, + ::testing::Combine( + ::testing::ValuesIn(layouts), + ::testing::Values(CommonTestUtils::DEVICE_CPU), + ::testing::ValuesIn(configs)), + InferRequestIOBBlobSetLayoutTest::getTestCaseName); + + INSTANTIATE_TEST_SUITE_P(smoke_Multi_BehaviorTests, InferRequestIOBBlobSetLayoutTest, + ::testing::Combine( + ::testing::ValuesIn(layouts), + ::testing::Values(CommonTestUtils::DEVICE_MULTI), + ::testing::ValuesIn(Multiconfigs)), + InferRequestIOBBlobSetLayoutTest::getTestCaseName); + + INSTANTIATE_TEST_SUITE_P(smoke_Auto_BehaviorTests, InferRequestIOBBlobSetLayoutTest, + ::testing::Combine( + ::testing::ValuesIn(layouts), + ::testing::Values(CommonTestUtils::DEVICE_AUTO), + ::testing::ValuesIn(Autoconfigs)), + InferRequestIOBBlobSetLayoutTest::getTestCaseName); + +} // namespace diff --git a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/infer_request.cpp b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/infer_request/multitheading.cpp similarity index 67% rename from inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/infer_request.cpp rename to inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/infer_request/multitheading.cpp index 07b3cf9ca40..083c1dad893 100644 --- a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/infer_request.cpp +++ b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/infer_request/multitheading.cpp @@ -4,16 +4,11 @@ #include -#include "behavior/infer_request.hpp" +#include "behavior/infer_request/multithreading.hpp" #include "ie_plugin_config.hpp" using namespace BehaviorTestsDefinitions; namespace { - const std::vector netPrecisions = { - InferenceEngine::Precision::FP32, - InferenceEngine::Precision::FP16 - }; - const std::vector> configs = { {}, {{InferenceEngine::PluginConfigParams::KEY_CPU_THROUGHPUT_STREAMS, InferenceEngine::PluginConfigParams::CPU_THROUGHPUT_AUTO}}, @@ -24,25 +19,22 @@ namespace { {{ MULTI_CONFIG_KEY(DEVICE_PRIORITIES) , CommonTestUtils::DEVICE_CPU}} }; - INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, InferRequestTests, + INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, InferRequestMultithreadingTests, ::testing::Combine( - ::testing::ValuesIn(netPrecisions), ::testing::Values(CommonTestUtils::DEVICE_CPU), ::testing::ValuesIn(configs)), - InferRequestTests::getTestCaseName); + InferRequestMultithreadingTests::getTestCaseName); - INSTANTIATE_TEST_SUITE_P(smoke_Multi_BehaviorTests, InferRequestTests, + INSTANTIATE_TEST_SUITE_P(smoke_Multi_BehaviorTests, InferRequestMultithreadingTests, ::testing::Combine( - ::testing::ValuesIn(netPrecisions), ::testing::Values(CommonTestUtils::DEVICE_MULTI), ::testing::ValuesIn(Multiconfigs)), - InferRequestTests::getTestCaseName); + InferRequestMultithreadingTests::getTestCaseName); - INSTANTIATE_TEST_SUITE_P(smoke_Auto_BehaviorTests, InferRequestTests, + INSTANTIATE_TEST_SUITE_P(smoke_Auto_BehaviorTests, InferRequestMultithreadingTests, ::testing::Combine( - ::testing::ValuesIn(netPrecisions), ::testing::Values(CommonTestUtils::DEVICE_AUTO), ::testing::ValuesIn(Multiconfigs)), - InferRequestTests::getTestCaseName); + InferRequestMultithreadingTests::getTestCaseName); } // namespace diff --git a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/infer_request/perf_counters.cpp b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/infer_request/perf_counters.cpp new file mode 100644 index 00000000000..684f1938b37 --- /dev/null +++ b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/infer_request/perf_counters.cpp @@ -0,0 +1,51 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "behavior/infer_request/perf_counters.hpp" + +using namespace BehaviorTestsDefinitions; +namespace { +TEST_P(InferRequestPerfCountersTest, CheckOperationInPerfMap) { + InferenceEngine::CNNNetwork cnnNet(function); + // Create InferRequest + InferenceEngine::InferRequest req; + ASSERT_NO_FATAL_FAILURE(req = execNet.CreateInferRequest()); + ASSERT_NO_THROW(req.Infer()); + + std::map perfMap; + ASSERT_NO_THROW(perfMap = req.GetPerformanceCounts()); + for (const auto& op : function->get_ops()) { + auto it = perfMap.begin(); + while (true) { + if (it->first.find(op->get_friendly_name() + "_") != std::string::npos || it->first == op->get_friendly_name()) { + break; + } + it++; + if (it == perfMap.end()) { + GTEST_FAIL(); + } + } + } +} + +const std::vector> configs = { + {} +}; + +const std::vector> Multiconfigs = { + {{ MULTI_CONFIG_KEY(DEVICE_PRIORITIES) , CommonTestUtils::DEVICE_CPU}} +}; + +INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, InferRequestPerfCountersTest, + ::testing::Combine( + ::testing::Values(CommonTestUtils::DEVICE_CPU), + ::testing::ValuesIn(configs)), + InferRequestPerfCountersTest::getTestCaseName); + +INSTANTIATE_TEST_SUITE_P(smoke_Multi_BehaviorTests, InferRequestPerfCountersTest, + ::testing::Combine( + ::testing::Values(CommonTestUtils::DEVICE_MULTI), + ::testing::ValuesIn(Multiconfigs)), + InferRequestPerfCountersTest::getTestCaseName); +} // namespace diff --git a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/infer_request/set_blob_by_type.cpp b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/infer_request/set_blob_by_type.cpp new file mode 100644 index 00000000000..be90ace9856 --- /dev/null +++ b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/infer_request/set_blob_by_type.cpp @@ -0,0 +1,48 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "behavior/infer_request/set_blob_by_type.hpp" +#include "common_test_utils/test_constants.hpp" + +using namespace BehaviorTestsDefinitions; +using namespace InferenceEngine; + +const std::vector BlobTypes = { + FuncTestUtils::BlobType::Compound, + FuncTestUtils::BlobType::Batched, + FuncTestUtils::BlobType::Memory, +// FuncTestUtils::BlobType::Remote, + FuncTestUtils::BlobType::I420, + FuncTestUtils::BlobType::NV12 +}; + +const std::map cpuConfig{}; //nothing special +const std::map autoConfig{}; +const std::map multiConfig{{ MULTI_CONFIG_KEY(DEVICE_PRIORITIES) , CommonTestUtils::DEVICE_CPU}}; +const std::map heteroConfig{{ "TARGET_FALLBACK", CommonTestUtils::DEVICE_CPU }}; + +INSTANTIATE_TEST_SUITE_P(smoke_Behavior, InferRequestSetBlobByType, + ::testing::Combine(::testing::ValuesIn(BlobTypes), + ::testing::Values(CommonTestUtils::DEVICE_CPU), + ::testing::Values(cpuConfig)), + InferRequestSetBlobByType::getTestCaseName); + + +INSTANTIATE_TEST_SUITE_P(smoke_Behavior_Multi, InferRequestSetBlobByType, + ::testing::Combine(::testing::ValuesIn(BlobTypes), + ::testing::Values(CommonTestUtils::DEVICE_MULTI), + ::testing::Values(multiConfig)), + InferRequestSetBlobByType::getTestCaseName); + +INSTANTIATE_TEST_SUITE_P(smoke_Behavior_Auto, InferRequestSetBlobByType, + ::testing::Combine(::testing::ValuesIn(BlobTypes), + ::testing::Values(CommonTestUtils::DEVICE_AUTO + std::string(":") + CommonTestUtils::DEVICE_CPU), + ::testing::Values(autoConfig)), + InferRequestSetBlobByType::getTestCaseName); + +INSTANTIATE_TEST_SUITE_P(smoke_Behavior_Hetero, InferRequestSetBlobByType, + ::testing::Combine(::testing::ValuesIn(BlobTypes), + ::testing::Values(CommonTestUtils::DEVICE_HETERO), + ::testing::Values(heteroConfig)), + InferRequestSetBlobByType::getTestCaseName); diff --git a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/infer_request/wait.cpp b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/infer_request/wait.cpp new file mode 100644 index 00000000000..06368b81ae2 --- /dev/null +++ b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/infer_request/wait.cpp @@ -0,0 +1,44 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include + +#include "behavior/infer_request/wait.hpp" +#include "ie_plugin_config.hpp" + +using namespace BehaviorTestsDefinitions; +namespace { + const std::vector> configs = { + {}, + {{InferenceEngine::PluginConfigParams::KEY_CPU_THROUGHPUT_STREAMS, InferenceEngine::PluginConfigParams::CPU_THROUGHPUT_AUTO}}, + {{InferenceEngine::PluginConfigParams::KEY_CPU_THROUGHPUT_STREAMS, "0"}, {InferenceEngine::PluginConfigParams::KEY_CPU_THREADS_NUM, "1"}} + }; + + const std::vector> Multiconfigs = { + {{ MULTI_CONFIG_KEY(DEVICE_PRIORITIES) , CommonTestUtils::DEVICE_CPU}} + }; + + const std::vector> Autoconfigs = { + {{ AUTO_CONFIG_KEY(DEVICE_LIST) , CommonTestUtils::DEVICE_CPU}} + }; + + INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, InferRequestWaitTests, + ::testing::Combine( + ::testing::Values(CommonTestUtils::DEVICE_CPU), + ::testing::ValuesIn(configs)), + InferRequestWaitTests::getTestCaseName); + + INSTANTIATE_TEST_SUITE_P(smoke_Multi_BehaviorTests, InferRequestWaitTests, + ::testing::Combine( + ::testing::Values(CommonTestUtils::DEVICE_MULTI), + ::testing::ValuesIn(Multiconfigs)), + InferRequestWaitTests::getTestCaseName); + + INSTANTIATE_TEST_SUITE_P(smoke_Auto_BehaviorTests, InferRequestWaitTests, + ::testing::Combine( + ::testing::Values(CommonTestUtils::DEVICE_AUTO), + ::testing::ValuesIn(Autoconfigs)), + InferRequestWaitTests::getTestCaseName); + +} // namespace diff --git a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/infer_request_input.cpp b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/infer_request_input.cpp deleted file mode 100644 index a2776a3da90..00000000000 --- a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/infer_request_input.cpp +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright (C) 2018-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#include "behavior/infer_request_input.hpp" - -using namespace BehaviorTestsDefinitions; -namespace { - const std::vector netPrecisions = { - InferenceEngine::Precision::FP32, - InferenceEngine::Precision::FP16, - InferenceEngine::Precision::U8, - InferenceEngine::Precision::U16, - InferenceEngine::Precision::I16 - }; - - const std::vector> configs = { - {}, - {{InferenceEngine::PluginConfigParams::KEY_CPU_THROUGHPUT_STREAMS, InferenceEngine::PluginConfigParams::CPU_THROUGHPUT_AUTO}} - }; - - const std::vector> multiConfigs = { - {{InferenceEngine::MultiDeviceConfigParams::KEY_MULTI_DEVICE_PRIORITIES , CommonTestUtils::DEVICE_CPU}}, - {{InferenceEngine::MultiDeviceConfigParams::KEY_MULTI_DEVICE_PRIORITIES , CommonTestUtils::DEVICE_CPU}, - {InferenceEngine::PluginConfigParams::KEY_CPU_THROUGHPUT_STREAMS, InferenceEngine::PluginConfigParams::CPU_THROUGHPUT_AUTO}} - }; - - INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, InferRequestInputTests, - ::testing::Combine( - ::testing::ValuesIn(netPrecisions), - ::testing::Values(CommonTestUtils::DEVICE_CPU), - ::testing::ValuesIn(configs)), - InferRequestInputTests::getTestCaseName); - - INSTANTIATE_TEST_SUITE_P(smoke_Multi_BehaviorTests, InferRequestInputTests, - ::testing::Combine( - ::testing::ValuesIn(netPrecisions), - ::testing::Values(CommonTestUtils::DEVICE_MULTI), - ::testing::ValuesIn(multiConfigs)), - InferRequestInputTests::getTestCaseName); - - INSTANTIATE_TEST_SUITE_P(smoke_Auto_BehaviorTests, InferRequestInputTests, - ::testing::Combine( - ::testing::ValuesIn(netPrecisions), - ::testing::Values(CommonTestUtils::DEVICE_AUTO), - ::testing::ValuesIn(multiConfigs)), - InferRequestInputTests::getTestCaseName); - -} // namespace diff --git a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/infer_request_output.cpp b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/infer_request_output.cpp deleted file mode 100644 index 3a8f8bf9c91..00000000000 --- a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/infer_request_output.cpp +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright (C) 2018-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#include "behavior/infer_request_output.hpp" - -using namespace BehaviorTestsDefinitions; -namespace { - const std::vector netPrecisions = { - InferenceEngine::Precision::FP32 - }; - - const std::vector> configs = { - {}, - {{InferenceEngine::PluginConfigParams::KEY_CPU_THROUGHPUT_STREAMS, InferenceEngine::PluginConfigParams::CPU_THROUGHPUT_AUTO}} - }; - - const std::vector> multiConfigs = { - {{InferenceEngine::MultiDeviceConfigParams::KEY_MULTI_DEVICE_PRIORITIES , CommonTestUtils::DEVICE_CPU}}, - {{InferenceEngine::MultiDeviceConfigParams::KEY_MULTI_DEVICE_PRIORITIES , CommonTestUtils::DEVICE_CPU}, - {InferenceEngine::PluginConfigParams::KEY_CPU_THROUGHPUT_STREAMS, InferenceEngine::PluginConfigParams::CPU_THROUGHPUT_AUTO}} - }; - - INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, InferRequestOutputTests, - ::testing::Combine( - ::testing::ValuesIn(netPrecisions), - ::testing::Values(CommonTestUtils::DEVICE_CPU), - ::testing::ValuesIn(configs)), - InferRequestOutputTests::getTestCaseName); - - INSTANTIATE_TEST_SUITE_P(smoke_Multi_BehaviorTests, InferRequestOutputTests, - ::testing::Combine( - ::testing::ValuesIn(netPrecisions), - ::testing::Values(CommonTestUtils::DEVICE_MULTI), - ::testing::ValuesIn(multiConfigs)), - InferRequestOutputTests::getTestCaseName); - - INSTANTIATE_TEST_SUITE_P(smoke_Auto_BehaviorTests, InferRequestOutputTests, - ::testing::Combine( - ::testing::ValuesIn(netPrecisions), - ::testing::Values(CommonTestUtils::DEVICE_AUTO), - ::testing::ValuesIn(multiConfigs)), - InferRequestOutputTests::getTestCaseName); - -} // namespace diff --git a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/layout.cpp b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/layout.cpp deleted file mode 100644 index f3854504d81..00000000000 --- a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/layout.cpp +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright (C) 2018-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#include "behavior/layout.hpp" - -using namespace BehaviorTestsDefinitions; -namespace { - const std::vector> configs = { - {} - }; - - const std::vector Layout = { - InferenceEngine::Layout::NCHW, - InferenceEngine::Layout::NHWC, - InferenceEngine::Layout::CHW, - InferenceEngine::Layout::HWC, - InferenceEngine::Layout::NC, - InferenceEngine::Layout::C - }; - - const std::vector> inputShapes = { - { 1, 3, 16, 16 }, - { 3, 32, 16 }, - { 1, 3 }, - { 3 } - }; - - INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, LayoutTest, - ::testing::Combine( - ::testing::Values(InferenceEngine::Precision::FP32), - ::testing::Values(CommonTestUtils::DEVICE_CPU, "HETERO:CPU"), - ::testing::ValuesIn(configs), - ::testing::ValuesIn(Layout), - ::testing::ValuesIn(inputShapes)), - LayoutTest::getTestCaseName); -} // namespace diff --git a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/perf_counters.cpp b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/perf_counters.cpp deleted file mode 100644 index 39aff76e6fd..00000000000 --- a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/perf_counters.cpp +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright (C) 2018-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#include "behavior/perf_counters.hpp" - -using namespace BehaviorTestsDefinitions; -namespace { - const std::vector> configs = { - {} - }; - - const std::vector> Multiconfigs = { - {{ MULTI_CONFIG_KEY(DEVICE_PRIORITIES) , CommonTestUtils::DEVICE_CPU}} - }; - - INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, PerfCountersTest, - ::testing::Combine( - ::testing::Values(InferenceEngine::Precision::FP32), - ::testing::Values(CommonTestUtils::DEVICE_CPU), - ::testing::ValuesIn(configs)), - PerfCountersTest::getTestCaseName); - - INSTANTIATE_TEST_SUITE_P(smoke_Multi_BehaviorTests, PerfCountersTest, - ::testing::Combine( - ::testing::Values(InferenceEngine::Precision::FP32), - ::testing::Values(CommonTestUtils::DEVICE_MULTI), - ::testing::ValuesIn(Multiconfigs)), - PerfCountersTest::getTestCaseName); - -} // namespace diff --git a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/preprocessing.cpp b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/preprocessing/preprocessing.cpp similarity index 96% rename from inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/preprocessing.cpp rename to inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/preprocessing/preprocessing.cpp index 657dfe5e947..f382fa3b6b1 100644 --- a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/preprocessing.cpp +++ b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/preprocessing/preprocessing.cpp @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 // -#include "behavior/preprocessing.hpp" +#include "behavior/preprocessing/preprocessing.hpp" using namespace BehaviorTestsDefinitions; diff --git a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/set_preprocess.cpp b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/preprocessing/set_preprocess.cpp similarity index 78% rename from inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/set_preprocess.cpp rename to inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/preprocessing/set_preprocess.cpp index 2acb232ea70..389ff2c5c09 100644 --- a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/set_preprocess.cpp +++ b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/preprocessing/set_preprocess.cpp @@ -2,9 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 // -#include - -#include "behavior/set_preprocess.hpp" +#include "behavior/preprocessing/set_preprocess.hpp" using namespace BehaviorTestsDefinitions; namespace { @@ -27,33 +25,33 @@ namespace { {{ InferenceEngine::MultiDeviceConfigParams::KEY_MULTI_DEVICE_PRIORITIES , CommonTestUtils::DEVICE_CPU}} }; - INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, PreprocessTest, + INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, InferRequestPreprocessTest, ::testing::Combine( ::testing::ValuesIn(netPrecisions), ::testing::Values(CommonTestUtils::DEVICE_CPU), ::testing::ValuesIn(configs)), - PreprocessTest::getTestCaseName); + InferRequestPreprocessTest::getTestCaseName); - INSTANTIATE_TEST_SUITE_P(smoke_Hetero_BehaviorTests, PreprocessTest, + INSTANTIATE_TEST_SUITE_P(smoke_Hetero_BehaviorTests, InferRequestPreprocessTest, ::testing::Combine( ::testing::ValuesIn(netPrecisions), ::testing::Values(CommonTestUtils::DEVICE_HETERO), ::testing::ValuesIn(heteroConfigs)), - PreprocessTest::getTestCaseName); + InferRequestPreprocessTest::getTestCaseName); - INSTANTIATE_TEST_SUITE_P(smoke_Multi_BehaviorTests, PreprocessTest, + INSTANTIATE_TEST_SUITE_P(smoke_Multi_BehaviorTests, InferRequestPreprocessTest, ::testing::Combine( ::testing::ValuesIn(netPrecisions), ::testing::Values(CommonTestUtils::DEVICE_MULTI), ::testing::ValuesIn(multiConfigs)), - PreprocessTest::getTestCaseName); + InferRequestPreprocessTest::getTestCaseName); - INSTANTIATE_TEST_SUITE_P(smoke_Auto_BehaviorTests, PreprocessTest, + INSTANTIATE_TEST_SUITE_P(smoke_Auto_BehaviorTests, InferRequestPreprocessTest, ::testing::Combine( ::testing::ValuesIn(netPrecisions), ::testing::Values(CommonTestUtils::DEVICE_AUTO), ::testing::ValuesIn(multiConfigs)), - PreprocessTest::getTestCaseName); + InferRequestPreprocessTest::getTestCaseName); const std::vector ioPrecisions = { @@ -70,7 +68,7 @@ namespace { InferenceEngine::Layout::NHWC }; - INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, PreprocessConversionTest, + INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, InferRequestPreprocessConversionTest, ::testing::Combine( ::testing::ValuesIn(netPrecisions), ::testing::ValuesIn(ioPrecisions), @@ -82,9 +80,9 @@ namespace { ::testing::Bool(), ::testing::Values(CommonTestUtils::DEVICE_CPU), ::testing::ValuesIn(configs)), - PreprocessConversionTest::getTestCaseName); + InferRequestPreprocessConversionTest::getTestCaseName); - INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, PreprocessDynamicallyInSetBlobTest, + INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, InferRequestPreprocessDynamicallyInSetBlobTest, ::testing::Combine( ::testing::ValuesIn(netPrecisions), ::testing::Bool(), @@ -96,9 +94,9 @@ namespace { ::testing::Values(true), // only SetBlob ::testing::Values(CommonTestUtils::DEVICE_CPU), ::testing::ValuesIn(configs)), - PreprocessDynamicallyInSetBlobTest::getTestCaseName); + InferRequestPreprocessDynamicallyInSetBlobTest::getTestCaseName); - INSTANTIATE_TEST_SUITE_P(smoke_Hetero_BehaviorTests, PreprocessConversionTest, + INSTANTIATE_TEST_SUITE_P(smoke_Hetero_BehaviorTests, InferRequestPreprocessConversionTest, ::testing::Combine( ::testing::ValuesIn(netPrecisions), ::testing::ValuesIn(ioPrecisions), @@ -110,9 +108,9 @@ namespace { ::testing::Bool(), ::testing::Values(CommonTestUtils::DEVICE_HETERO), ::testing::ValuesIn(heteroConfigs)), - PreprocessConversionTest::getTestCaseName); + InferRequestPreprocessConversionTest::getTestCaseName); - INSTANTIATE_TEST_SUITE_P(smoke_Hetero_BehaviorTests, PreprocessDynamicallyInSetBlobTest, + INSTANTIATE_TEST_SUITE_P(smoke_Hetero_BehaviorTests, InferRequestPreprocessDynamicallyInSetBlobTest, ::testing::Combine( ::testing::ValuesIn(netPrecisions), ::testing::Bool(), @@ -124,9 +122,9 @@ namespace { ::testing::Values(true), // only SetBlob ::testing::Values(CommonTestUtils::DEVICE_HETERO), ::testing::ValuesIn(heteroConfigs)), - PreprocessDynamicallyInSetBlobTest::getTestCaseName); + InferRequestPreprocessDynamicallyInSetBlobTest::getTestCaseName); - INSTANTIATE_TEST_SUITE_P(smoke_Multi_BehaviorTests, PreprocessConversionTest, + INSTANTIATE_TEST_SUITE_P(smoke_Multi_BehaviorTests, InferRequestPreprocessConversionTest, ::testing::Combine( ::testing::ValuesIn(netPrecisions), ::testing::ValuesIn(ioPrecisions), @@ -138,9 +136,9 @@ namespace { ::testing::Bool(), ::testing::Values(CommonTestUtils::DEVICE_MULTI), ::testing::ValuesIn(multiConfigs)), - PreprocessConversionTest::getTestCaseName); + InferRequestPreprocessConversionTest::getTestCaseName); - INSTANTIATE_TEST_SUITE_P(smoke_Multi_BehaviorTests, PreprocessDynamicallyInSetBlobTest, + INSTANTIATE_TEST_SUITE_P(smoke_Multi_BehaviorTests, InferRequestPreprocessDynamicallyInSetBlobTest, ::testing::Combine( ::testing::ValuesIn(netPrecisions), ::testing::Bool(), @@ -152,9 +150,9 @@ namespace { ::testing::Values(true), // only SetBlob ::testing::Values(CommonTestUtils::DEVICE_MULTI), ::testing::ValuesIn(multiConfigs)), - PreprocessDynamicallyInSetBlobTest::getTestCaseName); + InferRequestPreprocessDynamicallyInSetBlobTest::getTestCaseName); - INSTANTIATE_TEST_SUITE_P(smoke_Auto_BehaviorTests, PreprocessConversionTest, + INSTANTIATE_TEST_SUITE_P(smoke_Auto_BehaviorTests, InferRequestPreprocessConversionTest, ::testing::Combine( ::testing::ValuesIn(netPrecisions), ::testing::ValuesIn(ioPrecisions), @@ -166,9 +164,9 @@ namespace { ::testing::Bool(), ::testing::Values(CommonTestUtils::DEVICE_AUTO), ::testing::ValuesIn(multiConfigs)), - PreprocessConversionTest::getTestCaseName); + InferRequestPreprocessConversionTest::getTestCaseName); - INSTANTIATE_TEST_SUITE_P(smoke_Auto_BehaviorTests, PreprocessDynamicallyInSetBlobTest, + INSTANTIATE_TEST_SUITE_P(smoke_Auto_BehaviorTests, InferRequestPreprocessDynamicallyInSetBlobTest, ::testing::Combine( ::testing::ValuesIn(netPrecisions), ::testing::Bool(), @@ -180,6 +178,6 @@ namespace { ::testing::Values(true), // only SetBlob ::testing::Values(CommonTestUtils::DEVICE_AUTO), ::testing::ValuesIn(multiConfigs)), - PreprocessDynamicallyInSetBlobTest::getTestCaseName); + InferRequestPreprocessDynamicallyInSetBlobTest::getTestCaseName); } // namespace \ No newline at end of file diff --git a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/set_blob_of_kind.cpp b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/set_blob_of_kind.cpp deleted file mode 100644 index 5b2355476ec..00000000000 --- a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/set_blob_of_kind.cpp +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright (C) 2018-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#include "behavior/set_blob_of_kind.hpp" -#include "common_test_utils/test_constants.hpp" - -using namespace BehaviorTestsDefinitions; -using namespace InferenceEngine; - -const std::vector blobKinds = { - FuncTestUtils::BlobKind::Simple, - FuncTestUtils::BlobKind::Compound, - FuncTestUtils::BlobKind::BatchOfSimple -}; - -const SetBlobOfKindConfig cpuConfig{}; //nothing special -const SetBlobOfKindConfig multiConfig{{ MULTI_CONFIG_KEY(DEVICE_PRIORITIES) , CommonTestUtils::DEVICE_CPU}}; -const SetBlobOfKindConfig heteroConfig{{ "TARGET_FALLBACK", CommonTestUtils::DEVICE_CPU }}; - -INSTANTIATE_TEST_SUITE_P(smoke_SetBlobOfKindCPU, SetBlobOfKindTest, - ::testing::Combine(::testing::ValuesIn(blobKinds), - ::testing::Values(CommonTestUtils::DEVICE_CPU), - ::testing::Values(cpuConfig)), - SetBlobOfKindTest::getTestCaseName); - - -INSTANTIATE_TEST_SUITE_P(smoke_SetBlobOfKindMULTI, SetBlobOfKindTest, - ::testing::Combine(::testing::ValuesIn(blobKinds), - ::testing::Values(CommonTestUtils::DEVICE_MULTI), - ::testing::Values(multiConfig)), - SetBlobOfKindTest::getTestCaseName); - -INSTANTIATE_TEST_SUITE_P(smoke_SetBlobOfKindAUTO, SetBlobOfKindTest, - ::testing::Combine(::testing::ValuesIn(blobKinds), - ::testing::Values(CommonTestUtils::DEVICE_AUTO), - ::testing::Values(multiConfig)), - SetBlobOfKindTest::getTestCaseName); - -INSTANTIATE_TEST_SUITE_P(smoke_SetBlobOfKindHETERO, SetBlobOfKindTest, - ::testing::Combine(::testing::ValuesIn(blobKinds), - ::testing::Values(CommonTestUtils::DEVICE_HETERO), - ::testing::Values(heteroConfig)), - SetBlobOfKindTest::getTestCaseName); diff --git a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/skip_tests_config.cpp b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/skip_tests_config.cpp index 984250795b5..1bb848fcdca 100644 --- a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/skip_tests_config.cpp +++ b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/skip_tests_config.cpp @@ -25,8 +25,8 @@ std::vector disabledTestPatterns() { R"(.*(RangeAddSubgraphTest).*Start=1.2.*Stop=(5.2|-5.2).*Step=(0.1|-0.1).*netPRC=FP16.*)", R"(.*(RangeNumpyAddSubgraphTest).*netPRC=FP16.*)", // TODO: Issue: 43793 - R"(.*PreprocessDynamicallyInSetBlobTest.*iPRC=0.*_iLT=1.*)", - R"(.*PreprocessDynamicallyInSetBlobTest.*oPRC=0.*_oLT=1.*)", + R"(.*InferRequestPreprocessDynamicallyInSetBlobTest.*iPRC=0.*_iLT=1.*)", + R"(.*InferRequestPreprocessDynamicallyInSetBlobTest.*oPRC=0.*_oLT=1.*)", // TODO: Issue: 34348 R"(.*IEClassGetAvailableDevices.*)", // TODO: Issue: 25533 @@ -70,13 +70,23 @@ std::vector disabledTestPatterns() { // TODO: 55656 AUTO plugin and QueryNetwork R"(.*CoreThreading.*smoke_QueryNetwork.*targetDevice=AUTO_config.*)", // Unsupported config KEY_ENFORCE_BF16 for AUTO plugin - R"(.*smoke_SetBlobOfKindAUTO.*SetBlobOfKindTest.CompareWithRefs.*)", + R"(.*Behavior_Auto.*InferRequestSetBlobByType.*)", // TODO: 57562 No dynamic output shape support R"(.*NonZeroLayerTest.*)", // need to implement Export / Import R"(.*IEClassImportExportTestP.*)", + // CVS-58963: Not implemented yet + R"(.*Behavior.*InferRequest.*OutOfFirstOutIsInputForSecondNetwork.*)", + // Not expected behavior + R"(.*Behavior.*InferRequestIOBBlobSetLayoutTest.*layout=(95|OIHW).*)", + R"(.*Behavior.*InferRequestIOBBlobSetLayoutTest.*layout=(95|OIHW).*)", + R"(.*Behavior.*InferRequestIOBBlobSetLayoutTest.*CanSetOutBlobWithDifferentLayouts.*layout=HW.*)", + R"(.*Behavior.*InferRequestIOBBlobSetLayoutTest.*CanSetInBlobWithDifferentLayouts.*layout=NHWC.*targetDevice=(AUTO|MULTI).*)", + R"(.*Behavior.*InferRequestIOBBlobSetLayoutTest.*CanSetOutBlobWithDifferentLayouts.*layout=CN.*targetDevice=(AUTO|MULTI).*)", + R"(.*Behavior.*InferRequestSetBlobByType.*Batched.*)", + R"(.*Auto_Behavior.*InferRequestIOBBlobTest.*canProcessDeallocatedOutputBlobAfterGetAndSetBlob.*)", // azure is failing after #6199 - R"(.*/NmsLayerTest.*)" + R"(.*/NmsLayerTest.*)", }; #if ((IE_THREAD == IE_THREAD_TBB) || (IE_THREAD == IE_THREAD_TBB_AUTO)) diff --git a/inference-engine/tests/functional/plugin/gna/shared_tests_instances/behavior/caching_tests.cpp b/inference-engine/tests/functional/plugin/gna/shared_tests_instances/behavior/caching/caching_tests.cpp similarity index 95% rename from inference-engine/tests/functional/plugin/gna/shared_tests_instances/behavior/caching_tests.cpp rename to inference-engine/tests/functional/plugin/gna/shared_tests_instances/behavior/caching/caching_tests.cpp index 620e6285cd9..80bf64514ae 100644 --- a/inference-engine/tests/functional/plugin/gna/shared_tests_instances/behavior/caching_tests.cpp +++ b/inference-engine/tests/functional/plugin/gna/shared_tests_instances/behavior/caching/caching_tests.cpp @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 // -#include "behavior/caching_tests.hpp" +#include "behavior/caching/caching_tests.hpp" using namespace LayerTestsDefinitions; diff --git a/inference-engine/tests/functional/plugin/gna/shared_tests_instances/behavior/infer_request.cpp b/inference-engine/tests/functional/plugin/gna/shared_tests_instances/behavior/infer_request.cpp deleted file mode 100644 index 055c23f047a..00000000000 --- a/inference-engine/tests/functional/plugin/gna/shared_tests_instances/behavior/infer_request.cpp +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (C) 2018-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#include "behavior/infer_request.hpp" - -using namespace BehaviorTestsDefinitions; -namespace { -const std::vector netPrecisions = { - InferenceEngine::Precision::FP32 -}; - -INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, InferRequestTests, - ::testing::Combine( - ::testing::ValuesIn(netPrecisions), - ::testing::Values(CommonTestUtils::DEVICE_GNA), - ::testing::Values(std::map({}))), - InferRequestTests::getTestCaseName); - -INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, InferRequestTestsResultNotReady, - ::testing::Combine( - ::testing::ValuesIn(netPrecisions), - ::testing::Values(CommonTestUtils::DEVICE_GNA), - ::testing::Values(std::map({}))), - InferRequestTests::getTestCaseName); - -} // namespace diff --git a/inference-engine/tests/functional/plugin/gna/shared_tests_instances/behavior/infer_request_callback.cpp b/inference-engine/tests/functional/plugin/gna/shared_tests_instances/behavior/infer_request/callback.cpp similarity index 57% rename from inference-engine/tests/functional/plugin/gna/shared_tests_instances/behavior/infer_request_callback.cpp rename to inference-engine/tests/functional/plugin/gna/shared_tests_instances/behavior/infer_request/callback.cpp index 9336cb7efa3..891b05ff2cf 100644 --- a/inference-engine/tests/functional/plugin/gna/shared_tests_instances/behavior/infer_request_callback.cpp +++ b/inference-engine/tests/functional/plugin/gna/shared_tests_instances/behavior/infer_request/callback.cpp @@ -2,15 +2,10 @@ // SPDX-License-Identifier: Apache-2.0 // -#include "behavior/infer_request_callback.hpp" +#include "behavior/infer_request/callback.hpp" using namespace BehaviorTestsDefinitions; namespace { -const std::vector netPrecisions = { - InferenceEngine::Precision::FP32, - InferenceEngine::Precision::FP16 -}; - const std::vector> configs = { {}, }; @@ -20,17 +15,15 @@ const std::vector> multiConfigs = { }; -INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, CallbackTests, +INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, InferRequestCallbackTests, ::testing::Combine( - ::testing::ValuesIn(netPrecisions), ::testing::Values(CommonTestUtils::DEVICE_GNA), ::testing::ValuesIn(configs)), - CallbackTests::getTestCaseName); + InferRequestCallbackTests::getTestCaseName); -INSTANTIATE_TEST_SUITE_P(smoke_Multi_BehaviorTests, CallbackTests, +INSTANTIATE_TEST_SUITE_P(smoke_Multi_BehaviorTests, InferRequestCallbackTests, ::testing::Combine( - ::testing::ValuesIn(netPrecisions), ::testing::Values(CommonTestUtils::DEVICE_MULTI), ::testing::ValuesIn(multiConfigs)), - CallbackTests::getTestCaseName); + InferRequestCallbackTests::getTestCaseName); } // namespace diff --git a/inference-engine/tests/functional/plugin/gna/shared_tests_instances/behavior/infer_request_config.cpp b/inference-engine/tests/functional/plugin/gna/shared_tests_instances/behavior/infer_request/config.cpp similarity index 66% rename from inference-engine/tests/functional/plugin/gna/shared_tests_instances/behavior/infer_request_config.cpp rename to inference-engine/tests/functional/plugin/gna/shared_tests_instances/behavior/infer_request/config.cpp index c21747bd335..23d18863744 100644 --- a/inference-engine/tests/functional/plugin/gna/shared_tests_instances/behavior/infer_request_config.cpp +++ b/inference-engine/tests/functional/plugin/gna/shared_tests_instances/behavior/infer_request/config.cpp @@ -3,15 +3,10 @@ // #include "gna/gna_config.hpp" -#include "behavior/infer_request_config.hpp" +#include "behavior/infer_request/config.hpp" using namespace BehaviorTestsDefinitions; namespace { - const std::vector netPrecisions = { - InferenceEngine::Precision::FP32, - InferenceEngine::Precision::FP16 - }; - const std::vector> configs = { {} }; @@ -29,18 +24,10 @@ namespace { {{InferenceEngine::GNAConfigParams::KEY_GNA_COMPACT_MODE, InferenceEngine::PluginConfigParams::NO}} }; - INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, InferConfigTests, + INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, InferRequestConfigTest, ::testing::Combine( - ::testing::ValuesIn(netPrecisions), + ::testing::Values(0u), ::testing::Values(CommonTestUtils::DEVICE_GNA), ::testing::ValuesIn(configs)), - InferConfigTests::getTestCaseName); - - INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, InferConfigInTests, - ::testing::Combine( - ::testing::ValuesIn(netPrecisions), - ::testing::Values(CommonTestUtils::DEVICE_GNA), - ::testing::ValuesIn(Inconfigs)), - InferConfigInTests::getTestCaseName); - + InferRequestConfigTest::getTestCaseName); } // namespace diff --git a/inference-engine/tests/functional/plugin/gna/shared_tests_instances/behavior/infer_request/io_blob.cpp b/inference-engine/tests/functional/plugin/gna/shared_tests_instances/behavior/infer_request/io_blob.cpp new file mode 100644 index 00000000000..2eef496c11f --- /dev/null +++ b/inference-engine/tests/functional/plugin/gna/shared_tests_instances/behavior/infer_request/io_blob.cpp @@ -0,0 +1,16 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "behavior/infer_request/io_blob.hpp" + +using namespace BehaviorTestsDefinitions; +namespace { +INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, InferRequestIOBBlobTest, + ::testing::Combine( + ::testing::Values(CommonTestUtils::DEVICE_GNA), + ::testing::Values(std::map({}))), + InferRequestIOBBlobTest::getTestCaseName); + + +} // namespace diff --git a/inference-engine/tests/functional/plugin/gna/shared_tests_instances/behavior/memory_states.cpp b/inference-engine/tests/functional/plugin/gna/shared_tests_instances/behavior/infer_request/memory_states.cpp similarity index 92% rename from inference-engine/tests/functional/plugin/gna/shared_tests_instances/behavior/memory_states.cpp rename to inference-engine/tests/functional/plugin/gna/shared_tests_instances/behavior/infer_request/memory_states.cpp index c2db36ff9f3..e9278bd4dd0 100644 --- a/inference-engine/tests/functional/plugin/gna/shared_tests_instances/behavior/memory_states.cpp +++ b/inference-engine/tests/functional/plugin/gna/shared_tests_instances/behavior/infer_request/memory_states.cpp @@ -3,9 +3,12 @@ // #include -#include "behavior/memory_states.hpp" +#include "behavior/infer_request/memory_states.hpp" #include "functional_test_utils/plugin_cache.hpp" +using namespace BehaviorTestsDefinitions; + +namespace { static const char model[] = R"V0G0N( @@ -123,10 +126,12 @@ InferenceEngine::CNNNetwork getNetwork() { auto ie = PluginCache::get().ie(); return ie->ReadNetwork(model, InferenceEngine::Blob::Ptr{}); } + std::vector memoryStateTestCases = { memoryStateParams(getNetwork(), {"c_1-3", "r_1-3"}, CommonTestUtils::DEVICE_GNA) }; -INSTANTIATE_TEST_SUITE_P(smoke_VariableStateBasic, VariableStateTest, - ::testing::ValuesIn(memoryStateTestCases), - VariableStateTest::getTestCaseName); +INSTANTIATE_TEST_SUITE_P(smoke_VariableStateBasic, InferRequestVariableStateTest, + ::testing::ValuesIn(memoryStateTestCases), + InferRequestVariableStateTest::getTestCaseName); +} // namespace \ No newline at end of file diff --git a/inference-engine/tests/functional/plugin/gna/shared_tests_instances/behavior/infer_request/multitheading.cpp b/inference-engine/tests/functional/plugin/gna/shared_tests_instances/behavior/infer_request/multitheading.cpp new file mode 100644 index 00000000000..8ce5716f774 --- /dev/null +++ b/inference-engine/tests/functional/plugin/gna/shared_tests_instances/behavior/infer_request/multitheading.cpp @@ -0,0 +1,14 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "behavior/infer_request/multithreading.hpp" + +using namespace BehaviorTestsDefinitions; +namespace { +INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, InferRequestMultithreadingTests, + ::testing::Combine( + ::testing::Values(CommonTestUtils::DEVICE_GNA), + ::testing::Values(std::map({}))), + InferRequestMultithreadingTests::getTestCaseName); +} // namespace diff --git a/inference-engine/tests/functional/plugin/gna/shared_tests_instances/behavior/infer_request/wait.cpp b/inference-engine/tests/functional/plugin/gna/shared_tests_instances/behavior/infer_request/wait.cpp new file mode 100644 index 00000000000..4214f9eb312 --- /dev/null +++ b/inference-engine/tests/functional/plugin/gna/shared_tests_instances/behavior/infer_request/wait.cpp @@ -0,0 +1,16 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "behavior/infer_request/wait.hpp" + +using namespace BehaviorTestsDefinitions; +namespace { +INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, InferRequestWaitTests, + ::testing::Combine( + ::testing::Values(CommonTestUtils::DEVICE_GNA), + ::testing::Values(std::map({}))), + InferRequestWaitTests::getTestCaseName); + + +} // namespace diff --git a/inference-engine/tests/functional/plugin/gna/shared_tests_instances/behavior/infer_request_input.cpp b/inference-engine/tests/functional/plugin/gna/shared_tests_instances/behavior/infer_request_input.cpp deleted file mode 100644 index 6aa0825d34d..00000000000 --- a/inference-engine/tests/functional/plugin/gna/shared_tests_instances/behavior/infer_request_input.cpp +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (C) 2018-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#include "behavior/infer_request_input.hpp" - -using namespace BehaviorTestsDefinitions; -namespace { - const std::vector netPrecisions = { - InferenceEngine::Precision::U8, - InferenceEngine::Precision::I16 - }; - - const std::vector> configs = { - {} - }; - - INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, InferRequestInputTests, - ::testing::Combine( - ::testing::ValuesIn(netPrecisions), - ::testing::Values(CommonTestUtils::DEVICE_GNA), - ::testing::ValuesIn(configs)), - InferRequestInputTests::getTestCaseName); - -} // namespace diff --git a/inference-engine/tests/functional/plugin/gna/shared_tests_instances/behavior/infer_request_output.cpp b/inference-engine/tests/functional/plugin/gna/shared_tests_instances/behavior/infer_request_output.cpp deleted file mode 100644 index a8c4ed86f3e..00000000000 --- a/inference-engine/tests/functional/plugin/gna/shared_tests_instances/behavior/infer_request_output.cpp +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (C) 2018-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#include "behavior/infer_request_output.hpp" - -using namespace BehaviorTestsDefinitions; -namespace { - const std::vector netPrecisions = { - InferenceEngine::Precision::FP32 - }; - - const std::vector> configs = { - {} - }; - - INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, InferRequestOutputTests, - ::testing::Combine( - ::testing::ValuesIn(netPrecisions), - ::testing::Values(CommonTestUtils::DEVICE_GNA), - ::testing::ValuesIn(configs)), - InferRequestOutputTests::getTestCaseName); - -} // namespace diff --git a/inference-engine/tests/functional/plugin/gna/shared_tests_instances/behavior/layout.cpp b/inference-engine/tests/functional/plugin/gna/shared_tests_instances/behavior/layout.cpp deleted file mode 100644 index ccbab8aecb4..00000000000 --- a/inference-engine/tests/functional/plugin/gna/shared_tests_instances/behavior/layout.cpp +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright (C) 2018-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#include "behavior/layout.hpp" - -using namespace BehaviorTestsDefinitions; -namespace { - const std::vector> configs = { - {{"GNA_SCALE_FACTOR_0", "1638.4"}, {"GNA_SCALE_FACTOR_1", "1638.4"}} - }; - - const std::vector Layout = { - InferenceEngine::Layout::NCHW, - InferenceEngine::Layout::CHW, - InferenceEngine::Layout::NC - }; - - const std::vector> inputShapes = { - { 1, 3, 16, 16 }, - { 3, 32, 16 }, - { 1, 3 } - }; - - INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, LayoutTest, - ::testing::Combine( - ::testing::Values(InferenceEngine::Precision::FP32), - ::testing::Values(CommonTestUtils::DEVICE_GNA), - ::testing::ValuesIn(configs), - ::testing::ValuesIn(Layout), - ::testing::ValuesIn(inputShapes)), - LayoutTest::getTestCaseName); - -} // namespace \ No newline at end of file diff --git a/inference-engine/tests/functional/plugin/gna/shared_tests_instances/skip_tests_config.cpp b/inference-engine/tests/functional/plugin/gna/shared_tests_instances/skip_tests_config.cpp index 9d9436db568..c580b6501ff 100644 --- a/inference-engine/tests/functional/plugin/gna/shared_tests_instances/skip_tests_config.cpp +++ b/inference-engine/tests/functional/plugin/gna/shared_tests_instances/skip_tests_config.cpp @@ -11,9 +11,9 @@ std::vector disabledTestPatterns() { return { // TODO: FIX BUG 31661 // TODO: support InferRequest in GNAPlugin - ".*InferRequestTests\\.canRun3AsyncRequestsConsistentlyFromThreadsWithoutWait.*", + ".*InferRequestMultithreadingTests\\.canRun3AsyncRequestsConsistentlyFromThreadsWithoutWait.*", // TODO: FIX BUG 23741 - ".*InferRequestTests\\.canRun3SyncRequestsConsistentlyFromThreads.*", + ".*InferRequestMultithreadingTests\\.canRun3SyncRequestsConsistentlyFromThreads.*", // TODO: FIX BUG 59041 ".*Behavior.*CallbackThrowException.*", // TODO: FIX BUG 32210 @@ -36,7 +36,7 @@ std::vector disabledTestPatterns() { // TODO: Issue: 29577 R"(.*CoreThreadingTests.smoke_QueryNetwork.*)", //TODO: Issue: 46416 - R"(.*VariableStateTest.inferreq_smoke_VariableState_2infers*.*)", + R"(.*InferRequestVariableStateTest.inferreq_smoke_VariableState_2infers*.*)", // TODO: Issue 24839 R"(.*ConvolutionLayerTest.CompareWithRefs.*D=\(1.3\).*)", R"(.*ConvolutionLayerTest.CompareWithRefs.*D=\(3.1\).*)", @@ -52,5 +52,7 @@ std::vector disabledTestPatterns() { R"(.*smoke_MemoryTest.*iteration_count=4.*IS=\(1.10\).*)", R"(.*smoke_MemoryTest.*iteration_count=10.*IS=\(1.10\).*)", R"(.*smoke_MemoryTest.*LOW_LATENCY.*iteration_count=10.*IS=\(1.2\).*)", + // CVS-58963: Not implemented yet + R"(.*Behavior.*InferRequest.*OutOfFirstOutIsInputForSecondNetwork.*)", }; } diff --git a/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/behavior/caching_tests.cpp b/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/behavior/caching_tests.cpp index 247d1482e76..5287e42ffe1 100644 --- a/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/behavior/caching_tests.cpp +++ b/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/behavior/caching_tests.cpp @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 // -#include "behavior/caching_tests.hpp" +#include "behavior/caching/caching_tests.hpp" using namespace LayerTestsDefinitions; diff --git a/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/behavior/infer_request_callback.cpp b/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/behavior/infer_request/callback.cpp similarity index 55% rename from inference-engine/tests/functional/plugin/gpu/shared_tests_instances/behavior/infer_request_callback.cpp rename to inference-engine/tests/functional/plugin/gpu/shared_tests_instances/behavior/infer_request/callback.cpp index 8c8a0e7fb32..90a22c2435c 100644 --- a/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/behavior/infer_request_callback.cpp +++ b/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/behavior/infer_request/callback.cpp @@ -2,15 +2,10 @@ // SPDX-License-Identifier: Apache-2.0 // -#include "behavior/infer_request_callback.hpp" +#include "behavior/infer_request/callback.hpp" using namespace BehaviorTestsDefinitions; namespace { -const std::vector netPrecisions = { - InferenceEngine::Precision::FP32, - InferenceEngine::Precision::FP16 -}; - const std::vector> configs = { {}, }; @@ -19,24 +14,21 @@ const std::vector> multiConfigs = { {{ MULTI_CONFIG_KEY(DEVICE_PRIORITIES) , CommonTestUtils::DEVICE_GPU}} }; -INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, CallbackTests, +INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, InferRequestCallbackTests, ::testing::Combine( - ::testing::ValuesIn(netPrecisions), ::testing::Values(CommonTestUtils::DEVICE_GPU), ::testing::ValuesIn(configs)), - CallbackTests::getTestCaseName); + InferRequestCallbackTests::getTestCaseName); -INSTANTIATE_TEST_SUITE_P(smoke_Multi_BehaviorTests, CallbackTests, +INSTANTIATE_TEST_SUITE_P(smoke_Multi_BehaviorTests, InferRequestCallbackTests, ::testing::Combine( - ::testing::ValuesIn(netPrecisions), ::testing::Values(CommonTestUtils::DEVICE_MULTI), ::testing::ValuesIn(multiConfigs)), - CallbackTests::getTestCaseName); + InferRequestCallbackTests::getTestCaseName); -INSTANTIATE_TEST_SUITE_P(smoke_Auto_BehaviorTests, CallbackTests, +INSTANTIATE_TEST_SUITE_P(smoke_Auto_BehaviorTests, InferRequestCallbackTests, ::testing::Combine( - ::testing::ValuesIn(netPrecisions), ::testing::Values(CommonTestUtils::DEVICE_AUTO), ::testing::ValuesIn(multiConfigs)), - CallbackTests::getTestCaseName); + InferRequestCallbackTests::getTestCaseName); } // namespace diff --git a/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/behavior/infer_request/config.cpp b/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/behavior/infer_request/config.cpp new file mode 100644 index 00000000000..5b99ca1d7b1 --- /dev/null +++ b/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/behavior/infer_request/config.cpp @@ -0,0 +1,30 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "behavior/infer_request/config.hpp" + +using namespace BehaviorTestsDefinitions; +namespace { +const std::vector> configs = { + {} +}; + +const std::vector> multiConfigs = { + {{InferenceEngine::MultiDeviceConfigParams::KEY_MULTI_DEVICE_PRIORITIES, CommonTestUtils::DEVICE_GPU}} +}; + +INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, InferRequestConfigTest, + ::testing::Combine( + ::testing::Values(1u), + ::testing::Values(CommonTestUtils::DEVICE_GPU), + ::testing::ValuesIn(configs)), + InferRequestConfigTest::getTestCaseName); + +INSTANTIATE_TEST_SUITE_P(smoke_Multi_BehaviorTests, InferRequestConfigTest, + ::testing::Combine( + ::testing::Values(1u), + ::testing::Values(CommonTestUtils::DEVICE_MULTI), + ::testing::ValuesIn(multiConfigs)), + InferRequestConfigTest::getTestCaseName); +} // namespace diff --git a/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/configuration_tests/dynamic_batch.cpp b/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/behavior/infer_request/dynamic_batch.cpp similarity index 95% rename from inference-engine/tests/functional/plugin/gpu/shared_tests_instances/configuration_tests/dynamic_batch.cpp rename to inference-engine/tests/functional/plugin/gpu/shared_tests_instances/behavior/infer_request/dynamic_batch.cpp index 36a13d4ea5f..3b7c024af0d 100644 --- a/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/configuration_tests/dynamic_batch.cpp +++ b/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/behavior/infer_request/dynamic_batch.cpp @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 // -#include +#include #include "common_test_utils/test_constants.hpp" namespace ConfigurationTestsDefinitions { diff --git a/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/behavior/infer_request/io_blob.cpp b/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/behavior/infer_request/io_blob.cpp new file mode 100644 index 00000000000..1c40015506d --- /dev/null +++ b/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/behavior/infer_request/io_blob.cpp @@ -0,0 +1,120 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include + +#include "behavior/infer_request/io_blob.hpp" +#include "ie_plugin_config.hpp" + +using namespace BehaviorTestsDefinitions; +namespace { + const std::vector> configs = { + {{InferenceEngine::MultiDeviceConfigParams::KEY_MULTI_DEVICE_PRIORITIES, CommonTestUtils::DEVICE_GPU}} + }; + + const std::vector> autoconfigs = { + {{InferenceEngine::KEY_AUTO_DEVICE_LIST, CommonTestUtils::DEVICE_GPU}}, + {{InferenceEngine::KEY_AUTO_DEVICE_LIST , std::string(CommonTestUtils::DEVICE_CPU) + "," + CommonTestUtils::DEVICE_GPU}} + }; + + INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, InferRequestIOBBlobTest, + ::testing::Combine( + ::testing::Values(CommonTestUtils::DEVICE_GPU), + ::testing::Values(std::map({}))), + InferRequestIOBBlobTest::getTestCaseName); + + INSTANTIATE_TEST_SUITE_P(smoke_Multi_BehaviorTests, InferRequestIOBBlobTest, + ::testing::Combine( + ::testing::Values(CommonTestUtils::DEVICE_MULTI), + ::testing::ValuesIn(configs)), + InferRequestIOBBlobTest::getTestCaseName); + + INSTANTIATE_TEST_SUITE_P(smoke_Auto_BehaviorTests, InferRequestIOBBlobTest, + ::testing::Combine( + ::testing::Values(CommonTestUtils::DEVICE_AUTO), + ::testing::ValuesIn(autoconfigs)), + InferRequestIOBBlobTest::getTestCaseName); + +std::vector prcs = { + InferenceEngine::Precision::FP16, + InferenceEngine::Precision::FP32, + InferenceEngine::Precision::FP64, + InferenceEngine::Precision::I4, + InferenceEngine::Precision::I8, + InferenceEngine::Precision::I16, + InferenceEngine::Precision::I32, + InferenceEngine::Precision::I64, + InferenceEngine::Precision::U4, + InferenceEngine::Precision::U8, + InferenceEngine::Precision::U16, + InferenceEngine::Precision::U32, + InferenceEngine::Precision::U64, + InferenceEngine::Precision::BF16, + InferenceEngine::Precision::BIN, + InferenceEngine::Precision::BOOL, +}; + +INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, InferRequestIOBBlobSetPrecisionTest, + ::testing::Combine( + ::testing::ValuesIn(prcs), + ::testing::Values(CommonTestUtils::DEVICE_CPU), + ::testing::Values(std::map{})), + InferRequestIOBBlobSetPrecisionTest::getTestCaseName); + +INSTANTIATE_TEST_SUITE_P(smoke_Multi_BehaviorTests, InferRequestIOBBlobSetPrecisionTest, + ::testing::Combine( + ::testing::ValuesIn(prcs), + ::testing::Values(CommonTestUtils::DEVICE_MULTI), + ::testing::ValuesIn(configs)), + InferRequestIOBBlobSetPrecisionTest::getTestCaseName); + +INSTANTIATE_TEST_SUITE_P(smoke_Auto_BehaviorTests, InferRequestIOBBlobSetPrecisionTest, + ::testing::Combine( + ::testing::ValuesIn(prcs), + ::testing::Values(CommonTestUtils::DEVICE_AUTO), + ::testing::ValuesIn(autoconfigs)), + InferRequestIOBBlobSetPrecisionTest::getTestCaseName); + +std::vector layouts = { + InferenceEngine::Layout::ANY, + InferenceEngine::Layout::NCHW, + InferenceEngine::Layout::NHWC, + InferenceEngine::Layout::NCDHW, + InferenceEngine::Layout::NDHWC, + InferenceEngine::Layout::OIHW, + InferenceEngine::Layout::GOIHW, + InferenceEngine::Layout::OIDHW, + InferenceEngine::Layout::GOIDHW, + InferenceEngine::Layout::SCALAR, + InferenceEngine::Layout::C, + InferenceEngine::Layout::CHW, + InferenceEngine::Layout::HWC, + InferenceEngine::Layout::HW, + InferenceEngine::Layout::NC, + InferenceEngine::Layout::CN, + InferenceEngine::Layout::BLOCKED, +}; + +INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, InferRequestIOBBlobSetLayoutTest, + ::testing::Combine( + ::testing::ValuesIn(layouts), + ::testing::Values(CommonTestUtils::DEVICE_GPU), + ::testing::Values(std::map{})), + InferRequestIOBBlobSetLayoutTest::getTestCaseName); + +INSTANTIATE_TEST_SUITE_P(smoke_Multi_BehaviorTests, InferRequestIOBBlobSetLayoutTest, + ::testing::Combine( + ::testing::ValuesIn(layouts), + ::testing::Values(CommonTestUtils::DEVICE_MULTI), + ::testing::ValuesIn(configs)), + InferRequestIOBBlobSetLayoutTest::getTestCaseName); + +INSTANTIATE_TEST_SUITE_P(smoke_Auto_BehaviorTests, InferRequestIOBBlobSetLayoutTest, + ::testing::Combine( + ::testing::ValuesIn(layouts), + ::testing::Values(CommonTestUtils::DEVICE_AUTO), + ::testing::ValuesIn(autoconfigs)), + InferRequestIOBBlobSetLayoutTest::getTestCaseName); + +} // namespace \ No newline at end of file diff --git a/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/behavior/infer_request/multithreading.cpp b/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/behavior/infer_request/multithreading.cpp new file mode 100644 index 00000000000..afd7478a4cc --- /dev/null +++ b/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/behavior/infer_request/multithreading.cpp @@ -0,0 +1,39 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include + +#include "behavior/infer_request/multithreading.hpp" +#include "ie_plugin_config.hpp" + +using namespace BehaviorTestsDefinitions; +namespace { +const std::vector> configs = { + {{InferenceEngine::MultiDeviceConfigParams::KEY_MULTI_DEVICE_PRIORITIES, CommonTestUtils::DEVICE_GPU}} +}; + +const std::vector> autoconfigs = { + {{InferenceEngine::KEY_AUTO_DEVICE_LIST, CommonTestUtils::DEVICE_GPU}}, + {{InferenceEngine::KEY_AUTO_DEVICE_LIST , std::string(CommonTestUtils::DEVICE_CPU) + "," + CommonTestUtils::DEVICE_GPU}} +}; + +INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, InferRequestMultithreadingTests, + ::testing::Combine( + ::testing::Values(CommonTestUtils::DEVICE_GPU), + ::testing::Values(std::map({}))), + InferRequestMultithreadingTests::getTestCaseName); + +INSTANTIATE_TEST_SUITE_P(smoke_Multi_BehaviorTests, InferRequestMultithreadingTests, + ::testing::Combine( + ::testing::Values(CommonTestUtils::DEVICE_MULTI), + ::testing::ValuesIn(configs)), + InferRequestMultithreadingTests::getTestCaseName); + +INSTANTIATE_TEST_SUITE_P(smoke_Auto_BehaviorTests, InferRequestMultithreadingTests, + ::testing::Combine( + ::testing::Values(CommonTestUtils::DEVICE_AUTO), + ::testing::ValuesIn(autoconfigs)), + InferRequestMultithreadingTests::getTestCaseName); + +} // namespace \ No newline at end of file diff --git a/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/behavior/perf_counters.cpp b/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/behavior/infer_request/perf_counters.cpp similarity index 62% rename from inference-engine/tests/functional/plugin/gpu/shared_tests_instances/behavior/perf_counters.cpp rename to inference-engine/tests/functional/plugin/gpu/shared_tests_instances/behavior/infer_request/perf_counters.cpp index cc6a2a14a24..5a4a5852c5a 100644 --- a/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/behavior/perf_counters.cpp +++ b/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/behavior/infer_request/perf_counters.cpp @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 // -#include "behavior/perf_counters.hpp" +#include "behavior/infer_request/perf_counters.hpp" using namespace BehaviorTestsDefinitions; namespace { @@ -14,18 +14,16 @@ namespace { {{ MULTI_CONFIG_KEY(DEVICE_PRIORITIES) , CommonTestUtils::DEVICE_GPU}} }; - INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, PerfCountersTest, + INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, InferRequestPerfCountersTest, ::testing::Combine( - ::testing::Values(InferenceEngine::Precision::FP32), ::testing::Values(CommonTestUtils::DEVICE_GPU), ::testing::ValuesIn(configs)), - PerfCountersTest::getTestCaseName); + InferRequestPerfCountersTest::getTestCaseName); - INSTANTIATE_TEST_SUITE_P(smoke_Multi_BehaviorTests, PerfCountersTest, + INSTANTIATE_TEST_SUITE_P(smoke_Multi_BehaviorTests, InferRequestPerfCountersTest, ::testing::Combine( - ::testing::Values(InferenceEngine::Precision::FP32), ::testing::Values(CommonTestUtils::DEVICE_MULTI), ::testing::ValuesIn(Multiconfigs)), - PerfCountersTest::getTestCaseName); + InferRequestPerfCountersTest::getTestCaseName); } // namespace diff --git a/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/behavior/infer_request/set_blob_by_type.cpp b/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/behavior/infer_request/set_blob_by_type.cpp new file mode 100644 index 00000000000..9a7f8a094cb --- /dev/null +++ b/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/behavior/infer_request/set_blob_by_type.cpp @@ -0,0 +1,48 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "behavior/infer_request/set_blob_by_type.hpp" +#include "common_test_utils/test_constants.hpp" + +using namespace BehaviorTestsDefinitions; +using namespace InferenceEngine; + +const std::vector BlobTypes = { + FuncTestUtils::BlobType::Compound, + FuncTestUtils::BlobType::Batched, + FuncTestUtils::BlobType::Memory, +// FuncTestUtils::BlobType::Remote, + FuncTestUtils::BlobType::I420, + FuncTestUtils::BlobType::NV12 +}; + +const std::map cpuConfig{}; //nothing special +const std::map autoConfig{}; +const std::map multiConfig{{ MULTI_CONFIG_KEY(DEVICE_PRIORITIES) , CommonTestUtils::DEVICE_GPU}}; +const std::map heteroConfig{{ "TARGET_FALLBACK", CommonTestUtils::DEVICE_GPU }}; + +INSTANTIATE_TEST_SUITE_P(smoke_Behavior, InferRequestSetBlobByType, + ::testing::Combine(::testing::ValuesIn(BlobTypes), + ::testing::Values(CommonTestUtils::DEVICE_GPU), + ::testing::Values(cpuConfig)), + InferRequestSetBlobByType::getTestCaseName); + + +INSTANTIATE_TEST_SUITE_P(smoke_Behavior_Multi, InferRequestSetBlobByType, + ::testing::Combine(::testing::ValuesIn(BlobTypes), + ::testing::Values(CommonTestUtils::DEVICE_MULTI), + ::testing::Values(multiConfig)), + InferRequestSetBlobByType::getTestCaseName); + +INSTANTIATE_TEST_SUITE_P(smoke_Behavior_Auto, InferRequestSetBlobByType, + ::testing::Combine(::testing::ValuesIn(BlobTypes), + ::testing::Values(CommonTestUtils::DEVICE_AUTO + std::string(":") + CommonTestUtils::DEVICE_CPU), + ::testing::Values(autoConfig)), + InferRequestSetBlobByType::getTestCaseName); + +INSTANTIATE_TEST_SUITE_P(smoke_Behavior_Hetero, InferRequestSetBlobByType, + ::testing::Combine(::testing::ValuesIn(BlobTypes), + ::testing::Values(CommonTestUtils::DEVICE_HETERO), + ::testing::Values(heteroConfig)), + InferRequestSetBlobByType::getTestCaseName); diff --git a/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/behavior/infer_request.cpp b/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/behavior/infer_request/wait.cpp similarity index 61% rename from inference-engine/tests/functional/plugin/gpu/shared_tests_instances/behavior/infer_request.cpp rename to inference-engine/tests/functional/plugin/gpu/shared_tests_instances/behavior/infer_request/wait.cpp index ad94fdaa7e2..07fe3ddd855 100644 --- a/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/behavior/infer_request.cpp +++ b/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/behavior/infer_request/wait.cpp @@ -4,39 +4,31 @@ #include -#include "behavior/infer_request.hpp" +#include "behavior/infer_request/wait.hpp" #include "ie_plugin_config.hpp" using namespace BehaviorTestsDefinitions; namespace { - const std::vector netPrecisions = { - InferenceEngine::Precision::FP32, - InferenceEngine::Precision::FP16 - }; - const std::vector> configs = { {{InferenceEngine::MultiDeviceConfigParams::KEY_MULTI_DEVICE_PRIORITIES, CommonTestUtils::DEVICE_GPU}} }; - INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, InferRequestTests, + INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, InferRequestWaitTests, ::testing::Combine( - ::testing::ValuesIn(netPrecisions), ::testing::Values(CommonTestUtils::DEVICE_GPU), ::testing::Values(std::map({}))), - InferRequestTests::getTestCaseName); + InferRequestWaitTests::getTestCaseName); - INSTANTIATE_TEST_SUITE_P(smoke_Multi_BehaviorTests, InferRequestTests, + INSTANTIATE_TEST_SUITE_P(smoke_Multi_BehaviorTests, InferRequestWaitTests, ::testing::Combine( - ::testing::ValuesIn(netPrecisions), ::testing::Values(CommonTestUtils::DEVICE_MULTI), ::testing::ValuesIn(configs)), - InferRequestTests::getTestCaseName); + InferRequestWaitTests::getTestCaseName); - INSTANTIATE_TEST_SUITE_P(smoke_Auto_BehaviorTests, InferRequestTests, + INSTANTIATE_TEST_SUITE_P(smoke_Auto_BehaviorTests, InferRequestWaitTests, ::testing::Combine( - ::testing::ValuesIn(netPrecisions), ::testing::Values(CommonTestUtils::DEVICE_AUTO), ::testing::ValuesIn(configs)), - InferRequestTests::getTestCaseName); + InferRequestWaitTests::getTestCaseName); } // namespace \ No newline at end of file diff --git a/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/behavior/infer_request_config.cpp b/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/behavior/infer_request_config.cpp deleted file mode 100644 index 2ea7951f789..00000000000 --- a/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/behavior/infer_request_config.cpp +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (C) 2018-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#include "behavior/infer_request_config.hpp" - -using namespace BehaviorTestsDefinitions; -namespace { - const std::vector netPrecisions = { - InferenceEngine::Precision::FP32, - InferenceEngine::Precision::FP16 - }; - - const std::vector> configs = { - {} - }; - - const std::vector> multiConfigs = { - {{InferenceEngine::MultiDeviceConfigParams::KEY_MULTI_DEVICE_PRIORITIES, CommonTestUtils::DEVICE_GPU}} - }; - - INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, InferConfigTests, - ::testing::Combine( - ::testing::ValuesIn(netPrecisions), - ::testing::Values(CommonTestUtils::DEVICE_GPU), - ::testing::ValuesIn(configs)), - InferConfigTests::getTestCaseName); - - INSTANTIATE_TEST_SUITE_P(smoke_Multi_BehaviorTests, InferConfigTests, - ::testing::Combine( - ::testing::ValuesIn(netPrecisions), - ::testing::Values(CommonTestUtils::DEVICE_MULTI), - ::testing::ValuesIn(multiConfigs)), - InferConfigTests::getTestCaseName); - -} // namespace diff --git a/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/behavior/infer_request_input.cpp b/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/behavior/infer_request_input.cpp deleted file mode 100644 index bce8d53a25d..00000000000 --- a/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/behavior/infer_request_input.cpp +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright (C) 2018-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#include "behavior/infer_request_input.hpp" -#include "gpu/gpu_config.hpp" - -using namespace BehaviorTestsDefinitions; -namespace { - const std::vector netPrecisions = { - InferenceEngine::Precision::FP16, - InferenceEngine::Precision::U8, - InferenceEngine::Precision::I16, - InferenceEngine::Precision::I32 - }; - - const std::vector> configs = { - {}, - {{InferenceEngine::PluginConfigParams::KEY_GPU_THROUGHPUT_STREAMS, InferenceEngine::PluginConfigParams::GPU_THROUGHPUT_AUTO}} - }; - - const std::vector> multiConfigs = { - {{InferenceEngine::MultiDeviceConfigParams::KEY_MULTI_DEVICE_PRIORITIES , CommonTestUtils::DEVICE_GPU}, - {InferenceEngine::PluginConfigParams::KEY_GPU_THROUGHPUT_STREAMS, - InferenceEngine::PluginConfigParams::GPU_THROUGHPUT_AUTO}} - }; - - INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, InferRequestInputTests, - ::testing::Combine( - ::testing::ValuesIn(netPrecisions), - ::testing::Values(CommonTestUtils::DEVICE_GPU), - ::testing::ValuesIn(configs)), - InferRequestInputTests::getTestCaseName); - - INSTANTIATE_TEST_SUITE_P(smoke_Multi_BehaviorTests, InferRequestInputTests, - ::testing::Combine( - ::testing::ValuesIn(netPrecisions), - ::testing::Values(CommonTestUtils::DEVICE_MULTI), - ::testing::ValuesIn(multiConfigs)), - InferRequestInputTests::getTestCaseName); - - INSTANTIATE_TEST_SUITE_P(smoke_Auto_BehaviorTests, InferRequestInputTests, - ::testing::Combine( - ::testing::ValuesIn(netPrecisions), - ::testing::Values(CommonTestUtils::DEVICE_AUTO), - ::testing::ValuesIn(multiConfigs)), - InferRequestInputTests::getTestCaseName); - -} // namespace diff --git a/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/behavior/infer_request_output.cpp b/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/behavior/infer_request_output.cpp deleted file mode 100644 index b4e40a831b7..00000000000 --- a/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/behavior/infer_request_output.cpp +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright (C) 2018-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#include "behavior/infer_request_output.hpp" -#include "gpu/gpu_config.hpp" - -using namespace BehaviorTestsDefinitions; -namespace { - const std::vector netPrecisions = { - InferenceEngine::Precision::FP32 - }; - - const std::vector> configs = { - {}, - {{InferenceEngine::PluginConfigParams::KEY_GPU_THROUGHPUT_STREAMS, InferenceEngine::PluginConfigParams::GPU_THROUGHPUT_AUTO}} - }; - - const std::vector> multiConfigs = { - {{InferenceEngine::MultiDeviceConfigParams::KEY_MULTI_DEVICE_PRIORITIES , CommonTestUtils::DEVICE_GPU}, - {InferenceEngine::PluginConfigParams::KEY_GPU_THROUGHPUT_STREAMS, InferenceEngine::PluginConfigParams::GPU_THROUGHPUT_AUTO}} - }; - - INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, InferRequestOutputTests, - ::testing::Combine( - ::testing::ValuesIn(netPrecisions), - ::testing::Values(CommonTestUtils::DEVICE_GPU), - ::testing::ValuesIn(configs)), - InferRequestOutputTests::getTestCaseName); - - INSTANTIATE_TEST_SUITE_P(smoke_Multi_BehaviorTests, InferRequestOutputTests, - ::testing::Combine( - ::testing::ValuesIn(netPrecisions), - ::testing::Values(CommonTestUtils::DEVICE_MULTI), - ::testing::ValuesIn(multiConfigs)), - InferRequestOutputTests::getTestCaseName); - - INSTANTIATE_TEST_SUITE_P(smoke_Auto_BehaviorTests, InferRequestOutputTests, - ::testing::Combine( - ::testing::ValuesIn(netPrecisions), - ::testing::Values(CommonTestUtils::DEVICE_AUTO), - ::testing::ValuesIn(multiConfigs)), - InferRequestOutputTests::getTestCaseName); -} // namespace diff --git a/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/behavior/layout.cpp b/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/behavior/layout.cpp deleted file mode 100644 index c705c3a9d76..00000000000 --- a/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/behavior/layout.cpp +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (C) 2018-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#include "behavior/layout.hpp" - -using namespace BehaviorTestsDefinitions; -namespace { - const std::vector> configs = { - {} - }; - - const std::vector Layout = { - InferenceEngine::Layout::NCHW, - InferenceEngine::Layout::NC, - }; - - const std::vector> inputShapes = { - { 1, 3, 16, 16 }, - { 1, 3 }, - }; - - INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, LayoutTest, - ::testing::Combine( - ::testing::Values(InferenceEngine::Precision::FP32), - ::testing::Values(CommonTestUtils::DEVICE_GPU), - ::testing::ValuesIn(configs), - ::testing::ValuesIn(Layout), - ::testing::ValuesIn(inputShapes)), - LayoutTest::getTestCaseName); - -} // namespace \ No newline at end of file diff --git a/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/behavior/set_preprocess.cpp b/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/behavior/preprocessing/set_preprocess.cpp similarity index 79% rename from inference-engine/tests/functional/plugin/gpu/shared_tests_instances/behavior/set_preprocess.cpp rename to inference-engine/tests/functional/plugin/gpu/shared_tests_instances/behavior/preprocessing/set_preprocess.cpp index 97cdf1789e6..c6a17bb4bf7 100644 --- a/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/behavior/set_preprocess.cpp +++ b/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/behavior/preprocessing/set_preprocess.cpp @@ -3,7 +3,7 @@ // #include -#include "behavior/set_preprocess.hpp" +#include "behavior/preprocessing/set_preprocess.hpp" using namespace BehaviorTestsDefinitions; namespace { @@ -22,26 +22,26 @@ namespace { {{ InferenceEngine::MultiDeviceConfigParams::KEY_MULTI_DEVICE_PRIORITIES , CommonTestUtils::DEVICE_GPU}} }; - INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, PreprocessTest, + INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, InferRequestPreprocessTest, ::testing::Combine( ::testing::ValuesIn(netPrecisions), ::testing::Values(CommonTestUtils::DEVICE_GPU), ::testing::ValuesIn(configs)), - PreprocessTest::getTestCaseName); + InferRequestPreprocessTest::getTestCaseName); - INSTANTIATE_TEST_SUITE_P(smoke_Multi_BehaviorTests, PreprocessTest, + INSTANTIATE_TEST_SUITE_P(smoke_Multi_BehaviorTests, InferRequestPreprocessTest, ::testing::Combine( ::testing::ValuesIn(netPrecisions), ::testing::Values(CommonTestUtils::DEVICE_MULTI), ::testing::ValuesIn(multiConfigs)), - PreprocessTest::getTestCaseName); + InferRequestPreprocessTest::getTestCaseName); - INSTANTIATE_TEST_SUITE_P(smoke_Auto_BehaviorTests, PreprocessTest, + INSTANTIATE_TEST_SUITE_P(smoke_Auto_BehaviorTests, InferRequestPreprocessTest, ::testing::Combine( ::testing::ValuesIn(netPrecisions), ::testing::Values(CommonTestUtils::DEVICE_AUTO), ::testing::ValuesIn(multiConfigs)), - PreprocessTest::getTestCaseName); + InferRequestPreprocessTest::getTestCaseName); const std::vector ioPrecisions = { InferenceEngine::Precision::FP32, @@ -57,7 +57,7 @@ namespace { InferenceEngine::Layout::NHWC }; - INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, PreprocessConversionTest, + INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, InferRequestPreprocessConversionTest, ::testing::Combine( ::testing::ValuesIn(netPrecisions), ::testing::ValuesIn(ioPrecisions), @@ -69,9 +69,9 @@ namespace { ::testing::Bool(), ::testing::Values(CommonTestUtils::DEVICE_GPU), ::testing::ValuesIn(configs)), - PreprocessConversionTest::getTestCaseName); + InferRequestPreprocessConversionTest::getTestCaseName); - INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, PreprocessDynamicallyInSetBlobTest, + INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, InferRequestPreprocessDynamicallyInSetBlobTest, ::testing::Combine( ::testing::ValuesIn(netPrecisions), ::testing::Bool(), @@ -83,6 +83,6 @@ namespace { ::testing::Values(true), // only SetBlob ::testing::Values(CommonTestUtils::DEVICE_GPU), ::testing::ValuesIn(configs)), - PreprocessDynamicallyInSetBlobTest::getTestCaseName); + InferRequestPreprocessDynamicallyInSetBlobTest::getTestCaseName); } // namespace \ No newline at end of file diff --git a/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/behavior/set_blob_of_kind.cpp b/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/behavior/set_blob_of_kind.cpp deleted file mode 100644 index f055c0b0ec9..00000000000 --- a/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/behavior/set_blob_of_kind.cpp +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (C) 2018-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#include "behavior/set_blob_of_kind.hpp" -#include "common_test_utils/test_constants.hpp" - -using namespace BehaviorTestsDefinitions; -using namespace InferenceEngine; - -const std::vector blobKinds = { - FuncTestUtils::BlobKind::Simple, - FuncTestUtils::BlobKind::Compound - /* BatchOfSimple is not supported on GPU currently. Batch of remote is supported */ - /* , FuncTestUtils::BlobKind::BatchOfSimple */ -}; - -const SetBlobOfKindConfig gpuConfig{}; //nothing special - -INSTANTIATE_TEST_SUITE_P(smoke_SetBlobOfKindGPU, SetBlobOfKindTest, - ::testing::Combine(::testing::ValuesIn(blobKinds), - ::testing::Values(CommonTestUtils::DEVICE_GPU), - ::testing::Values(gpuConfig)), - SetBlobOfKindTest::getTestCaseName); diff --git a/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/skip_tests_config.cpp b/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/skip_tests_config.cpp index cbd31ad0075..bb8102fac79 100644 --- a/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/skip_tests_config.cpp +++ b/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/skip_tests_config.cpp @@ -22,9 +22,9 @@ std::vector disabledTestPatterns() { R"(.*(PreprocessTest).*(SetMeanValuePreProcessSetBlob).*)", R"(.*(PreprocessTest).*(SetMeanImagePreProcessSetBlob).*)", R"(.*(PreprocessTest).*(ReverseInputChannelsPreProcessGetBlob).*)", - R"(.*(PreprocessDynamicallyInSetBlobTest).*)", + R"(.*(InferRequestPreprocessDynamicallyInSetBlobTest).*)", // TODO: Issue: 51764 - ".*PreprocessConversionTest.*", + ".*InferRequestPreprocessConversionTest.*", // TODO: Issue: 41462 R"(.*(SoftMaxLayerTest).*axis=0.*)", // TODO: Issue: 43511 @@ -56,13 +56,20 @@ std::vector disabledTestPatterns() { R"(.*ActivationLayerTest.*SoftPlus.*)", // need to implement Export / Import R"(.*IEClassImportExportTestP.*)", - + R"(.*Behavior.*InferRequestSetBlobByType.*Device=HETERO.*)", // TODO: Issue: 59586, NormalizeL2 output mismatch for empty axes case R"(.*NormalizeL2LayerTest.*axes=\(\).*)", // Not allowed dynamic loop tests on GPU R"(.*smoke_StaticShapeLoop_dynamic_exit.*)", - + // CVS-58963: Not implemented yet + R"(.*Behavior.*InferRequest.*OutOfFirstOutIsInputForSecondNetwork.*)", + // Not expected behavior + R"(.*Behavior.*InferRequestIOBBlobSetLayoutTest.*layout=(95|OIHW).*)", + R"(.*Behavior.*InferRequestIOBBlobSetLayoutTest.*CanSetInBlobWithDifferentLayouts.*layout=NHWC.*)", + R"(.*Behavior.*InferRequestIOBBlobSetLayoutTest.*CanSetOutBlobWithDifferentLayouts.*layout=(CN|HW).*)", + R"(.*Behavior_Multi.*InferRequestSetBlobByType.*Batched.*)", + R"(.*(Multi|Auto).*Behavior.*InferRequestIOBBlobTest.*canProcessDeallocatedOutputBlobAfterGetAndSetBlob.*)", // TODO: until issue is xxx-59670 is resolved R"(.*Gather8LayerTest.*)" }; diff --git a/inference-engine/tests/functional/plugin/myriad/shared_tests_instances/behavior/caching_tests.cpp b/inference-engine/tests/functional/plugin/myriad/shared_tests_instances/behavior/caching/caching_tests.cpp similarity index 97% rename from inference-engine/tests/functional/plugin/myriad/shared_tests_instances/behavior/caching_tests.cpp rename to inference-engine/tests/functional/plugin/myriad/shared_tests_instances/behavior/caching/caching_tests.cpp index 6c17496e7c2..8437be2abb1 100644 --- a/inference-engine/tests/functional/plugin/myriad/shared_tests_instances/behavior/caching_tests.cpp +++ b/inference-engine/tests/functional/plugin/myriad/shared_tests_instances/behavior/caching/caching_tests.cpp @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 // -#include "behavior/caching_tests.hpp" +#include "behavior/caching/caching_tests.hpp" using namespace LayerTestsDefinitions; diff --git a/inference-engine/tests/functional/plugin/myriad/shared_tests_instances/behavior/infer_request_callback.cpp b/inference-engine/tests/functional/plugin/myriad/shared_tests_instances/behavior/infer_request/callback.cpp similarity index 59% rename from inference-engine/tests/functional/plugin/myriad/shared_tests_instances/behavior/infer_request_callback.cpp rename to inference-engine/tests/functional/plugin/myriad/shared_tests_instances/behavior/infer_request/callback.cpp index 4bb24fca393..8699dc4148d 100644 --- a/inference-engine/tests/functional/plugin/myriad/shared_tests_instances/behavior/infer_request_callback.cpp +++ b/inference-engine/tests/functional/plugin/myriad/shared_tests_instances/behavior/infer_request/callback.cpp @@ -2,14 +2,10 @@ // SPDX-License-Identifier: Apache-2.0 // -#include "behavior/infer_request_callback.hpp" +#include "behavior/infer_request/callback.hpp" using namespace BehaviorTestsDefinitions; namespace { -const std::vector netPrecisions = { - InferenceEngine::Precision::FP16 -}; - const std::vector> configs = { {}, }; @@ -18,17 +14,15 @@ const std::vector> multiConfigs = { {{ MULTI_CONFIG_KEY(DEVICE_PRIORITIES) , CommonTestUtils::DEVICE_MYRIAD}} }; -INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, CallbackTests, +INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, InferRequestCallbackTests, ::testing::Combine( - ::testing::ValuesIn(netPrecisions), ::testing::Values(CommonTestUtils::DEVICE_MYRIAD), ::testing::ValuesIn(configs)), - CallbackTests::getTestCaseName); + InferRequestCallbackTests::getTestCaseName); -INSTANTIATE_TEST_SUITE_P(smoke_Multi_BehaviorTests, CallbackTests, +INSTANTIATE_TEST_SUITE_P(smoke_Multi_BehaviorTests, InferRequestCallbackTests, ::testing::Combine( - ::testing::ValuesIn(netPrecisions), ::testing::Values(CommonTestUtils::DEVICE_MULTI), ::testing::ValuesIn(multiConfigs)), - CallbackTests::getTestCaseName); + InferRequestCallbackTests::getTestCaseName); } // namespace diff --git a/inference-engine/tests/functional/plugin/myriad/shared_tests_instances/behavior/infer_request_config.cpp b/inference-engine/tests/functional/plugin/myriad/shared_tests_instances/behavior/infer_request/config.cpp similarity index 71% rename from inference-engine/tests/functional/plugin/myriad/shared_tests_instances/behavior/infer_request_config.cpp rename to inference-engine/tests/functional/plugin/myriad/shared_tests_instances/behavior/infer_request/config.cpp index 225936f387d..897683a4750 100644 --- a/inference-engine/tests/functional/plugin/myriad/shared_tests_instances/behavior/infer_request_config.cpp +++ b/inference-engine/tests/functional/plugin/myriad/shared_tests_instances/behavior/infer_request/config.cpp @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 // -#include "behavior/infer_request_config.hpp" +#include "behavior/infer_request/config.hpp" #include "vpu/vpu_plugin_config.hpp" #include "vpu/private_plugin_config.hpp" @@ -12,10 +12,6 @@ IE_SUPPRESS_DEPRECATED_START using namespace BehaviorTestsDefinitions; namespace { - const std::vector netPrecisions = { - InferenceEngine::Precision::FP16 - }; - const std::vector> configs = { {} }; @@ -75,31 +71,17 @@ namespace { {VPU_CONFIG_KEY(HW_STAGES_OPTIMIZATION), CONFIG_VALUE(YES)}}, }; - INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, InferConfigTests, + INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, InferRequestConfigTest, ::testing::Combine( - ::testing::ValuesIn(netPrecisions), + ::testing::Values(2u), ::testing::Values(CommonTestUtils::DEVICE_MYRIAD), ::testing::ValuesIn(configs)), - InferConfigTests::getTestCaseName); + InferRequestConfigTest::getTestCaseName); - INSTANTIATE_TEST_SUITE_P(smoke_Multi_BehaviorTests, InferConfigTests, + INSTANTIATE_TEST_SUITE_P(smoke_Multi_BehaviorTests, InferRequestConfigTest, ::testing::Combine( - ::testing::ValuesIn(netPrecisions), + ::testing::Values(2u), ::testing::Values(CommonTestUtils::DEVICE_MULTI), ::testing::ValuesIn(multiConfigs)), - InferConfigTests::getTestCaseName); - - INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, InferConfigInTests, - ::testing::Combine( - ::testing::ValuesIn(netPrecisions), - ::testing::Values(CommonTestUtils::DEVICE_MYRIAD), - ::testing::ValuesIn(inferConfigs)), - InferConfigInTests::getTestCaseName); - - INSTANTIATE_TEST_SUITE_P(smoke_Multi_BehaviorTests, InferConfigInTests, - ::testing::Combine( - ::testing::ValuesIn(netPrecisions), - ::testing::Values(CommonTestUtils::DEVICE_MULTI), - ::testing::ValuesIn(inferMultiConfigs)), - InferConfigInTests::getTestCaseName); + InferRequestConfigTest::getTestCaseName); } // namespace diff --git a/inference-engine/tests/functional/plugin/myriad/shared_tests_instances/behavior/infer_request.cpp b/inference-engine/tests/functional/plugin/myriad/shared_tests_instances/behavior/infer_request/io_blob.cpp similarity index 61% rename from inference-engine/tests/functional/plugin/myriad/shared_tests_instances/behavior/infer_request.cpp rename to inference-engine/tests/functional/plugin/myriad/shared_tests_instances/behavior/infer_request/io_blob.cpp index f466f2d7172..20e146cab12 100644 --- a/inference-engine/tests/functional/plugin/myriad/shared_tests_instances/behavior/infer_request.cpp +++ b/inference-engine/tests/functional/plugin/myriad/shared_tests_instances/behavior/infer_request/io_blob.cpp @@ -4,37 +4,30 @@ #include -#include "behavior/infer_request.hpp" +#include "behavior/infer_request/io_blob.hpp" #include "ie_plugin_config.hpp" using namespace BehaviorTestsDefinitions; namespace { -const std::vector netPrecisions = { - InferenceEngine::Precision::FP16 -}; - const std::vector> configs = { {{InferenceEngine::MultiDeviceConfigParams::KEY_MULTI_DEVICE_PRIORITIES, CommonTestUtils::DEVICE_MYRIAD}} }; -INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, InferRequestTests, +INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, InferRequestIOBBlobTest, ::testing::Combine( - ::testing::ValuesIn(netPrecisions), ::testing::Values(CommonTestUtils::DEVICE_MYRIAD), ::testing::Values(std::map({}))), - InferRequestTests::getTestCaseName); + InferRequestIOBBlobTest::getTestCaseName); -INSTANTIATE_TEST_SUITE_P(smoke_Multi_BehaviorTests, InferRequestTests, +INSTANTIATE_TEST_SUITE_P(smoke_Multi_BehaviorTests, InferRequestIOBBlobTest, ::testing::Combine( - ::testing::ValuesIn(netPrecisions), ::testing::Values(CommonTestUtils::DEVICE_MULTI), ::testing::ValuesIn(configs)), - InferRequestTests::getTestCaseName); + InferRequestIOBBlobTest::getTestCaseName); -INSTANTIATE_TEST_SUITE_P(smoke_Auto_BehaviorTests, InferRequestTests, +INSTANTIATE_TEST_SUITE_P(smoke_Auto_BehaviorTests, InferRequestIOBBlobTest, ::testing::Combine( - ::testing::ValuesIn(netPrecisions), ::testing::Values(CommonTestUtils::DEVICE_AUTO), ::testing::ValuesIn(configs)), - InferRequestTests::getTestCaseName); + InferRequestIOBBlobTest::getTestCaseName); } // namespace diff --git a/inference-engine/tests/functional/plugin/myriad/shared_tests_instances/behavior/infer_request/multithreading.cpp b/inference-engine/tests/functional/plugin/myriad/shared_tests_instances/behavior/infer_request/multithreading.cpp new file mode 100644 index 00000000000..5323442d20f --- /dev/null +++ b/inference-engine/tests/functional/plugin/myriad/shared_tests_instances/behavior/infer_request/multithreading.cpp @@ -0,0 +1,27 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include + +#include "behavior/infer_request/multithreading.hpp" +#include "ie_plugin_config.hpp" + +using namespace BehaviorTestsDefinitions; +namespace { +const std::vector> configs = { + {{InferenceEngine::MultiDeviceConfigParams::KEY_MULTI_DEVICE_PRIORITIES, CommonTestUtils::DEVICE_MYRIAD}} +}; + +INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, InferRequestMultithreadingTests, + ::testing::Combine( + ::testing::Values(CommonTestUtils::DEVICE_MYRIAD), + ::testing::Values(std::map({}))), + InferRequestMultithreadingTests::getTestCaseName); + +INSTANTIATE_TEST_SUITE_P(smoke_Multi_BehaviorTests, InferRequestMultithreadingTests, + ::testing::Combine( + ::testing::Values(CommonTestUtils::DEVICE_MULTI), + ::testing::ValuesIn(configs)), + InferRequestMultithreadingTests::getTestCaseName); +} // namespace diff --git a/inference-engine/tests/functional/plugin/myriad/shared_tests_instances/behavior/infer_request/wait.cpp b/inference-engine/tests/functional/plugin/myriad/shared_tests_instances/behavior/infer_request/wait.cpp new file mode 100644 index 00000000000..ddbe5c589a4 --- /dev/null +++ b/inference-engine/tests/functional/plugin/myriad/shared_tests_instances/behavior/infer_request/wait.cpp @@ -0,0 +1,27 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include + +#include "behavior/infer_request/wait.hpp" +#include "ie_plugin_config.hpp" + +using namespace BehaviorTestsDefinitions; +namespace { +const std::vector> configs = { + {{InferenceEngine::MultiDeviceConfigParams::KEY_MULTI_DEVICE_PRIORITIES, CommonTestUtils::DEVICE_MYRIAD}} +}; + +INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, InferRequestWaitTests, + ::testing::Combine( + ::testing::Values(CommonTestUtils::DEVICE_MYRIAD), + ::testing::Values(std::map({}))), + InferRequestWaitTests::getTestCaseName); + +INSTANTIATE_TEST_SUITE_P(smoke_Multi_BehaviorTests, InferRequestWaitTests, + ::testing::Combine( + ::testing::Values(CommonTestUtils::DEVICE_MULTI), + ::testing::ValuesIn(configs)), + InferRequestWaitTests::getTestCaseName); +} // namespace diff --git a/inference-engine/tests/functional/plugin/myriad/shared_tests_instances/behavior/infer_request_input.cpp b/inference-engine/tests/functional/plugin/myriad/shared_tests_instances/behavior/infer_request_input.cpp deleted file mode 100644 index 8b97210ca01..00000000000 --- a/inference-engine/tests/functional/plugin/myriad/shared_tests_instances/behavior/infer_request_input.cpp +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (C) 2018-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#include "behavior/infer_request_input.hpp" - -using namespace BehaviorTestsDefinitions; -namespace { - const std::vector netPrecisions = { - InferenceEngine::Precision::FP16, - InferenceEngine::Precision::U8 - }; - - const std::vector> configs = { - {} - }; - - const std::vector> multiConfigs = { - {{InferenceEngine::MultiDeviceConfigParams::KEY_MULTI_DEVICE_PRIORITIES, CommonTestUtils::DEVICE_MYRIAD}} - }; - - INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, InferRequestInputTests, - ::testing::Combine( - ::testing::ValuesIn(netPrecisions), - ::testing::Values(CommonTestUtils::DEVICE_MYRIAD), - ::testing::ValuesIn(configs)), - InferRequestInputTests::getTestCaseName); - - INSTANTIATE_TEST_SUITE_P(smoke_Multi_BehaviorTests, InferRequestInputTests, - ::testing::Combine( - ::testing::ValuesIn(netPrecisions), - ::testing::Values(CommonTestUtils::DEVICE_MULTI), - ::testing::ValuesIn(multiConfigs)), - InferRequestInputTests::getTestCaseName); - -} // namespace diff --git a/inference-engine/tests/functional/plugin/myriad/shared_tests_instances/behavior/infer_request_output.cpp b/inference-engine/tests/functional/plugin/myriad/shared_tests_instances/behavior/infer_request_output.cpp deleted file mode 100644 index 4ef86349b9a..00000000000 --- a/inference-engine/tests/functional/plugin/myriad/shared_tests_instances/behavior/infer_request_output.cpp +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (C) 2018-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#include "behavior/infer_request_output.hpp" - -using namespace BehaviorTestsDefinitions; -namespace { - const std::vector netPrecisions = { - InferenceEngine::Precision::FP16, - InferenceEngine::Precision::U8 - }; - - const std::vector> configs = { - {} - }; - - const std::vector> multiConfigs = { - {{InferenceEngine::MultiDeviceConfigParams::KEY_MULTI_DEVICE_PRIORITIES, CommonTestUtils::DEVICE_MYRIAD}} - }; - - INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, InferRequestOutputTests, - ::testing::Combine( - ::testing::ValuesIn(netPrecisions), - ::testing::Values(CommonTestUtils::DEVICE_MYRIAD), - ::testing::ValuesIn(configs)), - InferRequestOutputTests::getTestCaseName); - - INSTANTIATE_TEST_SUITE_P(smoke_Multi_BehaviorTests, InferRequestOutputTests, - ::testing::Combine( - ::testing::ValuesIn(netPrecisions), - ::testing::Values(CommonTestUtils::DEVICE_MULTI), - ::testing::ValuesIn(multiConfigs)), - InferRequestOutputTests::getTestCaseName); - -} // namespace diff --git a/inference-engine/tests/functional/plugin/myriad/shared_tests_instances/behavior/layout.cpp b/inference-engine/tests/functional/plugin/myriad/shared_tests_instances/behavior/layout.cpp deleted file mode 100644 index 33f02720fef..00000000000 --- a/inference-engine/tests/functional/plugin/myriad/shared_tests_instances/behavior/layout.cpp +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (C) 2018-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#include "behavior/layout.hpp" - -using namespace BehaviorTestsDefinitions; -namespace { - const std::vector> configs = { - {} - }; - - const std::vector Layout = { - InferenceEngine::Layout::NCHW, - InferenceEngine::Layout::CHW, - InferenceEngine::Layout::NC, - InferenceEngine::Layout::C - }; - - const std::vector> inputShapes = { - { 1, 3, 16, 16 }, - { 3, 32, 16 }, - { 1, 3 }, - { 3 } - }; - - INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, LayoutTest, - ::testing::Combine( - ::testing::Values(InferenceEngine::Precision::FP16), - ::testing::Values(CommonTestUtils::DEVICE_MYRIAD), - ::testing::ValuesIn(configs), - ::testing::ValuesIn(Layout), - ::testing::ValuesIn(inputShapes)), - LayoutTest::getTestCaseName); - -} // namespace \ No newline at end of file diff --git a/inference-engine/tests/functional/plugin/myriad/shared_tests_instances/behavior/set_preprocess.cpp b/inference-engine/tests/functional/plugin/myriad/shared_tests_instances/behavior/preprocessing/set_preprocess.cpp similarity index 80% rename from inference-engine/tests/functional/plugin/myriad/shared_tests_instances/behavior/set_preprocess.cpp rename to inference-engine/tests/functional/plugin/myriad/shared_tests_instances/behavior/preprocessing/set_preprocess.cpp index 7ef46d71e7e..882fdbf9b4a 100644 --- a/inference-engine/tests/functional/plugin/myriad/shared_tests_instances/behavior/set_preprocess.cpp +++ b/inference-engine/tests/functional/plugin/myriad/shared_tests_instances/behavior/preprocessing/set_preprocess.cpp @@ -3,7 +3,7 @@ // #include -#include "behavior/set_preprocess.hpp" +#include "behavior/preprocessing/set_preprocess.hpp" using namespace BehaviorTestsDefinitions; namespace { @@ -20,19 +20,19 @@ namespace { {{ InferenceEngine::MultiDeviceConfigParams::KEY_MULTI_DEVICE_PRIORITIES , CommonTestUtils::DEVICE_MYRIAD}} }; - INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, PreprocessTest, + INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, InferRequestPreprocessTest, ::testing::Combine( ::testing::ValuesIn(netPrecisions), ::testing::Values(CommonTestUtils::DEVICE_MYRIAD), ::testing::ValuesIn(configs)), - PreprocessTest::getTestCaseName); + InferRequestPreprocessTest::getTestCaseName); - INSTANTIATE_TEST_SUITE_P(smoke_Multi_BehaviorTests, PreprocessTest, + INSTANTIATE_TEST_SUITE_P(smoke_Multi_BehaviorTests, InferRequestPreprocessTest, ::testing::Combine( ::testing::ValuesIn(netPrecisions), ::testing::Values(CommonTestUtils::DEVICE_MULTI), ::testing::ValuesIn(multiConfigs)), - PreprocessTest::getTestCaseName); + InferRequestPreprocessTest::getTestCaseName); const std::vector ioPrecisions = { InferenceEngine::Precision::FP32, @@ -48,7 +48,7 @@ namespace { InferenceEngine::Layout::NHWC }; - INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, PreprocessConversionTest, + INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, InferRequestPreprocessConversionTest, ::testing::Combine( ::testing::ValuesIn(netPrecisions), ::testing::ValuesIn(ioPrecisions), @@ -60,9 +60,9 @@ namespace { ::testing::Bool(), ::testing::Values(CommonTestUtils::DEVICE_MYRIAD), ::testing::ValuesIn(configs)), - PreprocessConversionTest::getTestCaseName); + InferRequestPreprocessConversionTest::getTestCaseName); - INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, PreprocessDynamicallyInSetBlobTest, + INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, InferRequestPreprocessDynamicallyInSetBlobTest, ::testing::Combine( ::testing::ValuesIn(netPrecisions), ::testing::Bool(), @@ -74,7 +74,7 @@ namespace { ::testing::Values(true), // only SetBlob ::testing::Values(CommonTestUtils::DEVICE_MYRIAD), ::testing::ValuesIn(configs)), - PreprocessDynamicallyInSetBlobTest::getTestCaseName); + InferRequestPreprocessDynamicallyInSetBlobTest::getTestCaseName); } // namespace \ No newline at end of file diff --git a/inference-engine/tests/functional/plugin/myriad/shared_tests_instances/skip_tests_config.cpp b/inference-engine/tests/functional/plugin/myriad/shared_tests_instances/skip_tests_config.cpp index d67ae3e6270..68d72bc5329 100644 --- a/inference-engine/tests/functional/plugin/myriad/shared_tests_instances/skip_tests_config.cpp +++ b/inference-engine/tests/functional/plugin/myriad/shared_tests_instances/skip_tests_config.cpp @@ -32,7 +32,7 @@ std::vector disabledTestPatterns() { // TODO: Issue 47315 ".*ProposalLayerTest.*", // TODO: Issue 51804 - ".*PreprocessConversionTest.*oPRC=U8.*", + ".*InferRequestPreprocessConversionTest.*oPRC=U8.*", // TODO: Issue: 56556 R"(.*(PreprocessTest).*(SetScalePreProcessSetBlob).*)", R"(.*(PreprocessTest).*(SetScalePreProcessGetBlob).*)", @@ -47,6 +47,8 @@ std::vector disabledTestPatterns() { R"(.*HoldersTestOnImportedNetwork\.CreateRequestWithCoreRemoved.*)", // TODO: Issue 58621 R"(.*IEClassNetworkTestP\.LoadNetworkActualNoThrow.*)", - R"(.*IEClassNetworkTestP\.LoadNetworkActualHeteroDeviceNoThrow.*)" + R"(.*IEClassNetworkTestP\.LoadNetworkActualHeteroDeviceNoThrow.*)", + // CVS-58963: Not implemented yet + R"(.*Behavior.*InferRequest.*OutOfFirstOutIsInputForSecondNetwork.*)", }; } diff --git a/inference-engine/tests/functional/plugin/shared/include/base/behavior_test_utils.hpp b/inference-engine/tests/functional/plugin/shared/include/base/behavior_test_utils.hpp index 5705bdc8ae3..b9bfcea4fe7 100644 --- a/inference-engine/tests/functional/plugin/shared/include/base/behavior_test_utils.hpp +++ b/inference-engine/tests/functional/plugin/shared/include/base/behavior_test_utils.hpp @@ -28,6 +28,8 @@ namespace BehaviorTestsUtils { +using namespace CommonTestUtils; + using BehaviorParamsEmptyConfig = std::tuple< InferenceEngine::Precision, // Network precision std::string // Device name @@ -65,12 +67,12 @@ typedef std::tuple< InferenceEngine::Precision, // Network precision std::string, // Device name std::map // Config -> BehaviorParams; +> BehaviorBasicParams; -class BehaviorTestsBasic : public testing::WithParamInterface, +class BehaviorTestsBasic : public testing::WithParamInterface, public CommonTestUtils::TestsCommon { public: - static std::string getTestCaseName(testing::TestParamInfo obj) { + static std::string getTestCaseName(testing::TestParamInfo obj) { InferenceEngine::Precision netPrecision; std::string targetDevice; std::map configuration; @@ -79,14 +81,13 @@ public: result << "netPRC=" << netPrecision.name() << "_"; result << "targetDevice=" << targetDevice; if (!configuration.empty()) { - for (auto& configItem : configuration) { - result << "configItem=" << configItem.first << "_" << configItem.second << "_"; - } + result << "config=" << configuration; } return result.str(); } void SetUp() override { + SKIP_IF_CURRENT_TEST_IS_DISABLED() std::tie(netPrecision, targetDevice, configuration) = this->GetParam(); function = ngraph::builder::subgraph::makeConvPoolRelu(); } @@ -105,6 +106,55 @@ public: std::map configuration; }; +typedef std::tuple< + std::string, // Device name + std::map // Config +> InferRequestParams; + +class InferRequestTests : public testing::WithParamInterface, + public CommonTestUtils::TestsCommon { +public: + static std::string getTestCaseName(testing::TestParamInfo obj) { + std::string targetDevice; + std::map configuration; + std::tie(targetDevice, configuration) = obj.param; + std::ostringstream result; + result << "targetDevice=" << targetDevice << "_"; + if (!configuration.empty()) { + for (auto &configItem : configuration) { + result << "configItem=" << configItem.first << "_" << configItem.second << "_"; + } + } + return result.str(); + } + + void SetUp() override { + // Skip test according to plugin specific disabledTestPatterns() (if any) + SKIP_IF_CURRENT_TEST_IS_DISABLED() + std::tie(targetDevice, configuration) = this->GetParam(); + function = ngraph::builder::subgraph::makeConvPoolRelu(); + cnnNet = InferenceEngine::CNNNetwork(function); + // Load CNNNetwork to target plugins + execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); + } + + void TearDown() override { + if (!configuration.empty()) { + PluginCache::get().reset(); + } + function.reset(); + } + +protected: + InferenceEngine::CNNNetwork cnnNet; + InferenceEngine::ExecutableNetwork execNet; + std::shared_ptr ie = PluginCache::get().ie(); + std::shared_ptr function; + InferenceEngine::Precision netPrecision; + std::string targetDevice; + std::map configuration; +}; + using BehaviorParamsSingleOption = std::tuple< InferenceEngine::Precision, // Network precision std::string, // Device name diff --git a/inference-engine/tests/functional/plugin/shared/include/behavior/caching_tests.hpp b/inference-engine/tests/functional/plugin/shared/include/behavior/caching/caching_tests.hpp similarity index 100% rename from inference-engine/tests/functional/plugin/shared/include/behavior/caching_tests.hpp rename to inference-engine/tests/functional/plugin/shared/include/behavior/caching/caching_tests.hpp diff --git a/inference-engine/tests/functional/plugin/shared/include/behavior/config.hpp b/inference-engine/tests/functional/plugin/shared/include/behavior/config.hpp index 3b305ebbf5f..dec8961c85f 100644 --- a/inference-engine/tests/functional/plugin/shared/include/behavior/config.hpp +++ b/inference-engine/tests/functional/plugin/shared/include/behavior/config.hpp @@ -31,7 +31,7 @@ namespace BehaviorTestsDefinitions { using EmptyConfigTests = BehaviorTestsUtils::BehaviorTestsEmptyConfig; - // Setting empty config doesn't throw +// Setting empty config doesn't throw TEST_P(EmptyConfigTests, SetEmptyConfig) { // Skip test according to plugin specific disabledTestPatterns() (if any) SKIP_IF_CURRENT_TEST_IS_DISABLED() diff --git a/inference-engine/tests/functional/plugin/shared/include/behavior/exec_graph_info.hpp b/inference-engine/tests/functional/plugin/shared/include/behavior/exec_graph_info.hpp index 9b93bbef0e2..e9b4d0fa520 100644 --- a/inference-engine/tests/functional/plugin/shared/include/behavior/exec_graph_info.hpp +++ b/inference-engine/tests/functional/plugin/shared/include/behavior/exec_graph_info.hpp @@ -35,22 +35,27 @@ inline std::vector separateStrToVec(std::string str, const char sep return result; } -namespace { - std::string timestamp() { - auto now = std::chrono::system_clock::now(); - auto epoch = now.time_since_epoch(); - auto ns = std::chrono::duration_cast(epoch); - return std::to_string(ns.count()); - } +// Load correct network to Plugin to get executable network +TEST_P(ExecGraphTests, canLoadCorrectNetworkToGetExecutable) { + // Skip test according to plugin specific disabledTestPatterns() (if any) + SKIP_IF_CURRENT_TEST_IS_DISABLED() + // Create CNNNetwork from ngrpah::Function + InferenceEngine::CNNNetwork cnnNet(function); + InferenceEngine::ExecutableNetwork execNet; + ASSERT_NO_THROW(execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration)); +} - std::string test_name() { - std::string test_name = - ::testing::UnitTest::GetInstance()->current_test_info()->name(); - std::replace_if(test_name.begin(), test_name.end(), - [](char c) { return (c == '/' || c == '='); }, '_'); - return test_name; +TEST_P(ExecGraphTests, CanCreateTwoExeNetworks) { + // Skip test according to plugin specific disabledTestPatterns() (if any) + SKIP_IF_CURRENT_TEST_IS_DISABLED() + // Create CNNNetwork from ngrpah::Function + InferenceEngine::CNNNetwork cnnNet(function); + InferenceEngine::ExecutableNetwork execNet; + for (auto i = 0; i < 2; i++) { + ASSERT_NO_THROW(execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration)); + ASSERT_NE(nullptr, cnnNet.getFunction()); } -} // namespace +} TEST_P(ExecGraphTests, CheckExecGraphInfoBeforeExecution) { // Skip test according to plugin specific disabledTestPatterns() (if any) @@ -202,8 +207,9 @@ TEST_P(ExecGraphTests, CheckExecGraphInfoSerialization) { // Skip test according to plugin specific disabledTestPatterns() (if any) SKIP_IF_CURRENT_TEST_IS_DISABLED() - std::string out_xml_path = test_name() + "_" + timestamp() + ".xml"; - std::string out_bin_path = test_name() + "_" + timestamp() + ".bin"; + auto ts = CommonTestUtils::GetTimestamp(); + std::string out_xml_path = GetTestName().substr(0, CommonTestUtils::maxFileNameLength) + "_" + ts + ".xml"; + std::string out_bin_path = GetTestName().substr(0, CommonTestUtils::maxFileNameLength) + "_" + ts + ".bin"; // Create CNNNetwork from ngrpah::Function InferenceEngine::CNNNetwork cnnNet(function); diff --git a/inference-engine/tests/functional/plugin/shared/include/behavior/infer_request.hpp b/inference-engine/tests/functional/plugin/shared/include/behavior/infer_request.hpp deleted file mode 100644 index c5b7a51fc69..00000000000 --- a/inference-engine/tests/functional/plugin/shared/include/behavior/infer_request.hpp +++ /dev/null @@ -1,657 +0,0 @@ -// Copyright (C) 2018-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#pragma once - -#include -#include -#include -#include -#include -#include -#include "ie_extension.h" -#include -#include "shared_test_classes/base/layer_test_utils.hpp" -#include "ngraph_functions/utils/ngraph_helpers.hpp" -#include "ngraph_functions/builders.hpp" -#include -#include -#include -#include -#include "common_test_utils/common_utils.hpp" -#include "functional_test_utils/plugin_cache.hpp" -#include "functional_test_utils/blob_utils.hpp" -#include "ngraph_functions/subgraph_builders.hpp" -#include "shared_test_classes/subgraph/basic_lstm.hpp" - -namespace BehaviorTestsDefinitions { -using InferRequestTests = BehaviorTestsUtils::BehaviorTestsBasic; - -// Setting empty config to LoadNetwork doesn't throw -TEST_P(InferRequestTests, SetEmptyConfig) { - // Skip test according to plugin specific disabledTestPatterns() (if any) - SKIP_IF_CURRENT_TEST_IS_DISABLED() - // Create CNNNetwork from ngrpah::Function - InferenceEngine::CNNNetwork cnnNet(function); - // Load CNNNetwork to target plugins - InferenceEngine::ExecutableNetwork execNet; - std::map config {}; - if (targetDevice.find(CommonTestUtils::DEVICE_AUTO) == std::string::npos && - targetDevice.find(CommonTestUtils::DEVICE_MULTI) == std::string::npos && - targetDevice.find(CommonTestUtils::DEVICE_HETERO) == std::string::npos) { - ASSERT_NO_THROW(ie->SetConfig(configuration, targetDevice)); - ASSERT_NO_THROW(execNet = ie->LoadNetwork(cnnNet, targetDevice, config)); - } else { - ASSERT_NO_THROW(ie->SetConfig(configuration, targetDevice)); - ASSERT_NO_THROW(execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration)); - } -} - -// Load correct network to Plugin to get executable network -TEST_P(InferRequestTests, canLoadCorrectNetworkToGetExecutable) { - // Skip test according to plugin specific disabledTestPatterns() (if any) - SKIP_IF_CURRENT_TEST_IS_DISABLED() - // Create CNNNetwork from ngrpah::Function - InferenceEngine::CNNNetwork cnnNet(function); - InferenceEngine::ExecutableNetwork execNet; - ASSERT_NO_THROW(execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration)); -} - -TEST_P(InferRequestTests, CanCreateTwoExeNetworks) { - // Skip test according to plugin specific disabledTestPatterns() (if any) - SKIP_IF_CURRENT_TEST_IS_DISABLED() - // Create CNNNetwork from ngrpah::Function - InferenceEngine::CNNNetwork cnnNet(function); - InferenceEngine::ExecutableNetwork execNet; - for (auto i = 0; i < 2; i++) { - ASSERT_NO_THROW(execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration)); - ASSERT_NE(nullptr, cnnNet.getFunction()); - } -} - -TEST_P(InferRequestTests, CanCreateInferRequest) { - // Skip test according to plugin specific disabledTestPatterns() (if any) - SKIP_IF_CURRENT_TEST_IS_DISABLED() - // Create CNNNetwork from ngrpah::Function - InferenceEngine::CNNNetwork cnnNet(function); - // Load CNNNetwork to target plugins - auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); - // Create InferRequest - InferenceEngine::InferRequest req; - ASSERT_NO_THROW(req = execNet.CreateInferRequest()); -} - -TEST_P(InferRequestTests, failToSetNullptrForInput) { - // Skip test according to plugin specific disabledTestPatterns() (if any) - SKIP_IF_CURRENT_TEST_IS_DISABLED() - // Create CNNNetwork from ngrpah::Function - InferenceEngine::CNNNetwork cnnNet(function); - // Load CNNNetwork to target plugins - auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); - // Create InferRequest - InferenceEngine::InferRequest req; - ASSERT_NO_THROW(req = execNet.CreateInferRequest()); - InferenceEngine::Blob::Ptr inputBlob = nullptr; - ASSERT_THROW(req.SetBlob(cnnNet.getInputsInfo().begin()->first, inputBlob), - InferenceEngine::Exception); -} - -TEST_P(InferRequestTests, failToSetEmptyInputBlob) { - // Skip test according to plugin specific disabledTestPatterns() (if any) - SKIP_IF_CURRENT_TEST_IS_DISABLED() - // Create CNNNetwork from ngrpah::Function - InferenceEngine::CNNNetwork cnnNet(function); - // Load CNNNetwork to target plugins - auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); - // Create InferRequest - InferenceEngine::InferRequest req; - ASSERT_NO_THROW(req = execNet.CreateInferRequest()); - InferenceEngine::Blob::Ptr blob; - ASSERT_THROW(req.SetBlob(cnnNet.getInputsInfo().begin()->first, blob), - InferenceEngine::Exception); -} - -TEST_P(InferRequestTests, failToSetEmptyOutputBlob) { - // Skip test according to plugin specific disabledTestPatterns() (if any) - SKIP_IF_CURRENT_TEST_IS_DISABLED() - // Create CNNNetwork from ngrpah::Function - InferenceEngine::CNNNetwork cnnNet(function); - // Load CNNNetwork to target plugins - auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); - // Create InferRequest - InferenceEngine::InferRequest req; - ASSERT_NO_THROW(req = execNet.CreateInferRequest()); - InferenceEngine::Blob::Ptr blob; - ASSERT_THROW(req.SetBlob(cnnNet.getOutputsInfo().begin()->first, blob), - InferenceEngine::Exception); -} - -TEST_P(InferRequestTests, failToSetNotAllocatedInput) { - // Skip test according to plugin specific disabledTestPatterns() (if any) - SKIP_IF_CURRENT_TEST_IS_DISABLED() - // Create CNNNetwork from ngrpah::Function - InferenceEngine::CNNNetwork cnnNet(function); - // Load CNNNetwork to target plugins - auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); - // Create InferRequest - InferenceEngine::InferRequest req; - ASSERT_NO_THROW(req = execNet.CreateInferRequest()); - InferenceEngine::Blob::Ptr blob = - FuncTestUtils::createAndFillBlob(cnnNet.getInputsInfo().begin()->second->getTensorDesc()); - ASSERT_NO_THROW(req.SetBlob(cnnNet.getInputsInfo().begin()->first, blob)); -} - -TEST_P(InferRequestTests, failToSetNotAllocatedOutput) { - // Skip test according to plugin specific disabledTestPatterns() (if any) - SKIP_IF_CURRENT_TEST_IS_DISABLED() - // Create CNNNetwork from ngrpah::Function - InferenceEngine::CNNNetwork cnnNet(function); - // Load CNNNetwork to target plugins - auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); - // Create InferRequest - InferenceEngine::InferRequest req; - ASSERT_NO_THROW(req = execNet.CreateInferRequest()); - InferenceEngine::Blob::Ptr blob = - FuncTestUtils::createAndFillBlob(cnnNet.getOutputsInfo().begin()->second->getTensorDesc()); - ASSERT_NO_THROW(req.SetBlob(cnnNet.getOutputsInfo().begin()->first, blob)); -} - -TEST_P(InferRequestTests, failToSetBlobWithIncorrectName) { - // Skip test according to plugin specific disabledTestPatterns() (if any) - SKIP_IF_CURRENT_TEST_IS_DISABLED() - // Create CNNNetwork from ngrpah::Function - InferenceEngine::CNNNetwork cnnNet(function); - // Load CNNNetwork to target plugins - auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); - // Create InferRequest - InferenceEngine::InferRequest req; - const char incorrect_input_name[] = "incorrect_input_name"; - ASSERT_NO_THROW(req = execNet.CreateInferRequest()); - InferenceEngine::Blob::Ptr blob = - FuncTestUtils::createAndFillBlob(cnnNet.getInputsInfo().begin()->second->getTensorDesc()); - blob->allocate(); - ASSERT_THROW(req.SetBlob(incorrect_input_name, blob), - InferenceEngine::Exception); -} - -TEST_P(InferRequestTests, failToSetInputWithIncorrectSizes) { - // Skip test according to plugin specific disabledTestPatterns() (if any) - SKIP_IF_CURRENT_TEST_IS_DISABLED() - // Create CNNNetwork from ngrpah::Function - InferenceEngine::CNNNetwork cnnNet(function); - // Load CNNNetwork to target plugins - auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); - // Create InferRequest - InferenceEngine::InferRequest req; - ASSERT_NO_THROW(req = execNet.CreateInferRequest()); - InferenceEngine::Blob::Ptr blob = - FuncTestUtils::createAndFillBlob(cnnNet.getInputsInfo().begin()->second->getTensorDesc()); - blob->allocate(); - blob->getTensorDesc().getDims()[0]*=2; - ASSERT_THROW(req.SetBlob(cnnNet.getInputsInfo().begin()->first, blob), - InferenceEngine::Exception); -} - -TEST_P(InferRequestTests, failToSetOutputWithIncorrectSizes) { - // Skip test according to plugin specific disabledTestPatterns() (if any) - SKIP_IF_CURRENT_TEST_IS_DISABLED() - // Create CNNNetwork from ngrpah::Function - InferenceEngine::CNNNetwork cnnNet(function); - // Load CNNNetwork to target plugins - auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); - // Create InferRequest - InferenceEngine::InferRequest req; - ASSERT_NO_THROW(req = execNet.CreateInferRequest()); - InferenceEngine::Blob::Ptr blob = - FuncTestUtils::createAndFillBlob(cnnNet.getOutputsInfo().begin()->second->getTensorDesc()); - blob->allocate(); - blob->getTensorDesc().getDims()[0]*=2; - ASSERT_THROW(req.SetBlob(cnnNet.getOutputsInfo().begin()->first, blob), - InferenceEngine::Exception); -} - -TEST_P(InferRequestTests, canInferWithoutSetAndGetInOut) { - // Skip test according to plugin specific disabledTestPatterns() (if any) - SKIP_IF_CURRENT_TEST_IS_DISABLED() - // Create CNNNetwork from ngrpah::Function - InferenceEngine::CNNNetwork cnnNet(function); - // Load CNNNetwork to target plugins - auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); - // Create InferRequest - InferenceEngine::InferRequest req; - ASSERT_NO_THROW(req = execNet.CreateInferRequest()); - ASSERT_NO_THROW(req.Infer()); -} - -TEST_P(InferRequestTests, canProcessDeallocatedInputBlobAfterGetBlob) { - // Skip test according to plugin specific disabledTestPatterns() (if any) - SKIP_IF_CURRENT_TEST_IS_DISABLED() - // Create CNNNetwork from ngrpah::Function - InferenceEngine::CNNNetwork cnnNet(function); - // Load CNNNetwork to target plugins - auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); - // Create InferRequest - InferenceEngine::InferRequest req; - InferenceEngine::Blob::Ptr blob; - ASSERT_NO_THROW(req = execNet.CreateInferRequest()); - ASSERT_NO_THROW(blob = req.GetBlob(cnnNet.getInputsInfo().begin()->first)); - ASSERT_NO_THROW(req.Infer()); -} - -TEST_P(InferRequestTests, canProcessDeallocatedInputBlobAfterGetBlobForAsync) { - // Skip test according to plugin specific disabledTestPatterns() (if any) - SKIP_IF_CURRENT_TEST_IS_DISABLED() - // Create CNNNetwork from ngrpah::Function - InferenceEngine::CNNNetwork cnnNet(function); - // Load CNNNetwork to target plugins - auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); - // Create InferRequest - InferenceEngine::InferRequest req; - InferenceEngine::Blob::Ptr blob; - ASSERT_NO_THROW(req = execNet.CreateInferRequest()); - ASSERT_NO_THROW(blob = req.GetBlob(cnnNet.getInputsInfo().begin()->first)); - ASSERT_NO_THROW(req.Infer()); - ASSERT_NO_THROW(req.StartAsync()); -} - -TEST_P(InferRequestTests, canProcessDeallocatedInputBlobAfterGetAndSetBlob) { - // Skip test according to plugin specific disabledTestPatterns() (if any) - SKIP_IF_CURRENT_TEST_IS_DISABLED() - // Create CNNNetwork from ngrpah::Function - InferenceEngine::CNNNetwork cnnNet(function); - // Load CNNNetwork to target plugins - auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); - // Create InferRequest - InferenceEngine::InferRequest req; - InferenceEngine::Blob::Ptr blob; - ASSERT_NO_THROW(req = execNet.CreateInferRequest()); - ASSERT_NO_THROW(blob = req.GetBlob(cnnNet.getInputsInfo().begin()->first)); - ASSERT_NO_THROW(req.SetBlob(cnnNet.getInputsInfo().begin()->first, blob)); - ASSERT_NO_THROW(req.Infer()); - ASSERT_NO_THROW(req.StartAsync()); -} - -TEST_P(InferRequestTests, canProcessDeallocatedInputBlobAfterSetBlob) { - // Skip test according to plugin specific disabledTestPatterns() (if any) - SKIP_IF_CURRENT_TEST_IS_DISABLED() - // Create CNNNetwork from ngrpah::Function - InferenceEngine::CNNNetwork cnnNet(function); - // Load CNNNetwork to target plugins - auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); - // Create InferRequest - InferenceEngine::InferRequest req; - InferenceEngine::Blob::Ptr blob = - FuncTestUtils::createAndFillBlob(cnnNet.getInputsInfo().begin()->second->getTensorDesc()); - ASSERT_NO_THROW(req = execNet.CreateInferRequest()); - blob->allocate(); - ASSERT_NO_THROW(req.SetBlob(cnnNet.getInputsInfo().begin()->first, blob)); - blob->deallocate(); - ASSERT_THROW(req.Infer(), InferenceEngine::Exception); -} - -TEST_P(InferRequestTests, canProcessDeallocatedOutputBlobAfterGetBlob) { - // Skip test according to plugin specific disabledTestPatterns() (if any) - SKIP_IF_CURRENT_TEST_IS_DISABLED() - // Create CNNNetwork from ngrpah::Function - InferenceEngine::CNNNetwork cnnNet(function); - // Load CNNNetwork to target plugins - auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); - // Create InferRequest - InferenceEngine::InferRequest req; - InferenceEngine::Blob::Ptr blob = - FuncTestUtils::createAndFillBlob(cnnNet.getOutputsInfo().begin()->second->getTensorDesc()); - ASSERT_NO_THROW(req = execNet.CreateInferRequest()); - blob->allocate(); - ASSERT_NO_THROW(req.SetBlob(cnnNet.getOutputsInfo().begin()->first, blob)); - blob->deallocate(); - ASSERT_THROW(req.Infer(), InferenceEngine::Exception); -} - -TEST_P(InferRequestTests, canProcessDeallocatedOutputBlobAfterGetBlobForAsync) { - // Skip test according to plugin specific disabledTestPatterns() (if any) - SKIP_IF_CURRENT_TEST_IS_DISABLED() - // Create CNNNetwork from ngrpah::Function - InferenceEngine::CNNNetwork cnnNet(function); - // Load CNNNetwork to target plugins - auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); - // Create InferRequest - InferenceEngine::InferRequest req; - InferenceEngine::Blob::Ptr blob = - FuncTestUtils::createAndFillBlob(cnnNet.getOutputsInfo().begin()->second->getTensorDesc()); - ASSERT_NO_THROW(req = execNet.CreateInferRequest()); - blob->allocate(); - ASSERT_NO_THROW(req.SetBlob(cnnNet.getOutputsInfo().begin()->first, blob)); - blob->deallocate(); - ASSERT_THROW(req.Infer(), InferenceEngine::Exception); - ASSERT_THROW({ req.StartAsync(); req.Wait(); }, InferenceEngine::Exception); -} - -TEST_P(InferRequestTests, canProcessDeallocatedOutputBlobAfterGetAndSetBlob) { - // Skip test according to plugin specific disabledTestPatterns() (if any) - SKIP_IF_CURRENT_TEST_IS_DISABLED() - // Create CNNNetwork from ngrpah::Function - InferenceEngine::CNNNetwork cnnNet(function); - // Load CNNNetwork to target plugins - auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); - // Create InferRequest - InferenceEngine::InferRequest req; - InferenceEngine::Blob::Ptr blob = - FuncTestUtils::createAndFillBlob(cnnNet.getOutputsInfo().begin()->second->getTensorDesc()); - ASSERT_NO_THROW(req = execNet.CreateInferRequest()); - blob->allocate(); - ASSERT_NO_THROW(blob = req.GetBlob(cnnNet.getOutputsInfo().begin()->first)); - ASSERT_NO_THROW(req.SetBlob(cnnNet.getOutputsInfo().begin()->first, blob)); - blob->deallocate(); - ASSERT_THROW(req.Infer(), InferenceEngine::Exception); -} - -TEST_P(InferRequestTests, canProcessDeallocatedOutputBlobAfterSetBlob) { - // Skip test according to plugin specific disabledTestPatterns() (if any) - SKIP_IF_CURRENT_TEST_IS_DISABLED() - // Create CNNNetwork from ngrpah::Function - InferenceEngine::CNNNetwork cnnNet(function); - // Load CNNNetwork to target plugins - auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); - // Create InferRequest - InferenceEngine::InferRequest req; - InferenceEngine::Blob::Ptr blob = - FuncTestUtils::createAndFillBlob(cnnNet.getOutputsInfo().begin()->second->getTensorDesc()); - ASSERT_NO_THROW(req = execNet.CreateInferRequest()); - blob->allocate(); - ASSERT_NO_THROW(req.SetBlob(cnnNet.getOutputsInfo().begin()->first, blob)); - blob->deallocate(); - ASSERT_THROW(req.Infer(), InferenceEngine::Exception); -} - -TEST_P(InferRequestTests, secondCallGetOutputDoNotReAllocateData) { - // Skip test according to plugin specific disabledTestPatterns() (if any) - SKIP_IF_CURRENT_TEST_IS_DISABLED() - // Create CNNNetwork from ngrpah::Function - InferenceEngine::CNNNetwork cnnNet(function); - // Load CNNNetwork to target plugins - auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); - // Create InferRequest - InferenceEngine::InferRequest req; - InferenceEngine::Blob::Ptr blob1; - InferenceEngine::Blob::Ptr blob2; - ASSERT_NO_THROW(req = execNet.CreateInferRequest()); - ASSERT_NO_THROW(blob1 = req.GetBlob(cnnNet.getInputsInfo().begin()->first)); - ASSERT_NO_THROW(blob2 = req.GetBlob(cnnNet.getInputsInfo().begin()->first)); - ASSERT_EQ(blob1.get(), blob2.get()); -} - -TEST_P(InferRequestTests, CorrectOneAsyncInferWithGetInOutWithInfWait) { - // Skip test according to plugin specific disabledTestPatterns() (if any) - SKIP_IF_CURRENT_TEST_IS_DISABLED() - // Create CNNNetwork from ngrpah::Function - InferenceEngine::CNNNetwork cnnNet(function); - // Load CNNNetwork to target plugins - auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); - // Create InferRequest - InferenceEngine::InferRequest req; - InferenceEngine::Blob::Ptr blob = - FuncTestUtils::createAndFillBlob(cnnNet.getOutputsInfo().begin()->second->getTensorDesc()); - ASSERT_NO_THROW(req = execNet.CreateInferRequest()); - ASSERT_NO_THROW(blob = req.GetBlob(cnnNet.getInputsInfo().begin()->first)); - req.Infer(); - req.StartAsync(); - InferenceEngine::StatusCode sts; - sts = req.Wait(InferenceEngine::InferRequest::WaitMode::RESULT_READY); - ASSERT_EQ(InferenceEngine::StatusCode::OK, sts); - ASSERT_NO_THROW(blob = req.GetBlob(cnnNet.getOutputsInfo().begin()->first)); -} - -// Plugin correct infer request with allocating input and result BlobMaps inside plugin -TEST_P(InferRequestTests, canStartAsyncInferWithGetInOutWithStatusOnlyWait) { - // Skip test according to plugin specific disabledTestPatterns() (if any) - SKIP_IF_CURRENT_TEST_IS_DISABLED() - // Create CNNNetwork from ngrpah::Function - InferenceEngine::CNNNetwork cnnNet(function); - // Load CNNNetwork to target plugins - auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); - // Create InferRequest - InferenceEngine::InferRequest req; - InferenceEngine::Blob::Ptr blob = - FuncTestUtils::createAndFillBlob(cnnNet.getOutputsInfo().begin()->second->getTensorDesc()); - ASSERT_NO_THROW(req = execNet.CreateInferRequest()); - ASSERT_NO_THROW(blob = req.GetBlob(cnnNet.getInputsInfo().begin()->first)); - req.Infer(); - req.StartAsync(); - InferenceEngine::StatusCode sts; - sts = req.Wait(InferenceEngine::InferRequest::WaitMode::STATUS_ONLY); - ASSERT_TRUE(sts == InferenceEngine::StatusCode::OK || - sts == InferenceEngine::StatusCode::RESULT_NOT_READY); -} - -// Plugin correct infer request with allocating input and result BlobMaps inside plugin -TEST_P(InferRequestTests, FailedAsyncInferWithNegativeTimeForWait) { - // Skip test according to plugin specific disabledTestPatterns() (if any) - SKIP_IF_CURRENT_TEST_IS_DISABLED() - // Create CNNNetwork from ngrpah::Function - InferenceEngine::CNNNetwork cnnNet(function); - // Load CNNNetwork to target plugins - auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); - // Create InferRequest - InferenceEngine::InferRequest req; - InferenceEngine::Blob::Ptr blob = - FuncTestUtils::createAndFillBlob(cnnNet.getOutputsInfo().begin()->second->getTensorDesc()); - ASSERT_NO_THROW(req = execNet.CreateInferRequest()); - ASSERT_NO_THROW(blob = req.GetBlob(cnnNet.getInputsInfo().begin()->first)); - req.Infer(); - req.StartAsync(); - ASSERT_THROW(req.Wait(-2), InferenceEngine::Exception); -} - -TEST_P(InferRequestTests, canRun3SyncRequestsConsistentlyFromThreads) { - // Skip test according to plugin specific disabledTestPatterns() (if any) - SKIP_IF_CURRENT_TEST_IS_DISABLED() - // Create CNNNetwork from ngrpah::Function - InferenceEngine::CNNNetwork cnnNet(function); - // Load CNNNetwork to target plugins - auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); - // Create InferRequest - auto req1 = execNet.CreateInferRequest(); - auto req2 = execNet.CreateInferRequest(); - auto req3 = execNet.CreateInferRequest(); - - - auto f1 = std::async(std::launch::async, [&] { req1.Infer();}); - auto f2 = std::async(std::launch::async, [&] { req2.Infer();}); - auto f3 = std::async(std::launch::async, [&] { req3.Infer();}); - - ASSERT_NO_THROW(f1.get()); - ASSERT_NO_THROW(f2.get()); - ASSERT_NO_THROW(f3.get()); -} - -TEST_P(InferRequestTests, canRun3AsyncRequestsConsistentlyWithWait) { - // Skip test according to plugin specific disabledTestPatterns() (if any) - SKIP_IF_CURRENT_TEST_IS_DISABLED() - // Create CNNNetwork from ngrpah::Function - InferenceEngine::CNNNetwork cnnNet(function); - // Load CNNNetwork to target plugins - auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); - // Create InferRequest - auto req1 = execNet.CreateInferRequest(); - auto req2 = execNet.CreateInferRequest(); - auto req3 = execNet.CreateInferRequest(); - - req1.StartAsync(); - ASSERT_NO_THROW(req1.Wait(InferenceEngine::InferRequest::WaitMode::RESULT_READY)); - - req2.Infer(); - ASSERT_NO_THROW(req2.Wait(InferenceEngine::InferRequest::WaitMode::RESULT_READY)); - - req3.Infer(); - ASSERT_NO_THROW(req3.Wait(InferenceEngine::InferRequest::WaitMode::RESULT_READY)); -} - -TEST_P(InferRequestTests, canRun3AsyncRequestsConsistentlyFromThreadsWithoutWait) { - // Skip test according to plugin specific disabledTestPatterns() (if any) - SKIP_IF_CURRENT_TEST_IS_DISABLED() - // Create CNNNetwork from ngrpah::Function - InferenceEngine::CNNNetwork cnnNet(function); - // Load CNNNetwork to target plugins - auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); - // Create InferRequest - auto req1 = execNet.CreateInferRequest(); - auto req2 = execNet.CreateInferRequest(); - auto req3 = execNet.CreateInferRequest(); - InferenceEngine::ResponseDesc response1, response2, response3; - InferenceEngine::StatusCode sts1, sts2, sts3; - - req1.Infer(); - req2.Infer(); - req3.Infer(); - - std::thread t1([&] { req1.StartAsync(); sts1 = req1.Wait(InferenceEngine::InferRequest::WaitMode::RESULT_READY); }); - std::thread t2([&] { req2.StartAsync(); sts2 = req2.Wait(InferenceEngine::InferRequest::WaitMode::RESULT_READY); }); - std::thread t3([&] { req3.StartAsync(); sts3 = req3.Wait(InferenceEngine::InferRequest::WaitMode::RESULT_READY); }); - - t1.join(); - t2.join(); - t3.join(); - - ASSERT_EQ(static_cast(InferenceEngine::StatusCode::OK), sts1) << response1.msg; - ASSERT_EQ(static_cast(InferenceEngine::StatusCode::OK), sts2) << response2.msg; - ASSERT_EQ(static_cast(InferenceEngine::StatusCode::OK), sts3) << response3.msg; -} - -TEST_P(InferRequestTests, canWaitWithotStartAsync) { - // Skip test according to plugin specific disabledTestPatterns() (if any) - SKIP_IF_CURRENT_TEST_IS_DISABLED() - // Create CNNNetwork from ngrpah::Function - InferenceEngine::CNNNetwork cnnNet(function); - // Load CNNNetwork to target plugins - auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); - // Create InferRequest - auto req = execNet.CreateInferRequest(); - ASSERT_NO_THROW(req.Wait(InferenceEngine::InferRequest::WaitMode::RESULT_READY)); - ASSERT_NO_THROW(req.Wait(InferenceEngine::InferRequest::WaitMode::STATUS_ONLY)); - ASSERT_NO_THROW(req.Wait(1)); -} - -TEST_P(InferRequestTests, returnDeviceBusyOnSetBlobAfterAsyncInfer) { - // Skip test according to plugin specific disabledTestPatterns() (if any) - SKIP_IF_CURRENT_TEST_IS_DISABLED() - auto&& config = configuration; - auto itConfig = config.find(CONFIG_KEY(CPU_THROUGHPUT_STREAMS)); - if (itConfig != config.end()) { - if (itConfig->second != "CPU_THROUGHPUT_AUTO") { - if (std::stoi(itConfig->second) == 0) { - GTEST_SKIP() << "Not applicable with disabled streams"; - } - } - } - // Create CNNNetwork from ngrpah::Function - InferenceEngine::CNNNetwork cnnNet(function); - // Load CNNNetwork to target plugins - auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); - // Create InferRequest - auto req = execNet.CreateInferRequest(); - auto outputBlob = req.GetBlob(cnnNet.getInputsInfo().begin()->first); - InferenceEngine::ResponseDesc response; - - InferenceEngine::StatusCode sts; - sts = req.Wait(InferenceEngine::InferRequest::WaitMode::STATUS_ONLY); - ASSERT_EQ(InferenceEngine::StatusCode::INFER_NOT_STARTED, sts) << response.msg; - req.StartAsync(); - sts = req.Wait(InferenceEngine::InferRequest::WaitMode::RESULT_READY); - ASSERT_EQ(static_cast(InferenceEngine::StatusCode::OK), sts) << response.msg; - try { - req.SetBlob(cnnNet.getInputsInfo().begin()->first, outputBlob); - } - catch (const std::exception &e) { - std::cout << "Exception: " << e.what() << std::endl; - } - sts = req.Wait(InferenceEngine::InferRequest::WaitMode::STATUS_ONLY); - ASSERT_TRUE(sts == InferenceEngine::StatusCode::OK || - sts == InferenceEngine::StatusCode::RESULT_NOT_READY) << response.msg; -} - -TEST_P(InferRequestTests, returnDeviceBusyOnGetBlobAfterAsyncInfer) { - // Skip test according to plugin specific disabledTestPatterns() (if any) - SKIP_IF_CURRENT_TEST_IS_DISABLED() - // Create CNNNetwork from ngrpah::Function - InferenceEngine::CNNNetwork cnnNet(function); - // Load CNNNetwork to target plugins - auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); - // Create InferRequest - auto req = execNet.CreateInferRequest(); - auto outputBlob = req.GetBlob(cnnNet.getInputsInfo().begin()->first); - InferenceEngine::ResponseDesc response; - InferenceEngine::StatusCode sts; - req.StartAsync(); - sts = req.Wait(InferenceEngine::InferRequest::WaitMode::RESULT_READY); - ASSERT_EQ(static_cast(InferenceEngine::StatusCode::OK), sts) << response.msg; - try { - req.SetBlob(cnnNet.getInputsInfo().begin()->first, outputBlob); - } - catch (const std::exception &e) { - std::cout << "Exception" << e.what() << std::endl; - } -} - -TEST_P(InferRequestTests, returnDeviceBusyOnGetPerformanceCountAfterAsyncInfer) { - // Skip test according to plugin specific disabledTestPatterns() (if any) - SKIP_IF_CURRENT_TEST_IS_DISABLED() - // Create CNNNetwork from ngrpah::Function - InferenceEngine::CNNNetwork cnnNet(function); - // Load CNNNetwork to target plugins - auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); - // Create InferRequest - auto req = execNet.CreateInferRequest(); - auto outputBlob = req.GetBlob(cnnNet.getInputsInfo().begin()->first); - InferenceEngine::ResponseDesc response; - InferenceEngine::StatusCode sts; - req.StartAsync(); - sts = req.Wait(InferenceEngine::InferRequest::WaitMode::RESULT_READY); - ASSERT_EQ(static_cast(InferenceEngine::StatusCode::OK), sts) << response.msg; - - std::map perfMap; - - try { - perfMap = req.GetPerformanceCounts(); - } - catch (const std::exception &e) { - std::cout << "Exception" << e.what() << std::endl; - } -} - -class InferRequestTestsResultNotReady : public InferRequestTests { -}; - -TEST_P(InferRequestTestsResultNotReady, ReturnResultNotReadyFromWaitInAsyncModeForTooSmallTimeout) { - // Skip test according to plugin specific disabledTestPatterns() (if any) - SKIP_IF_CURRENT_TEST_IS_DISABLED() - // Create CNNNetwork from ngraph::Function - // return ngrpah::Function - // GetNetwork(3000, 380) make inference around 20ms on GNA SW - // so increases chances for getting RESULT_NOT_READY - function = SubgraphTestsDefinitions::Basic_LSTM_S::GetNetwork(300, 38); - InferenceEngine::CNNNetwork cnnNet(function); - // Load CNNNetwork to target plugins - auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); - // Create InferRequest - InferenceEngine::InferRequest req; - ASSERT_NO_THROW(req = execNet.CreateInferRequest()); - InferenceEngine::StatusCode sts = InferenceEngine::StatusCode::OK; - std::promise callbackTimeStamp; - auto callbackTimeStampFuture = callbackTimeStamp.get_future(); - // add a callback to the request and capture the timestamp - req.SetCompletionCallback([&]() { - callbackTimeStamp.set_value(std::chrono::system_clock::now()); - }); - req.StartAsync(); - ASSERT_NO_THROW(sts = req.Wait(InferenceEngine::InferRequest::WaitMode::STATUS_ONLY)); - // get timestamp taken AFTER return from the Wait(STATUS_ONLY) - const auto afterWaitTimeStamp = std::chrono::system_clock::now(); - // IF the callback timestamp is larger than the afterWaitTimeStamp - // then we should observe RESULT_NOT_READY - if (afterWaitTimeStamp < callbackTimeStampFuture.get()) { - ASSERT_TRUE(sts == InferenceEngine::StatusCode::RESULT_NOT_READY); - } - ASSERT_NO_THROW(req.Wait(InferenceEngine::InferRequest::WaitMode::RESULT_READY)); -} -} // namespace BehaviorTestsDefinitions diff --git a/inference-engine/tests/functional/plugin/shared/include/behavior/infer_request_callback.hpp b/inference-engine/tests/functional/plugin/shared/include/behavior/infer_request/callback.hpp similarity index 58% rename from inference-engine/tests/functional/plugin/shared/include/behavior/infer_request_callback.hpp rename to inference-engine/tests/functional/plugin/shared/include/behavior/infer_request/callback.hpp index 48e51de3d19..7ed969f5e82 100644 --- a/inference-engine/tests/functional/plugin/shared/include/behavior/infer_request_callback.hpp +++ b/inference-engine/tests/functional/plugin/shared/include/behavior/infer_request/callback.hpp @@ -4,35 +4,15 @@ #pragma once -#include -#include -#include -#include #include -#include "ie_extension.h" -#include -#include "shared_test_classes/base/layer_test_utils.hpp" -#include "ngraph_functions/utils/ngraph_helpers.hpp" -#include "ngraph_functions/builders.hpp" -#include -#include -#include "common_test_utils/common_utils.hpp" -#include "functional_test_utils/plugin_cache.hpp" -#include "functional_test_utils/blob_utils.hpp" -#include "ngraph_functions/pass/convert_prc.hpp" -#include "ngraph_functions/subgraph_builders.hpp" -#include "behavior/infer_request_callback.hpp" + +#include "shared_test_classes/subgraph/basic_lstm.hpp" +#include "base/behavior_test_utils.hpp" namespace BehaviorTestsDefinitions { -using CallbackTests = BehaviorTestsUtils::BehaviorTestsBasic; +using InferRequestCallbackTests = BehaviorTestsUtils::InferRequestTests; -TEST_P(CallbackTests, canCallSyncAndAsyncWithCompletionCallback) { - // Skip test according to plugin specific disabledTestPatterns() (if any) - SKIP_IF_CURRENT_TEST_IS_DISABLED() - // Create CNNNetwork from ngrpah::Function - InferenceEngine::CNNNetwork cnnNet(function); - // Load CNNNetwork to target plugins - auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); +TEST_P(InferRequestCallbackTests, canCallAsyncWithCompletionCallback) { // Create InferRequest InferenceEngine::InferRequest req = execNet.CreateInferRequest(); bool isCalled = false; @@ -40,24 +20,35 @@ TEST_P(CallbackTests, canCallSyncAndAsyncWithCompletionCallback) { [&](InferenceEngine::InferRequest request, InferenceEngine::StatusCode status) { ASSERT_TRUE(req == request); //the callback is called on the same impl of the request // HSD_1805940120: Wait on starting callback return HDDL_ERROR_INVAL_TASK_HANDLE - if (targetDevice != CommonTestUtils::DEVICE_HDDL) { - ASSERT_EQ(static_cast(InferenceEngine::StatusCode::OK), status); - } + ASSERT_EQ(InferenceEngine::StatusCode::OK, status); isCalled = true; }); req.StartAsync(); InferenceEngine::StatusCode waitStatus = req.Wait(InferenceEngine::InferRequest::WaitMode::RESULT_READY); - ASSERT_EQ(static_cast(InferenceEngine::StatusCode::OK), waitStatus); + ASSERT_EQ(InferenceEngine::StatusCode::OK, waitStatus); ASSERT_TRUE(isCalled); } -// test that can wait all callbacks on dtor -TEST_P(CallbackTests, canStartSeveralAsyncInsideCompletionCallbackWithSafeDtor) { - // Skip test according to plugin specific disabledTestPatterns() (if any) - SKIP_IF_CURRENT_TEST_IS_DISABLED() +TEST_P(InferRequestCallbackTests, syncInferDoesNotCallCompletionCallback) { + // Create CNNNetwork from ngrpah::Function + InferenceEngine::CNNNetwork cnnNet(function); + // Load CNNNetwork to target plugins + auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); + // Create InferRequest + InferenceEngine::InferRequest req = execNet.CreateInferRequest(); + bool isCalled = false; + req.SetCompletionCallback>( + [&](InferenceEngine::InferRequest request, InferenceEngine::StatusCode status) { + isCalled = true; + }); + req.Infer(); + ASSERT_FALSE(isCalled); +} +// test that can wait all callbacks on dtor +TEST_P(InferRequestCallbackTests, canStartSeveralAsyncInsideCompletionCallbackWithSafeDtor) { const int NUM_ITER = 10; struct TestUserData { std::atomic numIter = {0}; @@ -65,10 +56,6 @@ TEST_P(CallbackTests, canStartSeveralAsyncInsideCompletionCallbackWithSafeDtor) }; TestUserData data; - // Create CNNNetwork from ngrpah::Function - InferenceEngine::CNNNetwork cnnNet(function); - // Load CNNNetwork to target plugins - auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); // Create InferRequest InferenceEngine::InferRequest req = execNet.CreateInferRequest(); req.SetCompletionCallback>( @@ -86,39 +73,15 @@ TEST_P(CallbackTests, canStartSeveralAsyncInsideCompletionCallbackWithSafeDtor) auto future = data.promise.get_future(); req.StartAsync(); InferenceEngine::StatusCode waitStatus = req.Wait(InferenceEngine::InferRequest::WaitMode::RESULT_READY); - ASSERT_EQ((int) InferenceEngine::StatusCode::OK, waitStatus); + ASSERT_EQ(InferenceEngine::StatusCode::OK, waitStatus); future.wait(); auto callbackStatus = future.get(); - ASSERT_EQ((int) InferenceEngine::StatusCode::OK, callbackStatus); + ASSERT_EQ(InferenceEngine::StatusCode::OK, callbackStatus); auto dataNumIter = data.numIter - 1; ASSERT_EQ(NUM_ITER, dataNumIter); } -TEST_P(CallbackTests, inferDoesNotCallCompletionCallback) { - // Skip test according to plugin specific disabledTestPatterns() (if any) - SKIP_IF_CURRENT_TEST_IS_DISABLED() - // Create CNNNetwork from ngrpah::Function - InferenceEngine::CNNNetwork cnnNet(function); - // Load CNNNetwork to target plugins - auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); - // Create InferRequest - InferenceEngine::InferRequest req = execNet.CreateInferRequest(); - bool isCalled = false; - req.SetCompletionCallback>( - [&](InferenceEngine::InferRequest request, InferenceEngine::StatusCode status) { - isCalled = true; - }); - req.Infer(); - ASSERT_FALSE(isCalled); -} - -TEST_P(CallbackTests, returnGeneralErrorIfCallbackThrowException) { - // Skip test according to plugin specific disabledTestPatterns() (if any) - SKIP_IF_CURRENT_TEST_IS_DISABLED() - // Create CNNNetwork from ngrpah::Function - InferenceEngine::CNNNetwork cnnNet(function); - // Load CNNNetwork to target plugins - auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); +TEST_P(InferRequestCallbackTests, returnGeneralErrorIfCallbackThrowException) { // Create InferRequest auto req = execNet.CreateInferRequest(); req.SetCompletionCallback([] { @@ -129,13 +92,7 @@ TEST_P(CallbackTests, returnGeneralErrorIfCallbackThrowException) { ASSERT_THROW(req.Wait(InferenceEngine::InferRequest::WaitMode::RESULT_READY), InferenceEngine::GeneralError); } -TEST_P(CallbackTests, LegacyCastAndSetuserDataGetUserData) { - // Skip test according to plugin specific disabledTestPatterns() (if any) - SKIP_IF_CURRENT_TEST_IS_DISABLED() - // Create CNNNetwork from ngrpah::Function - InferenceEngine::CNNNetwork cnnNet(function); - // Load CNNNetwork to target plugins - auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); +TEST_P(InferRequestCallbackTests, LegacyCastAndSetuserDataGetUserData) { // Create InferRequest InferenceEngine::InferRequest req = execNet.CreateInferRequest(); int userData = 0; @@ -157,4 +114,35 @@ TEST_P(CallbackTests, LegacyCastAndSetuserDataGetUserData) { ASSERT_EQ(42, userData); } +TEST_P(InferRequestCallbackTests, ReturnResultNotReadyFromWaitInAsyncModeForTooSmallTimeout) { + // Create CNNNetwork from ngraph::Function + // return ngrpah::Function + // GetNetwork(3000, 380) make inference around 20ms on GNA SW + // so increases chances for getting RESULT_NOT_READY + function = SubgraphTestsDefinitions::Basic_LSTM_S::GetNetwork(300, 38); + cnnNet = InferenceEngine::CNNNetwork(function); + // Load CNNNetwork to target plugins + execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); + // Create InferRequest + InferenceEngine::InferRequest req; + ASSERT_NO_THROW(req = execNet.CreateInferRequest()); + InferenceEngine::StatusCode sts = InferenceEngine::StatusCode::OK; + std::promise callbackTimeStamp; + auto callbackTimeStampFuture = callbackTimeStamp.get_future(); + // add a callback to the request and capture the timestamp + req.SetCompletionCallback([&]() { + callbackTimeStamp.set_value(std::chrono::system_clock::now()); + }); + req.StartAsync(); + ASSERT_NO_THROW(sts = req.Wait(InferenceEngine::InferRequest::WaitMode::STATUS_ONLY)); + // get timestamp taken AFTER return from the Wait(STATUS_ONLY) + const auto afterWaitTimeStamp = std::chrono::system_clock::now(); + // IF the callback timestamp is larger than the afterWaitTimeStamp + // then we should observe RESULT_NOT_READY + if (afterWaitTimeStamp < callbackTimeStampFuture.get()) { + ASSERT_TRUE(sts == InferenceEngine::StatusCode::RESULT_NOT_READY); + } + ASSERT_NO_THROW(req.Wait(InferenceEngine::InferRequest::WaitMode::RESULT_READY)); +} + } // namespace BehaviorTestsDefinitions \ No newline at end of file diff --git a/inference-engine/tests/functional/plugin/shared/include/behavior/infer_request_cancellation.hpp b/inference-engine/tests/functional/plugin/shared/include/behavior/infer_request/cancellation.hpp similarity index 51% rename from inference-engine/tests/functional/plugin/shared/include/behavior/infer_request_cancellation.hpp rename to inference-engine/tests/functional/plugin/shared/include/behavior/infer_request/cancellation.hpp index bbb2526d28d..07eb211f5dd 100644 --- a/inference-engine/tests/functional/plugin/shared/include/behavior/infer_request_cancellation.hpp +++ b/inference-engine/tests/functional/plugin/shared/include/behavior/infer_request/cancellation.hpp @@ -4,41 +4,26 @@ #pragma once -#include -#include -#include -#include -#include #include -#include -#include - -#include "shared_test_classes/base/layer_test_utils.hpp" - -#include "common_test_utils/common_utils.hpp" -#include "functional_test_utils/plugin_cache.hpp" -#include "functional_test_utils/blob_utils.hpp" - -#include "ngraph_functions/pass/convert_prc.hpp" -#include "ngraph_functions/subgraph_builders.hpp" -#include "ngraph_functions/utils/ngraph_helpers.hpp" -#include "ngraph_functions/builders.hpp" - #include "base/behavior_test_utils.hpp" -#include "behavior/infer_request_cancellation.hpp" namespace BehaviorTestsDefinitions { -using CancellationTests = BehaviorTestsUtils::BehaviorTestsBasic; -TEST_P(CancellationTests, canCancelAsyncRequest) { +class InferRequestCancellationTests : public BehaviorTestsUtils::InferRequestTests { +public: + void SetUp() override { + std::tie(targetDevice, configuration) = this->GetParam(); + function = ngraph::builder::subgraph::makeConvPoolRelu({1, 3, 640, 640}); + cnnNet = InferenceEngine::CNNNetwork(function); + // Load CNNNetwork to target plugins + execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); + } +}; + +TEST_P(InferRequestCancellationTests, canCancelAsyncRequest) { // Skip test according to plugin specific disabledTestPatterns() (if any) SKIP_IF_CURRENT_TEST_IS_DISABLED() - std::shared_ptr largeNetwork = ngraph::builder::subgraph::makeConvPoolRelu({1, 3, 640, 640}); - // Create CNNNetwork from ngrpah::Function - InferenceEngine::CNNNetwork cnnNet(largeNetwork); - // Load CNNNetwork to target plugins - auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); // Create InferRequest InferenceEngine::InferRequest req = execNet.CreateInferRequest(); req.StartAsync(); @@ -51,13 +36,9 @@ TEST_P(CancellationTests, canCancelAsyncRequest) { } } -TEST_P(CancellationTests, canResetAfterCancelAsyncRequest) { +TEST_P(InferRequestCancellationTests, canResetAfterCancelAsyncRequest) { // Skip test according to plugin specific disabledTestPatterns() (if any) SKIP_IF_CURRENT_TEST_IS_DISABLED() - // Create CNNNetwork from ngrpah::Function - InferenceEngine::CNNNetwork cnnNet(function); - // Load CNNNetwork to target plugins - auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); // Create InferRequest InferenceEngine::InferRequest req = execNet.CreateInferRequest(); @@ -73,28 +54,17 @@ TEST_P(CancellationTests, canResetAfterCancelAsyncRequest) { ASSERT_NO_THROW(req.Wait(InferenceEngine::InferRequest::WaitMode::RESULT_READY)); } -TEST_P(CancellationTests, canCancelBeforeAsyncRequest) { +TEST_P(InferRequestCancellationTests, canCancelBeforeAsyncRequest) { // Skip test according to plugin specific disabledTestPatterns() (if any) SKIP_IF_CURRENT_TEST_IS_DISABLED() - // Create CNNNetwork from ngrpah::Function - InferenceEngine::CNNNetwork cnnNet(function); - // Load CNNNetwork to target plugins - auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); // Create InferRequest InferenceEngine::InferRequest req = execNet.CreateInferRequest(); - ASSERT_NO_THROW(req.Cancel()); } -TEST_P(CancellationTests, canCancelInferRequest) { +TEST_P(InferRequestCancellationTests, canCancelInferRequest) { // Skip test according to plugin specific disabledTestPatterns() (if any) SKIP_IF_CURRENT_TEST_IS_DISABLED() - // Create function with large input, to have a time to Cancel request - std::shared_ptr largeNetwork = ngraph::builder::subgraph::makeConvPoolRelu({1, 3, 640, 640}); - // Create CNNNetwork from ngrpah::Function - InferenceEngine::CNNNetwork cnnNet(largeNetwork); - // Load CNNNetwork to target plugins - auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); // Create InferRequest InferenceEngine::InferRequest req = execNet.CreateInferRequest(); diff --git a/inference-engine/tests/functional/plugin/shared/include/behavior/infer_request/config.hpp b/inference-engine/tests/functional/plugin/shared/include/behavior/infer_request/config.hpp new file mode 100644 index 00000000000..bfc8ecd2b19 --- /dev/null +++ b/inference-engine/tests/functional/plugin/shared/include/behavior/infer_request/config.hpp @@ -0,0 +1,96 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +#include "threading/ie_executor_manager.hpp" + +#include "base/behavior_test_utils.hpp" + +namespace BehaviorTestsDefinitions { +using namespace CommonTestUtils; + +typedef std::tuple< + size_t, // Stream executor number + std::string, // Device name + std::map // Config +> InferRequestParams; + +class InferRequestConfigTest : public testing::WithParamInterface, + public CommonTestUtils::TestsCommon { +public: + void SetUp() override { + // Skip test according to plugin specific disabledTestPatterns() (if any) + SKIP_IF_CURRENT_TEST_IS_DISABLED() + std::tie(streamExecutorNumber, targetDevice, configuration) = this->GetParam(); + // Create CNNNetwork from ngrpah::Function + function = ngraph::builder::subgraph::makeConvPoolRelu({1, 1, 32, 32}); + cnnNet = InferenceEngine::CNNNetwork(function); + } + + static std::string getTestCaseName(testing::TestParamInfo obj) { + std::string targetDevice; + size_t streamExecutorNumber; + std::map configuration; + std::tie(streamExecutorNumber, targetDevice, configuration) = obj.param; + std::ostringstream result; + result << "targetDevice=" << targetDevice << "_"; + result << "streamExecutorNumber=" << targetDevice << "_"; + if (!configuration.empty()) { + result << "config=" << configuration; + } + return result.str(); + } + + void TearDown() override { + if (!configuration.empty()) { + PluginCache::get().reset(); + } + function.reset(); + } + +protected: + InferenceEngine::CNNNetwork cnnNet; + InferenceEngine::ExecutableNetwork execNet; + std::shared_ptr ie = PluginCache::get().ie(); + std::shared_ptr function; + InferenceEngine::Precision netPrecision; + std::string targetDevice; + std::map configuration; + size_t streamExecutorNumber; + + inline InferenceEngine::InferRequest createInferRequestWithConfig() { + // Load config + configuration.insert({CONFIG_KEY(EXCLUSIVE_ASYNC_REQUESTS), CONFIG_VALUE(YES)}); + if (targetDevice.find(CommonTestUtils::DEVICE_AUTO) == std::string::npos && + targetDevice.find(CommonTestUtils::DEVICE_MULTI) == std::string::npos && + targetDevice.find(CommonTestUtils::DEVICE_HETERO) == std::string::npos) { + ie->SetConfig(configuration, targetDevice); + } + // Load CNNNetwork to target plugins + execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); + return execNet.CreateInferRequest(); + } +}; + +TEST_P(InferRequestConfigTest, canSetExclusiveAsyncRequests) { + ASSERT_EQ(0ul, InferenceEngine::ExecutorManager::getInstance()->getExecutorsNumber()); + ASSERT_NO_THROW(createInferRequestWithConfig()); + if (targetDevice.find(CommonTestUtils::DEVICE_AUTO) == std::string::npos && + targetDevice.find(CommonTestUtils::DEVICE_MULTI) == std::string::npos && + targetDevice.find(CommonTestUtils::DEVICE_HETERO) == std::string::npos) { + ASSERT_EQ(streamExecutorNumber, InferenceEngine::ExecutorManager::getInstance()->getExecutorsNumber()); + } +} + +TEST_P(InferRequestConfigTest, withoutExclusiveAsyncRequests) { + ASSERT_EQ(0u, InferenceEngine::ExecutorManager::getInstance()->getExecutorsNumber()); + ASSERT_NO_THROW(createInferRequestWithConfig()); + if (targetDevice.find(CommonTestUtils::DEVICE_AUTO) == std::string::npos && + targetDevice.find(CommonTestUtils::DEVICE_MULTI) == std::string::npos && + targetDevice.find(CommonTestUtils::DEVICE_HETERO) == std::string::npos) { + ASSERT_EQ(streamExecutorNumber, InferenceEngine::ExecutorManager::getInstance()->getExecutorsNumber()); + } +} +} // namespace BehaviorTestsDefinitions \ No newline at end of file diff --git a/inference-engine/tests/functional/plugin/shared/include/configuration_tests/dynamic_batch.hpp b/inference-engine/tests/functional/plugin/shared/include/behavior/infer_request/dynamic_batch.hpp similarity index 100% rename from inference-engine/tests/functional/plugin/shared/include/configuration_tests/dynamic_batch.hpp rename to inference-engine/tests/functional/plugin/shared/include/behavior/infer_request/dynamic_batch.hpp diff --git a/inference-engine/tests/functional/plugin/shared/include/behavior/infer_request/io_blob.hpp b/inference-engine/tests/functional/plugin/shared/include/behavior/infer_request/io_blob.hpp new file mode 100644 index 00000000000..dc3a65cc45f --- /dev/null +++ b/inference-engine/tests/functional/plugin/shared/include/behavior/infer_request/io_blob.hpp @@ -0,0 +1,501 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +#include +#include + +#include "base/behavior_test_utils.hpp" +#include "shared_test_classes/subgraph/basic_lstm.hpp" + +namespace BehaviorTestsDefinitions { +using InferRequestIOBBlobTest = BehaviorTestsUtils::InferRequestTests; +using namespace CommonTestUtils; + +TEST_P(InferRequestIOBBlobTest, CanCreateInferRequest) { + // Create InferRequest + InferenceEngine::InferRequest req; + ASSERT_NO_THROW(req = execNet.CreateInferRequest()); +} + +TEST_P(InferRequestIOBBlobTest, failToSetNullptrForInput) { + // Create InferRequest + InferenceEngine::InferRequest req; + ASSERT_NO_THROW(req = execNet.CreateInferRequest()); + InferenceEngine::Blob::Ptr inputBlob = nullptr; + ASSERT_THROW(req.SetBlob(cnnNet.getInputsInfo().begin()->first, inputBlob), + InferenceEngine::Exception); +} + +TEST_P(InferRequestIOBBlobTest, failToSetNullptrForOutput) { + // Create InferRequest + InferenceEngine::InferRequest req; + ASSERT_NO_THROW(req = execNet.CreateInferRequest()); + InferenceEngine::Blob::Ptr outputBlob = nullptr; + ASSERT_THROW(req.SetBlob(cnnNet.getOutputsInfo().begin()->first, outputBlob), + InferenceEngine::Exception); +} + +TEST_P(InferRequestIOBBlobTest, failToSetUninitializedInputBlob) { + // Create InferRequest + InferenceEngine::InferRequest req; + ASSERT_NO_THROW(req = execNet.CreateInferRequest()); + InferenceEngine::Blob::Ptr blob; + ASSERT_THROW(req.SetBlob(cnnNet.getInputsInfo().begin()->first, blob), + InferenceEngine::Exception); +} + +TEST_P(InferRequestIOBBlobTest, failToSetUninitializedOutputBlob) { + // Create InferRequest + InferenceEngine::InferRequest req; + ASSERT_NO_THROW(req = execNet.CreateInferRequest()); + InferenceEngine::Blob::Ptr blob; + ASSERT_THROW(req.SetBlob(cnnNet.getOutputsInfo().begin()->first, blob), + InferenceEngine::Exception); +} + +TEST_P(InferRequestIOBBlobTest, setNotAllocatedInput) { + // Create InferRequest + InferenceEngine::InferRequest req; + ASSERT_NO_THROW(req = execNet.CreateInferRequest()); + InferenceEngine::Blob::Ptr blob = + FuncTestUtils::createAndFillBlob(cnnNet.getInputsInfo().begin()->second->getTensorDesc()); + ASSERT_NO_THROW(req.SetBlob(cnnNet.getInputsInfo().begin()->first, blob)); +} + +TEST_P(InferRequestIOBBlobTest, setNotAllocatedOutput) { + // Create InferRequest + InferenceEngine::InferRequest req; + ASSERT_NO_THROW(req = execNet.CreateInferRequest()); + InferenceEngine::Blob::Ptr blob = + FuncTestUtils::createAndFillBlob(cnnNet.getOutputsInfo().begin()->second->getTensorDesc()); + ASSERT_NO_THROW(req.SetBlob(cnnNet.getOutputsInfo().begin()->first, blob)); +} + +TEST_P(InferRequestIOBBlobTest, getAfterSetInputDoNotChangeInput) { + // Create InferRequest + InferenceEngine::InferRequest req = execNet.CreateInferRequest(); + std::shared_ptr inputBlob = FuncTestUtils::createAndFillBlob( + cnnNet.getInputsInfo().begin()->second->getTensorDesc()); + ASSERT_NO_THROW(req.SetBlob(cnnNet.getInputsInfo().begin()->first, inputBlob)); + std::shared_ptr actualBlob = nullptr; + ASSERT_NO_THROW(actualBlob = req.GetBlob(cnnNet.getInputsInfo().begin()->first)); + + ASSERT_TRUE(actualBlob); + ASSERT_FALSE(actualBlob->buffer() == nullptr); + ASSERT_EQ(inputBlob.get(), actualBlob.get()); + + ASSERT_TRUE(cnnNet.getInputsInfo().begin()->second->getTensorDesc() == actualBlob->getTensorDesc()); +} + +TEST_P(InferRequestIOBBlobTest, getAfterSetInputDoNotChangeOutput) { + // Create InferRequest + InferenceEngine::InferRequest req = execNet.CreateInferRequest(); + std::shared_ptr inputBlob = FuncTestUtils::createAndFillBlob( + cnnNet.getOutputsInfo().begin()->second->getTensorDesc()); + ASSERT_NO_THROW(req.SetBlob(cnnNet.getOutputsInfo().begin()->first, inputBlob)); + std::shared_ptr actualBlob; + ASSERT_NO_THROW(actualBlob = req.GetBlob(cnnNet.getOutputsInfo().begin()->first)); + ASSERT_EQ(inputBlob.get(), actualBlob.get()); + + ASSERT_TRUE(actualBlob); + ASSERT_FALSE(actualBlob->buffer() == nullptr); + ASSERT_EQ(inputBlob.get(), actualBlob.get()); + + ASSERT_TRUE(cnnNet.getOutputsInfo().begin()->second->getTensorDesc() == actualBlob->getTensorDesc()); +} + +TEST_P(InferRequestIOBBlobTest, failToSetBlobWithIncorrectName) { + // Create InferRequest + InferenceEngine::InferRequest req; + const char incorrect_input_name[] = "incorrect_input_name"; + ASSERT_NO_THROW(req = execNet.CreateInferRequest()); + InferenceEngine::Blob::Ptr blob = + FuncTestUtils::createAndFillBlob(cnnNet.getInputsInfo().begin()->second->getTensorDesc()); + blob->allocate(); + ASSERT_THROW(req.SetBlob(incorrect_input_name, blob), InferenceEngine::Exception); +} + +TEST_P(InferRequestIOBBlobTest, failToSetInputWithIncorrectSizes) { + // Create InferRequest + InferenceEngine::InferRequest req; + ASSERT_NO_THROW(req = execNet.CreateInferRequest()); + InferenceEngine::Blob::Ptr blob = + FuncTestUtils::createAndFillBlob(cnnNet.getInputsInfo().begin()->second->getTensorDesc()); + blob->allocate(); + blob->getTensorDesc().getDims()[0] *= 2; + ASSERT_THROW(req.SetBlob(cnnNet.getInputsInfo().begin()->first, blob), InferenceEngine::Exception); +} + +TEST_P(InferRequestIOBBlobTest, failToSetOutputWithIncorrectSizes) { + // Create InferRequest + InferenceEngine::InferRequest req; + ASSERT_NO_THROW(req = execNet.CreateInferRequest()); + InferenceEngine::Blob::Ptr blob = + FuncTestUtils::createAndFillBlob(cnnNet.getOutputsInfo().begin()->second->getTensorDesc()); + blob->allocate(); + blob->getTensorDesc().getDims()[0] *= 2; + ASSERT_THROW(req.SetBlob(cnnNet.getOutputsInfo().begin()->first, blob), InferenceEngine::Exception); +} + +TEST_P(InferRequestIOBBlobTest, canInferWithoutSetAndGetInOutSync) { + // Create InferRequest + InferenceEngine::InferRequest req; + ASSERT_NO_THROW(req = execNet.CreateInferRequest()); + ASSERT_NO_THROW(req.Infer()); +} + +TEST_P(InferRequestIOBBlobTest, canInferWithoutSetAndGetInOutAsync) { + // Create InferRequest + InferenceEngine::InferRequest req; + ASSERT_NO_THROW(req = execNet.CreateInferRequest()); + ASSERT_NO_THROW(req.StartAsync()); +} + +TEST_P(InferRequestIOBBlobTest, canProcessDeallocatedInputBlobAfterGetBlob) { + // Create InferRequest + InferenceEngine::InferRequest req; + InferenceEngine::Blob::Ptr blob; + ASSERT_NO_THROW(req = execNet.CreateInferRequest()); + ASSERT_NO_THROW(blob = req.GetBlob(cnnNet.getInputsInfo().begin()->first)); + ASSERT_NO_THROW(req.Infer()); + ASSERT_NO_THROW(req.StartAsync()); +} + +TEST_P(InferRequestIOBBlobTest, canProcessDeallocatedInputBlobAfterGetAndSetBlob) { + // Create InferRequest + InferenceEngine::InferRequest req; + InferenceEngine::Blob::Ptr blob; + ASSERT_NO_THROW(req = execNet.CreateInferRequest()); + ASSERT_NO_THROW(blob = req.GetBlob(cnnNet.getInputsInfo().begin()->first)); + ASSERT_NO_THROW(req.SetBlob(cnnNet.getInputsInfo().begin()->first, blob)); + ASSERT_NO_THROW(req.Infer()); + ASSERT_NO_THROW(req.StartAsync()); +} + +TEST_P(InferRequestIOBBlobTest, canProcessDeallocatedInputBlobAfterSetBlobSync) { + // Create InferRequest + InferenceEngine::InferRequest req; + InferenceEngine::Blob::Ptr blob = + FuncTestUtils::createAndFillBlob(cnnNet.getInputsInfo().begin()->second->getTensorDesc()); + ASSERT_NO_THROW(req = execNet.CreateInferRequest()); + blob->allocate(); + ASSERT_NO_THROW(req.SetBlob(cnnNet.getInputsInfo().begin()->first, blob)); + blob->deallocate(); + ASSERT_THROW(req.Infer(), InferenceEngine::Exception); +} + +TEST_P(InferRequestIOBBlobTest, canProcessDeallocatedInputBlobAfterSetBlobAsync) { + // Create InferRequest + InferenceEngine::InferRequest req; + InferenceEngine::Blob::Ptr blob = + FuncTestUtils::createAndFillBlob(cnnNet.getInputsInfo().begin()->second->getTensorDesc()); + ASSERT_NO_THROW(req = execNet.CreateInferRequest()); + blob->allocate(); + ASSERT_NO_THROW(req.SetBlob(cnnNet.getInputsInfo().begin()->first, blob)); + blob->deallocate(); + ASSERT_THROW({ req.StartAsync(); req.Wait(); }, InferenceEngine::Exception); +} + +TEST_P(InferRequestIOBBlobTest, canProcessDeallocatedOutputBlobAfterSetBlob) { + // Create InferRequest + InferenceEngine::InferRequest req; + InferenceEngine::Blob::Ptr blob = + FuncTestUtils::createAndFillBlob(cnnNet.getOutputsInfo().begin()->second->getTensorDesc()); + ASSERT_NO_THROW(req = execNet.CreateInferRequest()); + blob->allocate(); + ASSERT_NO_THROW(req.SetBlob(cnnNet.getOutputsInfo().begin()->first, blob)); + blob->deallocate(); + ASSERT_THROW(req.Infer(), InferenceEngine::Exception); + ASSERT_THROW({ req.StartAsync(); req.Wait(); }, InferenceEngine::Exception); +} + +TEST_P(InferRequestIOBBlobTest, canProcessDeallocatedOutputBlobAfterGetAndSetBlob) { + // Create InferRequest + InferenceEngine::InferRequest req; + InferenceEngine::Blob::Ptr blob = + FuncTestUtils::createAndFillBlob(cnnNet.getOutputsInfo().begin()->second->getTensorDesc()); + ASSERT_NO_THROW(req = execNet.CreateInferRequest()); + blob->allocate(); + ASSERT_NO_THROW(blob = req.GetBlob(cnnNet.getOutputsInfo().begin()->first)); + ASSERT_NO_THROW(req.SetBlob(cnnNet.getOutputsInfo().begin()->first, blob)); + blob->deallocate(); + ASSERT_THROW(req.Infer(), InferenceEngine::Exception); + ASSERT_THROW({ req.StartAsync(); req.Wait(); }, InferenceEngine::Exception); +} + +TEST_P(InferRequestIOBBlobTest, secondCallGetInputDoNotReAllocateData) { + // Create InferRequest + InferenceEngine::InferRequest req; + InferenceEngine::Blob::Ptr blob1, blob2; + ASSERT_NO_THROW(req = execNet.CreateInferRequest()); + ASSERT_NO_THROW(blob1 = req.GetBlob(cnnNet.getInputsInfo().begin()->first)); + ASSERT_NO_THROW(blob2 = req.GetBlob(cnnNet.getInputsInfo().begin()->first)); + ASSERT_EQ(blob1.get(), blob2.get()); +} + +TEST_P(InferRequestIOBBlobTest, secondCallGetOutputDoNotReAllocateData) { + // Create InferRequest + InferenceEngine::InferRequest req; + InferenceEngine::Blob::Ptr blob1, blob2; + ASSERT_NO_THROW(req = execNet.CreateInferRequest()); + ASSERT_NO_THROW(blob1 = req.GetBlob(cnnNet.getOutputsInfo().begin()->first)); + ASSERT_NO_THROW(blob2 = req.GetBlob(cnnNet.getOutputsInfo().begin()->first)); + ASSERT_EQ(blob1.get(), blob2.get()); +} + +TEST_P(InferRequestIOBBlobTest, secondCallGetInputAfterInferSync) { + // Create InferRequest + InferenceEngine::InferRequest req; + InferenceEngine::Blob::Ptr blob1, blob2; + ASSERT_NO_THROW(req = execNet.CreateInferRequest()); + ASSERT_NO_THROW(req.Infer()); + ASSERT_NO_THROW({ req.StartAsync(); req.Wait(); }); + ASSERT_NO_THROW(blob1 = req.GetBlob(cnnNet.getInputsInfo().begin()->first)); + ASSERT_NO_THROW(blob2 = req.GetBlob(cnnNet.getInputsInfo().begin()->first)); + ASSERT_EQ(blob1.get(), blob2.get()); +} + +TEST_P(InferRequestIOBBlobTest, secondCallGetOutputAfterInferSync) { + // Create InferRequest + InferenceEngine::InferRequest req; + InferenceEngine::Blob::Ptr blob1, blob2; + ASSERT_NO_THROW(req = execNet.CreateInferRequest()); + ASSERT_NO_THROW(req.Infer()); + ASSERT_NO_THROW({ req.StartAsync(); req.Wait(); }); + ASSERT_NO_THROW(blob1 = req.GetBlob(cnnNet.getOutputsInfo().begin()->first)); + ASSERT_NO_THROW(blob2 = req.GetBlob(cnnNet.getOutputsInfo().begin()->first)); + ASSERT_EQ(blob1.get(), blob2.get()); +} + +TEST_P(InferRequestIOBBlobTest, canSetInputBlobForInferRequest) { + // Create InferRequest + InferenceEngine::InferRequest req; + ASSERT_NO_THROW(req = execNet.CreateInferRequest()); + InferenceEngine::Blob::Ptr inputBlob = + FuncTestUtils::createAndFillBlob(cnnNet.getInputsInfo().begin()->second->getTensorDesc()); + ASSERT_NO_THROW(req.SetBlob(cnnNet.getInputsInfo().begin()->first, inputBlob)); + InferenceEngine::Blob::Ptr actualBlob; + ASSERT_NO_THROW(actualBlob = req.GetBlob(cnnNet.getInputsInfo().begin()->first)); + ASSERT_EQ(inputBlob, actualBlob); +} + +TEST_P(InferRequestIOBBlobTest, canSetOutputBlobForInferRequest) { + // Create InferRequest + InferenceEngine::InferRequest req = execNet.CreateInferRequest(); + std::shared_ptr outputBlob = FuncTestUtils::createAndFillBlob( + cnnNet.getOutputsInfo().begin()->second->getTensorDesc()); + ASSERT_NO_THROW(req.SetBlob(cnnNet.getOutputsInfo().begin()->first, outputBlob)); + std::shared_ptr actualBlob; + ASSERT_NO_THROW(actualBlob = req.GetBlob(cnnNet.getOutputsInfo().begin()->first)); + ASSERT_EQ(outputBlob.get(), actualBlob.get()); +} + +TEST_P(InferRequestIOBBlobTest, canInferWithSetInOutBlobs) { + // Create InferRequest + InferenceEngine::InferRequest req; + ASSERT_NO_THROW(req = execNet.CreateInferRequest()); + InferenceEngine::Blob::Ptr inputBlob = + FuncTestUtils::createAndFillBlob(cnnNet.getInputsInfo().begin()->second->getTensorDesc()); + req.SetBlob(cnnNet.getInputsInfo().begin()->first, inputBlob); + InferenceEngine::Blob::Ptr outputBlob = + FuncTestUtils::createAndFillBlob(cnnNet.getInputsInfo().begin()->second->getTensorDesc()); + req.SetBlob(cnnNet.getInputsInfo().begin()->first, outputBlob); + ASSERT_NO_THROW(req.Infer()); +} + +TEST_P(InferRequestIOBBlobTest, canInferWithGetIn) { + // Create InferRequest + InferenceEngine::InferRequest req; + ASSERT_NO_THROW(req = execNet.CreateInferRequest()); + InferenceEngine::Blob::Ptr inputBlob = req.GetBlob(cnnNet.getInputsInfo().begin()->first); + ASSERT_NO_THROW(req.Infer()); + InferenceEngine::StatusCode sts; + ASSERT_NO_THROW({ req.StartAsync(); sts = req.Wait(InferenceEngine::InferRequest::WaitMode::RESULT_READY); }); + ASSERT_EQ(InferenceEngine::StatusCode::OK, sts); + ASSERT_NO_THROW(InferenceEngine::Blob::Ptr outputBlob = req.GetBlob(cnnNet.getOutputsInfo().begin()->first)); +} + +TEST_P(InferRequestIOBBlobTest, canInferWithGetOut) { + // Create InferRequest + InferenceEngine::InferRequest req; + ASSERT_NO_THROW(req = execNet.CreateInferRequest()); + InferenceEngine::Blob::Ptr inputBlob = req.GetBlob(cnnNet.getOutputsInfo().begin()->first); + ASSERT_NO_THROW(req.Infer()); + InferenceEngine::StatusCode sts; + ASSERT_NO_THROW({ req.StartAsync(); sts = req.Wait(InferenceEngine::InferRequest::WaitMode::RESULT_READY); }); + ASSERT_EQ(InferenceEngine::StatusCode::OK, sts); + ASSERT_NO_THROW(InferenceEngine::Blob::Ptr outputBlob = req.GetBlob(cnnNet.getOutputsInfo().begin()->first)); +} + +TEST_P(InferRequestIOBBlobTest, OutOfFirstOutIsInputForSecondNetwork) { + auto params = ngraph::builder::makeParams(function->get_results().front()->get_element_type(), + {function->get_results().front()->get_shape()}); + + auto const1 = ngraph::opset1::Constant::create(function->get_results().front()->get_element_type(), + ngraph::Shape{1}, + {1}); + auto const2 = ngraph::opset1::Constant::create(ngraph::element::i64, + ngraph::Shape{function->get_results().front()->get_shape().size()}, + function->get_results().front()->get_shape()); + auto broadcast = std::make_shared(const1, const2); + auto add = std::make_shared(params.front(), broadcast); + ngraph::ResultVector results{std::make_shared(add)}; + std::shared_ptr secondFunction = std::make_shared(results, params); + + InferenceEngine::CNNNetwork secondCNNNetwork(secondFunction); + InferenceEngine::ExecutableNetwork secondExecNetwork = ie->LoadNetwork(secondCNNNetwork, targetDevice, configuration); + auto req1 = execNet.CreateInferRequest(); + auto req2 = secondExecNetwork.CreateInferRequest(); + auto outBlob = req1.GetBlob(cnnNet.getOutputsInfo().begin()->first); + auto inBlob = req2.GetBlob(secondCNNNetwork.getInputsInfo().begin()->first); + ASSERT_EQ(&outBlob, &inBlob); +} + +class InferRequestIOBBlobSetPrecisionTest : public BehaviorTestsUtils::BehaviorTestsBasic { +public: + void SetUp() override { + SKIP_IF_CURRENT_TEST_IS_DISABLED() + std::tie(netPrecision, targetDevice, configuration) = this->GetParam(); + function = ngraph::builder::subgraph::makeConvPoolRelu(); + cnnNet = InferenceEngine::CNNNetwork(function); + execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); + } +protected: + InferenceEngine::ExecutableNetwork execNet; + InferenceEngine::CNNNetwork cnnNet; +}; + + +TEST_P(InferRequestIOBBlobSetPrecisionTest, CanSetInBlobWithDifferentPrecision) { + // Create InferRequest + InferenceEngine::InferRequest req; + ASSERT_NO_THROW(req = execNet.CreateInferRequest()); + for (auto& outputInfo : cnnNet.getOutputsInfo()) { + InferenceEngine::TensorDesc td(netPrecision, outputInfo.second->getTensorDesc().getDims(), outputInfo.second->getTensorDesc().getLayout()); + InferenceEngine::Blob::Ptr blob = FuncTestUtils::createAndFillBlob(td); + if (outputInfo.second->getTensorDesc().getPrecision() == netPrecision) { + ASSERT_NO_THROW(req.SetBlob(outputInfo.first, blob)); + } else { + ASSERT_THROW(req.SetBlob(outputInfo.first, blob), InferenceEngine::Exception); + } + } +} + +TEST_P(InferRequestIOBBlobSetPrecisionTest, CanSetOutBlobWithDifferentPrecision) { + // Create InferRequest + InferenceEngine::InferRequest req; + ASSERT_NO_THROW(req = execNet.CreateInferRequest()); + + for (auto& inputInfo : cnnNet.getInputsInfo()) { + InferenceEngine::TensorDesc td(netPrecision, inputInfo.second->getTensorDesc().getDims(), inputInfo.second->getTensorDesc().getLayout()); + InferenceEngine::Blob::Ptr blob = FuncTestUtils::createAndFillBlob(td); + if (inputInfo.second->getTensorDesc().getPrecision() == netPrecision) { + ASSERT_NO_THROW(req.SetBlob(inputInfo.first, blob)); + } else { + ASSERT_THROW(req.SetBlob(inputInfo.first, blob), InferenceEngine::Exception); + } + } +} + +typedef std::tuple< + InferenceEngine::Layout, // Network precision + std::string, // Device name + std::map // Config +> InferRequestIOBBlobSetLayoutParams; + +class InferRequestIOBBlobSetLayoutTest : public testing::WithParamInterface, + public CommonTestUtils::TestsCommon { +public: + static std::string getTestCaseName(testing::TestParamInfo obj) { + InferenceEngine::Layout layout; + std::string targetDevice; + std::map configuration; + std::tie(layout, targetDevice, configuration) = obj.param; + std::ostringstream result; + result << "layout=" << layout << "_"; + result << "targetDevice=" << targetDevice << "_"; + if (!configuration.empty()) { + result << "config=" << configuration; + } + return result.str(); + } + + void SetUp() override { + SKIP_IF_CURRENT_TEST_IS_DISABLED() + std::tie(layout, targetDevice, configuration) = this->GetParam(); + function = ngraph::builder::subgraph::makeConvPoolRelu(); + cnnNet = InferenceEngine::CNNNetwork(function); + execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); + } + + void TearDown() override { + if (!configuration.empty()) { + PluginCache::get().reset(); + } + function.reset(); + } + + std::shared_ptr ie = PluginCache::get().ie(); + std::shared_ptr function; + InferenceEngine::Layout layout; + InferenceEngine::CNNNetwork cnnNet; + InferenceEngine::ExecutableNetwork execNet; + std::string targetDevice; + std::map configuration; +}; + +TEST_P(InferRequestIOBBlobSetLayoutTest, CanSetInBlobWithDifferentLayouts) { + // Create InferRequest + InferenceEngine::InferRequest req; + ASSERT_NO_THROW(req = execNet.CreateInferRequest()); + + for (auto& inputInfo : cnnNet.getInputsInfo()) { + InferenceEngine::TensorDesc td; + InferenceEngine::Blob::Ptr blob; + if (FuncTestUtils::checkLayout(layout, inputInfo.second->getTensorDesc().getDims())) { + ASSERT_NO_THROW(td = InferenceEngine::TensorDesc(inputInfo.second->getTensorDesc().getPrecision(), + inputInfo.second->getTensorDesc().getDims(), layout)); + ASSERT_NO_THROW(blob = FuncTestUtils::createAndFillBlob(td)); + if (inputInfo.second->getLayout() == layout || layout == InferenceEngine::Layout::ANY || + layout == InferenceEngine::Layout::BLOCKED || layout == InferenceEngine::Layout::SCALAR) { + ASSERT_NO_THROW(req.SetBlob(inputInfo.first, blob)); + } else { + ASSERT_ANY_THROW(req.SetBlob(inputInfo.first, blob)); + } + } else { + ASSERT_THROW(td = InferenceEngine::TensorDesc(inputInfo.second->getTensorDesc().getPrecision(), + inputInfo.second->getTensorDesc().getDims(), layout), InferenceEngine::Exception); + ASSERT_THROW(blob = FuncTestUtils::createAndFillBlob(td), InferenceEngine::Exception); + } + } +} + +TEST_P(InferRequestIOBBlobSetLayoutTest, CanSetOutBlobWithDifferentLayouts) { + // Create InferRequest + InferenceEngine::InferRequest req; + ASSERT_NO_THROW(req = execNet.CreateInferRequest()); + for (auto& outputInfo : cnnNet.getOutputsInfo()) { + InferenceEngine::TensorDesc td; + InferenceEngine::Blob::Ptr blob; + if (FuncTestUtils::checkLayout(layout, outputInfo.second->getTensorDesc().getDims())) { + ASSERT_NO_THROW(td = InferenceEngine::TensorDesc(outputInfo.second->getTensorDesc().getPrecision(), + outputInfo.second->getTensorDesc().getDims(), layout)); + ASSERT_NO_THROW(blob = FuncTestUtils::createAndFillBlob(td)); + if (outputInfo.second->getLayout() == layout || layout == InferenceEngine::Layout::ANY || + layout == InferenceEngine::Layout::BLOCKED || layout == InferenceEngine::Layout::SCALAR) { + ASSERT_NO_THROW(req.SetBlob(outputInfo.first, blob)); + } else { + ASSERT_ANY_THROW(req.SetBlob(outputInfo.first, blob)); + } + } else { + ASSERT_THROW(td = InferenceEngine::TensorDesc(outputInfo.second->getTensorDesc().getPrecision(), + outputInfo.second->getTensorDesc().getDims(), layout), InferenceEngine::Exception); + ASSERT_THROW(blob = FuncTestUtils::createAndFillBlob(td), InferenceEngine::Exception); + } + } +} + +} // namespace BehaviorTestsDefinitions diff --git a/inference-engine/tests/functional/plugin/shared/include/behavior/memory_states.hpp b/inference-engine/tests/functional/plugin/shared/include/behavior/infer_request/memory_states.hpp similarity index 72% rename from inference-engine/tests/functional/plugin/shared/include/behavior/memory_states.hpp rename to inference-engine/tests/functional/plugin/shared/include/behavior/infer_request/memory_states.hpp index 6c8c26ed41f..55fd730a0c0 100644 --- a/inference-engine/tests/functional/plugin/shared/include/behavior/memory_states.hpp +++ b/inference-engine/tests/functional/plugin/shared/include/behavior/infer_request/memory_states.hpp @@ -8,21 +8,25 @@ #include "common_test_utils/test_common.hpp" #include +namespace BehaviorTestsDefinitions { typedef std::tuple< InferenceEngine::CNNNetwork, // CNNNetwork to work with std::vector, // Memory States to query std::string> // Target device name - memoryStateParams; +memoryStateParams; -class VariableStateTest : public CommonTestUtils::TestsCommon, - public testing::WithParamInterface { +class InferRequestVariableStateTest : public CommonTestUtils::TestsCommon, + public testing::WithParamInterface { protected: InferenceEngine::CNNNetwork net; std::vector statesToQuery; std::string deviceName; void SetUp() override; + InferenceEngine::ExecutableNetwork PrepareNetwork(); + public: static std::string getTestCaseName(const testing::TestParamInfo &obj); }; +} // namespace BehaviorTestsDefinitions diff --git a/inference-engine/tests/functional/plugin/shared/include/behavior/infer_request/multithreading.hpp b/inference-engine/tests/functional/plugin/shared/include/behavior/infer_request/multithreading.hpp new file mode 100644 index 00000000000..4ce01c2dea7 --- /dev/null +++ b/inference-engine/tests/functional/plugin/shared/include/behavior/infer_request/multithreading.hpp @@ -0,0 +1,78 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +#include + +#include "base/behavior_test_utils.hpp" + +namespace BehaviorTestsDefinitions { +using InferRequestMultithreadingTests = BehaviorTestsUtils::InferRequestTests; + +TEST_P(InferRequestMultithreadingTests, canRun3SyncRequestsConsistentlyFromThreads) { + // Create InferRequest + auto req1 = execNet.CreateInferRequest(); + auto req2 = execNet.CreateInferRequest(); + auto req3 = execNet.CreateInferRequest(); + + + auto f1 = std::async(std::launch::async, [&] { req1.Infer(); }); + auto f2 = std::async(std::launch::async, [&] { req2.Infer(); }); + auto f3 = std::async(std::launch::async, [&] { req3.Infer(); }); + + ASSERT_NO_THROW(f1.get()); + ASSERT_NO_THROW(f2.get()); + ASSERT_NO_THROW(f3.get()); +} + +TEST_P(InferRequestMultithreadingTests, canRun3AsyncRequestsConsistentlyFromThreadsWithoutWait) { + // Create InferRequest + auto req1 = execNet.CreateInferRequest(); + auto req2 = execNet.CreateInferRequest(); + auto req3 = execNet.CreateInferRequest(); + InferenceEngine::StatusCode sts1, sts2, sts3; + + req1.Infer(); + req2.Infer(); + req3.Infer(); + + std::thread t1([&] { + req1.StartAsync(); + sts1 = req1.Wait(InferenceEngine::InferRequest::WaitMode::RESULT_READY); + }); + std::thread t2([&] { + req2.StartAsync(); + sts2 = req2.Wait(InferenceEngine::InferRequest::WaitMode::RESULT_READY); + }); + std::thread t3([&] { + req3.StartAsync(); + sts3 = req3.Wait(InferenceEngine::InferRequest::WaitMode::RESULT_READY); + }); + + t1.join(); + t2.join(); + t3.join(); + + ASSERT_EQ(InferenceEngine::StatusCode::OK, sts1); + ASSERT_EQ(InferenceEngine::StatusCode::OK, sts2); + ASSERT_EQ(InferenceEngine::StatusCode::OK, sts3); +} + +TEST_P(InferRequestMultithreadingTests, canRun3AsyncRequestsConsistentlyWithWait) { + // Create InferRequest + auto req1 = execNet.CreateInferRequest(); + auto req2 = execNet.CreateInferRequest(); + auto req3 = execNet.CreateInferRequest(); + + req1.StartAsync(); + ASSERT_NO_THROW(req1.Wait(InferenceEngine::InferRequest::WaitMode::RESULT_READY)); + + req2.Infer(); + ASSERT_NO_THROW(req2.Wait(InferenceEngine::InferRequest::WaitMode::RESULT_READY)); + + req3.Infer(); + ASSERT_NO_THROW(req3.Wait(InferenceEngine::InferRequest::WaitMode::RESULT_READY)); +} +} // namespace BehaviorTestsDefinitions diff --git a/inference-engine/tests/functional/plugin/shared/include/behavior/infer_request/perf_counters.hpp b/inference-engine/tests/functional/plugin/shared/include/behavior/infer_request/perf_counters.hpp new file mode 100644 index 00000000000..f7c36dd0753 --- /dev/null +++ b/inference-engine/tests/functional/plugin/shared/include/behavior/infer_request/perf_counters.hpp @@ -0,0 +1,50 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +#include "base/behavior_test_utils.hpp" + +namespace BehaviorTestsDefinitions { +class InferRequestPerfCountersTest : public BehaviorTestsUtils::InferRequestTests { +public: + void SetUp() override { + // Skip test according to plugin specific disabledTestPatterns() (if any) + SKIP_IF_CURRENT_TEST_IS_DISABLED() + std::tie(targetDevice, configuration) = this->GetParam(); + function = ngraph::builder::subgraph::makeConvPoolRelu(); + cnnNet = InferenceEngine::CNNNetwork(function); + configuration.insert({ InferenceEngine::PluginConfigParams::KEY_PERF_COUNT, InferenceEngine::PluginConfigParams::YES }); + // Load CNNNetwork to target plugins + execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); + } +}; + +TEST_P(InferRequestPerfCountersTest, NotEmptyAfterAsyncInfer) { + // Create InferRequest + auto req = execNet.CreateInferRequest(); + auto outputBlob = req.GetBlob(cnnNet.getInputsInfo().begin()->first); + InferenceEngine::StatusCode sts; + req.StartAsync(); + sts = req.Wait(InferenceEngine::InferRequest::WaitMode::RESULT_READY); + ASSERT_EQ(InferenceEngine::StatusCode::OK, sts); + + std::map perfMap; + ASSERT_NO_THROW(perfMap = req.GetPerformanceCounts()); + ASSERT_NE(perfMap.size(), 0); +} + +TEST_P(InferRequestPerfCountersTest, NotEmptyAfterSyncInfer) { + InferenceEngine::CNNNetwork cnnNet(function); + // Create InferRequest + InferenceEngine::InferRequest req; + ASSERT_NO_FATAL_FAILURE(req = execNet.CreateInferRequest()); + ASSERT_NO_THROW(req.Infer()); + + std::map perfMap; + ASSERT_NO_THROW(perfMap = req.GetPerformanceCounts()); + ASSERT_NE(perfMap.size(), 0); +} + +} // namespace BehaviorTestsDefinitions \ No newline at end of file diff --git a/inference-engine/tests/functional/plugin/shared/include/behavior/infer_request/set_blob_by_type.hpp b/inference-engine/tests/functional/plugin/shared/include/behavior/infer_request/set_blob_by_type.hpp new file mode 100644 index 00000000000..e6162428730 --- /dev/null +++ b/inference-engine/tests/functional/plugin/shared/include/behavior/infer_request/set_blob_by_type.hpp @@ -0,0 +1,94 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +#include + +#include "base/behavior_test_utils.hpp" +#include "common_test_utils/common_utils.hpp" + +namespace BehaviorTestsDefinitions { +using namespace CommonTestUtils; + +using InferRequestSetBlobByTypeParams = std::tuple< + FuncTestUtils::BlobType, // Blob type + std::string, // Device name + std::map // Device config +>; + +class InferRequestSetBlobByType : public testing::WithParamInterface, + public CommonTestUtils::TestsCommon { +public: + static std::string getTestCaseName(testing::TestParamInfo obj) { + FuncTestUtils::BlobType BlobType; + std::string targetDevice; + std::map configuration; + std::tie(BlobType, targetDevice, configuration) = obj.param; + + std::ostringstream result; + result << "BlobType=" << BlobType << "_"; + result << "Device="<< targetDevice << "_"; + result << "Config=" << configuration; + return result.str(); + } + + void SetUp() override { + // Skip test according to plugin specific disabledTestPatterns() (if any) + SKIP_IF_CURRENT_TEST_IS_DISABLED() + std::map config; + std::tie(blobType, targetDevice, config) = this->GetParam(); + std::shared_ptr function = ngraph::builder::subgraph::makeConvPoolRelu( + {4, 3, 6, 8}, ngraph::element::Type_t::u8); + InferenceEngine::CNNNetwork cnnNetwork(function); + executableNetwork = ie->LoadNetwork(cnnNetwork, targetDevice, config); + } + +protected: + bool blobTypeIsSupportedByDevice() { + switch (blobType) { + case FuncTestUtils::BlobType::Memory: + return true; + case FuncTestUtils::BlobType::Compound: + case FuncTestUtils::BlobType::I420: +// case FuncTestUtils::BlobType::Remote: + case FuncTestUtils::BlobType::NV12: + return false; + case FuncTestUtils::BlobType::Batched: { + const std::vector& supported_metrics = ie->GetMetric(targetDevice, METRIC_KEY(SUPPORTED_METRICS)); + if (std::find(supported_metrics.begin(), supported_metrics.end(), + METRIC_KEY(OPTIMIZATION_CAPABILITIES)) == supported_metrics.end()) { + return false; + } + + const std::vector& optimization_caps = + ie->GetMetric(targetDevice, METRIC_KEY(OPTIMIZATION_CAPABILITIES)); + return std::find(optimization_caps.begin(), optimization_caps.end(), + METRIC_VALUE(BATCHED_BLOB)) != optimization_caps.end(); + } + default: + IE_THROW() << "Test does not support the blob kind"; + } + } + + std::string targetDevice; + FuncTestUtils::BlobType blobType; + InferenceEngine::ExecutableNetwork executableNetwork; + std::shared_ptr ie = PluginCache::get().ie(); +}; + +TEST_P(InferRequestSetBlobByType, setInputBlobsByType) { + // Create InferRequest + auto req = executableNetwork.CreateInferRequest(); + for (const auto &input : executableNetwork.GetInputsInfo()) { + const auto &info = input.second; + auto blob = FuncTestUtils::createBlobByType(info->getTensorDesc(), blobType); + if (blobTypeIsSupportedByDevice()) { + EXPECT_NO_THROW(req.SetBlob(info->name(), blob)); + } else { + EXPECT_THROW(req.SetBlob(info->name(), blob), InferenceEngine::Exception); + } + } +} +} // namespace BehaviorTestsDefinitions diff --git a/inference-engine/tests/functional/plugin/shared/include/behavior/infer_request/wait.hpp b/inference-engine/tests/functional/plugin/shared/include/behavior/infer_request/wait.hpp new file mode 100644 index 00000000000..1f4bce61573 --- /dev/null +++ b/inference-engine/tests/functional/plugin/shared/include/behavior/infer_request/wait.hpp @@ -0,0 +1,103 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +#include "base/behavior_test_utils.hpp" + +namespace BehaviorTestsDefinitions { +using InferRequestWaitTests = BehaviorTestsUtils::InferRequestTests; + +TEST_P(InferRequestWaitTests, CorrectOneAsyncInferWithGetInOutWithInfWait) { + // Create InferRequest + InferenceEngine::InferRequest req; + InferenceEngine::Blob::Ptr blob = + FuncTestUtils::createAndFillBlob(cnnNet.getOutputsInfo().begin()->second->getTensorDesc()); + ASSERT_NO_THROW(req = execNet.CreateInferRequest()); + ASSERT_NO_THROW(blob = req.GetBlob(cnnNet.getInputsInfo().begin()->first)); + req.Infer(); + req.StartAsync(); + InferenceEngine::StatusCode sts; + sts = req.Wait(InferenceEngine::InferRequest::WaitMode::RESULT_READY); + ASSERT_EQ(InferenceEngine::StatusCode::OK, sts); + ASSERT_NO_THROW(blob = req.GetBlob(cnnNet.getOutputsInfo().begin()->first)); +} + +// Plugin correct infer request with allocating input and result BlobMaps inside plugin +TEST_P(InferRequestWaitTests, canStartAsyncInferWithGetInOutWithStatusOnlyWait) { + // Create InferRequest + InferenceEngine::InferRequest req; + InferenceEngine::Blob::Ptr blob = + FuncTestUtils::createAndFillBlob(cnnNet.getOutputsInfo().begin()->second->getTensorDesc()); + ASSERT_NO_THROW(req = execNet.CreateInferRequest()); + ASSERT_NO_THROW(blob = req.GetBlob(cnnNet.getInputsInfo().begin()->first)); + req.Infer(); + req.StartAsync(); + InferenceEngine::StatusCode sts; + sts = req.Wait(InferenceEngine::InferRequest::WaitMode::STATUS_ONLY); + ASSERT_TRUE(sts == InferenceEngine::StatusCode::OK || sts == InferenceEngine::StatusCode::RESULT_NOT_READY); +} + +// Plugin correct infer request with allocating input and result BlobMaps inside plugin +TEST_P(InferRequestWaitTests, FailedAsyncInferWithNegativeTimeForWait) { + // Create InferRequest + InferenceEngine::InferRequest req; + InferenceEngine::Blob::Ptr blob = + FuncTestUtils::createAndFillBlob(cnnNet.getOutputsInfo().begin()->second->getTensorDesc()); + ASSERT_NO_THROW(req = execNet.CreateInferRequest()); + ASSERT_NO_THROW(blob = req.GetBlob(cnnNet.getInputsInfo().begin()->first)); + req.Infer(); + req.StartAsync(); + ASSERT_THROW(req.Wait(-2), InferenceEngine::Exception); +} + +TEST_P(InferRequestWaitTests, canWaitWithotStartAsync) { + // Create InferRequest + auto req = execNet.CreateInferRequest(); + ASSERT_NO_THROW(req.Wait(InferenceEngine::InferRequest::WaitMode::RESULT_READY)); + ASSERT_NO_THROW(req.Wait(InferenceEngine::InferRequest::WaitMode::STATUS_ONLY)); + ASSERT_NO_THROW(req.Wait(1)); +} + +TEST_P(InferRequestWaitTests, returnDeviceBusyOnSetBlobAfterAsyncInfer) { + auto&& config = configuration; + auto itConfig = config.find(CONFIG_KEY(CPU_THROUGHPUT_STREAMS)); + if (itConfig != config.end()) { + if (itConfig->second != "CPU_THROUGHPUT_AUTO") { + if (std::stoi(itConfig->second) == 0) { + GTEST_SKIP() << "Not applicable with disabled streams"; + } + } + } + + // Create InferRequest + auto req = execNet.CreateInferRequest(); + auto outputBlob = req.GetBlob(cnnNet.getInputsInfo().begin()->first); + InferenceEngine::StatusCode sts; + sts = req.Wait(InferenceEngine::InferRequest::WaitMode::STATUS_ONLY); + ASSERT_EQ(InferenceEngine::StatusCode::INFER_NOT_STARTED, sts); + req.StartAsync(); + sts = req.Wait(InferenceEngine::InferRequest::WaitMode::RESULT_READY); + ASSERT_EQ(InferenceEngine::StatusCode::OK, sts); + try { + req.SetBlob(cnnNet.getInputsInfo().begin()->first, outputBlob); + } catch (const std::exception &e) { + std::cout << "Exception: " << e.what() << std::endl; + } + sts = req.Wait(InferenceEngine::InferRequest::WaitMode::STATUS_ONLY); + ASSERT_TRUE(sts == InferenceEngine::StatusCode::OK || sts == InferenceEngine::StatusCode::RESULT_NOT_READY); +} + +TEST_P(InferRequestWaitTests, returnDeviceBusyOnGetBlobAfterAsyncInfer) { + // Create InferRequest + auto req = execNet.CreateInferRequest(); + auto outputBlob = req.GetBlob(cnnNet.getInputsInfo().begin()->first); + InferenceEngine::StatusCode sts; + req.StartAsync(); + sts = req.Wait(InferenceEngine::InferRequest::WaitMode::RESULT_READY); + ASSERT_EQ(InferenceEngine::StatusCode::OK, sts); + ASSERT_NO_THROW(req.SetBlob(cnnNet.getInputsInfo().begin()->first, outputBlob)); +} + +} // namespace BehaviorTestsDefinitions diff --git a/inference-engine/tests/functional/plugin/shared/include/behavior/infer_request_config.hpp b/inference-engine/tests/functional/plugin/shared/include/behavior/infer_request_config.hpp deleted file mode 100644 index cb364c80f8c..00000000000 --- a/inference-engine/tests/functional/plugin/shared/include/behavior/infer_request_config.hpp +++ /dev/null @@ -1,100 +0,0 @@ -// Copyright (C) 2018-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#pragma once - -#include -#include -#include -#include -#include "ie_extension.h" -#include -#include "shared_test_classes/base/layer_test_utils.hpp" -#include "ngraph_functions/utils/ngraph_helpers.hpp" -#include "ngraph_functions/builders.hpp" -#include -#include -#include -#include -#include -#include "common_test_utils/common_utils.hpp" -#include "functional_test_utils/plugin_cache.hpp" -#include "functional_test_utils/blob_utils.hpp" -#include "ngraph_functions/subgraph_builders.hpp" - -namespace BehaviorTestsDefinitions { -// TODO: rename to SetupInferWithConfigTests -using InferConfigTests = BehaviorTestsUtils::BehaviorTestsBasic; - -TEST_P(InferConfigTests, canSetExclusiveAsyncRequests) { - ASSERT_EQ(0ul, InferenceEngine::ExecutorManager::getInstance()->getExecutorsNumber()); - // Skip test according to plugin specific disabledTestPatterns() (if any) - SKIP_IF_CURRENT_TEST_IS_DISABLED() - // Create CNNNetwork from ngrpah::Function - InferenceEngine::CNNNetwork cnnNet(function); - // Load config - std::map config = {{CONFIG_KEY(EXCLUSIVE_ASYNC_REQUESTS), CONFIG_VALUE(YES)}}; - config.insert(configuration.begin(), configuration.end()); - if (targetDevice.find(CommonTestUtils::DEVICE_AUTO) == std::string::npos && - targetDevice.find(CommonTestUtils::DEVICE_MULTI) == std::string::npos && - targetDevice.find(CommonTestUtils::DEVICE_HETERO) == std::string::npos) { - ASSERT_NO_THROW(ie->SetConfig(config, targetDevice)); - } - // Load CNNNetwork to target plugins - auto execNet = ie->LoadNetwork(cnnNet, targetDevice, config); - execNet.CreateInferRequest(); - - if ((targetDevice == CommonTestUtils::DEVICE_HDDL) || (targetDevice == CommonTestUtils::DEVICE_GNA)) { - ASSERT_EQ(0u, InferenceEngine::ExecutorManager::getInstance()->getExecutorsNumber()); - } else if ((targetDevice == CommonTestUtils::DEVICE_MYRIAD) || - (targetDevice == CommonTestUtils::DEVICE_KEEMBAY)) { - ASSERT_EQ(2u, InferenceEngine::ExecutorManager::getInstance()->getExecutorsNumber()); - } else if ((targetDevice == CommonTestUtils::DEVICE_AUTO) || (targetDevice == CommonTestUtils::DEVICE_MULTI)) { - } else { - ASSERT_EQ(1u, InferenceEngine::ExecutorManager::getInstance()->getExecutorsNumber()); - } -} - -TEST_P(InferConfigTests, withoutExclusiveAsyncRequests) { - ASSERT_EQ(0u, InferenceEngine::ExecutorManager::getInstance()->getExecutorsNumber()); - // Skip test according to plugin specific disabledTestPatterns() (if any) - SKIP_IF_CURRENT_TEST_IS_DISABLED() - // Create CNNNetwork from ngrpah::Function - InferenceEngine::CNNNetwork cnnNet(function); - // Load config - std::map config = {{CONFIG_KEY(EXCLUSIVE_ASYNC_REQUESTS), CONFIG_VALUE(YES)}}; - config.insert(configuration.begin(), configuration.end()); - if (targetDevice.find(CommonTestUtils::DEVICE_AUTO) == std::string::npos && - targetDevice.find(CommonTestUtils::DEVICE_MULTI) == std::string::npos && - targetDevice.find(CommonTestUtils::DEVICE_HETERO) == std::string::npos) { - ASSERT_NO_THROW(ie->SetConfig(config, targetDevice)); - } - // Load CNNNetwork to target plugins - auto execNet = ie->LoadNetwork(cnnNet, targetDevice, config); - execNet.CreateInferRequest(); - - if ((targetDevice == CommonTestUtils::DEVICE_GNA) || (targetDevice == CommonTestUtils::DEVICE_HDDL)) { - ASSERT_EQ(0u, InferenceEngine::ExecutorManager::getInstance()->getExecutorsNumber()); - } else if ((targetDevice == CommonTestUtils::DEVICE_AUTO) || (targetDevice == CommonTestUtils::DEVICE_MULTI)) { - } else if (targetDevice == CommonTestUtils::DEVICE_MYRIAD) { - ASSERT_EQ(2u, InferenceEngine::ExecutorManager::getInstance()->getExecutorsNumber()); - } else { - ASSERT_EQ(1u, InferenceEngine::ExecutorManager::getInstance()->getExecutorsNumber()); - } -} - -// TODO: rename to InferWithConfigTests -using InferConfigInTests = BehaviorTestsUtils::BehaviorTestsBasic; - -TEST_P(InferConfigInTests, CanInferWithConfig) { - // Skip test according to plugin specific disabledTestPatterns() (if any) - SKIP_IF_CURRENT_TEST_IS_DISABLED() - // Create CNNNetwork from ngrpah::Function - InferenceEngine::CNNNetwork cnnNet(function); - // Load CNNNetwork to target plugins - auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); - auto req = execNet.CreateInferRequest(); - ASSERT_NO_THROW(req.Infer()); -} -} // namespace BehaviorTestsDefinitions \ No newline at end of file diff --git a/inference-engine/tests/functional/plugin/shared/include/behavior/infer_request_input.hpp b/inference-engine/tests/functional/plugin/shared/include/behavior/infer_request_input.hpp deleted file mode 100644 index f2414f03e26..00000000000 --- a/inference-engine/tests/functional/plugin/shared/include/behavior/infer_request_input.hpp +++ /dev/null @@ -1,139 +0,0 @@ -// Copyright (C) 2018-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#pragma once - -#include -#include -#include -#include -#include "ie_extension.h" -#include -#include "shared_test_classes/base/layer_test_utils.hpp" -#include "ngraph_functions/utils/ngraph_helpers.hpp" -#include "ngraph_functions/builders.hpp" -#include -#include -#include "common_test_utils/common_utils.hpp" -#include "functional_test_utils/plugin_cache.hpp" -#include "functional_test_utils/blob_utils.hpp" -#include "ngraph_functions/subgraph_builders.hpp" -#include "behavior/infer_request_input.hpp" - -namespace BehaviorTestsDefinitions { -using InferRequestInputTests = BehaviorTestsUtils::BehaviorTestsBasic; - -TEST_P(InferRequestInputTests, canSetInputBlobForSyncRequest) { - // Skip test according to plugin specific disabledTestPatterns() (if any) - SKIP_IF_CURRENT_TEST_IS_DISABLED() - // Create CNNNetwork from ngrpah::Function - InferenceEngine::CNNNetwork cnnNet(function); - // Load CNNNetwork to target plugins - auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); - // Create InferRequest - InferenceEngine::InferRequest req; - ASSERT_NO_THROW(req = execNet.CreateInferRequest()); - InferenceEngine::Blob::Ptr inputBlob = - FuncTestUtils::createAndFillBlob(cnnNet.getInputsInfo().begin()->second->getTensorDesc()); - ASSERT_NO_THROW(req.SetBlob(cnnNet.getInputsInfo().begin()->first, inputBlob)); - InferenceEngine::Blob::Ptr actualBlob; - ASSERT_NO_THROW(actualBlob = req.GetBlob(cnnNet.getInputsInfo().begin()->first)); - ASSERT_EQ(inputBlob, actualBlob); -} - -TEST_P(InferRequestInputTests, canInferWithSetInOut) { - // Skip test according to plugin specific disabledTestPatterns() (if any) - SKIP_IF_CURRENT_TEST_IS_DISABLED() - // Create CNNNetwork from ngrpah::Function - InferenceEngine::CNNNetwork cnnNet(function); - // Load CNNNetwork to target plugins - auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); - // Create InferRequest - InferenceEngine::InferRequest req; - ASSERT_NO_THROW(req = execNet.CreateInferRequest()); - InferenceEngine::Blob::Ptr inputBlob = - FuncTestUtils::createAndFillBlob(cnnNet.getInputsInfo().begin()->second->getTensorDesc()); - req.SetBlob(cnnNet.getInputsInfo().begin()->first, inputBlob); - InferenceEngine::Blob::Ptr outputBlob = - FuncTestUtils::createAndFillBlob(cnnNet.getInputsInfo().begin()->second->getTensorDesc()); - req.SetBlob(cnnNet.getInputsInfo().begin()->first, outputBlob); - ASSERT_NO_THROW(req.Infer()); -} - -TEST_P(InferRequestInputTests, canGetInputBlob_deprecatedAPI) { - // Skip test according to plugin specific disabledTestPatterns() (if any) - SKIP_IF_CURRENT_TEST_IS_DISABLED() - // Create CNNNetwork from ngrpah::Function - InferenceEngine::CNNNetwork cnnNet(function); - // Load CNNNetwork to target plugins - auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); - // Create InferRequest - InferenceEngine::InferRequest req; - ASSERT_NO_THROW(req = execNet.CreateInferRequest()); - std::shared_ptr actualBlob; - - ASSERT_NO_THROW(actualBlob = req.GetBlob(cnnNet.getInputsInfo().begin()->first)); - ASSERT_TRUE(actualBlob) << "Plugin didn't allocate input blobs"; - ASSERT_FALSE(actualBlob->buffer() == nullptr) << "Plugin didn't allocate input blobs"; - - auto tensorDescription = actualBlob->getTensorDesc(); - auto dims = tensorDescription.getDims(); - ASSERT_TRUE(cnnNet.getInputsInfo().begin()->second->getTensorDesc().getDims() == dims) - << "Input blob dimensions don't match network input"; - - ASSERT_EQ(execNet.GetInputsInfo().begin()->second->getPrecision(), tensorDescription.getPrecision()) - << "Input blob precision don't match network input"; -} - -TEST_P(InferRequestInputTests, getAfterSetInputDoNotChangeInput) { - // Skip test according to plugin specific disabledTestPatterns() (if any) - SKIP_IF_CURRENT_TEST_IS_DISABLED() - // Create CNNNetwork from ngrpah::Function - InferenceEngine::CNNNetwork cnnNet(function); - // Load CNNNetwork to target plugins - auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); - // Create InferRequest - InferenceEngine::InferRequest req = execNet.CreateInferRequest(); - std::shared_ptr inputBlob = FuncTestUtils::createAndFillBlob( - cnnNet.getInputsInfo().begin()->second->getTensorDesc()); - ASSERT_NO_THROW(req.SetBlob(cnnNet.getInputsInfo().begin()->first, inputBlob)); - std::shared_ptr actualBlob; - ASSERT_NO_THROW(actualBlob = req.GetBlob(cnnNet.getInputsInfo().begin()->first)); - ASSERT_EQ(inputBlob.get(), actualBlob.get()); -} - -TEST_P(InferRequestInputTests, canInferWithGetInOut) { - // Skip test according to plugin specific disabledTestPatterns() (if any) - SKIP_IF_CURRENT_TEST_IS_DISABLED() - // Create CNNNetwork from ngrpah::Function - InferenceEngine::CNNNetwork cnnNet(function); - // Load CNNNetwork to target plugins - auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); - // Create InferRequest - InferenceEngine::InferRequest req; - ASSERT_NO_THROW(req = execNet.CreateInferRequest()); - InferenceEngine::Blob::Ptr inputBlob = req.GetBlob(cnnNet.getInputsInfo().begin()->first); - InferenceEngine::Blob::Ptr outputBlob = req.GetBlob(cnnNet.getOutputsInfo().begin()->first); - ASSERT_NO_THROW(req.Infer()); -} - -TEST_P(InferRequestInputTests, canStartAsyncInferWithGetInOut) { - // Skip test according to plugin specific disabledTestPatterns() (if any) - SKIP_IF_CURRENT_TEST_IS_DISABLED() - // Create CNNNetwork from ngrpah::Function - InferenceEngine::CNNNetwork cnnNet(function); - // Load CNNNetwork to target plugins - auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); - // Create InferRequest - InferenceEngine::InferRequest req; - ASSERT_NO_THROW(req = execNet.CreateInferRequest()); - InferenceEngine::Blob::Ptr inputBlob = req.GetBlob(cnnNet.getInputsInfo().begin()->first); - InferenceEngine::StatusCode sts; - ASSERT_NO_THROW(req.Infer()); - ASSERT_NO_THROW(req.StartAsync()); - sts = req.Wait(500); - ASSERT_EQ(InferenceEngine::StatusCode::OK, sts); - InferenceEngine::Blob::Ptr outputBlob = req.GetBlob(cnnNet.getOutputsInfo().begin()->first); -} -} // namespace BehaviorTestsDefinitions \ No newline at end of file diff --git a/inference-engine/tests/functional/plugin/shared/include/behavior/infer_request_output.hpp b/inference-engine/tests/functional/plugin/shared/include/behavior/infer_request_output.hpp deleted file mode 100644 index 42d1dbae594..00000000000 --- a/inference-engine/tests/functional/plugin/shared/include/behavior/infer_request_output.hpp +++ /dev/null @@ -1,137 +0,0 @@ -// Copyright (C) 2018-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#pragma once - -#include -#include -#include -#include -#include "ie_extension.h" -#include -#include "shared_test_classes/base/layer_test_utils.hpp" -#include "ngraph_functions/utils/ngraph_helpers.hpp" -#include "ngraph_functions/builders.hpp" -#include -#include -#include "common_test_utils/common_utils.hpp" -#include "functional_test_utils/plugin_cache.hpp" -#include "functional_test_utils/blob_utils.hpp" -#include "ngraph_functions/subgraph_builders.hpp" -#include "behavior/infer_request_output.hpp" - -namespace BehaviorTestsDefinitions { -using InferRequestOutputTests = BehaviorTestsUtils::BehaviorTestsBasic; - -TEST_P(InferRequestOutputTests, canGetInputBlobForSyncRequest) { - // Skip test according to plugin specific disabledTestPatterns() (if any) - SKIP_IF_CURRENT_TEST_IS_DISABLED() - // Create CNNNetwork from ngrpah::Function - InferenceEngine::CNNNetwork cnnNet(function); - // Load CNNNetwork to target plugins - auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); - // Create InferRequest - InferenceEngine::InferRequest req; - ASSERT_NO_THROW(req = execNet.CreateInferRequest()); - InferenceEngine::Blob::Ptr OutputBlob = - FuncTestUtils::createAndFillBlob(cnnNet.getOutputsInfo().begin()->second->getTensorDesc()); - ASSERT_NO_THROW(req.SetBlob(cnnNet.getOutputsInfo().begin()->first, OutputBlob)); - InferenceEngine::Blob::Ptr actualBlob; - ASSERT_NO_THROW(actualBlob = req.GetBlob(cnnNet.getOutputsInfo().begin()->first)); - ASSERT_EQ(OutputBlob, actualBlob); -} - -TEST_P(InferRequestOutputTests, canInferWithSetInOut) { - // Skip test according to plugin specific disabledTestPatterns() (if any) - SKIP_IF_CURRENT_TEST_IS_DISABLED() - // Create CNNNetwork from ngrpah::Function - InferenceEngine::CNNNetwork cnnNet(function); - // Load CNNNetwork to target plugins - auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); - // Create InferRequest - InferenceEngine::InferRequest req; - ASSERT_NO_THROW(req = execNet.CreateInferRequest()); - InferenceEngine::Blob::Ptr inputBlob = - FuncTestUtils::createAndFillBlob(cnnNet.getInputsInfo().begin()->second->getTensorDesc()); - req.SetBlob(cnnNet.getInputsInfo().begin()->first, inputBlob); - InferenceEngine::Blob::Ptr outputBlob = - FuncTestUtils::createAndFillBlob(cnnNet.getInputsInfo().begin()->second->getTensorDesc()); - req.SetBlob(cnnNet.getInputsInfo().begin()->first, outputBlob); - ASSERT_NO_THROW(req.Infer()); -} - -TEST_P(InferRequestOutputTests, canGetOutputBlob_deprecatedAPI) { - // Skip test according to plugin specific disabledTestPatterns() (if any) - SKIP_IF_CURRENT_TEST_IS_DISABLED() - // Create CNNNetwork from ngrpah::Function - InferenceEngine::CNNNetwork cnnNet(function); - // Load CNNNetwork to target plugins - auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); - // Create InferRequest - InferenceEngine::InferRequest req; - ASSERT_NO_THROW(req = execNet.CreateInferRequest()); - std::shared_ptr actualBlob; - - ASSERT_NO_THROW(actualBlob = req.GetBlob(cnnNet.getOutputsInfo().begin()->first)); - ASSERT_TRUE(actualBlob) << "Plugin didn't allocate Output blobs"; - ASSERT_FALSE(actualBlob->buffer() == nullptr) << "Plugin didn't allocate Output blobs"; - - auto tensorDescription = actualBlob->getTensorDesc(); - auto dims = tensorDescription.getDims(); - ASSERT_TRUE(cnnNet.getOutputsInfo().begin()->second->getTensorDesc().getDims() == dims) - << "Output blob dimensions don't match network Output"; - - ASSERT_EQ(execNet.GetInputsInfo().begin()->second->getPrecision(), tensorDescription.getPrecision()) - << "Output blob precision don't match network Output"; -} - -TEST_P(InferRequestOutputTests, getOutputAfterSetOutputDoNotChangeOutput) { - // Skip test according to plugin specific disabledTestPatterns() (if any) - SKIP_IF_CURRENT_TEST_IS_DISABLED() - // Create CNNNetwork from ngrpah::Function - InferenceEngine::CNNNetwork cnnNet(function); - // Load CNNNetwork to target plugins - auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); - // Create InferRequest - InferenceEngine::InferRequest req = execNet.CreateInferRequest(); - std::shared_ptr OutputBlob = FuncTestUtils::createAndFillBlob( - cnnNet.getOutputsInfo().begin()->second->getTensorDesc()); - ASSERT_NO_THROW(req.SetBlob(cnnNet.getOutputsInfo().begin()->first, OutputBlob)); - std::shared_ptr actualBlob; - ASSERT_NO_THROW(actualBlob = req.GetBlob(cnnNet.getOutputsInfo().begin()->first)); - ASSERT_EQ(OutputBlob.get(), actualBlob.get()); -} - -TEST_P(InferRequestOutputTests, canInferWithGetInOut) { - // Skip test according to plugin specific disabledTestPatterns() (if any) - SKIP_IF_CURRENT_TEST_IS_DISABLED() - // Create CNNNetwork from ngrpah::Function - InferenceEngine::CNNNetwork cnnNet(function); - // Load CNNNetwork to target plugins - auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); - // Create InferRequest - InferenceEngine::InferRequest req; - ASSERT_NO_THROW(req = execNet.CreateInferRequest()); - InferenceEngine::Blob::Ptr inputBlob = req.GetBlob(cnnNet.getInputsInfo().begin()->first); - InferenceEngine::Blob::Ptr outputBlob = req.GetBlob(cnnNet.getOutputsInfo().begin()->first); - ASSERT_NO_THROW(req.Infer()); -} - -TEST_P(InferRequestOutputTests, canStartAsyncInferWithGetInOut) { - // Skip test according to plugin specific disabledTestPatterns() (if any) - SKIP_IF_CURRENT_TEST_IS_DISABLED() - // Create CNNNetwork from ngrpah::Function - InferenceEngine::CNNNetwork cnnNet(function); - // Load CNNNetwork to target plugins - auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); - // Create InferRequest - InferenceEngine::InferRequest req; - ASSERT_NO_THROW(req = execNet.CreateInferRequest()); - InferenceEngine::Blob::Ptr inputBlob = req.GetBlob(cnnNet.getInputsInfo().begin()->first); - ASSERT_NO_THROW(req.Infer()); - ASSERT_NO_THROW(req.StartAsync()); - ASSERT_NO_THROW(req.Wait()); - InferenceEngine::Blob::Ptr outputBlob = req.GetBlob(cnnNet.getOutputsInfo().begin()->first); -} -} // namespace BehaviorTestsDefinitions \ No newline at end of file diff --git a/inference-engine/tests/functional/plugin/shared/include/behavior/layout.hpp b/inference-engine/tests/functional/plugin/shared/include/behavior/layout.hpp deleted file mode 100644 index 2d27800a762..00000000000 --- a/inference-engine/tests/functional/plugin/shared/include/behavior/layout.hpp +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright (C) 2018-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#pragma once - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "gtest/gtest.h" -#include "common_test_utils/common_utils.hpp" -#include "common_test_utils/test_common.hpp" - -#include "functional_test_utils/skip_tests_config.hpp" -#include "functional_test_utils/plugin_cache.hpp" -#include "functional_test_utils/blob_utils.hpp" -#include "functional_test_utils/precision_utils.hpp" -#include "ngraph_functions/utils/ngraph_helpers.hpp" -#include "ngraph_functions/pass/convert_prc.hpp" - -namespace BehaviorTestsDefinitions { - typedef std::tuple< - InferenceEngine::Precision, // Network precision - std::string, // Target device name - std::map, // Target config - InferenceEngine::Layout, // Layout - std::vector> // InputShapes - LayoutParams; - -class LayoutTest : public CommonTestUtils::TestsCommon, - public ::testing::WithParamInterface { -public: - static std::string getTestCaseName(testing::TestParamInfo obj); - - void SetUp() override; - - void TearDown() override; - - std::shared_ptr ie = PluginCache::get().ie(); - InferenceEngine::Layout layout; - std::vector inputShapes; - std::shared_ptr function; - InferenceEngine::Precision netPrecision; - std::string targetDevice; - std::map configuration; -}; -} // namespace BehaviorTestsDefinitions \ No newline at end of file diff --git a/inference-engine/tests/functional/plugin/shared/include/behavior/perf_counters.hpp b/inference-engine/tests/functional/plugin/shared/include/behavior/perf_counters.hpp deleted file mode 100644 index f1987b3c9a1..00000000000 --- a/inference-engine/tests/functional/plugin/shared/include/behavior/perf_counters.hpp +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright (C) 2018-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#include - -#include -#include "common_test_utils/test_assertions.hpp" -#include "common_test_utils/common_utils.hpp" -#include "functional_test_utils/plugin_cache.hpp" -#include "shared_test_classes/base/layer_test_utils.hpp" -#include "functional_test_utils/blob_utils.hpp" -#include "ie_preprocess.hpp" -#include "base/behavior_test_utils.hpp" - -namespace BehaviorTestsDefinitions { -using PerfCountersTest = BehaviorTestsUtils::BehaviorTestsBasic; - -TEST_P(PerfCountersTest, NotEmptyWhenExecuted) { - // Skip test according to plugin specific disabledTestPatterns() (if any) - SKIP_IF_CURRENT_TEST_IS_DISABLED() - // Create CNNNetwork from ngrpah::Function - InferenceEngine::CNNNetwork cnnNet(function); - std::map config = {{ InferenceEngine::PluginConfigParams::KEY_PERF_COUNT, - InferenceEngine::PluginConfigParams::YES }}; - config.insert(configuration.begin(), configuration.end()); - // Load CNNNetwork to target plugins - auto execNet = ie->LoadNetwork(cnnNet, targetDevice, config); - // Create InferRequest - InferenceEngine::InferRequest req; - InferenceEngine::ResponseDesc response; - ASSERT_NO_FATAL_FAILURE(req = execNet.CreateInferRequest()); - ASSERT_NO_THROW(req.Infer()) << response.msg; - - std::map perfMap; - perfMap = req.GetPerformanceCounts(); - ASSERT_NE(perfMap.size(), 0); -} -} // namespace BehaviorTestsDefinitions \ No newline at end of file diff --git a/inference-engine/tests/functional/plugin/shared/include/behavior/preprocessing.hpp b/inference-engine/tests/functional/plugin/shared/include/behavior/preprocessing/preprocessing.hpp similarity index 92% rename from inference-engine/tests/functional/plugin/shared/include/behavior/preprocessing.hpp rename to inference-engine/tests/functional/plugin/shared/include/behavior/preprocessing/preprocessing.hpp index 1733398a7cd..557a36803b3 100644 --- a/inference-engine/tests/functional/plugin/shared/include/behavior/preprocessing.hpp +++ b/inference-engine/tests/functional/plugin/shared/include/behavior/preprocessing/preprocessing.hpp @@ -118,6 +118,23 @@ public: function = copyOriginalFunction; } + void Run() override { + SKIP_IF_CURRENT_TEST_IS_DISABLED(); + try { + LoadNetwork(); + GenerateInputs(); + Infer(); + Validate(); + } + catch (const std::runtime_error &re) { + GTEST_FATAL_FAILURE_(re.what()); + } catch (const std::exception &ex) { + GTEST_FATAL_FAILURE_(ex.what()); + } catch (...) { + GTEST_FATAL_FAILURE_("Unknown failure occurred."); + } + } + public: std::shared_ptr ie = PluginCache::get().ie(); std::shared_ptr reference_function; @@ -127,8 +144,6 @@ public: TEST_P(PreprocessingPrecisionConvertTest, InternalPluginPrecisionConvert) { - // Skip test according to plugin specific disabledTestPatterns() (if any) - SKIP_IF_CURRENT_TEST_IS_DISABLED() Run(); } } // namespace BehaviorTestsDefinitions diff --git a/inference-engine/tests/functional/plugin/shared/include/behavior/set_preprocess.hpp b/inference-engine/tests/functional/plugin/shared/include/behavior/preprocessing/set_preprocess.hpp similarity index 93% rename from inference-engine/tests/functional/plugin/shared/include/behavior/set_preprocess.hpp rename to inference-engine/tests/functional/plugin/shared/include/behavior/preprocessing/set_preprocess.hpp index a3a53f160ed..950841fe361 100644 --- a/inference-engine/tests/functional/plugin/shared/include/behavior/set_preprocess.hpp +++ b/inference-engine/tests/functional/plugin/shared/include/behavior/preprocessing/set_preprocess.hpp @@ -16,11 +16,9 @@ #include "ie_ngraph_utils.hpp" namespace BehaviorTestsDefinitions { -using PreprocessTest = BehaviorTestsUtils::BehaviorTestsBasic; +using InferRequestPreprocessTest = BehaviorTestsUtils::BehaviorTestsBasic; -TEST_P(PreprocessTest, SetPreProcessToInputInfo) { - // Skip test according to plugin specific disabledTestPatterns() (if any) - SKIP_IF_CURRENT_TEST_IS_DISABLED() +TEST_P(InferRequestPreprocessTest, SetPreProcessToInputInfo) { // Create CNNNetwork from ngraph::Function InferenceEngine::CNNNetwork cnnNet(function); @@ -39,9 +37,7 @@ TEST_P(PreprocessTest, SetPreProcessToInputInfo) { } } -TEST_P(PreprocessTest, SetPreProcessToInferRequest) { - // Skip test according to plugin specific disabledTestPatterns() (if any) - SKIP_IF_CURRENT_TEST_IS_DISABLED() +TEST_P(InferRequestPreprocessTest, SetPreProcessToInferRequest) { // Create CNNNetwork from ngraph::Function InferenceEngine::CNNNetwork cnnNet(function); @@ -63,9 +59,7 @@ TEST_P(PreprocessTest, SetPreProcessToInferRequest) { } } -TEST_P(PreprocessTest, SetMeanImagePreProcessGetBlob) { - // Skip test according to plugin specific disabledTestPatterns() (if any) - SKIP_IF_CURRENT_TEST_IS_DISABLED() +TEST_P(InferRequestPreprocessTest, SetMeanImagePreProcessGetBlob) { std::shared_ptr ngraph; { ngraph::PartialShape shape({1, 3, 10, 10}); @@ -131,9 +125,7 @@ TEST_P(PreprocessTest, SetMeanImagePreProcessGetBlob) { } } -TEST_P(PreprocessTest, SetMeanImagePreProcessSetBlob) { - // Skip test according to plugin specific disabledTestPatterns() (if any) - SKIP_IF_CURRENT_TEST_IS_DISABLED() +TEST_P(InferRequestPreprocessTest, SetMeanImagePreProcessSetBlob) { std::shared_ptr ngraph; { ngraph::PartialShape shape({1, 3, 10, 10}); @@ -202,9 +194,7 @@ TEST_P(PreprocessTest, SetMeanImagePreProcessSetBlob) { } } -TEST_P(PreprocessTest, SetMeanValuePreProcessGetBlob) { - // Skip test according to plugin specific disabledTestPatterns() (if any) - SKIP_IF_CURRENT_TEST_IS_DISABLED() +TEST_P(InferRequestPreprocessTest, SetMeanValuePreProcessGetBlob) { std::shared_ptr ngraph; { ngraph::PartialShape shape({1, 3, 10, 10}); @@ -264,9 +254,7 @@ TEST_P(PreprocessTest, SetMeanValuePreProcessGetBlob) { } } -TEST_P(PreprocessTest, SetMeanValuePreProcessSetBlob) { - // Skip test according to plugin specific disabledTestPatterns() (if any) - SKIP_IF_CURRENT_TEST_IS_DISABLED() +TEST_P(InferRequestPreprocessTest, SetMeanValuePreProcessSetBlob) { std::shared_ptr ngraph; { ngraph::PartialShape shape({1, 3, 10, 10}); @@ -328,9 +316,7 @@ TEST_P(PreprocessTest, SetMeanValuePreProcessSetBlob) { } } -TEST_P(PreprocessTest, ReverseInputChannelsPreProcessGetBlob) { - // Skip test according to plugin specific disabledTestPatterns() (if any) - SKIP_IF_CURRENT_TEST_IS_DISABLED() +TEST_P(InferRequestPreprocessTest, ReverseInputChannelsPreProcessGetBlob) { std::shared_ptr ngraph; { ngraph::PartialShape shape({1, 3, 10, 10}); @@ -391,9 +377,7 @@ TEST_P(PreprocessTest, ReverseInputChannelsPreProcessGetBlob) { } } -TEST_P(PreprocessTest, ReverseInputChannelsPreProcessSetBlob) { - // Skip test according to plugin specific disabledTestPatterns() (if any) - SKIP_IF_CURRENT_TEST_IS_DISABLED() +TEST_P(InferRequestPreprocessTest, ReverseInputChannelsPreProcessSetBlob) { std::shared_ptr ngraph; { ngraph::PartialShape shape({1, 3, 10, 10}); @@ -457,9 +441,7 @@ TEST_P(PreprocessTest, ReverseInputChannelsPreProcessSetBlob) { } } -TEST_P(PreprocessTest, SetScalePreProcessGetBlob) { - // Skip test according to plugin specific disabledTestPatterns() (if any) - SKIP_IF_CURRENT_TEST_IS_DISABLED() +TEST_P(InferRequestPreprocessTest, SetScalePreProcessGetBlob) { std::shared_ptr ngraph; { ngraph::PartialShape shape({1, 3, 10, 10}); @@ -519,9 +501,7 @@ TEST_P(PreprocessTest, SetScalePreProcessGetBlob) { } } -TEST_P(PreprocessTest, SetScalePreProcessSetBlob) { - // Skip test according to plugin specific disabledTestPatterns() (if any) - SKIP_IF_CURRENT_TEST_IS_DISABLED() +TEST_P(InferRequestPreprocessTest, SetScalePreProcessSetBlob) { std::shared_ptr ngraph; { ngraph::PartialShape shape({1, 3, 10, 10}); @@ -596,8 +576,8 @@ typedef std::tuple< std::map // Config > PreprocessConversionParams; -class PreprocessConversionTest : public testing::WithParamInterface, - public CommonTestUtils::TestsCommon { +class InferRequestPreprocessConversionTest : public testing::WithParamInterface, + public CommonTestUtils::TestsCommon { public: static std::string getTestCaseName(testing::TestParamInfo obj) { InferenceEngine::Precision netPrecision, iPrecision, oPrecision; @@ -646,6 +626,8 @@ public: } void SetUp() override { + // Skip test according to plugin specific disabledTestPatterns() (if any) + SKIP_IF_CURRENT_TEST_IS_DISABLED() std::tie(netPrecision, iPrecision, oPrecision, netLayout, iLayout, oLayout, setInputBlob, setOutputBlob, @@ -666,9 +648,7 @@ public: std::map configuration; }; -TEST_P(PreprocessConversionTest, Infer) { - // Skip test according to plugin specific disabledTestPatterns() (if any) - SKIP_IF_CURRENT_TEST_IS_DISABLED() +TEST_P(InferRequestPreprocessConversionTest, Infer) { std::shared_ptr ngraph; unsigned int shape_size = 9, channels = 3, batch = 1, offset = 0; { @@ -784,8 +764,8 @@ typedef std::tuple< std::map // Config > PreprocessSetBlobCheckParams; -class PreprocessDynamicallyInSetBlobTest : public testing::WithParamInterface, - public CommonTestUtils::TestsCommon { +class InferRequestPreprocessDynamicallyInSetBlobTest : public testing::WithParamInterface, + public CommonTestUtils::TestsCommon { public: static std::string getTestCaseName(testing::TestParamInfo obj) { InferenceEngine::Precision netPrecision; @@ -836,6 +816,8 @@ public: } void SetUp() override { + // Skip test according to plugin specific disabledTestPatterns() (if any) + SKIP_IF_CURRENT_TEST_IS_DISABLED() std::tie(netPrecision, changeIPrecision, changeOPrecision, netLayout, changeILayout, changeOLayout, setInputBlob, setOutputBlob, @@ -858,9 +840,7 @@ public: std::map configuration; }; -TEST_P(PreprocessDynamicallyInSetBlobTest, Infer) { - // Skip test according to plugin specific disabledTestPatterns() (if any) - SKIP_IF_CURRENT_TEST_IS_DISABLED() +TEST_P(InferRequestPreprocessDynamicallyInSetBlobTest, Infer) { std::shared_ptr ngraph; unsigned int shape_size = 9, channels = 3, batch = 1; { @@ -992,9 +972,7 @@ TEST_P(PreprocessDynamicallyInSetBlobTest, Infer) { } } -TEST_P(PreprocessTest, InferWithRGB2BGRConversion) { - // Skip test according to plugin specific disabledTestPatterns() (if any) - SKIP_IF_CURRENT_TEST_IS_DISABLED() +TEST_P(InferRequestPreprocessTest, InferWithRGB2BGRConversion) { std::shared_ptr ngraphFunc; const unsigned int shape_size = 9, channels = 3, batch = 1; { diff --git a/inference-engine/tests/functional/plugin/shared/include/behavior/set_blob_of_kind.hpp b/inference-engine/tests/functional/plugin/shared/include/behavior/set_blob_of_kind.hpp deleted file mode 100644 index a27ce1c5072..00000000000 --- a/inference-engine/tests/functional/plugin/shared/include/behavior/set_blob_of_kind.hpp +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (C) 2018-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#pragma once - -#include "shared_test_classes/base/layer_test_utils.hpp" -#include "common_test_utils/common_utils.hpp" - -namespace BehaviorTestsDefinitions { - -using SetBlobOfKindConfig = std::remove_referenceGetConfiguration())>::type; - -using SetBlobOfKindParams = std::tuple; // configuration - -class SetBlobOfKindTest : public testing::WithParamInterface, virtual public LayerTestsUtils::LayerTestsCommon { -public: - InferenceEngine::Blob::Ptr GenerateInput(const InferenceEngine::InputInfo &info) const override; - void Run() override; - static std::string getTestCaseName(testing::TestParamInfo obj); - void ExpectSetBlobThrow(); - -protected: - void SetUp() override; - -private: - FuncTestUtils::BlobKind blobKind; -}; - -} // namespace BehaviorTestsDefinitions diff --git a/inference-engine/tests/functional/plugin/shared/src/behavior/caching_tests.cpp b/inference-engine/tests/functional/plugin/shared/src/behavior/caching/caching_tests.cpp similarity index 99% rename from inference-engine/tests/functional/plugin/shared/src/behavior/caching_tests.cpp rename to inference-engine/tests/functional/plugin/shared/src/behavior/caching/caching_tests.cpp index 167afc80b6e..8b3e37ee501 100644 --- a/inference-engine/tests/functional/plugin/shared/src/behavior/caching_tests.cpp +++ b/inference-engine/tests/functional/plugin/shared/src/behavior/caching/caching_tests.cpp @@ -6,7 +6,7 @@ #include #include -#include "behavior/caching_tests.hpp" +#include "behavior/caching/caching_tests.hpp" #include "common_test_utils/file_utils.hpp" #include "ngraph_functions/builders.hpp" #include "ngraph_functions/subgraph_builders.hpp" diff --git a/inference-engine/tests/functional/plugin/shared/src/configuration_tests/dynamic_batch.cpp b/inference-engine/tests/functional/plugin/shared/src/behavior/infer_request/dynamic_batch.cpp similarity index 92% rename from inference-engine/tests/functional/plugin/shared/src/configuration_tests/dynamic_batch.cpp rename to inference-engine/tests/functional/plugin/shared/src/behavior/infer_request/dynamic_batch.cpp index 94ec0c1e4b6..b4eafc7fe29 100644 --- a/inference-engine/tests/functional/plugin/shared/src/configuration_tests/dynamic_batch.cpp +++ b/inference-engine/tests/functional/plugin/shared/src/behavior/infer_request/dynamic_batch.cpp @@ -5,24 +5,14 @@ #include #include #include -#include -#include #include #include "ie_core.hpp" #include "ie_transformations.hpp" #include "common_test_utils/common_utils.hpp" -#include "functional_test_utils/blob_utils.hpp" -#include "functional_test_utils/precision_utils.hpp" -#include "functional_test_utils/plugin_cache.hpp" #include "functional_test_utils/skip_tests_config.hpp" -#include "ngraph_functions/utils/ngraph_helpers.hpp" -#include "ngraph_functions/builders.hpp" - -#include -#include "transformations/control_flow/unroll_tensor_iterator.hpp" -#include "configuration_tests/dynamic_batch.hpp" +#include "behavior/infer_request/dynamic_batch.hpp" #include "ngraph_functions/subgraph_builders.hpp" diff --git a/inference-engine/tests/functional/plugin/shared/src/behavior/memory_states.cpp b/inference-engine/tests/functional/plugin/shared/src/behavior/infer_request/memory_states.cpp similarity index 80% rename from inference-engine/tests/functional/plugin/shared/src/behavior/memory_states.cpp rename to inference-engine/tests/functional/plugin/shared/src/behavior/infer_request/memory_states.cpp index 5b002da7dcd..fee48a7bb86 100644 --- a/inference-engine/tests/functional/plugin/shared/src/behavior/memory_states.cpp +++ b/inference-engine/tests/functional/plugin/shared/src/behavior/infer_request/memory_states.cpp @@ -3,12 +3,12 @@ // #include -#include -#include "behavior/memory_states.hpp" +#include "behavior/infer_request/memory_states.hpp" #include "functional_test_utils/plugin_cache.hpp" #include "blob_factory.hpp" -std::string VariableStateTest::getTestCaseName(const testing::TestParamInfo &obj) { +namespace BehaviorTestsDefinitions { +std::string InferRequestVariableStateTest::getTestCaseName(const testing::TestParamInfo &obj) { std::ostringstream result; InferenceEngine::CNNNetwork net; std::string targetDevice; @@ -18,18 +18,18 @@ std::string VariableStateTest::getTestCaseName(const testing::TestParamInfoLoadNetwork(net, deviceName); } -TEST_P(VariableStateTest, smoke_VariableState_QueryState) { +TEST_P(InferRequestVariableStateTest, smoke_VariableState_QueryState) { // Skip test according to plugin specific disabledTestPatterns() (if any) SKIP_IF_CURRENT_TEST_IS_DISABLED() IE_SUPPRESS_DEPRECATED_START @@ -38,21 +38,21 @@ TEST_P(VariableStateTest, smoke_VariableState_QueryState) { auto states = executableNet.QueryState(); ASSERT_TRUE(states.size() == 2) << "Incorrect number of VariableStates"; - for (auto&& state : states) { + for (auto &&state : states) { auto name = state.GetName(); ASSERT_TRUE(std::find(statesToQuery.begin(), statesToQuery.end(), name) != statesToQuery.end()) - << "State " << name << "expected to be in memory states but it is not!"; + << "State " << name << "expected to be in memory states but it is not!"; } IE_SUPPRESS_DEPRECATED_END } -TEST_P(VariableStateTest, smoke_VariableState_SetState) { +TEST_P(InferRequestVariableStateTest, smoke_VariableState_SetState) { // Skip test according to plugin specific disabledTestPatterns() (if any) SKIP_IF_CURRENT_TEST_IS_DISABLED() IE_SUPPRESS_DEPRECATED_START auto executableNet = PrepareNetwork(); const float new_state_val = 13.0f; - for (auto&& state : executableNet.QueryState()) { + for (auto &&state : executableNet.QueryState()) { state.Reset(); auto state_val = state.GetState(); auto element_count = state_val->size(); @@ -64,14 +64,14 @@ TEST_P(VariableStateTest, smoke_VariableState_SetState) { auto stateBlob = make_blob_with_precision(state_val->getTensorDesc()); stateBlob->allocate(); std::memcpy(stateBlob->buffer(), new_state_data, element_count * sizeof(float)); - delete []new_state_data; + delete[]new_state_data; state.SetState(stateBlob); } - for (auto&& state : executableNet.QueryState()) { + for (auto &&state : executableNet.QueryState()) { auto lastState = state.GetState(); auto last_state_size = lastState->size(); - auto last_state_data = lastState->cbuffer().as(); + auto last_state_data = lastState->cbuffer().as(); ASSERT_TRUE(last_state_size != 0) << "State size should not be 0"; for (int i = 0; i < last_state_size; i++) { @@ -81,13 +81,13 @@ TEST_P(VariableStateTest, smoke_VariableState_SetState) { IE_SUPPRESS_DEPRECATED_END } -TEST_P(VariableStateTest, smoke_VariableState_Reset) { +TEST_P(InferRequestVariableStateTest, smoke_VariableState_Reset) { // Skip test according to plugin specific disabledTestPatterns() (if any) SKIP_IF_CURRENT_TEST_IS_DISABLED() IE_SUPPRESS_DEPRECATED_START auto executableNet = PrepareNetwork(); const float new_state_val = 13.0f; - for (auto&& state : executableNet.QueryState()) { + for (auto &&state : executableNet.QueryState()) { state.Reset(); auto state_val = state.GetState(); auto element_count = state_val->size(); @@ -99,7 +99,7 @@ TEST_P(VariableStateTest, smoke_VariableState_Reset) { auto stateBlob = make_blob_with_precision(state_val->getTensorDesc()); stateBlob->allocate(); std::memcpy(stateBlob->buffer(), new_state_data, element_count * sizeof(float)); - delete []new_state_data; + delete[]new_state_data; state.SetState(stateBlob); } @@ -110,7 +110,7 @@ TEST_P(VariableStateTest, smoke_VariableState_Reset) { for (int i = 0; i < states.size(); ++i) { auto lastState = states[i].GetState(); auto last_state_size = lastState->size(); - auto last_state_data = lastState->cbuffer().as(); + auto last_state_data = lastState->cbuffer().as(); ASSERT_TRUE(last_state_size != 0) << "State size should not be 0"; @@ -127,7 +127,7 @@ TEST_P(VariableStateTest, smoke_VariableState_Reset) { IE_SUPPRESS_DEPRECATED_END } -TEST_P(VariableStateTest, inferreq_smoke_VariableState_QueryState) { +TEST_P(InferRequestVariableStateTest, inferreq_smoke_VariableState_QueryState) { // Skip test according to plugin specific disabledTestPatterns() (if any) SKIP_IF_CURRENT_TEST_IS_DISABLED() auto executableNet = PrepareNetwork(); @@ -136,21 +136,21 @@ TEST_P(VariableStateTest, inferreq_smoke_VariableState_QueryState) { auto states = inferReq.QueryState(); ASSERT_TRUE(states.size() == 2) << "Incorrect number of VariableStates"; - for (auto&& state : states) { + for (auto &&state : states) { auto name = state.GetName(); ASSERT_TRUE(std::find(statesToQuery.begin(), statesToQuery.end(), name) != statesToQuery.end()) - << "State " << name << "expected to be in memory states but it is not!"; + << "State " << name << "expected to be in memory states but it is not!"; } } -TEST_P(VariableStateTest, inferreq_smoke_VariableState_SetState) { +TEST_P(InferRequestVariableStateTest, inferreq_smoke_VariableState_SetState) { // Skip test according to plugin specific disabledTestPatterns() (if any) SKIP_IF_CURRENT_TEST_IS_DISABLED() auto executableNet = PrepareNetwork(); auto inferReq = executableNet.CreateInferRequest(); const float new_state_val = 13.0f; - for (auto&& state : inferReq.QueryState()) { + for (auto &&state : inferReq.QueryState()) { state.Reset(); auto state_val = state.GetState(); auto element_count = state_val->size(); @@ -162,14 +162,14 @@ TEST_P(VariableStateTest, inferreq_smoke_VariableState_SetState) { auto stateBlob = make_blob_with_precision(state_val->getTensorDesc()); stateBlob->allocate(); std::memcpy(stateBlob->buffer(), new_state_data, element_count * sizeof(float)); - delete []new_state_data; + delete[]new_state_data; state.SetState(stateBlob); } - for (auto&& state : inferReq.QueryState()) { + for (auto &&state : inferReq.QueryState()) { auto lastState = state.GetState(); auto last_state_size = lastState->size(); - auto last_state_data = lastState->cbuffer().as(); + auto last_state_data = lastState->cbuffer().as(); ASSERT_TRUE(last_state_size != 0) << "State size should not be 0"; for (int i = 0; i < last_state_size; i++) { EXPECT_NEAR(new_state_val, last_state_data[i], 1e-5); @@ -177,14 +177,14 @@ TEST_P(VariableStateTest, inferreq_smoke_VariableState_SetState) { } } -TEST_P(VariableStateTest, inferreq_smoke_VariableState_Reset) { +TEST_P(InferRequestVariableStateTest, inferreq_smoke_VariableState_Reset) { // Skip test according to plugin specific disabledTestPatterns() (if any) SKIP_IF_CURRENT_TEST_IS_DISABLED() auto executableNet = PrepareNetwork(); auto inferReq = executableNet.CreateInferRequest(); const float new_state_val = 13.0f; - for (auto&& state : inferReq.QueryState()) { + for (auto &&state : inferReq.QueryState()) { state.Reset(); auto state_val = state.GetState(); auto element_count = state_val->size(); @@ -196,7 +196,7 @@ TEST_P(VariableStateTest, inferreq_smoke_VariableState_Reset) { auto stateBlob = make_blob_with_precision(state_val->getTensorDesc()); stateBlob->allocate(); std::memcpy(stateBlob->buffer(), new_state_data, element_count * sizeof(float)); - delete []new_state_data; + delete[]new_state_data; state.SetState(stateBlob); } @@ -207,7 +207,7 @@ TEST_P(VariableStateTest, inferreq_smoke_VariableState_Reset) { for (int i = 0; i < states.size(); ++i) { auto lastState = states[i].GetState(); auto last_state_size = lastState->size(); - auto last_state_data = lastState->cbuffer().as(); + auto last_state_data = lastState->cbuffer().as(); ASSERT_TRUE(last_state_size != 0) << "State size should not be 0"; if (i == 0) { @@ -222,7 +222,7 @@ TEST_P(VariableStateTest, inferreq_smoke_VariableState_Reset) { } } -TEST_P(VariableStateTest, inferreq_smoke_VariableState_2infers_set) { +TEST_P(InferRequestVariableStateTest, inferreq_smoke_VariableState_2infers_set) { // Skip test according to plugin specific disabledTestPatterns() (if any) SKIP_IF_CURRENT_TEST_IS_DISABLED() auto executableNet = PrepareNetwork(); @@ -230,7 +230,7 @@ TEST_P(VariableStateTest, inferreq_smoke_VariableState_2infers_set) { auto inferReq2 = executableNet.CreateInferRequest(); const float new_state_val = 13.0f; - for (auto&& state : inferReq.QueryState()) { + for (auto &&state : inferReq.QueryState()) { state.Reset(); auto state_val = state.GetState(); auto element_count = state_val->size(); @@ -242,10 +242,10 @@ TEST_P(VariableStateTest, inferreq_smoke_VariableState_2infers_set) { auto stateBlob = make_blob_with_precision(state_val->getTensorDesc()); stateBlob->allocate(); std::memcpy(stateBlob->buffer(), new_state_data, element_count * sizeof(float)); - delete []new_state_data; + delete[]new_state_data; state.SetState(stateBlob); } - for (auto&& state : inferReq2.QueryState()) { + for (auto &&state : inferReq2.QueryState()) { state.Reset(); } @@ -254,7 +254,7 @@ TEST_P(VariableStateTest, inferreq_smoke_VariableState_2infers_set) { for (int i = 0; i < states.size(); ++i) { auto lastState = states[i].GetState(); auto last_state_size = lastState->size(); - auto last_state_data = lastState->cbuffer().as(); + auto last_state_data = lastState->cbuffer().as(); ASSERT_TRUE(last_state_size != 0) << "State size should not be 0"; @@ -265,7 +265,7 @@ TEST_P(VariableStateTest, inferreq_smoke_VariableState_2infers_set) { for (int i = 0; i < states2.size(); ++i) { auto lastState = states2[i].GetState(); auto last_state_size = lastState->size(); - auto last_state_data = lastState->cbuffer().as(); + auto last_state_data = lastState->cbuffer().as(); ASSERT_TRUE(last_state_size != 0) << "State size should not be 0"; @@ -275,7 +275,7 @@ TEST_P(VariableStateTest, inferreq_smoke_VariableState_2infers_set) { } } -TEST_P(VariableStateTest, inferreq_smoke_VariableState_2infers) { +TEST_P(InferRequestVariableStateTest, inferreq_smoke_VariableState_2infers) { // Skip test according to plugin specific disabledTestPatterns() (if any) SKIP_IF_CURRENT_TEST_IS_DISABLED() auto executableNet = PrepareNetwork(); @@ -291,10 +291,10 @@ TEST_P(VariableStateTest, inferreq_smoke_VariableState_2infers) { inferReq.SetBlob(info->name(), inBlob); } - for (auto&& state : inferReq.QueryState()) { + for (auto &&state : inferReq.QueryState()) { state.Reset(); } - for (auto&& state : inferReq2.QueryState()) { + for (auto &&state : inferReq2.QueryState()) { state.Reset(); } @@ -305,7 +305,7 @@ TEST_P(VariableStateTest, inferreq_smoke_VariableState_2infers) { for (int i = 0; i < states.size(); ++i) { auto lastState = states[i].GetState(); auto last_state_size = lastState->size(); - auto last_state_data = lastState->cbuffer().as(); + auto last_state_data = lastState->cbuffer().as(); ASSERT_TRUE(last_state_size != 0) << "State size should not be 0"; @@ -322,7 +322,7 @@ TEST_P(VariableStateTest, inferreq_smoke_VariableState_2infers) { for (int i = 0; i < states2.size(); ++i) { auto lastState = states2[i].GetState(); auto last_state_size = lastState->size(); - auto last_state_data = lastState->cbuffer().as(); + auto last_state_data = lastState->cbuffer().as(); ASSERT_TRUE(last_state_size != 0) << "State size should not be 0"; @@ -331,3 +331,4 @@ TEST_P(VariableStateTest, inferreq_smoke_VariableState_2infers) { } } } +} // namespace BehaviorTestsDefinitions diff --git a/inference-engine/tests/functional/plugin/shared/src/behavior/layout.cpp b/inference-engine/tests/functional/plugin/shared/src/behavior/layout.cpp deleted file mode 100644 index 5b4abea77b2..00000000000 --- a/inference-engine/tests/functional/plugin/shared/src/behavior/layout.cpp +++ /dev/null @@ -1,111 +0,0 @@ -// Copyright (C) 2018-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#include "behavior/layout.hpp" - -namespace BehaviorTestsDefinitions { -std::string LayoutTest::getTestCaseName(testing::TestParamInfo obj) { - InferenceEngine::Precision netPrecision; - std::string targetDevice; - InferenceEngine::Layout layout; - std::vector inputShapes; - std::map configuration; - std::tie(netPrecision, targetDevice, configuration, layout, inputShapes) = obj.param; - std::ostringstream result; - result << "netPRC=" << netPrecision.name() << "_"; - result << "targetDevice=" << targetDevice << "_"; - result << "layout=" << layout << "_"; - result << "inputShapes="; - if (!inputShapes.empty()) { - for (auto &Item : inputShapes) { - result << Item << "x"; - } - } - auto str = result.str(); - str.pop_back(); - - return str; -} - -void LayoutTest::SetUp() { - std::tie(netPrecision, targetDevice, configuration, - layout, inputShapes) = this->GetParam(); - function = ngraph::builder::subgraph::make2InputSubtract( - inputShapes, FuncTestUtils::PrecisionUtils::convertIE2nGraphPrc(netPrecision)); -} - -void LayoutTest::TearDown() { - if ((targetDevice == CommonTestUtils::DEVICE_GPU) || (!configuration.empty())) { - PluginCache::get().reset(); - } - function.reset(); -} - -inline bool checkLayout(InferenceEngine::Layout layout, std::vector &inputShapes) { - bool check = false; - switch (layout) { - case InferenceEngine::Layout::C: - check = 1 == inputShapes.size(); - break; - case InferenceEngine::Layout::BLOCKED: - case InferenceEngine::Layout::ANY: - check = true; - break; - case InferenceEngine::Layout::GOIDHW: - check = 6 == inputShapes.size(); - break; - case InferenceEngine::Layout::NCDHW: - case InferenceEngine::Layout::NDHWC: - case InferenceEngine::Layout::OIDHW: - case InferenceEngine::Layout::GOIHW: - check = 5 == inputShapes.size(); - break; - case InferenceEngine::Layout::OIHW: - case InferenceEngine::Layout::NCHW: - case InferenceEngine::Layout::NHWC: - check = 4 == inputShapes.size(); - break; - case InferenceEngine::Layout::CHW: - case InferenceEngine::Layout::HWC: - check = 3 == inputShapes.size(); - break; - case InferenceEngine::Layout::CN: - case InferenceEngine::Layout::NC: - case InferenceEngine::Layout::HW: - check = 2 == inputShapes.size(); - break; - default: - break; - } - return check; -} - -TEST_P(LayoutTest, NetWithLayout) { - // Skip test according to plugin specific disabledTestPatterns() (if any) - SKIP_IF_CURRENT_TEST_IS_DISABLED(); - // Create CNNNetwork from ngrpah::Function - InferenceEngine::CNNNetwork cnnNet(function); - if (checkLayout(layout, inputShapes)) { - ASSERT_NO_THROW(cnnNet.getInputsInfo().begin()->second->setLayout(layout)); - - if (targetDevice == CommonTestUtils::DEVICE_GNA) { - return; - } - - InferenceEngine::ExecutableNetwork exeNetwork; - ASSERT_NO_THROW(exeNetwork = ie->LoadNetwork(cnnNet, targetDevice, configuration)); - - InferenceEngine::InferRequest request; - ASSERT_NO_THROW(request = exeNetwork.CreateInferRequest()); - - InferenceEngine::Blob::Ptr inputBlob; - ASSERT_NO_THROW(inputBlob = request.GetBlob(cnnNet.getInputsInfo().begin()->second->name())); - - ASSERT_EQ(inputBlob->getTensorDesc().getLayout(), layout); - } else { - ASSERT_THROW(cnnNet.getInputsInfo().begin()->second->setLayout(layout), - InferenceEngine::Exception); - } -} -} // namespace BehaviorTestsDefinitions diff --git a/inference-engine/tests/functional/plugin/shared/src/behavior/set_blob.cpp b/inference-engine/tests/functional/plugin/shared/src/behavior/set_blob.cpp index 5f2c8ff7806..d958870ca1a 100644 --- a/inference-engine/tests/functional/plugin/shared/src/behavior/set_blob.cpp +++ b/inference-engine/tests/functional/plugin/shared/src/behavior/set_blob.cpp @@ -66,7 +66,7 @@ void SetBlobTest::Infer() { const auto &info = input.second; Blob::Ptr inBlob; if (type == setType::INPUT || type == setType::BOTH) { - inBlob = make_blob_with_precision(precNet, info->getTensorDesc()); + inBlob = make_blob_with_precision(inPrc, info->getTensorDesc()); inBlob->allocate(); fillBlob(inBlob); } else { @@ -79,7 +79,7 @@ void SetBlobTest::Infer() { if (type == setType::OUTPUT || type == setType::BOTH) { for (const auto &output : executableNetwork.GetOutputsInfo()) { const auto &info = output.second; - Blob::Ptr outBlob = make_blob_with_precision(precNet, info->getTensorDesc()); + Blob::Ptr outBlob = make_blob_with_precision(outPrc, info->getTensorDesc()); outBlob->allocate(); fillBlob(outBlob); inferRequest.SetBlob(info->getName(), outBlob); diff --git a/inference-engine/tests/functional/plugin/shared/src/behavior/set_blob_of_kind.cpp b/inference-engine/tests/functional/plugin/shared/src/behavior/set_blob_of_kind.cpp deleted file mode 100644 index 34e1b475245..00000000000 --- a/inference-engine/tests/functional/plugin/shared/src/behavior/set_blob_of_kind.cpp +++ /dev/null @@ -1,106 +0,0 @@ -// Copyright (C) 2018-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#include "behavior/set_blob_of_kind.hpp" - -#include - -#include - -using namespace InferenceEngine; - -namespace BehaviorTestsDefinitions { - -std::string SetBlobOfKindTest::getTestCaseName(testing::TestParamInfo obj) { - FuncTestUtils::BlobKind blobKind; - std::string targetDevice; - std::map configuration; - std::tie(blobKind, targetDevice, configuration) = obj.param; - - std::ostringstream result; - result << "Kind=" << blobKind; - result << " Device="<< targetDevice; - return result.str(); -} - -namespace { - -bool isBatchedBlobSupported(const std::shared_ptr& core, const LayerTestsUtils::TargetDevice& targetDevice) { - const std::vector supported_metrics = core->GetMetric(targetDevice, METRIC_KEY(SUPPORTED_METRICS)); - - if (std::find(supported_metrics.begin(), supported_metrics.end(), - METRIC_KEY(OPTIMIZATION_CAPABILITIES)) == supported_metrics.end()) { - return false; - } - - const std::vector optimization_caps = - core->GetMetric(targetDevice, METRIC_KEY(OPTIMIZATION_CAPABILITIES)); - - return std::find(optimization_caps.begin(), optimization_caps.end(), - METRIC_VALUE(BATCHED_BLOB)) != optimization_caps.end(); -} - -bool isBlobKindSupported(const std::shared_ptr& core, - const LayerTestsUtils::TargetDevice& targetDevice, - FuncTestUtils::BlobKind blobKind) { - switch (blobKind) { - case FuncTestUtils::BlobKind::Simple: - return true; - case FuncTestUtils::BlobKind::Compound: - return false; - case FuncTestUtils::BlobKind::BatchOfSimple: - return isBatchedBlobSupported(core, targetDevice); - default: - IE_THROW() << "Test does not support the blob kind"; - } -} - -} // namespace - -Blob::Ptr SetBlobOfKindTest::GenerateInput(const InferenceEngine::InputInfo& info) const { - return makeBlobOfKind(info.getTensorDesc(), blobKind); -} - -void SetBlobOfKindTest::Run() { - SKIP_IF_CURRENT_TEST_IS_DISABLED() - - LoadNetwork(); - GenerateInputs(); - - if (isBlobKindSupported(core, targetDevice, blobKind)) { - Infer(); - } else { - ExpectSetBlobThrow(); - } -} - -void SetBlobOfKindTest::ExpectSetBlobThrow() { - inferRequest = executableNetwork.CreateInferRequest(); - - for (const auto &input : executableNetwork.GetInputsInfo()) { - const auto &info = input.second; - auto blob = GenerateInput(*info); - EXPECT_THROW(inferRequest.SetBlob(info->name(), blob), - InferenceEngine::Exception); - } -} - -void SetBlobOfKindTest::SetUp() { - SizeVector IS{4, 3, 6, 8}; - std::tie(blobKind, targetDevice, configuration) = this->GetParam(); - - auto ngPrc = FuncTestUtils::PrecisionUtils::convertIE2nGraphPrc(Precision::FP32); - auto params = ngraph::builder::makeParams(ngPrc, {IS}); - auto paramOuts = ngraph::helpers::convert2OutputVector(ngraph::helpers::castOps2Nodes(params)); - auto axisNode = std::make_shared(ngraph::element::Type_t::i64, ngraph::Shape{}, std::vector{-1})->output(0); - auto cumSum = std::dynamic_pointer_cast(ngraph::builder::makeCumSum(paramOuts[0], axisNode, false, false)); - ngraph::ResultVector results{std::make_shared(cumSum)}; - function = std::make_shared(results, params, "InferSetBlob"); -} - -TEST_P(SetBlobOfKindTest, CompareWithRefs) { - Run(); -} - -} // namespace BehaviorTestsDefinitions diff --git a/inference-engine/tests/functional/shared_test_classes/include/shared_test_classes/base/layer_test_utils.hpp b/inference-engine/tests/functional/shared_test_classes/include/shared_test_classes/base/layer_test_utils.hpp index 9140f970cff..0fffe60ead7 100644 --- a/inference-engine/tests/functional/shared_test_classes/include/shared_test_classes/base/layer_test_utils.hpp +++ b/inference-engine/tests/functional/shared_test_classes/include/shared_test_classes/base/layer_test_utils.hpp @@ -33,7 +33,7 @@ namespace LayerTestsUtils { -constexpr std::size_t maxFileNameLength = 140; + using TargetDevice = std::string; diff --git a/inference-engine/tests/functional/shared_test_classes/src/base/layer_test_utils.cpp b/inference-engine/tests/functional/shared_test_classes/src/base/layer_test_utils.cpp index b9f679cb2a9..7ba0a1d90b4 100644 --- a/inference-engine/tests/functional/shared_test_classes/src/base/layer_test_utils.cpp +++ b/inference-engine/tests/functional/shared_test_classes/src/base/layer_test_utils.cpp @@ -67,7 +67,7 @@ void LayerTestsCommon::Run() { void LayerTestsCommon::Serialize() { SKIP_IF_CURRENT_TEST_IS_DISABLED(); - std::string output_name = GetTestName().substr(0, maxFileNameLength) + "_" + GetTimestamp(); + std::string output_name = GetTestName().substr(0, CommonTestUtils::maxFileNameLength) + "_" + GetTimestamp(); std::string out_xml_path = output_name + ".xml"; std::string out_bin_path = output_name + ".bin"; diff --git a/inference-engine/tests/ie_test_utils/common_test_utils/common_utils.hpp b/inference-engine/tests/ie_test_utils/common_test_utils/common_utils.hpp index 39ea049ba1a..9c20a00913d 100644 --- a/inference-engine/tests/ie_test_utils/common_test_utils/common_utils.hpp +++ b/inference-engine/tests/ie_test_utils/common_test_utils/common_utils.hpp @@ -134,4 +134,12 @@ inline std::string GetTimestamp() { return std::to_string(ns.count()); } +inline std::ostream& operator<<(std::ostream& os, const std::map& config) { + os << "("; + for (const auto& configItem : config) { + os << configItem.first << "=" << configItem.second << "_"; + } + os << ")"; + return os; +} } // namespace CommonTestUtils diff --git a/inference-engine/tests/ie_test_utils/common_test_utils/test_constants.hpp b/inference-engine/tests/ie_test_utils/common_test_utils/test_constants.hpp index 21dbeef03b0..7d8087fb925 100644 --- a/inference-engine/tests/ie_test_utils/common_test_utils/test_constants.hpp +++ b/inference-engine/tests/ie_test_utils/common_test_utils/test_constants.hpp @@ -20,6 +20,8 @@ const char DEVICE_HETERO[] = "HETERO"; const char REPORT_FILENAME[] = "report"; const char REPORT_EXTENSION[] = ".xml"; +const unsigned int maxFileNameLength = 140; + #ifdef _WIN32 #ifdef __MINGW32__ const char pre[] = "lib"; diff --git a/inference-engine/tests/ie_test_utils/functional_test_utils/include/functional_test_utils/blob_utils.hpp b/inference-engine/tests/ie_test_utils/functional_test_utils/include/functional_test_utils/blob_utils.hpp index 88a4cf280fb..cf8133127a4 100644 --- a/inference-engine/tests/ie_test_utils/functional_test_utils/include/functional_test_utils/blob_utils.hpp +++ b/inference-engine/tests/ie_test_utils/functional_test_utils/include/functional_test_utils/blob_utils.hpp @@ -471,17 +471,21 @@ inline InferenceEngine::Blob::Ptr createAndFillBlob(const InferenceEngine::Tenso blob->allocate(); switch (td.getPrecision()) { #define CASE(X) case X: CommonTestUtils::fill_data_random(blob, range, start_from, resolution, seed); break; + CASE(InferenceEngine::Precision::FP64) CASE(InferenceEngine::Precision::FP32) CASE(InferenceEngine::Precision::FP16) CASE(InferenceEngine::Precision::BF16) + CASE(InferenceEngine::Precision::U4) CASE(InferenceEngine::Precision::U8) + CASE(InferenceEngine::Precision::U32) CASE(InferenceEngine::Precision::U16) + CASE(InferenceEngine::Precision::U64) + CASE(InferenceEngine::Precision::I4) CASE(InferenceEngine::Precision::I8) CASE(InferenceEngine::Precision::I16) - CASE(InferenceEngine::Precision::I64) - CASE(InferenceEngine::Precision::U64) - CASE(InferenceEngine::Precision::BIN) CASE(InferenceEngine::Precision::I32) + CASE(InferenceEngine::Precision::I64) + CASE(InferenceEngine::Precision::BIN) CASE(InferenceEngine::Precision::BOOL) #undef CASE default: @@ -648,45 +652,122 @@ inline short reducePrecisionBitwiseS(const float in) { } // namespace Bf16TestUtils -enum class BlobKind { - Simple, +enum class BlobType { + Memory, + Batched, Compound, - BatchOfSimple +// Remote, + I420, + NV12, }; -inline std::ostream& operator<<(std::ostream& os, BlobKind kind) { - switch (kind) { - case BlobKind::Simple: - return os << "Simple"; - case BlobKind::Compound: +inline std::ostream& operator<<(std::ostream& os, BlobType type) { + switch (type) { + case BlobType::Memory: + return os << "Memory"; + case BlobType::Batched: + return os << "Batched"; + case BlobType::Compound: return os << "Compound"; - case BlobKind::BatchOfSimple: - return os << "BatchOfSimple"; +// case BlobType::Remote: +// return os << "Remote"; + case BlobType::I420: + return os << "I40"; + case BlobType::NV12: + return os << "NV12"; default: - IE_THROW() << "Test does not support the blob kind"; - } + IE_THROW() << "Not supported blob type"; + } } -inline InferenceEngine::Blob::Ptr makeBlobOfKind(const InferenceEngine::TensorDesc& td, BlobKind blobKind) { - using namespace ::InferenceEngine; - switch (blobKind) { - case BlobKind::Simple: +inline InferenceEngine::Blob::Ptr createBlobByType(const InferenceEngine::TensorDesc& td, BlobType blobType) { + switch (blobType) { + case BlobType::Memory: return createAndFillBlob(td); - case BlobKind::Compound: - return make_shared_blob(std::vector{}); - case BlobKind::BatchOfSimple: { - const auto subBlobsNum = td.getDims()[0]; - auto subBlobDesc = td; - subBlobDesc.getDims()[0] = 1; - std::vector subBlobs; + case BlobType::Batched: + case BlobType::Compound: { + auto dims = td.getDims(); + const size_t subBlobsNum = dims.front(); + dims[0] = 1; + std::vector subBlobs; + InferenceEngine::TensorDesc subBlobDesc(td.getPrecision(), dims, td.getLayout()); for (size_t i = 0; i < subBlobsNum; i++) { - subBlobs.push_back(makeBlobOfKind(subBlobDesc, BlobKind::Simple)); + subBlobs.push_back(createAndFillBlob(subBlobDesc)); } - return make_shared_blob(subBlobs); + return blobType == BlobType::Batched ? InferenceEngine::make_shared_blob(subBlobs) : + InferenceEngine::make_shared_blob(subBlobs); + } +// TODO: ocl + remote +// case BlobType::Remote: +// return InferenceEngine::as(createAndFillBlob(td)); + case BlobType::I420: { + InferenceEngine::SizeVector dims = td.getDims(); + dims[1] = 1; + InferenceEngine::TensorDesc td1(InferenceEngine::Precision::U8, dims, InferenceEngine::Layout::NHWC); + InferenceEngine::Blob::Ptr y_blob = createAndFillBlob(td1); + dims[2] /= 2; + dims[3] /= 2; + td1 = InferenceEngine::TensorDesc(InferenceEngine::Precision::U8, dims, InferenceEngine::Layout::NHWC); + InferenceEngine::Blob::Ptr u_blob = createAndFillBlob(td1); + InferenceEngine::Blob::Ptr v_blob = createAndFillBlob(td1); + return InferenceEngine::make_shared_blob(y_blob, u_blob, v_blob); + } + case BlobType::NV12: { + InferenceEngine::SizeVector dims = td.getDims(); + dims[1] = 1; + InferenceEngine::TensorDesc td1(InferenceEngine::Precision::U8, dims, InferenceEngine::Layout::NHWC); + InferenceEngine::Blob::Ptr y_blob = createAndFillBlob(td1); + dims[1] = 2; + dims[2] /= 2; + dims[3] /= 2; + td1 = InferenceEngine::TensorDesc(InferenceEngine::Precision::U8, dims, InferenceEngine::Layout::NHWC); + InferenceEngine::Blob::Ptr uv_blob = createAndFillBlob(td1); + return InferenceEngine::make_shared_blob(y_blob, uv_blob); } default: IE_THROW() << "Test does not support the blob kind"; } } +inline bool checkLayout(InferenceEngine::Layout layout, const std::vector &inputShapes) { + bool check = false; + switch (layout) { + case InferenceEngine::Layout::SCALAR: + check = inputShapes.size() == 0; + break; + case InferenceEngine::Layout::C: + check = 1 == inputShapes.size(); + break; + case InferenceEngine::Layout::BLOCKED: + case InferenceEngine::Layout::ANY: + check = true; + break; + case InferenceEngine::Layout::GOIDHW: + check = 6 == inputShapes.size(); + break; + case InferenceEngine::Layout::NCDHW: + case InferenceEngine::Layout::NDHWC: + case InferenceEngine::Layout::OIDHW: + case InferenceEngine::Layout::GOIHW: + check = 5 == inputShapes.size(); + break; + case InferenceEngine::Layout::OIHW: + case InferenceEngine::Layout::NCHW: + case InferenceEngine::Layout::NHWC: + check = 4 == inputShapes.size(); + break; + case InferenceEngine::Layout::CHW: + case InferenceEngine::Layout::HWC: + check = 3 == inputShapes.size(); + break; + case InferenceEngine::Layout::CN: + case InferenceEngine::Layout::NC: + case InferenceEngine::Layout::HW: + check = 2 == inputShapes.size(); + break; + default: + break; + } + return check; +} } // namespace FuncTestUtils diff --git a/inference-engine/tests/unit/inference_engine/cpp_interfaces/ie_memory_state_internal_test.cpp b/inference-engine/tests/unit/inference_engine/cpp_interfaces/ie_memory_state_internal_test.cpp index dec0f9e9d29..bf6ba93750c 100644 --- a/inference-engine/tests/unit/inference_engine/cpp_interfaces/ie_memory_state_internal_test.cpp +++ b/inference-engine/tests/unit/inference_engine/cpp_interfaces/ie_memory_state_internal_test.cpp @@ -20,7 +20,7 @@ using namespace InferenceEngine; using namespace InferenceEngine::details; -class VariableStateTests : public ::testing::Test { +class InferRequestVariableStateTests : public ::testing::Test { protected: shared_ptr mockExeNetworkInternal; shared_ptr mockInferRequestInternal; @@ -43,7 +43,7 @@ class VariableStateTests : public ::testing::Test { } }; -TEST_F(VariableStateTests, ExecutableNetworkCanConvertOneVariableStateFromCppToAPI) { +TEST_F(InferRequestVariableStateTests, ExecutableNetworkCanConvertOneVariableStateFromCppToAPI) { IE_SUPPRESS_DEPRECATED_START std::vector toReturn(1); toReturn[0] = mockVariableStateInternal; @@ -55,7 +55,7 @@ TEST_F(VariableStateTests, ExecutableNetworkCanConvertOneVariableStateFromCppToA IE_SUPPRESS_DEPRECATED_END } -TEST_F(VariableStateTests, ExecutableNetworkCanConvertZeroVariableStateFromCppToAPI) { +TEST_F(InferRequestVariableStateTests, ExecutableNetworkCanConvertZeroVariableStateFromCppToAPI) { IE_SUPPRESS_DEPRECATED_START std::vector toReturn; @@ -66,7 +66,7 @@ TEST_F(VariableStateTests, ExecutableNetworkCanConvertZeroVariableStateFromCppTo IE_SUPPRESS_DEPRECATED_END } -TEST_F(VariableStateTests, ExecutableNetworkCanConvert2VariableStatesFromCPPtoAPI) { +TEST_F(InferRequestVariableStateTests, ExecutableNetworkCanConvert2VariableStatesFromCPPtoAPI) { IE_SUPPRESS_DEPRECATED_START std::vector toReturn; toReturn.push_back(mockVariableStateInternal); @@ -79,7 +79,7 @@ TEST_F(VariableStateTests, ExecutableNetworkCanConvert2VariableStatesFromCPPtoAP IE_SUPPRESS_DEPRECATED_END } -TEST_F(VariableStateTests, VariableStatePropagatesReset) { +TEST_F(InferRequestVariableStateTests, VariableStatePropagatesReset) { IE_SUPPRESS_DEPRECATED_START std::vector toReturn; toReturn.push_back(mockVariableStateInternal); @@ -92,7 +92,7 @@ TEST_F(VariableStateTests, VariableStatePropagatesReset) { IE_SUPPRESS_DEPRECATED_END } -TEST_F(VariableStateTests, VariableStatePropagatesExceptionsFromReset) { +TEST_F(InferRequestVariableStateTests, VariableStatePropagatesExceptionsFromReset) { IE_SUPPRESS_DEPRECATED_START std::vector toReturn; toReturn.push_back(mockVariableStateInternal); @@ -105,7 +105,7 @@ TEST_F(VariableStateTests, VariableStatePropagatesExceptionsFromReset) { IE_SUPPRESS_DEPRECATED_END } -TEST_F(VariableStateTests, VariableStatePropagatesGetName) { +TEST_F(InferRequestVariableStateTests, VariableStatePropagatesGetName) { IE_SUPPRESS_DEPRECATED_START std::vector toReturn; toReturn.push_back(mockVariableStateInternal); @@ -118,7 +118,7 @@ TEST_F(VariableStateTests, VariableStatePropagatesGetName) { IE_SUPPRESS_DEPRECATED_END } -TEST_F(VariableStateTests, VariableStatePropagatesGetNameWithZeroLen) { +TEST_F(InferRequestVariableStateTests, VariableStatePropagatesGetNameWithZeroLen) { IE_SUPPRESS_DEPRECATED_START std::vector toReturn; toReturn.push_back(mockVariableStateInternal); @@ -132,7 +132,7 @@ TEST_F(VariableStateTests, VariableStatePropagatesGetNameWithZeroLen) { } -TEST_F(VariableStateTests, VariableStatePropagatesGetNameWithLenOfOne) { +TEST_F(InferRequestVariableStateTests, VariableStatePropagatesGetNameWithLenOfOne) { IE_SUPPRESS_DEPRECATED_START std::vector toReturn; toReturn.push_back(mockVariableStateInternal); @@ -147,7 +147,7 @@ TEST_F(VariableStateTests, VariableStatePropagatesGetNameWithLenOfOne) { IE_SUPPRESS_DEPRECATED_END } -TEST_F(VariableStateTests, VariableStatePropagatesGetNameWithLenOfTwo) { +TEST_F(InferRequestVariableStateTests, VariableStatePropagatesGetNameWithLenOfTwo) { IE_SUPPRESS_DEPRECATED_START std::vector toReturn; toReturn.push_back(mockVariableStateInternal); @@ -162,7 +162,7 @@ TEST_F(VariableStateTests, VariableStatePropagatesGetNameWithLenOfTwo) { IE_SUPPRESS_DEPRECATED_END } -TEST_F(VariableStateTests, VariableStateCanPropagateSetState) { +TEST_F(InferRequestVariableStateTests, VariableStateCanPropagateSetState) { IE_SUPPRESS_DEPRECATED_START std::vector toReturn; Blob::Ptr saver; @@ -181,7 +181,7 @@ TEST_F(VariableStateTests, VariableStateCanPropagateSetState) { IE_SUPPRESS_DEPRECATED_END } -TEST_F(VariableStateTests, VariableStateCanPropagateGetLastState) { +TEST_F(InferRequestVariableStateTests, VariableStateCanPropagateGetLastState) { IE_SUPPRESS_DEPRECATED_START std::vector toReturn; toReturn.push_back(mockVariableStateInternal); @@ -205,12 +205,12 @@ class VariableStateInternalMockImpl : public IVariableStateInternal { MOCK_METHOD0(Reset, void()); }; -TEST_F(VariableStateTests, VariableStateInternalCanSaveName) { +TEST_F(InferRequestVariableStateTests, VariableStateInternalCanSaveName) { IVariableStateInternal::Ptr pState(new VariableStateInternalMockImpl("VariableStateInternalMockImpl")); ASSERT_STREQ(pState->GetName().c_str(), "VariableStateInternalMockImpl"); } -TEST_F(VariableStateTests, VariableStateInternalCanSaveState) { +TEST_F(InferRequestVariableStateTests, VariableStateInternalCanSaveState) { IVariableStateInternal::Ptr pState(new VariableStateInternalMockImpl("VariableStateInternalMockImpl")); float data[] = {123, 124, 125}; auto stateBlob = make_shared_blob({ Precision::FP32, {3}, C }, data, sizeof(data) / sizeof(*data)); @@ -225,7 +225,7 @@ TEST_F(VariableStateTests, VariableStateInternalCanSaveState) { } -TEST_F(VariableStateTests, VariableStateInternalCanSaveStateByReference) { +TEST_F(InferRequestVariableStateTests, VariableStateInternalCanSaveStateByReference) { IVariableStateInternal::Ptr pState(new VariableStateInternalMockImpl("VariableStateInternalMockImpl")); float data[] = {123, 124, 125}; auto stateBlob = make_shared_blob({ Precision::FP32, {3}, C }, data, sizeof(data) / sizeof(*data)); @@ -244,7 +244,7 @@ TEST_F(VariableStateTests, VariableStateInternalCanSaveStateByReference) { } // Tests for InferRequest::QueryState -TEST_F(VariableStateTests, InferRequestCanConvertOneVariableStateFromCppToAPI) { +TEST_F(InferRequestVariableStateTests, InferRequestCanConvertOneVariableStateFromCppToAPI) { std::vector toReturn(1); toReturn[0] = mockVariableStateInternal; @@ -254,7 +254,7 @@ TEST_F(VariableStateTests, InferRequestCanConvertOneVariableStateFromCppToAPI) { ASSERT_EQ(state.size(), 1); } -TEST_F(VariableStateTests, InferRequestCanConvertZeroVariableStateFromCppToAPI) { +TEST_F(InferRequestVariableStateTests, InferRequestCanConvertZeroVariableStateFromCppToAPI) { std::vector toReturn; EXPECT_CALL(*mockInferRequestInternal.get(), QueryState()).WillOnce(Return(toReturn)); @@ -263,7 +263,7 @@ TEST_F(VariableStateTests, InferRequestCanConvertZeroVariableStateFromCppToAPI) ASSERT_EQ(state.size(), 0); } -TEST_F(VariableStateTests, InferRequestCanConvert2VariableStatesFromCPPtoAPI) { +TEST_F(InferRequestVariableStateTests, InferRequestCanConvert2VariableStatesFromCPPtoAPI) { std::vector toReturn; toReturn.push_back(mockVariableStateInternal); toReturn.push_back(mockVariableStateInternal); @@ -274,7 +274,7 @@ TEST_F(VariableStateTests, InferRequestCanConvert2VariableStatesFromCPPtoAPI) { ASSERT_EQ(state.size(), 2); } -TEST_F(VariableStateTests, InfReqVariableStatePropagatesReset) { +TEST_F(InferRequestVariableStateTests, InfReqVariableStatePropagatesReset) { std::vector toReturn; toReturn.push_back(mockVariableStateInternal); @@ -285,7 +285,7 @@ TEST_F(VariableStateTests, InfReqVariableStatePropagatesReset) { state.front()->Reset(); } -TEST_F(VariableStateTests, InfReqVariableStatePropagatesExceptionsFromReset) { +TEST_F(InferRequestVariableStateTests, InfReqVariableStatePropagatesExceptionsFromReset) { std::vector toReturn; toReturn.push_back(mockVariableStateInternal); @@ -296,7 +296,7 @@ TEST_F(VariableStateTests, InfReqVariableStatePropagatesExceptionsFromReset) { EXPECT_ANY_THROW(state.front()->Reset()); } -TEST_F(VariableStateTests, InfReqVariableStatePropagatesGetName) { +TEST_F(InferRequestVariableStateTests, InfReqVariableStatePropagatesGetName) { std::vector toReturn; toReturn.push_back(mockVariableStateInternal); @@ -307,7 +307,7 @@ TEST_F(VariableStateTests, InfReqVariableStatePropagatesGetName) { EXPECT_STREQ(state.front()->GetName().c_str(), "someName"); } -TEST_F(VariableStateTests, InfReqVariableStateCanPropagateSetState) { +TEST_F(InferRequestVariableStateTests, InfReqVariableStateCanPropagateSetState) { std::vector toReturn; Blob::Ptr saver; toReturn.push_back(mockVariableStateInternal); @@ -324,7 +324,7 @@ TEST_F(VariableStateTests, InfReqVariableStateCanPropagateSetState) { ASSERT_FLOAT_EQ(saver->buffer().as()[2], 125); } -TEST_F(VariableStateTests, InfReqVariableStateCanPropagateGetLastState) { +TEST_F(InferRequestVariableStateTests, InfReqVariableStateCanPropagateGetLastState) { std::vector toReturn; float data[] = {123, 124, 125}; From 48c7247a914eda8c33ad07a319b830ded24a5f13 Mon Sep 17 00:00:00 2001 From: Alexey Lebedev Date: Wed, 25 Aug 2021 15:03:11 +0300 Subject: [PATCH 37/76] [IE PYTHON] remove useless variables (#7229) * Remove ie_core_impl from Executable Network * remove to_std_string function * Remove some variables in Blob constructor --- .../python/src/openvino/inference_engine/ie_api.pxd | 1 - .../python/src/openvino/inference_engine/ie_api.pyx | 8 -------- 2 files changed, 9 deletions(-) diff --git a/inference-engine/ie_bridges/python/src/openvino/inference_engine/ie_api.pxd b/inference-engine/ie_bridges/python/src/openvino/inference_engine/ie_api.pxd index efb389259d3..e7d4f2c85a7 100644 --- a/inference-engine/ie_bridges/python/src/openvino/inference_engine/ie_api.pxd +++ b/inference-engine/ie_bridges/python/src/openvino/inference_engine/ie_api.pxd @@ -47,7 +47,6 @@ cdef class IENetwork: cdef class ExecutableNetwork: cdef unique_ptr[C.IEExecNetwork] impl - cdef C.IECore ie_core_impl cpdef wait(self, num_requests = ?, timeout = ?) cpdef get_idle_request_id(self) cdef public: diff --git a/inference-engine/ie_bridges/python/src/openvino/inference_engine/ie_api.pyx b/inference-engine/ie_bridges/python/src/openvino/inference_engine/ie_api.pyx index 5f7a0a02bcb..109a6a51a02 100644 --- a/inference-engine/ie_bridges/python/src/openvino/inference_engine/ie_api.pyx +++ b/inference-engine/ie_bridges/python/src/openvino/inference_engine/ie_api.pyx @@ -35,9 +35,6 @@ warnings.filterwarnings(action="module", category=DeprecationWarning) cdef extern from "" namespace "std" nogil: cdef unique_ptr[C.IEExecNetwork] move(unique_ptr[C.IEExecNetwork]) -cdef string to_std_string(str py_string): - return py_string.encode() - cdef to_py_string(const string & std_string): return bytes(std_string).decode() @@ -167,9 +164,6 @@ cdef class Blob: cdef uint32_t[::1] U32_array_memview cdef uint64_t[::1] U64_array_memview - cdef int16_t[:] x_as_uint - cdef int16_t[:] y_as_uint - self._is_const = False self._array_data = array self._initial_shape = array.shape if array is not None else None @@ -379,7 +373,6 @@ cdef class IECore: "or zero for auto detection") if config: c_config = dict_to_c_map(config) - exec_net.ie_core_impl = self.impl c_device_name = device_name.encode() if isinstance(network, str): c_network_path = network.encode() @@ -416,7 +409,6 @@ cdef class IECore: "or zero for auto detection") if config: c_config = dict_to_c_map(config) - exec_net.ie_core_impl = self.impl exec_net.impl = move(self.impl.importNetwork(model_file.encode(), device_name.encode(), c_config, num_requests)) return exec_net From 0a4781f3441aaa7595fdcb457461ac6ff5859264 Mon Sep 17 00:00:00 2001 From: Ilya Churaev Date: Wed, 25 Aug 2021 16:54:48 +0300 Subject: [PATCH 38/76] Moved ngraph::ngraph_error to ov::Exception (#7235) --- ngraph/core/include/ngraph/except.hpp | 15 +++++-------- ngraph/core/include/openvino/core/except.hpp | 23 ++++++++++++++++++++ ngraph/test/backend/unhandled_op.in.cpp | 2 ++ 3 files changed, 31 insertions(+), 9 deletions(-) create mode 100644 ngraph/core/include/openvino/core/except.hpp diff --git a/ngraph/core/include/ngraph/except.hpp b/ngraph/core/include/ngraph/except.hpp index aef9b67b53c..e965c625098 100644 --- a/ngraph/core/include/ngraph/except.hpp +++ b/ngraph/core/include/ngraph/except.hpp @@ -4,22 +4,19 @@ #pragma once +#include #include #include #include +#include "openvino/core/except.hpp" + namespace ngraph { /// Base error for ngraph runtime errors. -class NGRAPH_API ngraph_error : public std::runtime_error { -public: - explicit ngraph_error(const std::string& what_arg) : std::runtime_error(what_arg) {} +using ngraph_error = ov::Exception; - explicit ngraph_error(const char* what_arg) : std::runtime_error(what_arg) {} - - explicit ngraph_error(const std::stringstream& what_arg) : std::runtime_error(what_arg.str()) {} -}; - -class NGRAPH_API unsupported_op : public std::runtime_error { +class NGRAPH_DEPRECATED("This class is deprecated and will be removed soon.") NGRAPH_API unsupported_op + : public std::runtime_error { public: unsupported_op(const std::string& what_arg) : std::runtime_error(what_arg) {} }; diff --git a/ngraph/core/include/openvino/core/except.hpp b/ngraph/core/include/openvino/core/except.hpp new file mode 100644 index 00000000000..30372a344d4 --- /dev/null +++ b/ngraph/core/include/openvino/core/except.hpp @@ -0,0 +1,23 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +#include +#include + +#include "openvino/core/core_visibility.hpp" + +namespace ov { +/// Base error for ov runtime errors. +class OPENVINO_API Exception : public std::runtime_error { +public: + explicit Exception(const std::string& what_arg) : std::runtime_error(what_arg) {} + + explicit Exception(const char* what_arg) : std::runtime_error(what_arg) {} + + explicit Exception(const std::stringstream& what_arg) : std::runtime_error(what_arg.str()) {} +}; + +} // namespace ov diff --git a/ngraph/test/backend/unhandled_op.in.cpp b/ngraph/test/backend/unhandled_op.in.cpp index d7727cfcbb5..2a88ccd4531 100644 --- a/ngraph/test/backend/unhandled_op.in.cpp +++ b/ngraph/test/backend/unhandled_op.in.cpp @@ -38,6 +38,7 @@ constexpr NodeTypeInfo UnhandledOp::type_info; } // namespace NGRAPH_TEST(${BACKEND_NAME}, unhandled_op) { + NGRAPH_SUPPRESS_DEPRECATED_START Shape shape{2, 2}; auto A = make_shared(element::f32, shape); auto unhandled = make_shared(A); @@ -47,4 +48,5 @@ NGRAPH_TEST(${BACKEND_NAME}, unhandled_op) { shared_ptr a = backend->create_tensor(shape); shared_ptr result = backend->create_tensor(shape); ASSERT_THROW(auto handle = backend->compile(f); handle->call_with_validate({result}, {a}), unsupported_op); + NGRAPH_SUPPRESS_DEPRECATED_END } From dec93bb2f14281f9182f31231012f3ddb9730c53 Mon Sep 17 00:00:00 2001 From: Gleb Kazantaev Date: Wed, 25 Aug 2021 18:04:12 +0300 Subject: [PATCH 39/76] IR FrontEnd (#7152) * IR FronteEnd * Codestyle fix * Fix typo * Fix cmake * Fix build * Cleanup includes * Fix build * Cleanup * use ie_option --- cmake/features.cmake | 5 +- cmake/templates/ngraphConfig.cmake.in | 1 + inference-engine/src/CMakeLists.txt | 3 +- .../src/readers/ir_reader/CMakeLists.txt | 2 + .../src/readers/ir_reader/ie_ir_parser.cpp | 919 +---------------- .../src/readers/ir_reader/ie_ir_parser.hpp | 21 - ngraph/frontend/CMakeLists.txt | 4 + ngraph/frontend/ir/CMakeLists.txt | 61 ++ .../ir/include/ir_frontend/frontend.hpp | 80 ++ .../frontend/ir/include/ir_frontend/model.hpp | 35 + .../ir/include/ir_frontend/utility.hpp | 22 + ngraph/frontend/ir/src/frontend.cpp | 86 ++ ngraph/frontend/ir/src/model.cpp | 938 ++++++++++++++++++ 13 files changed, 1241 insertions(+), 936 deletions(-) create mode 100644 ngraph/frontend/ir/CMakeLists.txt create mode 100644 ngraph/frontend/ir/include/ir_frontend/frontend.hpp create mode 100644 ngraph/frontend/ir/include/ir_frontend/model.hpp create mode 100644 ngraph/frontend/ir/include/ir_frontend/utility.hpp create mode 100644 ngraph/frontend/ir/src/frontend.cpp create mode 100644 ngraph/frontend/ir/src/model.cpp diff --git a/cmake/features.cmake b/cmake/features.cmake index 3df1af5ef91..cf9fbebbe94 100644 --- a/cmake/features.cmake +++ b/cmake/features.cmake @@ -124,6 +124,7 @@ endif() ie_dependent_option(NGRAPH_ONNX_FRONTEND_ENABLE "Enable ONNX FrontEnd" ON "protoc_available" OFF) ie_dependent_option(NGRAPH_PDPD_FRONTEND_ENABLE "Enable PaddlePaddle FrontEnd" ON "protoc_available" OFF) +ie_option(IR_FRONTEND_ENABLE "Enable IR FrontEnd" ON) ie_dependent_option(NGRAPH_USE_PROTOBUF_LITE "Compiles and links with protobuf-lite" ON "NGRAPH_ONNX_FRONTEND_ENABLE" OFF) ie_dependent_option(NGRAPH_USE_SYSTEM_PROTOBUF "Use system protobuf" OFF @@ -131,8 +132,8 @@ ie_dependent_option(NGRAPH_USE_SYSTEM_PROTOBUF "Use system protobuf" OFF ie_dependent_option(NGRAPH_UNIT_TEST_ENABLE "Enables ngraph unit tests" ON "ENABLE_TESTS;NOT ANDROID" OFF) ie_dependent_option(NGRAPH_UNIT_TEST_BACKENDS_ENABLE "Control the building of unit tests using backends" ON "NGRAPH_UNIT_TEST_ENABLE" OFF) -option(NGRAPH_DEBUG_ENABLE "Enable output for NGRAPH_DEBUG statements" OFF) -option(ENABLE_REQUIREMENTS_INSTALL "Dynamic dependencies install" ON) +ie_option(NGRAPH_DEBUG_ENABLE "Enable output for NGRAPH_DEBUG statements" OFF) +ie_option(ENABLE_REQUIREMENTS_INSTALL "Dynamic dependencies install" ON) # WA for ngraph python build on Windows debug list(REMOVE_ITEM IE_OPTIONS NGRAPH_UNIT_TEST_ENABLE NGRAPH_UNIT_TEST_BACKENDS_ENABLE) diff --git a/cmake/templates/ngraphConfig.cmake.in b/cmake/templates/ngraphConfig.cmake.in index 543c14daba6..1c17cbeb4cc 100644 --- a/cmake/templates/ngraphConfig.cmake.in +++ b/cmake/templates/ngraphConfig.cmake.in @@ -59,5 +59,6 @@ if(ngraph_onnx_importer_FOUND) endif() set(ngraph_paddlepaddle_frontend_FOUND @NGRAPH_PDPD_FRONTEND_ENABLE@) +set(ir_frontend_FOUND @IR_FRONTEND_ENABLE@) check_required_components(ngraph) diff --git a/inference-engine/src/CMakeLists.txt b/inference-engine/src/CMakeLists.txt index 5f3959223fb..2b53ce68481 100644 --- a/inference-engine/src/CMakeLists.txt +++ b/inference-engine/src/CMakeLists.txt @@ -50,7 +50,8 @@ add_custom_target(ie_libraries ALL DEPENDS inference_engine_transformations inference_engine_legacy inference_engine inference_engine_preproc inference_engine_ir_v7_reader inference_engine_ir_reader - inference_engine_lp_transformations inference_engine_snippets) + inference_engine_lp_transformations inference_engine_snippets + ir_frontend) if(NGRAPH_ONNX_FRONTEND_ENABLE) add_dependencies(ie_libraries inference_engine_onnx_reader) diff --git a/inference-engine/src/readers/ir_reader/CMakeLists.txt b/inference-engine/src/readers/ir_reader/CMakeLists.txt index cdf265567c0..6433bd7cf1e 100644 --- a/inference-engine/src/readers/ir_reader/CMakeLists.txt +++ b/inference-engine/src/readers/ir_reader/CMakeLists.txt @@ -29,6 +29,8 @@ target_compile_definitions(${TARGET_NAME} PRIVATE IMPLEMENT_INFERENCE_ENGINE_PLU target_include_directories(${TARGET_NAME} PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}") target_link_libraries(${TARGET_NAME} PRIVATE ngraph + ir_frontend + frontend_manager inference_engine_reader_api inference_engine_plugin_api inference_engine diff --git a/inference-engine/src/readers/ir_reader/ie_ir_parser.cpp b/inference-engine/src/readers/ir_reader/ie_ir_parser.cpp index 5faf7bc37c4..95d087a9d68 100644 --- a/inference-engine/src/readers/ir_reader/ie_ir_parser.cpp +++ b/inference-engine/src/readers/ir_reader/ie_ir_parser.cpp @@ -5,23 +5,11 @@ #include "ie_ir_parser.hpp" #include "ie_ir_itt.hpp" -#include -#include -#include #include #include #include -#include +#include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include #include #include @@ -29,10 +17,7 @@ #include #include -#include #include "blob_factory.hpp" -#include "caseless.hpp" -#include "precision_utils.h" using namespace XMLParseUtils; namespace InferenceEngine { @@ -54,886 +39,18 @@ CNNNetwork IRParser::parse( return parser->parse(root, weights); } -namespace { - -bool getStrAttribute(const pugi::xml_node& node, const std::string& name, std::string& value) { - if (!node) return false; - - auto attr = node.attribute(name.c_str()); - if (attr.empty()) return false; - value = std::string(attr.value()); - return true; -} - -template -bool getParameters(const pugi::xml_node& node, const std::string& name, std::vector& value) { - std::string param; - if (!getStrAttribute(node, name, param)) return false; - std::stringstream ss(param); - std::string field; - while (getline(ss, field, ',')) { - if (field.empty()) - IE_THROW() << "Cannot get vector of parameters! \"" << param - << "\" is incorrect"; - std::stringstream fs(field); - T val; - fs >> val; - value.emplace_back(val); - } - return true; -} - -template -T stringToType(const std::string& valStr) { - T ret{0}; - std::istringstream ss(valStr); - if (!ss.eof()) { - ss >> ret; - } - return ret; -} - -class XmlDeserializer : public ngraph::AttributeVisitor { -public: - /// TODO: move whole class to src file - explicit XmlDeserializer( - const pugi::xml_node& node, - const Blob::CPtr& weights, - const std::unordered_map& opsets, - std::unordered_map>& variables) - : node(node), weights(weights), opsets(opsets), variables(variables) {} - - void on_adapter(const std::string& name, ngraph::ValueAccessor& value) override { - std::string val; - if (!getStrAttribute(node.child("data"), name, val)) return; - value.set(val); - } - void on_adapter(const std::string& name, ngraph::ValueAccessor& value) override { - std::string val; - if (!getStrAttribute(node.child("data"), name, val)) return; - std::transform(val.begin(), val.end(), val.begin(), [](char ch) { - return std::tolower(static_cast(ch)); - }); - std::set true_names{"true", "1"}; - std::set false_names{"false", "0"}; - - bool is_true = true_names.find(val) != true_names.end(); - bool is_false = false_names.find(val) != false_names.end(); - - if (!is_true && !is_false) return; - value.set(is_true); - } - void on_adapter(const std::string& name, ngraph::ValueAccessor& adapter) override; - - void on_adapter(const std::string& name, ngraph::ValueAccessor& adapter) override { - std::string val; - if (!getStrAttribute(node.child("data"), name, val)) return; - adapter.set(stringToType(val)); - } - void on_adapter(const std::string& name, ngraph::ValueAccessor& adapter) override { - std::string val; - if (!getStrAttribute(node.child("data"), name, val)) return; - adapter.set(stringToType(val)); - } - - void on_adapter( - const std::string& name, - ngraph::ValueAccessor>& adapter) override; - - void on_adapter( - const std::string& name, ngraph::ValueAccessor>& adapter) override { - std::vector value; - if (!getParameters(node.child("data"), name, value)) return; - adapter.set(value); - } - - void on_adapter( - const std::string& name, ngraph::ValueAccessor>& adapter) override { - std::vector value; - if (!getParameters(node.child("data"), name, value)) return; - adapter.set(value); - } - - void on_adapter( - const std::string& name, ngraph::ValueAccessor>& adapter) override { - std::vector value; - if (!getParameters(node.child("data"), name, value)) return; - adapter.set(value); - } - - void on_adapter( - const std::string& name, - ngraph::ValueAccessor>& adapter) override { - std::vector value; - if (!getParameters(node.child("data"), name, value)) return; - adapter.set(value); - } - - void use_framework_node(bool flag) { m_use_framework_node = flag; } - -private: - struct IoMap { - using NodeIdToIoIndex = - std::unordered_map; - NodeIdToIoIndex inputs; - NodeIdToIoIndex outputs; - }; - - /// \brief Traverses port_map in order to create vector of InputDescription shared_ptrs. - /// Shall be used only for ops which have port_map attribute. - /// \param node xml op representation - std::vector> - parseInputDescription(const pugi::xml_node& node); - /// \brief Traverses port_map in order to create vector of OutputDescription shared_ptrs. - /// Shall be used only for ops which have port_map attribute. - /// \param node xml op representation - std::vector> - parseOutputDescription(const pugi::xml_node& node); - - // TODO consider to call only once per layer/TI-Loop node - IoMap updated_io_map(const pugi::xml_node& node); - - /// \brief Traverses xml node representation in order to create nGraph function for it. - /// \param node xml node representation - /// \param weights weights attached to current node - /// \return shared pointer to function representing input node - std::shared_ptr parse_function( - const pugi::xml_node& root, const Blob::CPtr& weights); - /// \brief Traverses xml node representation in order to get the purpose attribute of - /// inputs/outputs in the body of Loop op. \param node xml node representation \return struct - /// with value of purpuse attribute - ngraph::op::v5::Loop::SpecialBodyPorts parsePurposeAttribute(const pugi::xml_node& node); - - V10Parser::GenericLayerParams parseGenericParams(const pugi::xml_node& node); - - std::shared_ptr createNode( - const ngraph::OutputVector& inputs, - const pugi::xml_node& node, - const Blob::CPtr& weights, - const V10Parser::GenericLayerParams& params); - - // -- DATA -- - const pugi::xml_node node; - const Blob::CPtr& weights; - const std::unordered_map& opsets; - std::unordered_map>& variables; - - /// - /// store information about parameters/results order during function creation - /// it will be used during Inputs/Outputs Description creation in SubGraph processing - /// - IoMap io_map; - - bool m_use_framework_node{false}; -}; - -XmlDeserializer::IoMap XmlDeserializer::updated_io_map(const pugi::xml_node& node) { - auto body_node = node.child("body"); - - if (body_node.empty()) { - IE_THROW() << "Missing body part."; - } - // Fill map: parameter/result id to parameter/result number in Function - - auto extend_io_map = io_map; - - FOREACH_CHILD(layer, body_node.child("layers"), "layer") { - auto type = XMLParseUtils::GetStrAttr(layer, "type"); - - if (type == "Parameter") { - auto id = XMLParseUtils::GetUIntAttr(layer, "id"); - extend_io_map.inputs.insert({id, -1}); // try add as unconnected - } else if (type == "Result") { - auto id = XMLParseUtils::GetUIntAttr(layer, "id"); - extend_io_map.outputs.insert({id, -1}); // try add as unconnected - } - } - return extend_io_map; -} - -std::vector> -XmlDeserializer::parseInputDescription(const pugi::xml_node& node) { - std::vector> inputs; - const auto up_io_map = updated_io_map(node); - - // Parse PortMap: external_port_id for inputs does not always appear in consecutive order - std::map input_map; - FOREACH_CHILD(input, node.child("port_map"), "input") { - int64_t ext_port_id = GetInt64Attr(input, "external_port_id"); - input_map.emplace(ext_port_id, input); - } - - for (const auto& input : input_map) { - auto& xml_input = input.second; - auto axis_attr = xml_input.attribute("axis"); - int64_t ti_input_index = XMLParseUtils::GetInt64Attr(xml_input, "external_port_id"); - size_t body_parameter_index = XMLParseUtils::GetUIntAttr(xml_input, "internal_layer_id"); - - // if axis is set, then slicing is enabled. Create ngraph::TensorIterator::SlicedInput. - if (!axis_attr.empty()) { - size_t axis = XMLParseUtils::GetUIntAttr(xml_input, "axis"); - int64_t start = XMLParseUtils::GetInt64Attr(xml_input, "start", 0); - int64_t stride = XMLParseUtils::GetInt64Attr(xml_input, "stride", 1); - int64_t end = XMLParseUtils::GetInt64Attr(xml_input, "end", -1); - int64_t part_size = XMLParseUtils::GetInt64Attr(xml_input, "part_size", 1); - - const auto input_index = up_io_map.inputs.at(body_parameter_index); - - inputs.push_back(std::make_shared( - ti_input_index, input_index, start, stride, part_size, end, axis)); - } else { - // otherwise find corresponding back edge and create ngraph::TensorIterator::MergedInput - bool is_back_edge_exist = false; - FOREACH_CHILD(xml_edge, node.child("back_edges"), "edge") { - size_t to_layer = XMLParseUtils::GetUIntAttr(xml_edge, "to-layer"); - - if (to_layer == body_parameter_index) { - size_t from_layer = XMLParseUtils::GetUIntAttr(xml_edge, "from-layer"); - - const auto input_index = up_io_map.inputs.at(body_parameter_index); - const auto output_index = up_io_map.outputs.at(from_layer); - - inputs.push_back( - std::make_shared( - ti_input_index, input_index, output_index)); - - is_back_edge_exist = true; - break; - } - } - - // ti_input_index = -1 means that Parameter of the body is not connected to inputs of - // TensorIterator and is used only for internal needs. - if (!is_back_edge_exist && ti_input_index >= 0) { - const auto input_index = up_io_map.inputs.at(body_parameter_index); - - inputs.push_back( - std::make_shared( - ti_input_index, input_index)); - } - } - } - return inputs; -} - -std::vector> -XmlDeserializer::parseOutputDescription(const pugi::xml_node& node) { - std::vector> outputs; - const auto up_io_map = updated_io_map(node); - - // Parse PortMap: outputs - std::map output_map; - FOREACH_CHILD(output, node.child("port_map"), "output") { - int64_t ext_port_id = GetInt64Attr(output, "external_port_id"); - output_map.emplace(ext_port_id, output); - } - - uint64_t output_number = 0; - for (const auto& output : output_map) { - auto& xml_output = output.second; - auto axis_attr = xml_output.attribute("axis"); - size_t body_result_index = XMLParseUtils::GetUIntAttr(xml_output, "internal_layer_id"); - - // if external_port_id < 0 it means that this body result isn't connected to the Loop output - // and is used only for internal needs. For TensorIterator external_port_id is always > 0. - if (XMLParseUtils::GetInt64Attr(xml_output, "external_port_id") >= 0) { - // if axis is set, then concatenation is enabled. Create - // ngraph::TensorIterator::ConcatOutput. - if (!axis_attr.empty()) { - int64_t axis = XMLParseUtils::GetInt64Attr(xml_output, "axis"); - int64_t start = XMLParseUtils::GetInt64Attr(xml_output, "start", 0); - int64_t stride = XMLParseUtils::GetInt64Attr(xml_output, "stride", 1); - int64_t end = XMLParseUtils::GetInt64Attr(xml_output, "end", -1); - int64_t part_size = XMLParseUtils::GetInt64Attr(xml_output, "part_size", 1); - - const auto output_index = up_io_map.outputs.at(body_result_index); - - outputs.push_back( - std::make_shared( - output_index, output_number, start, stride, part_size, end, axis)); - } else { - // otherwise create ngraph::TensorIterator::BodyOutput. -1 means last iteration. - const auto output_index = up_io_map.outputs.at(body_result_index); - - outputs.push_back( - std::make_shared( - output_index, output_number, -1)); - } - output_number++; - } - } - return outputs; -} - -ngraph::op::v5::Loop::SpecialBodyPorts XmlDeserializer::parsePurposeAttribute( - const pugi::xml_node& node) { - ngraph::op::v5::Loop::SpecialBodyPorts result = {-1, -1}; - const auto up_io_map = updated_io_map(node); - - NGRAPH_CHECK( - !up_io_map.inputs.empty() || !up_io_map.outputs.empty(), - "No parameters or results found in body Function."); - - // Parse PortMap: external_port_id for inputs/outputs does not always appear in consecutive - // order - std::map input_map; - FOREACH_CHILD(input, node.child("port_map"), "input") { - int64_t ext_port_id = GetInt64Attr(input, "external_port_id"); - input_map.emplace(ext_port_id, input); - } - std::map output_map; - FOREACH_CHILD(output, node.child("port_map"), "output") { - int64_t ext_port_id = GetInt64Attr(output, "external_port_id"); - output_map.emplace(ext_port_id, output); - } - - for (const auto& input : input_map) { - auto& xml_input = input.second; - auto purpose = XMLParseUtils::GetStrAttr(xml_input, "purpose", ""); - size_t body_parameter_index = XMLParseUtils::GetUIntAttr(xml_input, "internal_layer_id"); - if (purpose == "current_iteration") { - result.current_iteration_input_idx = up_io_map.inputs.at(body_parameter_index); - } - } - - for (const auto& output : output_map) { - auto& xml_output = output.second; - auto purpose = XMLParseUtils::GetStrAttr(xml_output, "purpose", ""); - size_t body_parameter_index = XMLParseUtils::GetUIntAttr(xml_output, "internal_layer_id"); - if (purpose == "execution_condition") { - result.body_condition_output_idx = up_io_map.outputs.at(body_parameter_index); - } - } - - return result; -} - -void XmlDeserializer::on_adapter(const std::string& name, ngraph::ValueAccessor& adapter) { - static const std::unordered_set skip_names = { - "input_descriptions", "output_descriptions", "special_body_ports"}; - std::string val; - - // for TensorIterator look for 'port_map' as 'data' does not exist - if (node.child("port_map")) { - if (auto a = ngraph::as_type>>>( - &adapter)) { - a->set(parseInputDescription(node)); - } else if ( - auto a = ngraph::as_type>>>( - &adapter)) { - a->set(parseOutputDescription(node)); - } else if ( - auto a = - ngraph::as_type>( - &adapter)) { - a->set(parsePurposeAttribute(node)); - } - } - - if (skip_names.count(name) && !getStrAttribute(node.child("data"), name, val)) return; - if (auto a = ngraph::as_type>(&adapter)) { - static_cast(*a) = details::convertPrecision(val); - } else if (auto a = ngraph::as_type>(&adapter)) { - std::vector shape; - std::vector dims; - if (!getParameters(node.child("data"), name, shape)) return; - for (const auto& dim : shape) dims.emplace_back(dim); - static_cast(*a) = ngraph::PartialShape(dims); - } else if (auto a = ngraph::as_type>(&adapter)) { - std::vector shape; - if (!getParameters(node.child("data"), name, shape)) return; - static_cast(*a) = ngraph::Shape(shape); - } else if (auto a = ngraph::as_type>(&adapter)) { - std::vector shape; - if (!getParameters(node.child("data"), name, shape)) return; - static_cast(*a) = ngraph::Strides(shape); -#ifdef __APPLE__ - } else if (auto a = ngraph::as_type>>(&adapter)) { - std::vector result; - if (!getParameters(node.child("data"), name, result)) return; - static_cast&>(*a) = result; -#else - } else if (auto a = ngraph::as_type>>(&adapter)) { - std::vector result; - if (!getParameters(node.child("data"), name, result)) return; - a->set(result); -#endif - } else if (auto a = ngraph::as_type>(&adapter)) { - std::vector axes; - if (!getParameters(node.child("data"), name, axes)) return; - static_cast(*a) = ngraph::AxisSet(axes); - } else if ( - auto a = ngraph::as_type>(&adapter)) { - if (!getStrAttribute(node.child("data"), name, val)) return; - static_cast(*a) = ngraph::as_enum(val); - } else if (auto a = ngraph::as_type>(&adapter)) { - if (!getStrAttribute(node.child("data"), name, val)) return; - static_cast(*a) = ngraph::as_enum(val); - } else if ( - auto a = ngraph::as_type>(&adapter)) { - std::vector shape; - if (!getParameters(node.child("data"), name, shape)) return; - std::vector coord_diff(shape.begin(), shape.end()); - static_cast(*a) = ngraph::CoordinateDiff(coord_diff); - } else if ( - auto a = ngraph::as_type>>( - &adapter)) { - std::string variable_id; - if (!getStrAttribute(node.child("data"), name, variable_id)) return; - if (!variables.count(variable_id)) { - variables[variable_id] = std::make_shared(ngraph::VariableInfo{ - ngraph::PartialShape::dynamic(), ngraph::element::dynamic, variable_id}); - } - a->set(variables[variable_id]); - } else if ( - auto a = ngraph::as_type< - ngraph::AttributeAdapter>>(&adapter)) { - std::string value; - pugi::xml_node dn = node.child("data"); - auto type = XMLParseUtils::GetStrAttr(node, "type"); - - if (dn.empty()) IE_THROW() << "No attrtibutes defined for " << type << " op!"; - - if (getStrAttribute(dn, name, value)) { - auto buffer = std::make_shared(value.size()); - auto data = static_cast(buffer->get_ptr()); - value.copy(data, value.size()); - a->set(buffer); - } else if (name == "value" && type == "Const") { - std::vector shape; - std::string el_type_str; - - size_t offset = XMLParseUtils::GetUInt64Attr(dn, "offset"); - size_t size = XMLParseUtils::GetUInt64Attr(dn, "size"); - if (!getStrAttribute(dn, "element_type", el_type_str)) return; - if (!getParameters(dn, "shape", shape)) return; - - ngraph::element::Type el_type = details::convertPrecision(el_type_str); - - size_t length = weights->byteSize(); - if (!length) - IE_THROW() << "Empty weights data in bin file or bin file cannot be found!"; - if (length < offset + size) IE_THROW() << "Incorrect weights in bin file!"; - if (size < std::ceil(ngraph::shape_size(shape) * el_type.bitwidth() / 8.f)) - IE_THROW() << "Attribute and shape size are inconsistent for " << type - << " op!"; - - char* data = weights->cbuffer().as() + offset; - - using SharedBuffer = ngraph::runtime::SharedBuffer; - auto buffer = std::make_shared(data, size, weights); - a->set(buffer); - } - } else if (auto a = ngraph::as_type< - ngraph::AttributeAdapter>(&adapter)) { - const auto & type = XMLParseUtils::GetStrAttr(node, "type"); - const auto & version = XMLParseUtils::GetStrAttr(node, "version"); - - ngraph::op::FrameworkNodeAttrs node_attrs; - node_attrs.set_opset_name(version); - node_attrs.set_type_name(type); - - pugi::xml_node dn = node.child("data"); - - if (!dn.empty()) { - for (const auto & data_attr : dn.attributes()) { - node_attrs[data_attr.name()] = data_attr.as_string(); - } - } - - a->set(node_attrs); - } else { - IE_THROW() << "Error IR reading. Attribute adapter can not be found for " << name - << " parameter"; - } -} - -void XmlDeserializer::on_adapter( - const std::string& name, ngraph::ValueAccessor>& adapter) { - std::shared_ptr ngraph_function; - if (!name.compare("body")) { - auto body_node = node.child(name.c_str()); - if (body_node.empty()) { - IE_THROW() << "TensorIterator has no body."; - } - ngraph_function = parse_function(node.child(name.c_str()), weights); - } else if (!name.compare("net")) { - ngraph_function = parse_function(node, weights); - } else { - IE_THROW() << "Error: not recognized adapter name: " << name << "."; - } - adapter.set(ngraph_function); -} - -std::shared_ptr XmlDeserializer::parse_function( - const pugi::xml_node& root, const Blob::CPtr& weights) { - OV_ITT_SCOPE_CHAIN(FIRST_INFERENCE, taskChain, itt::domains::V10Reader_RT, "V10Parser", "Parse"); - - struct FunctionNodes { - ngraph::ParameterVector parameters; - ngraph::ResultVector results; - ngraph::NodeVector all; - ngraph::SinkVector sinks; - }; - - struct edge { - size_t fromLayerId, fromPortId, toPortId; - }; - struct node_params { - pugi::xml_node xml; - V10Parser::GenericLayerParams params; - }; - - std::map params; - - std::vector outputs; - std::unordered_set opName; - - // Read all layers and store their parameters in params map - FOREACH_CHILD(node, root.child("layers"), "layer") { - auto node_param = parseGenericParams(node); - if (opName.find(node_param.name) != opName.end() && node_param.type != "Result") - IE_THROW() << "Invalid IR! " << node_param.name << " name is not unique!"; - opName.insert(node_param.name); - params[node_param.layerId] = {node, node_param}; - if (node_param.type == "Result" || node_param.type == "Assign") { - outputs.push_back(node_param.layerId); - } - } - - std::map> edges; - std::map> id_to_node; - - // Read all edges and store them for further usage - FOREACH_CHILD(_ec, root.child("edges"), "edge") { - size_t fromLayer = GetUIntAttr(_ec, "from-layer"); - size_t fromPort = GetUIntAttr(_ec, "from-port"); - size_t toLayer = GetUIntAttr(_ec, "to-layer"); - size_t toPort = GetUIntAttr(_ec, "to-port"); - edges[toLayer].push_back({fromLayer, fromPort, toPort}); - } - - // Run DFS starting from outputs to get nodes topological order - std::set used; - std::vector order; - std::function dfs = [&edges, &order, &used, &dfs](const size_t id) { - if (used.count(id)) return; - used.insert(id); - for (auto& edge : edges[id]) { - dfs(edge.fromLayerId); - } - order.push_back(id); - }; - std::for_each(outputs.begin(), outputs.end(), dfs); - - OV_ITT_SCOPE_NEXT(FIRST_INFERENCE, taskChain, "ConstructNgraphNodes"); - - FunctionNodes func_nodes; - - std::map> variable_id_to_read_value; - - // Following topological order create nGraph operations - for (auto& layer_id : order) { - auto& p = params[layer_id]; - ngraph::OutputVector inputs(edges[layer_id].size()); - for (auto& e : edges[layer_id]) { - auto input_node = id_to_node[e.fromLayerId]; - if (!input_node) { - IE_THROW() << "Attempt to access node " << e.fromLayerId - << " that not in graph."; - } - auto& p_output = params[e.fromLayerId].params; - size_t const realInputPortId = p.params.getRealInputPortId(e.toPortId); - if (realInputPortId >= inputs.size()) - IE_THROW() << p.params.type << " layer " << p.params.name - << " with id: " << p.params.layerId << " is inconsistent!"; - inputs[realInputPortId] = - input_node->output(p_output.getRealOutputPortId(e.fromPortId)); - } - - auto node = createNode(inputs, p.xml, weights, p.params); - id_to_node[layer_id] = node; - - // Check that output shape after nGraph node validation the same as in IR - // because IR always right! - // Temporary disabled! - // for (size_t i = 0; i < p.params.outputPorts.size(); ++i) { - // if (p.params.outputPorts[i].dims != node->output(i).get_shape()) { - // IE_THROW() << "Shape after nGraph infer " << - // details::dumpVec(node->output(i).get_shape()) - // << " differ from IR shapes: " << - // details::dumpVec(p.params.outputPorts[i].dims); - // } - // } - - if (const auto& parameter_node = std::dynamic_pointer_cast(node)) { - io_map.inputs.insert({layer_id, func_nodes.parameters.size()}); - func_nodes.parameters.emplace_back(parameter_node); - } - - if (const auto& result_node = std::dynamic_pointer_cast(node)) { - io_map.outputs.insert({layer_id, func_nodes.results.size()}); - func_nodes.results.emplace_back(result_node); - } - - if (const auto& sink = std::dynamic_pointer_cast(node)) { - func_nodes.sinks.emplace_back(sink); - } - - if (const auto& read_value = std::dynamic_pointer_cast(node)) { - variable_id_to_read_value[read_value->get_variable_id()] = read_value; - } - - func_nodes.all.emplace_back(node); - } - - OV_ITT_SCOPE_NEXT(FIRST_INFERENCE, taskChain, "ConstructNgraphFunction"); - - auto function = std::make_shared( - func_nodes.results, func_nodes.sinks, func_nodes.parameters, GetStrAttr(root, "name", "")); - for (const auto& sink : func_nodes.sinks) { - if (const auto& assign = std::dynamic_pointer_cast(sink)) { - assign->add_control_dependency(variable_id_to_read_value.at(assign->get_variable_id())); - } - } - - return function; -} - -V10Parser::V10Parser::GenericLayerParams XmlDeserializer::parseGenericParams( - const pugi::xml_node& node) { - const auto parsePort = [this]( - const pugi::xml_node& parentNode, - const V10Parser::GenericLayerParams& params, - bool input) -> V10Parser::GenericLayerParams::LayerPortData { - V10Parser::GenericLayerParams::LayerPortData port; - - port.portId = GetIntAttr(parentNode, "id"); - - FOREACH_CHILD(node, parentNode, "dim") { - int64_t dim = 0; - const pugi::char_t* dimVal = node.child_value(); - std::stringstream ss(dimVal); - if (!(ss >> dim) || dim < -1) { - IE_THROW() << "dimension (" << dimVal << ") in node " << node.name() - << " must be greater or equal to -1: at offset " - << node.offset_debug(); - } - port.dims.push_back(dim); - } - - ngraph::element::Type type(ngraph::element::Type_t::undefined); - // Input port hasn't precision - if (!input) { - const std::string& preStr = GetStrAttr(parentNode, "precision"); - type = InferenceEngine::details::convertPrecision(preStr); - } - port.precision = type; - std::vector names; - if (getParameters(parentNode, "names", names)) { - for (size_t i = 0; i < names.size(); i++) { - std::string name = names[i]; - // Restore original name if it contains delimiter - // getParameters(...) returns the vector of names which were split by delimiter ',' - // but some names can contain ',' as a part of name, in this case we use '\' to - // escape delimiter the cycle below is needed in order to find names which contained - // delimiter and restore the original name - while (i < names.size() && names[i].at(names[i].length() - 1) == '\\') { - name.replace(names[i].length() - 1, 1, ","); - name += names[++i]; - } - port.names.emplace(name); - } - } - return port; - }; - V10Parser::GenericLayerParams params; - - params.layerId = GetIntAttr(node, "id"); - params.version = GetStrAttr(node, "version"); - - params.type = XMLParseUtils::GetStrAttr(node, "type"); - - params.name = GetStrAttr(node, "name"); - - auto outNode = node.child("output"); - if (!outNode.empty()) { - FOREACH_CHILD(_cn, outNode, "port") { - params.outputPorts.emplace_back(parsePort(_cn, params, false)); - } - } - auto inpNode = node.child("input"); - if (!inpNode.empty()) { - FOREACH_CHILD(_cn, inpNode, "port") { - params.inputPorts.emplace_back(parsePort(_cn, params, true)); - } - } - return params; -} - -std::shared_ptr XmlDeserializer::createNode( - const std::vector>& inputs, - const pugi::xml_node& node, - const Blob::CPtr& weights, - const V10Parser::GenericLayerParams& params) { - // Check that inputs are correctly defined - for (size_t i = 0; i < inputs.size(); i++) { - if (!inputs[i].get_node()) - IE_THROW() << params.type << " layer " << params.name - << " with id: " << params.layerId - << " has incorrect input with index " << i << "!"; - if (ngraph::element::Type_t::undefined == inputs[i].get_element_type()) - IE_THROW() << params.type << " layer " << params.name - << " with id: " << params.layerId - << " has undefined element type for input with index " << i << "!"; - } - - std::shared_ptr ngraphNode; - - // Find registered opset - auto opsetIt = opsets.find(params.version); - - // Try to create operation from loaded opsets - static const std::unordered_set experimental_ops_added_to_opset = { - "ExperimentalDetectronDetectionOutput", - "ExperimentalDetectronGenerateProposalsSingleImage", - "ExperimentalDetectronPriorGridGenerator", - "ExperimentalDetectronROIFeatureExtractor", - "ExperimentalDetectronTopKROIs", - "GRUCell", - "RNNCell", - "Proposal"}; - - if (experimental_ops_added_to_opset.count(params.type) && - (params.version == "experimental" || params.version == "extension")) { - opsetIt = opsets.find("opset6"); - } - - if (!ngraphNode && opsetIt != opsets.end()) { - auto const& type = params.type == "Const" ? "Constant" : params.type; - - if (params.version == "opset1") { - // MVN, ROIPooling and ReorgYolo were missing in opset1 - if (type == "MVN" || type == "ROIPooling" || type == "ReorgYolo") { - opsetIt = opsets.find("opset2"); - if (opsetIt == opsets.end()) { - IE_THROW() << "Cannot create " << params.type << " layer " - << params.name << " id:" << params.layerId - << " from unsupported opset: " << params.version; - } - } - } - - auto const& opset = opsetIt->second; - - ngraphNode = std::shared_ptr(opset.create_insensitive(type)); - if (!ngraphNode) { - IE_THROW() << "Opset " << params.version - << " doesn't contain the operation with type: " << type; - } - // Share Weights form constant blob - if (auto constant = std::dynamic_pointer_cast(ngraphNode)) { - constant->alloc_buffer_on_visit_attributes(false); - } - ngraphNode->set_arguments(inputs); - XmlDeserializer visitor(node, weights, opsets, variables); - - if (ngraphNode->visit_attributes(visitor)) { - ngraphNode->constructor_validate_and_infer_types(); - } - - // To be sure that all default values will be initialized: - ngraphNode = ngraphNode->clone_with_new_inputs(ngraphNode->input_values()); - } - - if (!ngraphNode && m_use_framework_node) { - ngraphNode = std::make_shared(inputs); - XmlDeserializer visitor(node, weights, opsets, variables); - ngraphNode->visit_attributes(visitor); - - size_t index{0}; - for (const auto & output_params : params.outputPorts) { - ngraphNode->set_output_type(index, output_params.precision, ngraph::PartialShape(output_params.dims)); - ++index; - } - } - - if (!ngraphNode) { - IE_THROW() << "Cannot create " << params.type << " layer " << params.name - << " id:" << params.layerId - << " from unsupported opset: " << params.version; - } - - // Save run time info - auto& rtInfo = ngraphNode->get_rt_info(); - pugi::xml_node dn = node.child("data"); - if (dn) { - const auto pr_data = dn.attribute("PrimitivesPriority"); - if (pr_data) { - rtInfo["PrimitivesPriority"] = - std::make_shared<::ngraph::VariantWrapper>(pr_data.value()); - } - const auto aw_data = dn.attribute("alt_width"); - if (aw_data) { - rtInfo["alt_width"] = - std::make_shared<::ngraph::VariantWrapper>(aw_data.value()); - } - } - - ngraphNode->set_friendly_name(params.name); - for (size_t i = 0; i < params.outputPorts.size() && i < ngraphNode->get_output_size(); ++i) { - if (!params.outputPorts[i].names.empty()) - ngraphNode->get_output_tensor(i).set_names(params.outputPorts[i].names); - } - - return ngraphNode; -} - -} // namespace - -V10Parser::V10Parser(const std::vector& exts) : _exts(exts) { - // Load default opsets - opsets["opset1"] = ngraph::get_opset1(); - opsets["opset2"] = ngraph::get_opset2(); - opsets["opset3"] = ngraph::get_opset3(); - opsets["opset4"] = ngraph::get_opset4(); - opsets["opset5"] = ngraph::get_opset5(); - opsets["opset6"] = ngraph::get_opset6(); - opsets["opset7"] = ngraph::get_opset7(); - opsets["opset8"] = ngraph::get_opset8(); - - // Load custom opsets - for (const auto& ext : exts) { - for (const auto& it : ext->getOpSets()) { - if (opsets.find(it.first) != opsets.end()) - IE_THROW() << "Cannot add opset with name: " << it.first - << ". Opset with the same name already exists."; - opsets[it.first] = it.second; - } - } -} +V10Parser::V10Parser(const std::vector& exts) : _exts(exts) {} CNNNetwork V10Parser::parse( const pugi::xml_node& root, const Blob::CPtr& weights) { - std::shared_ptr function; - XmlDeserializer visitor(root, weights, opsets, variables); - bool use_framework_node{false}; - for (const auto & ext : _exts) { - const InferenceEngine::Version * version = nullptr; - ext->GetVersion(version); - if (version && version->description && strcmp(version->description, "framework_node_ext") == 0) { - use_framework_node = true; - break; - } - } - visitor.use_framework_node(use_framework_node); - visitor.on_attribute("net", function); + + auto ir_fe = std::make_shared(); + auto model = ir_fe->load(root, weights, _exts); + auto f = ir_fe->convert(model); OV_ITT_SCOPE(FIRST_INFERENCE, itt::domains::V10Reader_RT, "ConstructCNNNetwork"); - CNNNetwork net(function, _exts); + CNNNetwork net(f, _exts); parsePreProcess(net, root, weights); return net; @@ -1065,26 +182,4 @@ void V10Parser::parsePreProcess( << validMeanImageIds; } } - -size_t V10Parser::GenericLayerParams::getRealInputPortId(size_t id) const { - size_t real_id = 0; - for (auto& it : inputPorts) { - if (it.portId == id) { - return real_id; - } - ++real_id; - } - IE_THROW() << "Can not find input port with id " << id << " in layer " << name; -} - -size_t V10Parser::GenericLayerParams::getRealOutputPortId(size_t id) const { - size_t real_id = 0; - for (auto& it : outputPorts) { - if (it.portId == id) { - return real_id; - } - ++real_id; - } - IE_THROW() << "Can not find output port with id " << id << " in layer " << name; -} } // namespace InferenceEngine diff --git a/inference-engine/src/readers/ir_reader/ie_ir_parser.hpp b/inference-engine/src/readers/ir_reader/ie_ir_parser.hpp index 15ac63f531e..379dd9dfff4 100644 --- a/inference-engine/src/readers/ir_reader/ie_ir_parser.hpp +++ b/inference-engine/src/readers/ir_reader/ie_ir_parser.hpp @@ -64,31 +64,10 @@ public: CNNNetwork parse( const pugi::xml_node& root, const Blob::CPtr& weights) override; - struct GenericLayerParams { - struct LayerPortData { - size_t portId; - std::vector dims; - ngraph::element::Type_t precision; - std::unordered_set names; - }; - size_t layerId; - std::string version; - std::string name; - std::string type; - std::vector inputPorts; - std::vector outputPorts; - - size_t getRealInputPortId(size_t id) const; - - size_t getRealOutputPortId(size_t id) const; - }; - private: void parsePreProcess( CNNNetwork& network, const pugi::xml_node& root, const Blob::CPtr& weights); - std::unordered_map opsets; - std::unordered_map> variables; const std::vector _exts; }; diff --git a/ngraph/frontend/CMakeLists.txt b/ngraph/frontend/CMakeLists.txt index ef1bed270f1..7689778a115 100644 --- a/ngraph/frontend/CMakeLists.txt +++ b/ngraph/frontend/CMakeLists.txt @@ -13,3 +13,7 @@ endif() if (NGRAPH_PDPD_FRONTEND_ENABLE) add_subdirectory(paddlepaddle) endif() + +if (IR_FRONTEND_ENABLE) + add_subdirectory(ir) +endif() diff --git a/ngraph/frontend/ir/CMakeLists.txt b/ngraph/frontend/ir/CMakeLists.txt new file mode 100644 index 00000000000..181bfda9d62 --- /dev/null +++ b/ngraph/frontend/ir/CMakeLists.txt @@ -0,0 +1,61 @@ +# Copyright (C) 2018-2021 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 +# + +set(TARGET_NAME "ir_frontend") + +file(GLOB_RECURSE LIBRARY_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp) +file(GLOB_RECURSE LIBRARY_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/src/*.hpp) +file(GLOB_RECURSE LIBRARY_PUBLIC_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/include/*.hpp) + +set(${TARGET_NAME}_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/include) + +# Create named folders for the sources within the .vcproj +# Empty name lists them directly under the .vcproj + +source_group("src" FILES ${LIBRARY_SRC}) +source_group("include" FILES ${LIBRARY_HEADERS}) +source_group("public include" FILES ${LIBRARY_PUBLIC_HEADERS}) + +# Create shared library +add_library(${TARGET_NAME} SHARED ${LIBRARY_SRC} ${LIBRARY_HEADERS} ${LIBRARY_PUBLIC_HEADERS}) + +ov_ncc_naming_style(FOR_TARGET ${TARGET_NAME} + INCLUDE_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/include" + ADDITIONAL_INCLUDE_DIRECTORIES + $) + +target_include_directories(${TARGET_NAME} + PUBLIC + $ + $ + PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/src + ${CMAKE_CURRENT_BINARY_DIR}) + +target_include_directories(${TARGET_NAME} SYSTEM PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) + +if(COMMAND ie_add_vs_version_file) + ie_add_vs_version_file(NAME ${TARGET_NAME} + FILEDESCRIPTION "FrontEnd to load and convert IR file format") +endif() + +target_link_libraries(${TARGET_NAME} PRIVATE ngraph::frontend_manager::static + PRIVATE ngraph::builder inference_engine_transformations + inference_engine pugixml::static inference_engine_plugin_api) + +add_clang_format_target(${TARGET_NAME}_clang FOR_TARGETS ${TARGET_NAME} + EXCLUDE_PATTERNS ${PROTO_SRCS} ${PROTO_HDRS}) + +install(TARGETS ${TARGET_NAME} EXPORT ngraphTargets + RUNTIME DESTINATION ${NGRAPH_INSTALL_LIB} COMPONENT ngraph + ARCHIVE DESTINATION ${NGRAPH_INSTALL_LIB} COMPONENT ngraph + LIBRARY DESTINATION ${NGRAPH_INSTALL_LIB} COMPONENT ngraph) + +install(DIRECTORY ${${TARGET_NAME}_INCLUDE_DIR}/ir_frontend + DESTINATION ${FRONTEND_INSTALL_INCLUDE} + COMPONENT ngraph_dev + FILES_MATCHING PATTERN "*.hpp" +) + +export(TARGETS ${TARGET_NAME} NAMESPACE ngraph:: APPEND FILE "${NGRAPH_TARGETS_FILE}") diff --git a/ngraph/frontend/ir/include/ir_frontend/frontend.hpp b/ngraph/frontend/ir/include/ir_frontend/frontend.hpp new file mode 100644 index 00000000000..eba7371fbd3 --- /dev/null +++ b/ngraph/frontend/ir/include/ir_frontend/frontend.hpp @@ -0,0 +1,80 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +#include +#include +#include +#include + +#include "utility.hpp" + +namespace ngraph { +namespace frontend { + +class IR_API FrontEndIR : public FrontEnd { +public: + FrontEndIR() = default; + + /// \brief Completely convert the remaining, not converted part of a function. + /// \param partiallyConverted partially converted nGraph function + /// \return fully converted nGraph function + std::shared_ptr convert(InputModel::Ptr model) const override; + + /// \brief Gets name of this FrontEnd. Can be used by clients + /// if frontend is selected automatically by FrontEndManager::load_by_model + /// + /// \return IR frontend name. + std::string get_name() const override; + +protected: + /// \brief Check if FrontEndIR can recognize model from given parts + /// \param params Can be path to the model file or std::istream + /// \return InputModel::Ptr + bool supported_impl(const std::vector>& variants) const override; + + /// \brief Reads model from file or std::istream + /// \param params Can be path to the model file or std::istream + /// \return InputModel::Ptr + InputModel::Ptr load_impl(const std::vector>& params) const override; +}; + +} // namespace frontend +} // namespace ngraph + +namespace ov { + +template <> +class IR_API VariantWrapper : public VariantImpl { +public: + static constexpr VariantTypeInfo type_info{"Variant::pugi::xml_node", 0}; + const VariantTypeInfo& get_type_info() const override { + return type_info; + } + VariantWrapper(const value_type& value) : VariantImpl(value) {} +}; + +template <> +class IR_API VariantWrapper : public VariantImpl { +public: + static constexpr VariantTypeInfo type_info{"Variant::Blob::CPtr", 0}; + const VariantTypeInfo& get_type_info() const override { + return type_info; + } + VariantWrapper(const value_type& value) : VariantImpl(value) {} +}; + +template <> +class IR_API VariantWrapper> + : public VariantImpl> { +public: + static constexpr VariantTypeInfo type_info{"Variant::Extensions", 0}; + const VariantTypeInfo& get_type_info() const override { + return type_info; + } + VariantWrapper(const value_type& value) : VariantImpl(value) {} +}; + +} // namespace ov diff --git a/ngraph/frontend/ir/include/ir_frontend/model.hpp b/ngraph/frontend/ir/include/ir_frontend/model.hpp new file mode 100644 index 00000000000..1f43c779a77 --- /dev/null +++ b/ngraph/frontend/ir/include/ir_frontend/model.hpp @@ -0,0 +1,35 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +#include +#include +#include +#include +#include +#include + +namespace ngraph { +namespace frontend { +class IR_API InputModelIR : public InputModel { + friend class FrontEndIR; + + pugi::xml_node m_root; + InferenceEngine::Blob::CPtr m_weights; + std::vector m_exts; + +public: + explicit InputModelIR(const pugi::xml_node& root, + const InferenceEngine::Blob::CPtr& weights, + const std::vector& exts) + : m_root(root), + m_weights(weights), + m_exts(exts) {} + + std::shared_ptr convert(); +}; + +} // namespace frontend +} // namespace ngraph diff --git a/ngraph/frontend/ir/include/ir_frontend/utility.hpp b/ngraph/frontend/ir/include/ir_frontend/utility.hpp new file mode 100644 index 00000000000..d2ccba48366 --- /dev/null +++ b/ngraph/frontend/ir/include/ir_frontend/utility.hpp @@ -0,0 +1,22 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +// Defined if we are building the plugin DLL (instead of using it) +#ifdef ir_frontend_EXPORTS +# define IR_API NGRAPH_HELPER_DLL_EXPORT +#else +# define IR_API NGRAPH_HELPER_DLL_IMPORT +#endif // ir_frontend_EXPORTS + +#define IR_ASSERT(ex, msg) \ + { \ + if (!(ex)) \ + throw std::runtime_error(msg); \ + } + +#define IR_THROW(msg) throw std::runtime_error(std::string("ERROR: ") + msg) + +#define NOT_IMPLEMENTED(msg) throw std::runtime_error(std::string(msg) + " is not implemented") diff --git a/ngraph/frontend/ir/src/frontend.cpp b/ngraph/frontend/ir/src/frontend.cpp new file mode 100644 index 00000000000..2803d804d6d --- /dev/null +++ b/ngraph/frontend/ir/src/frontend.cpp @@ -0,0 +1,86 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include +#include +#include +#include +#include +#include + +using namespace ngraph; + +namespace ov { +constexpr VariantTypeInfo VariantWrapper::type_info; +constexpr VariantTypeInfo VariantWrapper::type_info; +constexpr VariantTypeInfo VariantWrapper>::type_info; +} // namespace ov + +namespace ngraph { +namespace frontend { + +bool FrontEndIR::supported_impl(const std::vector>& variants) const { + // FrontEndIR can only load model specified by xml_node, weights_ptr and vector of extensions + if (variants.size() != 3) { + return false; + } + + bool has_xml_node{false}; + bool has_weights{false}; + bool has_exts{false}; + + for (const auto& variant : variants) { + if (ov::is_type>(variant)) { + has_xml_node = true; + } else if (ov::is_type>(variant)) { + has_weights = true; + } else if (ov::is_type>>(variant)) { + has_exts = true; + } + return false; + } + + return has_xml_node && has_weights && has_exts; +} + +InputModel::Ptr FrontEndIR::load_impl(const std::vector>& variants) const { + pugi::xml_node root; + InferenceEngine::Blob::CPtr weights; + std::vector exts; + + for (const auto& variant : variants) { + if (ov::is_type>(variant)) { + root = ov::as_type_ptr>(variant)->get(); + } else if (ov::is_type>(variant)) { + weights = ov::as_type_ptr>(variant)->get(); + } else if (ov::is_type>>(variant)) { + exts = ov::as_type_ptr>>(variant)->get(); + } + } + return std::make_shared(root, weights, exts); +} + +std::shared_ptr FrontEndIR::convert(InputModel::Ptr model) const { + auto ir_model = std::dynamic_pointer_cast(model); + return ir_model->convert(); +} + +std::string FrontEndIR::get_name() const { + return "ir"; +} +} // namespace frontend +} // namespace ngraph + +extern "C" IR_API ngraph::frontend::FrontEndVersion GetAPIVersion() { + return OV_FRONTEND_API_VERSION; +} + +extern "C" IR_API void* GetFrontEndData() { + frontend::FrontEndPluginInfo* res = new frontend::FrontEndPluginInfo(); + res->m_name = "ir"; + res->m_creator = []() { + return std::make_shared(); + }; + return res; +} diff --git a/ngraph/frontend/ir/src/model.cpp b/ngraph/frontend/ir/src/model.cpp new file mode 100644 index 00000000000..096e1ebcc65 --- /dev/null +++ b/ngraph/frontend/ir/src/model.cpp @@ -0,0 +1,938 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "ir_frontend/model.hpp" + +#include + +#include +#include + +using namespace ngraph; +using namespace InferenceEngine; + +namespace { + +struct GenericLayerParams { + struct LayerPortData { + size_t portId; + std::vector dims; + ngraph::element::Type_t precision; + std::unordered_set names; + }; + size_t layerId; + std::string version; + std::string name; + std::string type; + std::vector inputPorts; + std::vector outputPorts; + + size_t getRealInputPortId(size_t id) const { + size_t real_id = 0; + for (auto& it : inputPorts) { + if (it.portId == id) { + return real_id; + } + ++real_id; + } + IE_THROW() << "Can not find input port with id " << id << " in layer " << name; + } + + size_t getRealOutputPortId(size_t id) const { + size_t real_id = 0; + for (auto& it : outputPorts) { + if (it.portId == id) { + return real_id; + } + ++real_id; + } + IE_THROW() << "Can not find output port with id " << id << " in layer " << name; + } +}; + +bool getStrAttribute(const pugi::xml_node& node, const std::string& name, std::string& value) { + if (!node) + return false; + + auto attr = node.attribute(name.c_str()); + if (attr.empty()) + return false; + value = std::string(attr.value()); + return true; +} + +template +bool getParameters(const pugi::xml_node& node, const std::string& name, std::vector& value) { + std::string param; + if (!getStrAttribute(node, name, param)) + return false; + std::stringstream ss(param); + std::string field; + while (getline(ss, field, ',')) { + if (field.empty()) + IE_THROW() << "Cannot get vector of parameters! \"" << param << "\" is incorrect"; + std::stringstream fs(field); + T val; + fs >> val; + value.emplace_back(val); + } + return true; +} + +template +T stringToType(const std::string& valStr) { + T ret{0}; + std::istringstream ss(valStr); + if (!ss.eof()) { + ss >> ret; + } + return ret; +} + +class XmlDeserializer : public ngraph::AttributeVisitor { +public: + explicit XmlDeserializer(const pugi::xml_node& node, + const Blob::CPtr& weights, + const std::unordered_map& opsets, + std::unordered_map>& variables) + : m_node(node), + m_weights(weights), + m_opsets(opsets), + m_variables(variables) {} + + void on_adapter(const std::string& name, ngraph::ValueAccessor& value) override { + std::string val; + if (!getStrAttribute(m_node.child("data"), name, val)) + return; + value.set(val); + } + void on_adapter(const std::string& name, ngraph::ValueAccessor& value) override { + std::string val; + if (!getStrAttribute(m_node.child("data"), name, val)) + return; + std::transform(val.begin(), val.end(), val.begin(), [](char ch) { + return std::tolower(static_cast(ch)); + }); + std::set true_names{"true", "1"}; + std::set false_names{"false", "0"}; + + bool is_true = true_names.find(val) != true_names.end(); + bool is_false = false_names.find(val) != false_names.end(); + + if (!is_true && !is_false) + return; + value.set(is_true); + } + void on_adapter(const std::string& name, ngraph::ValueAccessor& adapter) override; + + void on_adapter(const std::string& name, ngraph::ValueAccessor& adapter) override { + std::string val; + if (!getStrAttribute(m_node.child("data"), name, val)) + return; + adapter.set(stringToType(val)); + } + void on_adapter(const std::string& name, ngraph::ValueAccessor& adapter) override { + std::string val; + if (!getStrAttribute(m_node.child("data"), name, val)) + return; + adapter.set(stringToType(val)); + } + + void on_adapter(const std::string& name, + ngraph::ValueAccessor>& adapter) override; + + void on_adapter(const std::string& name, ngraph::ValueAccessor>& adapter) override { + std::vector value; + if (!getParameters(m_node.child("data"), name, value)) + return; + adapter.set(value); + } + + void on_adapter(const std::string& name, ngraph::ValueAccessor>& adapter) override { + std::vector value; + if (!getParameters(m_node.child("data"), name, value)) + return; + adapter.set(value); + } + + void on_adapter(const std::string& name, ngraph::ValueAccessor>& adapter) override { + std::vector value; + if (!getParameters(m_node.child("data"), name, value)) + return; + adapter.set(value); + } + + void on_adapter(const std::string& name, ngraph::ValueAccessor>& adapter) override { + std::vector value; + if (!getParameters(m_node.child("data"), name, value)) + return; + adapter.set(value); + } + + void use_framework_node(bool flag) { + m_use_framework_node = flag; + } + +private: + struct IoMap { + using NodeIdToIoIndex = std::unordered_map; + NodeIdToIoIndex inputs; + NodeIdToIoIndex outputs; + }; + + /// \brief Traverses port_map in order to create vector of InputDescription shared_ptrs. + /// Shall be used only for ops which have port_map attribute. + /// \param node xml op representation + std::vector> parseInputDescription( + const pugi::xml_node& node); + /// \brief Traverses port_map in order to create vector of OutputDescription shared_ptrs. + /// Shall be used only for ops which have port_map attribute. + /// \param node xml op representation + std::vector> parseOutputDescription( + const pugi::xml_node& node); + + // TODO consider to call only once per layer/TI-Loop node + IoMap updated_io_map(const pugi::xml_node& node); + + /// \brief Traverses xml node representation in order to create nGraph function for it. + /// \param node xml node representation + /// \param weights weights attached to current node + /// \return shared pointer to function representing input node + std::shared_ptr parse_function(const pugi::xml_node& root, const Blob::CPtr& weights); + /// \brief Traverses xml node representation in order to get the purpose attribute of + /// inputs/outputs in the body of Loop op. \param node xml node representation \return struct + /// with value of purpuse attribute + ngraph::op::v5::Loop::SpecialBodyPorts parsePurposeAttribute(const pugi::xml_node& node); + + GenericLayerParams parseGenericParams(const pugi::xml_node& node); + + std::shared_ptr createNode(const ngraph::OutputVector& inputs, + const pugi::xml_node& node, + const Blob::CPtr& weights, + const GenericLayerParams& params); + + // -- DATA -- + const pugi::xml_node m_node; + const Blob::CPtr& m_weights; + const std::unordered_map& m_opsets; + std::unordered_map>& m_variables; + + /// + /// store information about parameters/results order during function creation + /// it will be used during Inputs/Outputs Description creation in SubGraph processing + /// + IoMap io_map; + + bool m_use_framework_node{false}; +}; + +XmlDeserializer::IoMap XmlDeserializer::updated_io_map(const pugi::xml_node& node) { + auto body_node = node.child("body"); + + if (body_node.empty()) { + IE_THROW() << "Missing body part."; + } + // Fill map: parameter/result id to parameter/result number in Function + + auto extend_io_map = io_map; + + FOREACH_CHILD (layer, body_node.child("layers"), "layer") { + auto type = XMLParseUtils::GetStrAttr(layer, "type"); + + if (type == "Parameter") { + auto id = XMLParseUtils::GetUIntAttr(layer, "id"); + extend_io_map.inputs.insert({id, -1}); // try add as unconnected + } else if (type == "Result") { + auto id = XMLParseUtils::GetUIntAttr(layer, "id"); + extend_io_map.outputs.insert({id, -1}); // try add as unconnected + } + } + return extend_io_map; +} + +std::vector> XmlDeserializer::parseInputDescription( + const pugi::xml_node& node) { + std::vector> inputs; + const auto up_io_map = updated_io_map(node); + + // Parse PortMap: external_port_id for inputs does not always appear in consecutive order + std::map input_map; + FOREACH_CHILD (input, node.child("port_map"), "input") { + int64_t ext_port_id = XMLParseUtils::GetInt64Attr(input, "external_port_id"); + input_map.emplace(ext_port_id, input); + } + + for (const auto& input : input_map) { + auto& xml_input = input.second; + auto axis_attr = xml_input.attribute("axis"); + int64_t ti_input_index = XMLParseUtils::GetInt64Attr(xml_input, "external_port_id"); + size_t body_parameter_index = XMLParseUtils::GetUIntAttr(xml_input, "internal_layer_id"); + + // if axis is set, then slicing is enabled. Create ngraph::TensorIterator::SlicedInput. + if (!axis_attr.empty()) { + size_t axis = XMLParseUtils::GetUIntAttr(xml_input, "axis"); + int64_t start = XMLParseUtils::GetInt64Attr(xml_input, "start", 0); + int64_t stride = XMLParseUtils::GetInt64Attr(xml_input, "stride", 1); + int64_t end = XMLParseUtils::GetInt64Attr(xml_input, "end", -1); + int64_t part_size = XMLParseUtils::GetInt64Attr(xml_input, "part_size", 1); + + const auto input_index = up_io_map.inputs.at(body_parameter_index); + + inputs.push_back(std::make_shared(ti_input_index, + input_index, + start, + stride, + part_size, + end, + axis)); + } else { + // otherwise find corresponding back edge and create ngraph::TensorIterator::MergedInput + bool is_back_edge_exist = false; + FOREACH_CHILD (xml_edge, node.child("back_edges"), "edge") { + size_t to_layer = XMLParseUtils::GetUIntAttr(xml_edge, "to-layer"); + + if (to_layer == body_parameter_index) { + size_t from_layer = XMLParseUtils::GetUIntAttr(xml_edge, "from-layer"); + + const auto input_index = up_io_map.inputs.at(body_parameter_index); + const auto output_index = up_io_map.outputs.at(from_layer); + + inputs.push_back( + std::make_shared(ti_input_index, + input_index, + output_index)); + + is_back_edge_exist = true; + break; + } + } + + // ti_input_index = -1 means that Parameter of the body is not connected to inputs of + // TensorIterator and is used only for internal needs. + if (!is_back_edge_exist && ti_input_index >= 0) { + const auto input_index = up_io_map.inputs.at(body_parameter_index); + + inputs.push_back( + std::make_shared(ti_input_index, + input_index)); + } + } + } + return inputs; +} + +std::vector> XmlDeserializer::parseOutputDescription( + const pugi::xml_node& node) { + std::vector> outputs; + const auto up_io_map = updated_io_map(node); + + // Parse PortMap: outputs + std::map output_map; + FOREACH_CHILD (output, node.child("port_map"), "output") { + int64_t ext_port_id = XMLParseUtils::GetInt64Attr(output, "external_port_id"); + output_map.emplace(ext_port_id, output); + } + + uint64_t output_number = 0; + for (const auto& output : output_map) { + auto& xml_output = output.second; + auto axis_attr = xml_output.attribute("axis"); + size_t body_result_index = XMLParseUtils::GetUIntAttr(xml_output, "internal_layer_id"); + + // if external_port_id < 0 it means that this body result isn't connected to the Loop output + // and is used only for internal needs. For TensorIterator external_port_id is always > 0. + if (XMLParseUtils::GetInt64Attr(xml_output, "external_port_id") >= 0) { + // if axis is set, then concatenation is enabled. Create + // ngraph::TensorIterator::ConcatOutput. + if (!axis_attr.empty()) { + int64_t axis = XMLParseUtils::GetInt64Attr(xml_output, "axis"); + int64_t start = XMLParseUtils::GetInt64Attr(xml_output, "start", 0); + int64_t stride = XMLParseUtils::GetInt64Attr(xml_output, "stride", 1); + int64_t end = XMLParseUtils::GetInt64Attr(xml_output, "end", -1); + int64_t part_size = XMLParseUtils::GetInt64Attr(xml_output, "part_size", 1); + + const auto output_index = up_io_map.outputs.at(body_result_index); + + outputs.push_back(std::make_shared(output_index, + output_number, + start, + stride, + part_size, + end, + axis)); + } else { + // otherwise create ngraph::TensorIterator::BodyOutput. -1 means last iteration. + const auto output_index = up_io_map.outputs.at(body_result_index); + + outputs.push_back(std::make_shared(output_index, + output_number, + -1)); + } + output_number++; + } + } + return outputs; +} + +ngraph::op::v5::Loop::SpecialBodyPorts XmlDeserializer::parsePurposeAttribute(const pugi::xml_node& node) { + ngraph::op::v5::Loop::SpecialBodyPorts result = {-1, -1}; + const auto up_io_map = updated_io_map(node); + + NGRAPH_CHECK(!up_io_map.inputs.empty() || !up_io_map.outputs.empty(), + "No parameters or results found in body Function."); + + // Parse PortMap: external_port_id for inputs/outputs does not always appear in consecutive + // order + std::map input_map; + FOREACH_CHILD (input, node.child("port_map"), "input") { + int64_t ext_port_id = XMLParseUtils::GetInt64Attr(input, "external_port_id"); + input_map.emplace(ext_port_id, input); + } + std::map output_map; + FOREACH_CHILD (output, node.child("port_map"), "output") { + int64_t ext_port_id = XMLParseUtils::GetInt64Attr(output, "external_port_id"); + output_map.emplace(ext_port_id, output); + } + + for (const auto& input : input_map) { + auto& xml_input = input.second; + auto purpose = XMLParseUtils::GetStrAttr(xml_input, "purpose", ""); + size_t body_parameter_index = XMLParseUtils::GetUIntAttr(xml_input, "internal_layer_id"); + if (purpose == "current_iteration") { + result.current_iteration_input_idx = up_io_map.inputs.at(body_parameter_index); + } + } + + for (const auto& output : output_map) { + auto& xml_output = output.second; + auto purpose = XMLParseUtils::GetStrAttr(xml_output, "purpose", ""); + size_t body_parameter_index = XMLParseUtils::GetUIntAttr(xml_output, "internal_layer_id"); + if (purpose == "execution_condition") { + result.body_condition_output_idx = up_io_map.outputs.at(body_parameter_index); + } + } + + return result; +} + +void XmlDeserializer::on_adapter(const std::string& name, ngraph::ValueAccessor& adapter) { + static const std::unordered_set skip_names = {"input_descriptions", + "output_descriptions", + "special_body_ports"}; + std::string val; + + // for TensorIterator look for 'port_map' as 'data' does not exist + if (m_node.child("port_map")) { + if (auto a = ngraph::as_type< + ngraph::AttributeAdapter>>>( + &adapter)) { + a->set(parseInputDescription(m_node)); + } else if (auto a = ngraph::as_type>>>(&adapter)) { + a->set(parseOutputDescription(m_node)); + } else if (auto a = + ngraph::as_type>(&adapter)) { + a->set(parsePurposeAttribute(m_node)); + } + } + + if (skip_names.count(name) && !getStrAttribute(m_node.child("data"), name, val)) + return; + if (auto a = ngraph::as_type>(&adapter)) { + static_cast(*a) = details::convertPrecision(val); + } else if (auto a = ngraph::as_type>(&adapter)) { + std::vector shape; + std::vector dims; + if (!getParameters(m_node.child("data"), name, shape)) + return; + for (const auto& dim : shape) + dims.emplace_back(dim); + static_cast(*a) = ngraph::PartialShape(dims); + } else if (auto a = ngraph::as_type>(&adapter)) { + std::vector shape; + if (!getParameters(m_node.child("data"), name, shape)) + return; + static_cast(*a) = ngraph::Shape(shape); + } else if (auto a = ngraph::as_type>(&adapter)) { + std::vector shape; + if (!getParameters(m_node.child("data"), name, shape)) + return; + static_cast(*a) = ngraph::Strides(shape); +#ifdef __APPLE__ + } else if (auto a = ngraph::as_type>>(&adapter)) { + std::vector result; + if (!getParameters(m_node.child("data"), name, result)) + return; + static_cast&>(*a) = result; +#else + } else if (auto a = ngraph::as_type>>(&adapter)) { + std::vector result; + if (!getParameters(m_node.child("data"), name, result)) + return; + a->set(result); +#endif + } else if (auto a = ngraph::as_type>(&adapter)) { + std::vector axes; + if (!getParameters(m_node.child("data"), name, axes)) + return; + static_cast(*a) = ngraph::AxisSet(axes); + } else if (auto a = ngraph::as_type>(&adapter)) { + if (!getStrAttribute(m_node.child("data"), name, val)) + return; + static_cast(*a) = ngraph::as_enum(val); + } else if (auto a = ngraph::as_type>(&adapter)) { + if (!getStrAttribute(m_node.child("data"), name, val)) + return; + static_cast(*a) = ngraph::as_enum(val); + } else if (auto a = ngraph::as_type>(&adapter)) { + std::vector shape; + if (!getParameters(m_node.child("data"), name, shape)) + return; + std::vector coord_diff(shape.begin(), shape.end()); + static_cast(*a) = ngraph::CoordinateDiff(coord_diff); + } else if (auto a = ngraph::as_type>>(&adapter)) { + std::string variable_id; + if (!getStrAttribute(m_node.child("data"), name, variable_id)) + return; + if (!m_variables.count(variable_id)) { + m_variables[variable_id] = std::make_shared( + ngraph::VariableInfo{ngraph::PartialShape::dynamic(), ngraph::element::dynamic, variable_id}); + } + a->set(m_variables[variable_id]); + } else if (auto a = ngraph::as_type>>( + &adapter)) { + std::string value; + pugi::xml_node dn = m_node.child("data"); + auto type = XMLParseUtils::GetStrAttr(m_node, "type"); + + if (dn.empty()) + IE_THROW() << "No attrtibutes defined for " << type << " op!"; + + if (getStrAttribute(dn, name, value)) { + auto buffer = std::make_shared(value.size()); + auto data = static_cast(buffer->get_ptr()); + value.copy(data, value.size()); + a->set(buffer); + } else if (name == "value" && type == "Const") { + std::vector shape; + std::string el_type_str; + + size_t offset = XMLParseUtils::GetUInt64Attr(dn, "offset"); + size_t size = XMLParseUtils::GetUInt64Attr(dn, "size"); + if (!getStrAttribute(dn, "element_type", el_type_str)) + return; + if (!getParameters(dn, "shape", shape)) + return; + + ngraph::element::Type el_type = details::convertPrecision(el_type_str); + + size_t length = m_weights->byteSize(); + if (!length) + IE_THROW() << "Empty weights data in bin file or bin file cannot be found!"; + if (length < offset + size) + IE_THROW() << "Incorrect weights in bin file!"; + if (size < std::ceil(ngraph::shape_size(shape) * el_type.bitwidth() / 8.f)) + IE_THROW() << "Attribute and shape size are inconsistent for " << type << " op!"; + + char* data = m_weights->cbuffer().as() + offset; + + using SharedBuffer = ngraph::runtime::SharedBuffer; + auto buffer = std::make_shared(data, size, m_weights); + a->set(buffer); + } + } else if (auto a = ngraph::as_type>(&adapter)) { + const auto& type = XMLParseUtils::GetStrAttr(m_node, "type"); + const auto& version = XMLParseUtils::GetStrAttr(m_node, "version"); + + ngraph::op::FrameworkNodeAttrs node_attrs; + node_attrs.set_opset_name(version); + node_attrs.set_type_name(type); + + pugi::xml_node dn = m_node.child("data"); + + if (!dn.empty()) { + for (const auto& data_attr : dn.attributes()) { + node_attrs[data_attr.name()] = data_attr.as_string(); + } + } + + a->set(node_attrs); + } else { + IE_THROW() << "Error IR reading. Attribute adapter can not be found for " << name << " parameter"; + } +} + +void XmlDeserializer::on_adapter(const std::string& name, + ngraph::ValueAccessor>& adapter) { + std::shared_ptr ngraph_function; + if (!name.compare("body")) { + auto body_node = m_node.child(name.c_str()); + if (body_node.empty()) { + IE_THROW() << "TensorIterator has no body."; + } + ngraph_function = parse_function(m_node.child(name.c_str()), m_weights); + } else if (!name.compare("net")) { + ngraph_function = parse_function(m_node, m_weights); + } else { + IE_THROW() << "Error: not recognized adapter name: " << name << "."; + } + adapter.set(ngraph_function); +} + +std::shared_ptr XmlDeserializer::parse_function(const pugi::xml_node& root, + const Blob::CPtr& weights) { + // OV_ITT_SCOPE_CHAIN(FIRST_INFERENCE, taskChain, itt::domains::V10Reader_RT, "V10Parser", "Parse"); + + struct FunctionNodes { + ngraph::ParameterVector parameters; + ngraph::ResultVector results; + ngraph::NodeVector all; + ngraph::SinkVector sinks; + }; + + struct edge { + size_t fromLayerId, fromPortId, toPortId; + }; + struct node_params { + pugi::xml_node xml; + GenericLayerParams params; + }; + + std::map params; + + std::vector outputs; + std::unordered_set opName; + + // Read all layers and store their parameters in params map + FOREACH_CHILD (node, root.child("layers"), "layer") { + auto node_param = parseGenericParams(node); + if (opName.find(node_param.name) != opName.end() && node_param.type != "Result") + IE_THROW() << "Invalid IR! " << node_param.name << " name is not unique!"; + opName.insert(node_param.name); + params[node_param.layerId] = {node, node_param}; + if (node_param.type == "Result" || node_param.type == "Assign") { + outputs.push_back(node_param.layerId); + } + } + + std::map> edges; + std::map> id_to_node; + + // Read all edges and store them for further usage + FOREACH_CHILD (_ec, root.child("edges"), "edge") { + size_t fromLayer = XMLParseUtils::GetUIntAttr(_ec, "from-layer"); + size_t fromPort = XMLParseUtils::GetUIntAttr(_ec, "from-port"); + size_t toLayer = XMLParseUtils::GetUIntAttr(_ec, "to-layer"); + size_t toPort = XMLParseUtils::GetUIntAttr(_ec, "to-port"); + edges[toLayer].push_back({fromLayer, fromPort, toPort}); + } + + // Run DFS starting from outputs to get nodes topological order + std::set used; + std::vector order; + std::function dfs = [&edges, &order, &used, &dfs](const size_t id) { + if (used.count(id)) + return; + used.insert(id); + for (auto& edge : edges[id]) { + dfs(edge.fromLayerId); + } + order.push_back(id); + }; + std::for_each(outputs.begin(), outputs.end(), dfs); + + // OV_ITT_SCOPE_NEXT(FIRST_INFERENCE, taskChain, "ConstructNgraphNodes"); + + FunctionNodes func_nodes; + + std::map> variable_id_to_read_value; + + // Following topological order create nGraph operations + for (auto& layer_id : order) { + auto& p = params[layer_id]; + ngraph::OutputVector inputs(edges[layer_id].size()); + for (auto& e : edges[layer_id]) { + auto input_node = id_to_node[e.fromLayerId]; + if (!input_node) { + IE_THROW() << "Attempt to access node " << e.fromLayerId << " that not in graph."; + } + auto& p_output = params[e.fromLayerId].params; + size_t const realInputPortId = p.params.getRealInputPortId(e.toPortId); + if (realInputPortId >= inputs.size()) + IE_THROW() << p.params.type << " layer " << p.params.name << " with id: " << p.params.layerId + << " is inconsistent!"; + inputs[realInputPortId] = input_node->output(p_output.getRealOutputPortId(e.fromPortId)); + } + + auto node = createNode(inputs, p.xml, weights, p.params); + id_to_node[layer_id] = node; + + // Check that output shape after nGraph node validation the same as in IR + // because IR always right! + // Temporary disabled! + // for (size_t i = 0; i < p.params.outputPorts.size(); ++i) { + // if (p.params.outputPorts[i].dims != node->output(i).get_shape()) { + // IE_THROW() << "Shape after nGraph infer " << + // details::dumpVec(node->output(i).get_shape()) + // << " differ from IR shapes: " << + // details::dumpVec(p.params.outputPorts[i].dims); + // } + // } + + if (const auto& parameter_node = std::dynamic_pointer_cast(node)) { + io_map.inputs.insert({layer_id, func_nodes.parameters.size()}); + func_nodes.parameters.emplace_back(parameter_node); + } + + if (const auto& result_node = std::dynamic_pointer_cast(node)) { + io_map.outputs.insert({layer_id, func_nodes.results.size()}); + func_nodes.results.emplace_back(result_node); + } + + if (const auto& sink = std::dynamic_pointer_cast(node)) { + func_nodes.sinks.emplace_back(sink); + } + + if (const auto& read_value = std::dynamic_pointer_cast(node)) { + variable_id_to_read_value[read_value->get_variable_id()] = read_value; + } + + func_nodes.all.emplace_back(node); + } + + // OV_ITT_SCOPE_NEXT(FIRST_INFERENCE, taskChain, "ConstructNgraphFunction"); + + auto function = std::make_shared(func_nodes.results, + func_nodes.sinks, + func_nodes.parameters, + XMLParseUtils::GetStrAttr(root, "name", "")); + for (const auto& sink : func_nodes.sinks) { + if (const auto& assign = std::dynamic_pointer_cast(sink)) { + assign->add_control_dependency(variable_id_to_read_value.at(assign->get_variable_id())); + } + } + + return function; +} + +GenericLayerParams XmlDeserializer::parseGenericParams(const pugi::xml_node& node) { + const auto parsePort = [this](const pugi::xml_node& parentNode, + const GenericLayerParams& params, + bool input) -> GenericLayerParams::LayerPortData { + GenericLayerParams::LayerPortData port; + + port.portId = XMLParseUtils::GetIntAttr(parentNode, "id"); + + FOREACH_CHILD (node, parentNode, "dim") { + int64_t dim = 0; + const pugi::char_t* dimVal = node.child_value(); + std::stringstream ss(dimVal); + if (!(ss >> dim) || dim < -1) { + IE_THROW() << "dimension (" << dimVal << ") in node " << node.name() + << " must be greater or equal to -1: at offset " << node.offset_debug(); + } + port.dims.push_back(dim); + } + + ngraph::element::Type type(ngraph::element::Type_t::undefined); + // Input port hasn't precision + if (!input) { + const std::string& preStr = XMLParseUtils::GetStrAttr(parentNode, "precision"); + type = InferenceEngine::details::convertPrecision(preStr); + } + port.precision = type; + std::vector names; + if (getParameters(parentNode, "names", names)) { + for (size_t i = 0; i < names.size(); i++) { + std::string name = names[i]; + // Restore original name if it contains delimiter + // getParameters(...) returns the vector of names which were split by delimiter ',' + // but some names can contain ',' as a part of name, in this case we use '\' to + // escape delimiter the cycle below is needed in order to find names which contained + // delimiter and restore the original name + while (i < names.size() && names[i].at(names[i].length() - 1) == '\\') { + name.replace(names[i].length() - 1, 1, ","); + name += names[++i]; + } + port.names.emplace(name); + } + } + return port; + }; + GenericLayerParams params; + + params.layerId = XMLParseUtils::GetIntAttr(node, "id"); + params.version = XMLParseUtils::GetStrAttr(node, "version"); + + params.type = XMLParseUtils::GetStrAttr(node, "type"); + + params.name = XMLParseUtils::GetStrAttr(node, "name"); + + auto outNode = node.child("output"); + if (!outNode.empty()) { + FOREACH_CHILD (_cn, outNode, "port") { params.outputPorts.emplace_back(parsePort(_cn, params, false)); } + } + auto inpNode = node.child("input"); + if (!inpNode.empty()) { + FOREACH_CHILD (_cn, inpNode, "port") { params.inputPorts.emplace_back(parsePort(_cn, params, true)); } + } + return params; +} + +std::shared_ptr XmlDeserializer::createNode(const std::vector>& inputs, + const pugi::xml_node& node, + const Blob::CPtr& weights, + const GenericLayerParams& params) { + // Check that inputs are correctly defined + for (size_t i = 0; i < inputs.size(); i++) { + if (!inputs[i].get_node()) + IE_THROW() << params.type << " layer " << params.name << " with id: " << params.layerId + << " has incorrect input with index " << i << "!"; + if (ngraph::element::Type_t::undefined == inputs[i].get_element_type()) + IE_THROW() << params.type << " layer " << params.name << " with id: " << params.layerId + << " has undefined element type for input with index " << i << "!"; + } + + std::shared_ptr ngraphNode; + + // Find registered opset + auto opsetIt = m_opsets.find(params.version); + + // Try to create operation from loaded opsets + static const std::unordered_set experimental_ops_added_to_opset = { + "ExperimentalDetectronDetectionOutput", + "ExperimentalDetectronGenerateProposalsSingleImage", + "ExperimentalDetectronPriorGridGenerator", + "ExperimentalDetectronROIFeatureExtractor", + "ExperimentalDetectronTopKROIs", + "GRUCell", + "RNNCell", + "Proposal"}; + + if (experimental_ops_added_to_opset.count(params.type) && + (params.version == "experimental" || params.version == "extension")) { + opsetIt = m_opsets.find("opset6"); + } + + if (!ngraphNode && opsetIt != m_opsets.end()) { + auto const& type = params.type == "Const" ? "Constant" : params.type; + + if (params.version == "opset1") { + // MVN, ROIPooling and ReorgYolo were missing in opset1 + if (type == "MVN" || type == "ROIPooling" || type == "ReorgYolo") { + opsetIt = m_opsets.find("opset2"); + if (opsetIt == m_opsets.end()) { + IE_THROW() << "Cannot create " << params.type << " layer " << params.name + << " id:" << params.layerId << " from unsupported opset: " << params.version; + } + } + } + + auto const& opset = opsetIt->second; + + ngraphNode = std::shared_ptr(opset.create_insensitive(type)); + if (!ngraphNode) { + IE_THROW() << "Opset " << params.version << " doesn't contain the operation with type: " << type; + } + // Share Weights form constant blob + if (auto constant = std::dynamic_pointer_cast(ngraphNode)) { + constant->alloc_buffer_on_visit_attributes(false); + } + ngraphNode->set_arguments(inputs); + XmlDeserializer visitor(node, weights, m_opsets, m_variables); + + if (ngraphNode->visit_attributes(visitor)) { + ngraphNode->constructor_validate_and_infer_types(); + } + + // To be sure that all default values will be initialized: + ngraphNode = ngraphNode->clone_with_new_inputs(ngraphNode->input_values()); + } + + if (!ngraphNode && m_use_framework_node) { + ngraphNode = std::make_shared(inputs); + XmlDeserializer visitor(node, weights, m_opsets, m_variables); + ngraphNode->visit_attributes(visitor); + + size_t index{0}; + for (const auto& output_params : params.outputPorts) { + ngraphNode->set_output_type(index, output_params.precision, ngraph::PartialShape(output_params.dims)); + ++index; + } + } + + if (!ngraphNode) { + IE_THROW() << "Cannot create " << params.type << " layer " << params.name << " id:" << params.layerId + << " from unsupported opset: " << params.version; + } + + // Save run time info + auto& rtInfo = ngraphNode->get_rt_info(); + pugi::xml_node dn = node.child("data"); + if (dn) { + const auto pr_data = dn.attribute("PrimitivesPriority"); + if (pr_data) { + rtInfo["PrimitivesPriority"] = std::make_shared<::ngraph::VariantWrapper>(pr_data.value()); + } + const auto aw_data = dn.attribute("alt_width"); + if (aw_data) { + rtInfo["alt_width"] = std::make_shared<::ngraph::VariantWrapper>(aw_data.value()); + } + } + + ngraphNode->set_friendly_name(params.name); + for (size_t i = 0; i < params.outputPorts.size() && i < ngraphNode->get_output_size(); ++i) { + if (!params.outputPorts[i].names.empty()) + ngraphNode->get_output_tensor(i).set_names(params.outputPorts[i].names); + } + + return ngraphNode; +} + +} // namespace + +namespace ngraph { +namespace frontend { +std::shared_ptr InputModelIR::convert() { + std::unordered_map opsets; + std::unordered_map> variables; + + // Load default opsets + opsets["opset1"] = ngraph::get_opset1(); + opsets["opset2"] = ngraph::get_opset2(); + opsets["opset3"] = ngraph::get_opset3(); + opsets["opset4"] = ngraph::get_opset4(); + opsets["opset5"] = ngraph::get_opset5(); + opsets["opset6"] = ngraph::get_opset6(); + opsets["opset7"] = ngraph::get_opset7(); + opsets["opset8"] = ngraph::get_opset8(); + + // Load custom opsets + for (const auto& ext : m_exts) { + for (const auto& it : ext->getOpSets()) { + if (opsets.find(it.first) != opsets.end()) + IE_THROW() << "Cannot add opset with name: " << it.first + << ". Opset with the same name already exists."; + opsets[it.first] = it.second; + } + } + + XmlDeserializer visitor(m_root, m_weights, opsets, variables); + bool use_framework_node{false}; + for (const auto& ext : m_exts) { + const InferenceEngine::Version* version = nullptr; + ext->GetVersion(version); + if (version && version->description && strcmp(version->description, "framework_node_ext") == 0) { + use_framework_node = true; + break; + } + } + visitor.use_framework_node(use_framework_node); + + std::shared_ptr function; + visitor.on_attribute("net", function); + return function; +} +} // namespace frontend +} // namespace ngraph \ No newline at end of file From 0926ec4e820980d436159a8f4118591e93d58a6f Mon Sep 17 00:00:00 2001 From: Alexander Shchepetov Date: Wed, 25 Aug 2021 18:09:58 +0300 Subject: [PATCH 40/76] Run layer tests in pre-commit CI validation on Azure (#6537) * add layer test to azure ci * Add pythonpath var, change pytest call method * add mo root to pythonpath * install mo requirements * split requirements install cmd * add --ir_version cmd parameter * Change Add layer test ro Roll layer test * resolve conversations * Reduction in accordance with recent changes * set environment variables in setupvars.sh * fix layer tests target dir * fix PYTHONPATH for layer tests * . * set layer tests env variables in setup.sh script * changes according to layer_tests ci changes * change layer_tests source to tests_pkg * Update setupvars.sh * Update linux.yml * Add cmake build and install for layer tests * Update linux.yml * Update linux.yml * Update linux.yml * Update linux.yml * Update linux.yml * Update linux.yml * Update linux.yml * Update linux.yml * Update linux.yml * Update linux.yml * Update linux.yml * Update linux.yml * Remove MO_ROOT from PYTHONPATH --- .ci/azure/linux.yml | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/.ci/azure/linux.yml b/.ci/azure/linux.yml index 40f07b58922..493d492d04a 100644 --- a/.ci/azure/linux.yml +++ b/.ci/azure/linux.yml @@ -29,8 +29,10 @@ jobs: WORK_DIR: $(Pipeline.Workspace)/_w BUILD_DIR: $(WORK_DIR)/build BUILD_SAMPLES_DIR: $(WORK_DIR)/build_samples + BUILD_LAYER_TESTS_DIR: $(WORK_DIR)/build_layer_tests INSTALL_DIR: $(WORK_DIR)/install_pkg INSTALL_TEST_DIR: $(INSTALL_DIR)/tests + LAYER_TESTS_DIR: $(INSTALL_TEST_DIR)/layer_tests SETUPVARS: $(INSTALL_DIR)/bin/setupvars.sh steps: @@ -138,6 +140,21 @@ jobs: - script: cmake -DCMAKE_INSTALL_PREFIX=$(INSTALL_DIR) -P cmake_install.cmake workingDirectory: $(BUILD_DIR) displayName: 'Install' + + - task: CMake@1 + inputs: + cmakeArgs: > + -GNinja + $(REPO_DIR)/tests/layer_tests + workingDirectory: $(BUILD_LAYER_TESTS_DIR) + + - script: ninja + workingDirectory: $(BUILD_LAYER_TESTS_DIR) + displayName: 'Build Layer Tests' + + - script: cmake -DCOMPONENT=tests -DCMAKE_INSTALL_PREFIX=$(INSTALL_DIR) -P cmake_install.cmake + workingDirectory: $(BUILD_LAYER_TESTS_DIR) + displayName: 'Install Layer Tests' - script: ls -alR $(INSTALL_DIR) displayName: 'List install files' @@ -149,7 +166,7 @@ jobs: cp -R $(REPO_DIR)/inference-engine/temp/opencv_4.5.2_ubuntu20/opencv/* $(INSTALL_DIR)/opencv/ workingDirectory: $(BUILD_DIR) displayName: 'Install tests' - + - script: ls -alR $(INSTALL_DIR) displayName: 'List install files' @@ -160,7 +177,7 @@ jobs: - script: $(INSTALL_DIR)/deployment_tools/inference_engine/samples/c/build_samples.sh workingDirectory: $(BUILD_SAMPLES_DIR) displayName: 'Build c samples' - + - script: rm -fr $(BUILD_DIR) displayName: 'Clean build dir' continueOnError: false @@ -236,6 +253,16 @@ jobs: . $(SETUPVARS) -pyver 3.8 && python3 -m pytest --junitxml=TEST-PythonAPI.xml displayName: 'Python API Tests' continueOnError: false + + - script: | + . $(SETUPVARS) + python3 -m pip install -r requirements.txt + export MO_ROOT=$(INSTALL_DIR)/deployment_tools/model_optimizer + export PYTHONPATH=$(LAYER_TESTS_DIR):$PYTHONPATH + python3 -m pytest tensorflow_tests/test_tf_Roll.py --ir_version=10 --junitxml=TEST-tf_Roll.xmlTEST + workingDirectory: $(LAYER_TESTS_DIR) + displayName: 'Layer Tests' + continueOnError: false - task: PublishTestResults@2 condition: always() From 788fcf2e1b72ea3a64bf89ed82d4c544eebc0614 Mon Sep 17 00:00:00 2001 From: Anton Pankratv Date: Wed, 25 Aug 2021 18:13:32 +0300 Subject: [PATCH 41/76] Changed internal GetExecGraph API (#7189) --- .../src/cldnn_engine/cldnn_executable_network.cpp | 2 +- .../src/cldnn_engine/cldnn_executable_network.h | 2 +- inference-engine/src/cldnn_engine/cldnn_graph.cpp | 8 +++----- inference-engine/src/cldnn_engine/cldnn_graph.h | 6 +++--- .../inference_engine/src/cpp/ie_executable_network.cpp | 2 +- .../src/cpp/ie_executable_network_base.hpp | 2 +- .../interface/ie_iexecutable_network_internal.cpp | 2 +- .../src/mkldnn_plugin/mkldnn_exec_network.cpp | 4 ++-- inference-engine/src/mkldnn_plugin/mkldnn_exec_network.h | 2 +- inference-engine/src/mkldnn_plugin/mkldnn_graph.cpp | 2 +- inference-engine/src/mkldnn_plugin/mkldnn_graph.h | 4 ++-- .../src/mkldnn_plugin/mkldnn_graph_dumper.cpp | 6 ++---- inference-engine/src/mkldnn_plugin/mkldnn_graph_dumper.h | 2 +- .../interface/ie_iexecutable_network_internal.hpp | 2 +- .../graph_transformer/include/vpu/utils/runtime_graph.hpp | 2 +- .../src/vpu/graph_transformer/src/utils/runtime_graph.cpp | 6 ++---- .../src/vpu/myriad_plugin/myriad_executable_network.cpp | 2 +- .../src/vpu/myriad_plugin/myriad_executable_network.h | 2 +- .../interface/mock_iexecutable_network_internal.hpp | 2 +- 19 files changed, 27 insertions(+), 33 deletions(-) diff --git a/inference-engine/src/cldnn_engine/cldnn_executable_network.cpp b/inference-engine/src/cldnn_engine/cldnn_executable_network.cpp index 94245c1d3b6..acea788716c 100644 --- a/inference-engine/src/cldnn_engine/cldnn_executable_network.cpp +++ b/inference-engine/src/cldnn_engine/cldnn_executable_network.cpp @@ -95,7 +95,7 @@ IInferRequestInternal::Ptr CLDNNExecNetwork::CreateInferRequest() { return CreateAsyncInferRequestFromSync(); } -InferenceEngine::CNNNetwork CLDNNExecNetwork::GetExecGraphInfo() { +std::shared_ptr CLDNNExecNetwork::GetExecGraphInfo() { if (m_graphs.empty()) IE_THROW(NetworkNotLoaded); diff --git a/inference-engine/src/cldnn_engine/cldnn_executable_network.h b/inference-engine/src/cldnn_engine/cldnn_executable_network.h index 60c886a3fe7..590da3bdb1b 100644 --- a/inference-engine/src/cldnn_engine/cldnn_executable_network.h +++ b/inference-engine/src/cldnn_engine/cldnn_executable_network.h @@ -25,7 +25,7 @@ public: CLDNNExecNetwork(InferenceEngine::CNNNetwork &network, InferenceEngine::RemoteContext::Ptr context, Config config); - InferenceEngine::CNNNetwork GetExecGraphInfo() override; + std::shared_ptr GetExecGraphInfo() override; InferenceEngine::IInferRequestInternal::Ptr CreateInferRequest() override; InferenceEngine::IInferRequestInternal::Ptr CreateInferRequestImpl(InferenceEngine::InputsDataMap networkInputs, InferenceEngine::OutputsDataMap networkOutputs) override; diff --git a/inference-engine/src/cldnn_engine/cldnn_graph.cpp b/inference-engine/src/cldnn_engine/cldnn_graph.cpp index 53cefa30cf7..75ea9d2a251 100644 --- a/inference-engine/src/cldnn_engine/cldnn_graph.cpp +++ b/inference-engine/src/cldnn_engine/cldnn_graph.cpp @@ -106,7 +106,7 @@ std::shared_ptr CLDNNGraph::BuildNetwork(std::shared_ptr& primitives_info, +std::shared_ptr CLDNNGraph::GetExecGraphInfoByPrimitivesInfo(std::vector& primitives_info, bool filter_const_primitives) { OV_ITT_SCOPED_TASK(itt::domains::CLDNNPlugin, "CLDNNGraph::GetExecGraphInfoByPrimitivesInfo"); if (m_config.useProfiling) { @@ -467,12 +467,10 @@ InferenceEngine::CNNNetwork CLDNNGraph::GetExecGraphInfoByPrimitivesInfo(std::ve create_ngraph_node(pi); } - auto function = std::make_shared(results, params, "runtime_gpu_graph"); - InferenceEngine::CNNNetwork net(function); - return net; + return std::make_shared(results, params, "runtime_gpu_graph"); } -InferenceEngine::CNNNetwork CLDNNGraph::GetExecGraphInfo() { +std::shared_ptr CLDNNGraph::GetExecGraphInfo() { auto primitives_info = GetNetwork()->get_primitives_info(); return GetExecGraphInfoByPrimitivesInfo(primitives_info, true); } diff --git a/inference-engine/src/cldnn_engine/cldnn_graph.h b/inference-engine/src/cldnn_engine/cldnn_graph.h index feae62a03c2..206c58aaccd 100644 --- a/inference-engine/src/cldnn_engine/cldnn_graph.h +++ b/inference-engine/src/cldnn_engine/cldnn_graph.h @@ -34,7 +34,7 @@ public: CLDNNGraph(InferenceEngine::CNNNetwork& network, InferenceEngine::gpu::ClContext::Ptr context, Config config, uint16_t stream_id = 0); explicit CLDNNGraph(std::shared_ptr graph, uint16_t stream_id = 0); - InferenceEngine::CNNNetwork GetExecGraphInfo(); + std::shared_ptr GetExecGraphInfo(); bool IsLoaded() const; @@ -78,8 +78,8 @@ protected: void Build(); void UpdateLayersMaps(); void UpdateImplementationsMap(); - InferenceEngine::CNNNetwork GetExecGraphInfoByPrimitivesInfo(std::vector& pi, - bool filter_const_primitives = true); + std::shared_ptr GetExecGraphInfoByPrimitivesInfo(std::vector& pi, + bool filter_const_primitives = true); }; } // namespace CLDNNPlugin diff --git a/inference-engine/src/inference_engine/src/cpp/ie_executable_network.cpp b/inference-engine/src/inference_engine/src/cpp/ie_executable_network.cpp index e0b48fb223d..1f43560ad8b 100644 --- a/inference-engine/src/inference_engine/src/cpp/ie_executable_network.cpp +++ b/inference-engine/src/inference_engine/src/cpp/ie_executable_network.cpp @@ -78,7 +78,7 @@ void ExecutableNetwork::Export(std::ostream& networkModel) { } CNNNetwork ExecutableNetwork::GetExecGraphInfo() { - EXEC_NET_CALL_STATEMENT(return _impl->GetExecGraphInfo()); + EXEC_NET_CALL_STATEMENT(return CNNNetwork{_impl->GetExecGraphInfo()}); } void ExecutableNetwork::SetConfig(const std::map& config) { diff --git a/inference-engine/src/inference_engine/src/cpp/ie_executable_network_base.hpp b/inference-engine/src/inference_engine/src/cpp/ie_executable_network_base.hpp index 52cb5e0a374..d008be74f76 100644 --- a/inference-engine/src/inference_engine/src/cpp/ie_executable_network_base.hpp +++ b/inference-engine/src/inference_engine/src/cpp/ie_executable_network_base.hpp @@ -65,7 +65,7 @@ public: } StatusCode GetExecGraphInfo(ICNNNetwork::Ptr& graphPtr, ResponseDesc* resp) noexcept override { - TO_STATUS(graphPtr = _impl->GetExecGraphInfo()); + TO_STATUS(graphPtr = CNNNetwork{_impl->GetExecGraphInfo()}); } StatusCode SetConfig(const std::map& config, ResponseDesc* resp) noexcept override { diff --git a/inference-engine/src/inference_engine/src/cpp_interfaces/interface/ie_iexecutable_network_internal.cpp b/inference-engine/src/inference_engine/src/cpp_interfaces/interface/ie_iexecutable_network_internal.cpp index be42b176595..d79fba69cc3 100644 --- a/inference-engine/src/inference_engine/src/cpp_interfaces/interface/ie_iexecutable_network_internal.cpp +++ b/inference-engine/src/inference_engine/src/cpp_interfaces/interface/ie_iexecutable_network_internal.cpp @@ -62,7 +62,7 @@ void IExecutableNetworkInternal::Export(std::ostream& networkModel) { IE_THROW(NotImplemented); } -CNNNetwork IExecutableNetworkInternal::GetExecGraphInfo() { +std::shared_ptr IExecutableNetworkInternal::GetExecGraphInfo() { IE_THROW(NotImplemented); } diff --git a/inference-engine/src/mkldnn_plugin/mkldnn_exec_network.cpp b/inference-engine/src/mkldnn_plugin/mkldnn_exec_network.cpp index b21b39f104a..6e4746e2a8c 100644 --- a/inference-engine/src/mkldnn_plugin/mkldnn_exec_network.cpp +++ b/inference-engine/src/mkldnn_plugin/mkldnn_exec_network.cpp @@ -196,7 +196,7 @@ InferenceEngine::IInferRequestInternal::Ptr MKLDNNExecNetwork::CreateInferReques return CreateAsyncInferRequestFromSync(); } -InferenceEngine::CNNNetwork MKLDNNExecNetwork::GetExecGraphInfo() { +std::shared_ptr MKLDNNExecNetwork::GetExecGraphInfo() { if (_graphs.size() == 0) IE_THROW() << "No graph was found"; @@ -219,7 +219,7 @@ InferenceEngine::Parameter MKLDNNExecNetwork::GetMetric(const std::string &name) IE_THROW() << "No graph was found"; if (name == METRIC_KEY(NETWORK_NAME)) { - IE_SET_METRIC_RETURN(NETWORK_NAME, GetGraph()._graph.dump().getName()); + IE_SET_METRIC_RETURN(NETWORK_NAME, GetGraph()._graph.dump()->get_friendly_name()); } else if (name == METRIC_KEY(SUPPORTED_METRICS)) { std::vector metrics; metrics.push_back(METRIC_KEY(NETWORK_NAME)); diff --git a/inference-engine/src/mkldnn_plugin/mkldnn_exec_network.h b/inference-engine/src/mkldnn_plugin/mkldnn_exec_network.h index a96098b133d..b16336711b3 100644 --- a/inference-engine/src/mkldnn_plugin/mkldnn_exec_network.h +++ b/inference-engine/src/mkldnn_plugin/mkldnn_exec_network.h @@ -38,7 +38,7 @@ public: InferenceEngine::Parameter GetMetric(const std::string &name) const override; - InferenceEngine::CNNNetwork GetExecGraphInfo() override; + std::shared_ptr GetExecGraphInfo() override; INFERENCE_ENGINE_DEPRECATED("Use InferRequest::QueryState instead") std::vector QueryState() override; diff --git a/inference-engine/src/mkldnn_plugin/mkldnn_graph.cpp b/inference-engine/src/mkldnn_plugin/mkldnn_graph.cpp index e97912762e7..2a41d514b8f 100644 --- a/inference-engine/src/mkldnn_plugin/mkldnn_graph.cpp +++ b/inference-engine/src/mkldnn_plugin/mkldnn_graph.cpp @@ -1200,6 +1200,6 @@ void MKLDNNGraph::EnforceBF16() { } } -InferenceEngine::CNNNetwork MKLDNNGraph::dump() const { +std::shared_ptr MKLDNNGraph::dump() const { return dump_graph_as_ie_ngraph_net(*this); } diff --git a/inference-engine/src/mkldnn_plugin/mkldnn_graph.h b/inference-engine/src/mkldnn_plugin/mkldnn_graph.h index 50ccd0be4f0..a946d47bc6a 100644 --- a/inference-engine/src/mkldnn_plugin/mkldnn_graph.h +++ b/inference-engine/src/mkldnn_plugin/mkldnn_graph.h @@ -162,7 +162,7 @@ public: */ bool InsertNode(MKLDNNNodePtr parent, MKLDNNNodePtr child, MKLDNNNodePtr node, int parentPort, int childPort, bool initNode = false); - InferenceEngine::CNNNetwork dump() const; + std::shared_ptr dump() const; void ResetInferCount() { infer_count = 0; } @@ -223,7 +223,7 @@ protected: friend class MKLDNNInferRequest; friend class MKLDNNGraphlessInferRequest; - friend InferenceEngine::CNNNetwork dump_graph_as_ie_ngraph_net(const MKLDNNGraph &graph); + friend std::shared_ptr dump_graph_as_ie_ngraph_net(const MKLDNNGraph &graph); private: // these node pointers (from graphNodes) are to avoid regular checking for diff --git a/inference-engine/src/mkldnn_plugin/mkldnn_graph_dumper.cpp b/inference-engine/src/mkldnn_plugin/mkldnn_graph_dumper.cpp index 909a5083f71..523d5dce81b 100644 --- a/inference-engine/src/mkldnn_plugin/mkldnn_graph_dumper.cpp +++ b/inference-engine/src/mkldnn_plugin/mkldnn_graph_dumper.cpp @@ -109,7 +109,7 @@ std::map extract_node_metadata(const MKLDNNNodePtr &no } // namespace -InferenceEngine::CNNNetwork dump_graph_as_ie_ngraph_net(const MKLDNNGraph &graph) { +std::shared_ptr dump_graph_as_ie_ngraph_net(const MKLDNNGraph &graph) { std::map > node2layer; ngraph::ResultVector results; @@ -200,9 +200,7 @@ InferenceEngine::CNNNetwork dump_graph_as_ie_ngraph_net(const MKLDNNGraph &graph holder->add_control_dependency(node); } - auto function = std::make_shared(results, params, graph._name); - InferenceEngine::CNNNetwork net(function); - return net; + return std::make_shared(results, params, graph._name); } #ifdef CPU_DEBUG_CAPS diff --git a/inference-engine/src/mkldnn_plugin/mkldnn_graph_dumper.h b/inference-engine/src/mkldnn_plugin/mkldnn_graph_dumper.h index 597568224f3..511acebecf8 100644 --- a/inference-engine/src/mkldnn_plugin/mkldnn_graph_dumper.h +++ b/inference-engine/src/mkldnn_plugin/mkldnn_graph_dumper.h @@ -12,7 +12,7 @@ namespace MKLDNNPlugin { -InferenceEngine::CNNNetwork dump_graph_as_ie_ngraph_net(const MKLDNNGraph &graph); +std::shared_ptr dump_graph_as_ie_ngraph_net(const MKLDNNGraph &graph); #ifdef CPU_DEBUG_CAPS void serialize(const MKLDNNGraph &graph); #endif // CPU_DEBUG_CAPS diff --git a/inference-engine/src/plugin_api/cpp_interfaces/interface/ie_iexecutable_network_internal.hpp b/inference-engine/src/plugin_api/cpp_interfaces/interface/ie_iexecutable_network_internal.hpp index 27e0cf3b544..2dd1086861a 100644 --- a/inference-engine/src/plugin_api/cpp_interfaces/interface/ie_iexecutable_network_internal.hpp +++ b/inference-engine/src/plugin_api/cpp_interfaces/interface/ie_iexecutable_network_internal.hpp @@ -85,7 +85,7 @@ public: * @brief Get executable graph information from a device * @return A network object to store executable graph information */ - virtual CNNNetwork GetExecGraphInfo(); + virtual std::shared_ptr GetExecGraphInfo(); /** * @deprecated Need to implement GetVariablesInfo for ExecutableNetwork diff --git a/inference-engine/src/vpu/graph_transformer/include/vpu/utils/runtime_graph.hpp b/inference-engine/src/vpu/graph_transformer/include/vpu/utils/runtime_graph.hpp index 93bededfceb..ee5ddcad1b6 100644 --- a/inference-engine/src/vpu/graph_transformer/include/vpu/utils/runtime_graph.hpp +++ b/inference-engine/src/vpu/graph_transformer/include/vpu/utils/runtime_graph.hpp @@ -11,7 +11,7 @@ namespace vpu { -InferenceEngine::CNNNetwork buildRuntimeGraph( +std::shared_ptr buildRuntimeGraph( GraphMetaInfo& graphMetaInfo, const std::vector& perfInfo); diff --git a/inference-engine/src/vpu/graph_transformer/src/utils/runtime_graph.cpp b/inference-engine/src/vpu/graph_transformer/src/utils/runtime_graph.cpp index ff55ae40140..ed67650de9c 100644 --- a/inference-engine/src/vpu/graph_transformer/src/utils/runtime_graph.cpp +++ b/inference-engine/src/vpu/graph_transformer/src/utils/runtime_graph.cpp @@ -25,7 +25,7 @@ std::map extractMeta(const StageMetaInfo&); } // namespace -InferenceEngine::CNNNetwork buildRuntimeGraph(GraphMetaInfo& graphMetaInfo, const std::vector& perfInfo) { +std::shared_ptr buildRuntimeGraph(GraphMetaInfo& graphMetaInfo, const std::vector& perfInfo) { std::map> stageMetaIndexToNode; std::function createNodeFromMeta; @@ -112,9 +112,7 @@ InferenceEngine::CNNNetwork buildRuntimeGraph(GraphMetaInfo& graphMetaInfo, cons createNodeFromMeta(i); } - auto ngraph = std::make_shared(results, params, graphMetaInfo.graphName); - InferenceEngine::CNNNetwork net(ngraph); - return net; + return std::make_shared(results, params, graphMetaInfo.graphName); } namespace { diff --git a/inference-engine/src/vpu/myriad_plugin/myriad_executable_network.cpp b/inference-engine/src/vpu/myriad_plugin/myriad_executable_network.cpp index f9bd974a0ff..d70622cfab5 100644 --- a/inference-engine/src/vpu/myriad_plugin/myriad_executable_network.cpp +++ b/inference-engine/src/vpu/myriad_plugin/myriad_executable_network.cpp @@ -191,7 +191,7 @@ InferenceEngine::Parameter ExecutableNetwork::GetMetric(const std::string &name) } } -InferenceEngine::CNNNetwork ExecutableNetwork::GetExecGraphInfo() { +std::shared_ptr ExecutableNetwork::GetExecGraphInfo() { auto perfInfo = _executor->getPerfTimeInfo(_graphDesc._graphHandle); if (_graphDesc._name == importedNetworkName) IE_THROW() << diff --git a/inference-engine/src/vpu/myriad_plugin/myriad_executable_network.h b/inference-engine/src/vpu/myriad_plugin/myriad_executable_network.h index d093597cd49..22e0f3781c9 100644 --- a/inference-engine/src/vpu/myriad_plugin/myriad_executable_network.h +++ b/inference-engine/src/vpu/myriad_plugin/myriad_executable_network.h @@ -94,7 +94,7 @@ public: ie::Parameter GetMetric(const std::string &name) const override; - ie::CNNNetwork GetExecGraphInfo() override; + std::shared_ptr GetExecGraphInfo() override; void Import(std::istream& strm, std::vector &devicePool, const PluginConfiguration& configuration); diff --git a/inference-engine/tests/ie_test_utils/unit_test_utils/mocks/cpp_interfaces/interface/mock_iexecutable_network_internal.hpp b/inference-engine/tests/ie_test_utils/unit_test_utils/mocks/cpp_interfaces/interface/mock_iexecutable_network_internal.hpp index c1cc30a944b..434d2c2e4eb 100644 --- a/inference-engine/tests/ie_test_utils/unit_test_utils/mocks/cpp_interfaces/interface/mock_iexecutable_network_internal.hpp +++ b/inference-engine/tests/ie_test_utils/unit_test_utils/mocks/cpp_interfaces/interface/mock_iexecutable_network_internal.hpp @@ -25,7 +25,7 @@ public: MOCK_METHOD1(Export, void(const std::string &)); void Export(std::ostream &) override {}; MOCK_METHOD0(QueryState, std::vector(void)); - MOCK_METHOD0(GetExecGraphInfo, CNNNetwork(void)); + MOCK_METHOD0(GetExecGraphInfo, std::shared_ptr(void)); MOCK_METHOD1(SetConfig, void(const std::map &config)); MOCK_CONST_METHOD1(GetConfig, Parameter(const std::string &name)); From 6750b8c33663bf63ac7c5333122be14805fd99bd Mon Sep 17 00:00:00 2001 From: Anton Pankratv Date: Wed, 25 Aug 2021 18:16:41 +0300 Subject: [PATCH 42/76] Created Remote context c++ API (#7114) --- .../ncc_naming_style/openvino.style | 4 +- .../src/cldnn_engine/cldnn_engine.cpp | 16 +- .../src/cldnn_engine/cldnn_engine.h | 6 +- .../cldnn_engine/cldnn_executable_network.cpp | 4 +- .../cldnn_engine/cldnn_executable_network.h | 4 +- .../src/cldnn_engine/cldnn_remote_context.cpp | 4 +- .../src/cldnn_engine/cldnn_remote_context.h | 17 +-- .../src/gna_plugin/gna_plugin.hpp | 10 +- .../include/ie/gpu/gpu_context_api_ocl.hpp | 4 +- .../include/ie/ie_remote_blob.hpp | 75 ++++++++++ .../include/ie/ie_remote_context.hpp | 58 +------- .../include/openvino/runtime/common.hpp | 1 + .../include/openvino/runtime/core.hpp | 9 +- .../openvino/runtime/remote_context.hpp | 139 ++++++++++++++++++ .../src/cpp/ie_executable_network.cpp | 1 + .../src/cpp/ie_executable_network_base.hpp | 1 + .../inference_engine/src/cpp/ie_plugin.hpp | 12 +- .../ie_iexecutable_network_internal.cpp | 2 +- .../interface/ie_iplugin_internal.cpp | 10 +- .../interface/ie_iremote_context.cpp | 19 +++ .../src/inference_engine/src/ie_core.cpp | 43 ++++-- .../inference_engine/src/remote_context.cpp | 43 ++++++ .../multi_device_exec_network.cpp | 2 +- .../multi_device_exec_network.hpp | 2 +- .../ie_iexecutable_network_internal.hpp | 4 +- .../interface/ie_iplugin_internal.hpp | 16 +- .../interface/ie_iremote_context.hpp | 67 +++++++++ .../inference_engine/caching_test.cpp | 15 +- .../ov_remote_context_test.cpp | 25 ++++ .../include/behavior/ov_core_integration.hpp | 13 -- .../include/multi/multi_remote_blob_tests.hpp | 2 +- .../cpp_interfaces/interface/mock_icore.hpp | 4 +- .../mock_iexecutable_network_internal.hpp | 2 +- .../interface/mock_iinference_plugin.hpp | 8 +- .../mocks/mock_engine/mock_plugin.cpp | 6 +- .../mocks/mock_engine/mock_plugin.hpp | 6 +- 36 files changed, 485 insertions(+), 169 deletions(-) create mode 100644 inference-engine/src/inference_engine/include/ie/ie_remote_blob.hpp create mode 100644 inference-engine/src/inference_engine/include/openvino/runtime/remote_context.hpp create mode 100644 inference-engine/src/inference_engine/src/cpp_interfaces/interface/ie_iremote_context.cpp create mode 100644 inference-engine/src/inference_engine/src/remote_context.cpp create mode 100644 inference-engine/src/plugin_api/cpp_interfaces/interface/ie_iremote_context.hpp create mode 100644 inference-engine/tests/functional/inference_engine/ov_remote_context_test.cpp diff --git a/cmake/developer_package/ncc_naming_style/openvino.style b/cmake/developer_package/ncc_naming_style/openvino.style index 6832847ae3a..efe1c2bbad1 100644 --- a/cmake/developer_package/ncc_naming_style/openvino.style +++ b/cmake/developer_package/ncc_naming_style/openvino.style @@ -6,10 +6,10 @@ ClassName: '^([A-Z][\w]+|b?float16|numeric_limits|ngraph_error|stopwatch|unsuppo StructName: '^([A-Z][\w]+|element_type_traits|hash|oi_pair)$' FunctionName: '^(operator\W+|[a-z_\d]+)$' Namespace: '^([a-z\d_]+|InferenceEngine)$' -NamespaceAlias: '^[a-z\d_]+$' +NamespaceAlias: '^([a-z\d_]+|InferenceEngine)$' UnionName: '[A-Z][\w]+$' TemplateTemplateParameter: '[A-Z][\w]+' -NamespaceReference: '^[a-z\d_]+$' +NamespaceReference: '^([a-z\d_]+|InferenceEngine)$' TemplateNonTypeParameter: '^\w*$' ClassTemplate: '^([A-Z][\w]+|element_type_traits)$' TemplateTypeParameter: '^\w*$' diff --git a/inference-engine/src/cldnn_engine/cldnn_engine.cpp b/inference-engine/src/cldnn_engine/cldnn_engine.cpp index e84f9d2d9cf..90e42510eae 100644 --- a/inference-engine/src/cldnn_engine/cldnn_engine.cpp +++ b/inference-engine/src/cldnn_engine/cldnn_engine.cpp @@ -617,7 +617,7 @@ IExecutableNetworkInternal::Ptr clDNNEngine::LoadExeNetworkImpl(const InferenceE } IExecutableNetworkInternal::Ptr clDNNEngine::LoadExeNetworkImpl(const InferenceEngine::CNNNetwork &network, - const RemoteContext::Ptr &context, + const IRemoteContext::Ptr &context, const std::map &config) { InferenceEngine::InputsDataMap _networkInputs = network.getInputsInfo(); check_inputs(_networkInputs); @@ -634,30 +634,28 @@ IExecutableNetworkInternal::Ptr clDNNEngine::LoadExeNetworkImpl(const InferenceE return std::make_shared(transformedNetwork, casted, conf); } -RemoteContext::Ptr clDNNEngine::CreateContext(const ParamMap& params) { +IRemoteContext::Ptr clDNNEngine::CreateContext(const ParamMap& params) { // parameter map is non-empty std::string contextTypeStr = _StrFromParams(params, GPU_PARAM_KEY(CONTEXT_TYPE)); if (GPU_PARAM_VALUE(OCL) == contextTypeStr) { - auto context = std::make_shared(shared_from_this(), params, _impl->m_config); - return std::dynamic_pointer_cast(context); + return std::make_shared(shared_from_this(), params, _impl->m_config); } else if (GPU_PARAM_VALUE(VA_SHARED) == contextTypeStr) { #ifdef _WIN32 - auto context = std::make_shared(shared_from_this(), params, _impl->m_config); + return std::make_shared(shared_from_this(), params, _impl->m_config); #else - auto context = std::make_shared(shared_from_this(), params, _impl->m_config); + return std::make_shared(shared_from_this(), params, _impl->m_config); #endif - return std::dynamic_pointer_cast(context); } else { IE_THROW() << "Invalid remote context type" << contextTypeStr; } } -RemoteContext::Ptr clDNNEngine::GetDefaultContext(const ParamMap& params) { +IRemoteContext::Ptr clDNNEngine::GetDefaultContext(const ParamMap& params) { if (nullptr == m_defaultContext) { m_defaultContext.reset(new CLDNNRemoteCLContext(shared_from_this(), params, _impl->m_config)); } - return std::dynamic_pointer_cast(m_defaultContext); + return m_defaultContext; } void clDNNEngine::SetConfig(const std::map &config) { diff --git a/inference-engine/src/cldnn_engine/cldnn_engine.h b/inference-engine/src/cldnn_engine/cldnn_engine.h index 10933cd7287..12ac3203205 100644 --- a/inference-engine/src/cldnn_engine/cldnn_engine.h +++ b/inference-engine/src/cldnn_engine/cldnn_engine.h @@ -40,7 +40,7 @@ public: const std::map &config) override; InferenceEngine::IExecutableNetworkInternal::Ptr LoadExeNetworkImpl(const InferenceEngine::CNNNetwork &network, - const InferenceEngine::RemoteContext::Ptr& context, + const std::shared_ptr &context, const std::map &config) override; void SetConfig(const std::map &config) override; @@ -49,8 +49,8 @@ public: InferenceEngine::QueryNetworkResult QueryNetwork(const InferenceEngine::CNNNetwork& network, const std::map& config) const override; - InferenceEngine::RemoteContext::Ptr CreateContext(const InferenceEngine::ParamMap& params) override; - InferenceEngine::RemoteContext::Ptr GetDefaultContext(const InferenceEngine::ParamMap& params) override; + std::shared_ptr CreateContext(const InferenceEngine::ParamMap& params) override; + std::shared_ptr GetDefaultContext(const InferenceEngine::ParamMap& params) override; }; }; // namespace CLDNNPlugin diff --git a/inference-engine/src/cldnn_engine/cldnn_executable_network.cpp b/inference-engine/src/cldnn_engine/cldnn_executable_network.cpp index acea788716c..7102a0ac439 100644 --- a/inference-engine/src/cldnn_engine/cldnn_executable_network.cpp +++ b/inference-engine/src/cldnn_engine/cldnn_executable_network.cpp @@ -32,7 +32,7 @@ using namespace InferenceEngine::details; namespace CLDNNPlugin { -CLDNNExecNetwork::CLDNNExecNetwork(InferenceEngine::CNNNetwork &network, RemoteContext::Ptr context, Config config) : +CLDNNExecNetwork::CLDNNExecNetwork(InferenceEngine::CNNNetwork &network, std::shared_ptr context, Config config) : InferenceEngine::ExecutableNetworkThreadSafeDefault{[&]()->InferenceEngine::ITaskExecutor::Ptr { if (config.throughput_streams > 1) { return std::make_shared( @@ -135,7 +135,7 @@ InferenceEngine::Parameter CLDNNExecNetwork::GetMetric(const std::string &name) } } -RemoteContext::Ptr CLDNNExecNetwork::GetContext() const { +std::shared_ptr CLDNNExecNetwork::GetContext() const { return m_context; } diff --git a/inference-engine/src/cldnn_engine/cldnn_executable_network.h b/inference-engine/src/cldnn_engine/cldnn_executable_network.h index 590da3bdb1b..88267797d71 100644 --- a/inference-engine/src/cldnn_engine/cldnn_executable_network.h +++ b/inference-engine/src/cldnn_engine/cldnn_executable_network.h @@ -23,7 +23,7 @@ class CLDNNExecNetwork : public InferenceEngine::ExecutableNetworkThreadSafeDefa public: typedef std::shared_ptr Ptr; - CLDNNExecNetwork(InferenceEngine::CNNNetwork &network, InferenceEngine::RemoteContext::Ptr context, Config config); + CLDNNExecNetwork(InferenceEngine::CNNNetwork &network, std::shared_ptr context, Config config); std::shared_ptr GetExecGraphInfo() override; InferenceEngine::IInferRequestInternal::Ptr CreateInferRequest() override; @@ -32,7 +32,7 @@ public: InferenceEngine::Parameter GetMetric(const std::string &name) const override; InferenceEngine::Parameter GetConfig(const std::string &name) const override; - InferenceEngine::RemoteContext::Ptr GetContext() const override; + std::shared_ptr GetContext() const override; std::vector> m_graphs; InferenceEngine::gpu::ClContext::Ptr m_context; diff --git a/inference-engine/src/cldnn_engine/cldnn_remote_context.cpp b/inference-engine/src/cldnn_engine/cldnn_remote_context.cpp index 1ee476390d6..5e2519cc9ba 100644 --- a/inference-engine/src/cldnn_engine/cldnn_remote_context.cpp +++ b/inference-engine/src/cldnn_engine/cldnn_remote_context.cpp @@ -134,8 +134,8 @@ std::string CLDNNRemoteBlobImpl::getDeviceName() const noexcept { return getContextImpl(m_context.lock())->getDeviceName(); }; -std::shared_ptr CLDNNRemoteBlobImpl::getContext() const noexcept { - return std::dynamic_pointer_cast(m_context.lock()); +std::shared_ptr CLDNNRemoteBlobImpl::getContext() const noexcept { + return m_context.lock(); } void CLDNNRemoteBlobImpl::lock() const { diff --git a/inference-engine/src/cldnn_engine/cldnn_remote_context.h b/inference-engine/src/cldnn_engine/cldnn_remote_context.h index a68612df041..d35cd7c0410 100644 --- a/inference-engine/src/cldnn_engine/cldnn_remote_context.h +++ b/inference-engine/src/cldnn_engine/cldnn_remote_context.h @@ -8,6 +8,7 @@ #include #include #include +#include #include "cldnn_config.h" #include "cldnn_common_utils.h" @@ -53,7 +54,7 @@ public: bool deallocate() noexcept; InferenceEngine::ParamMap getParams() const; std::string getDeviceName() const noexcept; - std::shared_ptr getContext() const noexcept; + std::shared_ptr getContext() const noexcept; InferenceEngine::LockedMemory buffer() noexcept; InferenceEngine::LockedMemory cbuffer() const noexcept; InferenceEngine::LockedMemory rwmap()noexcept; @@ -245,8 +246,7 @@ protected: }; template -class typedCLDNNExecutionContext : public TpublicContextAPI, - public std::enable_shared_from_this> { +class typedCLDNNExecutionContext : public TpublicContextAPI { template struct _Key { T1 _surf; @@ -292,8 +292,7 @@ class typedCLDNNExecutionContext : public TpublicContextAPI, ImageFormatFromLayout(tensorDesc.getLayout()), CldnnTensorFromIEDims(tensorDesc.getDims())); auto smart_this = - std::dynamic_pointer_cast - (std::enable_shared_from_this>::shared_from_this()); + std::dynamic_pointer_cast(this->shared_from_this()); #ifdef _WIN32 ret = std::make_shared(smart_this, stream, tensorDesc, layout, mem, 0, plane, @@ -328,8 +327,7 @@ class typedCLDNNExecutionContext : public TpublicContextAPI, FormatFromLayout(tensorDesc.getLayout()), CldnnTensorFromIEDims(tensorDesc.getDims())); auto smart_this = - std::dynamic_pointer_cast - (std::enable_shared_from_this>::shared_from_this()); + std::dynamic_pointer_cast(this->shared_from_this()); switch (blob_type) { case CLDNNRemoteBlobImpl::BlobType::BT_BUF_SHARED: @@ -358,8 +356,7 @@ class typedCLDNNExecutionContext : public TpublicContextAPI, cldnn::layout layout(DataTypeFromPrecision(tensorDesc.getPrecision()), FormatFromLayout(tensorDesc.getLayout()), CldnnTensorFromIEDims(tensorDesc.getDims())); - auto smart_this = std::dynamic_pointer_cast - (std::enable_shared_from_this>::shared_from_this()); + auto smart_this = std::dynamic_pointer_cast(this->shared_from_this()); auto& stream = _impl.GetEngine()->get_program_stream(); return std::make_shared(smart_this, stream, @@ -373,6 +370,7 @@ class typedCLDNNExecutionContext : public TpublicContextAPI, if (GetType() != CLDNNExecutionContextImpl::ContextType::DEV_SHARED) IE_THROW() << "Shared context is required to to share this type of memory"; } + public: using Ptr = std::shared_ptr; using CPtr = std::shared_ptr; @@ -427,6 +425,7 @@ public: CLDNNExecutionContextImpl::ContextType GetType() const { return _impl.GetType(); } CLDNNExecutionContextImpl* getImpl() { return &_impl; } + protected: CLDNNExecutionContextImpl _impl; }; diff --git a/inference-engine/src/gna_plugin/gna_plugin.hpp b/inference-engine/src/gna_plugin/gna_plugin.hpp index 2ce54f4f9ab..941dc209cea 100644 --- a/inference-engine/src/gna_plugin/gna_plugin.hpp +++ b/inference-engine/src/gna_plugin/gna_plugin.hpp @@ -114,8 +114,12 @@ class GNAPlugin : public InferenceEngine::IInferencePlugin { const std::map & options) const override; InferenceEngine::Parameter GetMetric(const std::string& name, const std::map & options) const override; - InferenceEngine::RemoteContext::Ptr CreateContext(const InferenceEngine::ParamMap& params) override { THROW_GNA_EXCEPTION << "Not implemented"; } - InferenceEngine::RemoteContext::Ptr GetDefaultContext(const InferenceEngine::ParamMap&) override { THROW_GNA_EXCEPTION << "Not implemented"; } + std::shared_ptr CreateContext(const InferenceEngine::ParamMap& params) override { + THROW_GNA_EXCEPTION << "Not implemented"; + } + std::shared_ptr GetDefaultContext(const InferenceEngine::ParamMap&) override { + THROW_GNA_EXCEPTION << "Not implemented"; + } void Wait(uint32_t sync, InferenceEngine::Blob &result) { THROW_GNA_EXCEPTION << "Not implemented"; } @@ -126,7 +130,7 @@ class GNAPlugin : public InferenceEngine::IInferencePlugin { THROW_GNA_EXCEPTION << "Not implemented"; } InferenceEngine::IExecutableNetworkInternal::Ptr ImportNetwork(std::istream& networkModel, - const InferenceEngine::RemoteContext::Ptr& context, + const std::shared_ptr& context, const std::map &config) override { THROW_GNA_EXCEPTION << "Not implemented"; } diff --git a/inference-engine/src/inference_engine/include/ie/gpu/gpu_context_api_ocl.hpp b/inference-engine/src/inference_engine/include/ie/gpu/gpu_context_api_ocl.hpp index 8ab1393291d..27a1c0f1a80 100644 --- a/inference-engine/src/inference_engine/include/ie/gpu/gpu_context_api_ocl.hpp +++ b/inference-engine/src/inference_engine/include/ie/gpu/gpu_context_api_ocl.hpp @@ -10,6 +10,7 @@ */ #pragma once +#include #include #include @@ -18,7 +19,6 @@ #include "gpu/gpu_params.hpp" #include "ie_compound_blob.h" #include "ie_core.hpp" -#include "ie_remote_context.hpp" namespace InferenceEngine { @@ -29,7 +29,7 @@ namespace gpu { * The plugin object derived from this class can be obtained either with * GetContext() method of Executable network or using CreateContext() Core call. */ -class ClContext : public RemoteContext, public details::param_map_obj_getter { +class ClContext : public IRemoteContext, public details::param_map_obj_getter { public: /** * @brief A smart pointer to the ClContext object diff --git a/inference-engine/src/inference_engine/include/ie/ie_remote_blob.hpp b/inference-engine/src/inference_engine/include/ie/ie_remote_blob.hpp new file mode 100644 index 00000000000..e08a70fc0c1 --- /dev/null +++ b/inference-engine/src/inference_engine/include/ie/ie_remote_blob.hpp @@ -0,0 +1,75 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +/** + * @brief This is a header file for the IE RemoteContext and RemoteBlob classes + * + * @file ie_remote_context.hpp + */ +#pragma once + +#include +#include +#include + +#include "ie_blob.h" +#include "ie_parameter.hpp" + +namespace InferenceEngine { +class RemoteContext; + +/** + * @brief This class represents an Inference Engine abstraction to the memory allocated + * on the remote (non-CPU) accelerator device + */ +class RemoteBlob : public MemoryBlob { +public: + /** + * @brief A smart pointer to the RemoteBlob object + */ + using Ptr = std::shared_ptr; + + /** + * @brief A smart pointer to the const RemoteBlob object + */ + using CPtr = std::shared_ptr; + + /** + * @brief RemoteBlob virtual destructor + */ + virtual ~RemoteBlob() = default; + + /** + * @brief Constructor. Creates an empty RemoteBlob object with the specified precision. + * @param tensorDesc Defines the layout and dims of the blob + */ + explicit RemoteBlob(const TensorDesc& tensorDesc) : MemoryBlob(tensorDesc) {} + + /** + * @brief Returns a map of device-specific parameters required for low-level + * operations with underlying object. + * Parameters include device/context/surface/buffer handles, access flags, + * etc. Contents of the map returned depend on remote execution context that is + * currently set on the device (working scenario). + * Abstract method. + * @return A map of name/parameter elements. + */ + virtual ParamMap getParams() const = 0; + + /** + * @brief Returns name of the device on which underlying object is allocated. + * Abstract method. + * @return A device name string in the same format as that in plugin metric. + */ + virtual std::string getDeviceName() const noexcept = 0; + + /** + * @brief Returns device context which underlying object belongs to. + * Abstract method. + * @return Pointer to plugin-specific context class object, which is derived from RemoteContext. + * Dynamic casting should be used if it is necessary to retrieve a pointer to original class. + */ + virtual std::shared_ptr getContext() const noexcept = 0; +}; +} // namespace InferenceEngine diff --git a/inference-engine/src/inference_engine/include/ie/ie_remote_context.hpp b/inference-engine/src/inference_engine/include/ie/ie_remote_context.hpp index ca1c5de14e1..86baaf22884 100644 --- a/inference-engine/src/inference_engine/include/ie/ie_remote_context.hpp +++ b/inference-engine/src/inference_engine/include/ie/ie_remote_context.hpp @@ -13,66 +13,10 @@ #include #include -#include "ie_blob.h" #include "ie_parameter.hpp" +#include "ie_remote_blob.hpp" namespace InferenceEngine { -class RemoteContext; - -/** - * @brief This class represents an Inference Engine abstraction to the memory allocated - * on the remote (non-CPU) accelerator device - */ -class RemoteBlob : public MemoryBlob { -public: - /** - * @brief A smart pointer to the RemoteBlob object - */ - using Ptr = std::shared_ptr; - - /** - * @brief A smart pointer to the const RemoteBlob object - */ - using CPtr = std::shared_ptr; - - /** - * @brief RemoteBlob virtual destructor - */ - virtual ~RemoteBlob() = default; - - /** - * @brief Constructor. Creates an empty RemoteBlob object with the specified precision. - * @param tensorDesc Defines the layout and dims of the blob - */ - explicit RemoteBlob(const TensorDesc& tensorDesc) : MemoryBlob(tensorDesc) {} - - /** - * @brief Returns a map of device-specific parameters required for low-level - * operations with underlying object. - * Parameters include device/context/surface/buffer handles, access flags, - * etc. Contents of the map returned depend on remote execution context that is - * currently set on the device (working scenario). - * Abstract method. - * @return A map of name/parameter elements. - */ - virtual ParamMap getParams() const = 0; - - /** - * @brief Returns name of the device on which underlying object is allocated. - * Abstract method. - * @return A device name string in the same format as that in plugin metric. - */ - virtual std::string getDeviceName() const noexcept = 0; - - /** - * @brief Returns device context which underlying object belongs to. - * Abstract method. - * @return Pointer to plugin-specific context class object, which is derived from RemoteContext. - * Dynamic casting should be used if it is necessary to retrieve a pointer to original class. - */ - virtual std::shared_ptr getContext() const noexcept = 0; -}; - /** * @brief This class represents an Inference Engine abstraction * for remote (non-CPU) accelerator device-specific execution context. diff --git a/inference-engine/src/inference_engine/include/openvino/runtime/common.hpp b/inference-engine/src/inference_engine/include/openvino/runtime/common.hpp index 4cb98fa034f..c2dea4c2304 100644 --- a/inference-engine/src/inference_engine/include/openvino/runtime/common.hpp +++ b/inference-engine/src/inference_engine/include/openvino/runtime/common.hpp @@ -13,6 +13,7 @@ #include #include +namespace InferenceEngine {}; namespace ov { namespace ie = InferenceEngine; namespace runtime { diff --git a/inference-engine/src/inference_engine/include/openvino/runtime/core.hpp b/inference-engine/src/inference_engine/include/openvino/runtime/core.hpp index e54babcc3f3..0ee954167e7 100644 --- a/inference-engine/src/inference_engine/include/openvino/runtime/core.hpp +++ b/inference-engine/src/inference_engine/include/openvino/runtime/core.hpp @@ -19,6 +19,7 @@ #include "cpp/ie_executable_network.hpp" #include "ie_plugin_config.hpp" #include "ie_version.hpp" +#include "remote_context.hpp" namespace InferenceEngine { class IExtension; @@ -146,7 +147,7 @@ public: * @return An executable network object */ ie::ExecutableNetwork compile_model(const std::shared_ptr& network, - const std::shared_ptr& context, + const RemoteContext& context, const ConfigMap& config = {}); /** @@ -178,7 +179,7 @@ public: * @return An executable network reference */ ie::ExecutableNetwork import_model(std::istream& networkModel, - const std::shared_ptr& context, + const RemoteContext& context, const ConfigMap& config = {}); /** @@ -291,14 +292,14 @@ public: * @param params Map of device-specific shared context parameters. * @return A shared pointer to a created remote context. */ - std::shared_ptr create_context(const std::string& deviceName, const ie::ParamMap& params); + RemoteContext create_context(const std::string& deviceName, const ie::ParamMap& params); /** * @brief Get a pointer to default(plugin-supplied) shared context object for specified accelerator device. * @param deviceName - A name of a device to get create shared context from. * @return A shared pointer to a default remote context. */ - std::shared_ptr get_default_context(const std::string& deviceName); + RemoteContext get_default_context(const std::string& deviceName); }; } // namespace runtime } // namespace ov diff --git a/inference-engine/src/inference_engine/include/openvino/runtime/remote_context.hpp b/inference-engine/src/inference_engine/include/openvino/runtime/remote_context.hpp new file mode 100644 index 00000000000..7a46b99fff7 --- /dev/null +++ b/inference-engine/src/inference_engine/include/openvino/runtime/remote_context.hpp @@ -0,0 +1,139 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +/** + * @brief This is a header file for the IE RemoteContext and RemoteBlob classes + * + * @file ie_remote_context.hpp + */ +#pragma once + +#include +#include +#include + +#include "common.hpp" +#include "details/ie_so_loader.h" +#include "ie_parameter.hpp" +#include "ie_remote_context.hpp" + +namespace InferenceEngine { +class IRemoteContext; +class RemoteBlob; +} // namespace InferenceEngine + +namespace ov { +namespace runtime { + +class Core; + +/** + * @brief This class represents an abstraction + * for remote (non-CPU) accelerator device-specific execution context. + * Such context represents a scope on the device within which executable + * networks and remote memory blobs can exist, function and exchange data. + */ +class INFERENCE_ENGINE_API_CLASS(RemoteContext) { + ie::details::SharedObjectLoader _so; + std::shared_ptr _impl; + + /** + * @brief Constructs RemoteContext from the initialized std::shared_ptr + * @param so Plugin to use. This is required to ensure that RemoteContext can work properly even if plugin + * object is destroyed. + * @param impl Initialized shared pointer + */ + RemoteContext(const ie::details::SharedObjectLoader& so, const std::shared_ptr& impl); + friend class Core; + +public: + /** + * @brief Default constructor + */ + RemoteContext() = default; + + /** + * @brief Checks if the RemoteContext object can be cast to the type T* + * + * @tparam T Type to be checked. Must represent a class derived from the RemoteContext + * @return true if this object can be dynamically cast to the type T*. Otherwise, false + */ + template ::value && !std::is_reference::value, int>::type = 0, + typename std::enable_if::value, int>::type = 0> + bool is() noexcept { + return dynamic_cast(_impl.get()) != nullptr; + } + + /** + * @brief Checks if the RemoteContext object can be cast to the type const T* + * + * @tparam T Type to be checked. Must represent a class derived from the RemoteContext + * @return true if this object can be dynamically cast to the type const T*. Otherwise, false + */ + template ::value && !std::is_reference::value, int>::type = 0, + typename std::enable_if::value, int>::type = 0> + bool is() const noexcept { + return dynamic_cast(_impl.get()) != nullptr; + } + + /** + * @brief Casts this RemoteContext object to the type T*. + * + * @tparam T Type to cast to. Must represent a class derived from the RemoteContext + * @return Raw pointer to the object of the type T or nullptr on error + */ + template ::value && !std::is_reference::value, int>::type = 0, + typename std::enable_if::value, int>::type = 0> + T* as() noexcept { + return dynamic_cast(_impl.get()); + } + + /** + * @brief Casts this RemoteContext object to the type const T*. + * + * @tparam T Type to cast to. Must represent a class derived from the RemoteContext + * @return Raw pointer to the object of the type const T or nullptr on error + */ + template ::value && !std::is_reference::value, int>::type = 0, + typename std::enable_if::value, int>::type = 0> + const T* as() const noexcept { + return dynamic_cast(_impl.get()); + } + + /** + * @brief Returns name of the device on which underlying object is allocated. + * Abstract method. + * @return A device name string in the same format as that in plugin metric. + */ + std::string get_device_name() const; + + /** + * @brief Allocates memory blob in device memory or wraps user-supplied memory handle + * using the specified tensor description and low-level device-specific parameters. + * Returns a pointer to the object which implements RemoteBlob interface. + * @param tensorDesc Defines the layout and dims of the blob + * @param params Map of the low-level blob object parameters. + * Abstract method. + * @return A pointer to plugin object that implements RemoteBlob interface. + */ + std::shared_ptr create_blob(const ie::TensorDesc& tensorDesc, const ie::ParamMap& params = {}); + + /** + * @brief Returns a map of device-specific parameters required for low-level + * operations with underlying object. + * Parameters include device/context handles, access flags, + * etc. Contents of the map returned depend on remote execution context that is + * currently set on the device (working scenario). + * Abstract method. + * @return A map of name/parameter elements. + */ + ie::ParamMap get_params() const; +}; + +} // namespace runtime +} // namespace ov diff --git a/inference-engine/src/inference_engine/src/cpp/ie_executable_network.cpp b/inference-engine/src/inference_engine/src/cpp/ie_executable_network.cpp index 1f43560ad8b..0ddd99db096 100644 --- a/inference-engine/src/inference_engine/src/cpp/ie_executable_network.cpp +++ b/inference-engine/src/inference_engine/src/cpp/ie_executable_network.cpp @@ -6,6 +6,7 @@ #include "cpp/exception2status.hpp" #include "cpp_interfaces/interface/ie_iexecutable_network_internal.hpp" +#include "cpp_interfaces/interface/ie_iremote_context.hpp" #include "ie_common.h" #include "ie_executable_network_base.hpp" diff --git a/inference-engine/src/inference_engine/src/cpp/ie_executable_network_base.hpp b/inference-engine/src/inference_engine/src/cpp/ie_executable_network_base.hpp index d008be74f76..559fe1ace6d 100644 --- a/inference-engine/src/inference_engine/src/cpp/ie_executable_network_base.hpp +++ b/inference-engine/src/inference_engine/src/cpp/ie_executable_network_base.hpp @@ -17,6 +17,7 @@ #include "cpp/exception2status.hpp" #include "cpp_interfaces/interface/ie_iexecutable_network_internal.hpp" #include "cpp_interfaces/interface/ie_ivariable_state_internal.hpp" +#include "cpp_interfaces/interface/ie_iremote_context.hpp" #include "ie_iexecutable_network.hpp" #include "ie_infer_async_request_base.hpp" diff --git a/inference-engine/src/inference_engine/src/cpp/ie_plugin.hpp b/inference-engine/src/inference_engine/src/cpp/ie_plugin.hpp index ff00823c802..a6fd3ab6a20 100644 --- a/inference-engine/src/inference_engine/src/cpp/ie_plugin.hpp +++ b/inference-engine/src/inference_engine/src/cpp/ie_plugin.hpp @@ -65,7 +65,7 @@ public: } details::SOPointer LoadNetwork(const CNNNetwork& network, - const std::shared_ptr& context, + const std::shared_ptr& context, const std::map& config) { PLUGIN_CALL_STATEMENT(return {_so, _ptr->LoadNetwork(network, config, context)}); } @@ -93,7 +93,7 @@ public: } details::SOPointer ImportNetwork(std::istream& networkModel, - const std::shared_ptr& context, + const std::shared_ptr& context, const std::map& config) { PLUGIN_CALL_STATEMENT(return {_so, _ptr->ImportNetwork(networkModel, context, config)}); } @@ -102,12 +102,12 @@ public: PLUGIN_CALL_STATEMENT(return _ptr->GetMetric(name, options)); } - std::shared_ptr CreateContext(const ParamMap& params) { - PLUGIN_CALL_STATEMENT(return _ptr->CreateContext(params)); + details::SOPointer CreateContext(const ParamMap& params) { + PLUGIN_CALL_STATEMENT(return {_so, _ptr->CreateContext(params)}); } - std::shared_ptr GetDefaultContext(const ParamMap& params) { - PLUGIN_CALL_STATEMENT(return _ptr->GetDefaultContext(params)); + details::SOPointer GetDefaultContext(const ParamMap& params) { + PLUGIN_CALL_STATEMENT(return {_so, _ptr->GetDefaultContext(params)}); } Parameter GetConfig(const std::string& name, const std::map& options) const { diff --git a/inference-engine/src/inference_engine/src/cpp_interfaces/interface/ie_iexecutable_network_internal.cpp b/inference-engine/src/inference_engine/src/cpp_interfaces/interface/ie_iexecutable_network_internal.cpp index d79fba69cc3..d084f6ab797 100644 --- a/inference-engine/src/inference_engine/src/cpp_interfaces/interface/ie_iexecutable_network_internal.cpp +++ b/inference-engine/src/inference_engine/src/cpp_interfaces/interface/ie_iexecutable_network_internal.cpp @@ -86,7 +86,7 @@ Parameter IExecutableNetworkInternal::GetMetric(const std::string&) const { IE_THROW(NotImplemented); } -std::shared_ptr IExecutableNetworkInternal::GetContext() const { +std::shared_ptr IExecutableNetworkInternal::GetContext() const { IE_THROW(NotImplemented); } diff --git a/inference-engine/src/inference_engine/src/cpp_interfaces/interface/ie_iplugin_internal.cpp b/inference-engine/src/inference_engine/src/cpp_interfaces/interface/ie_iplugin_internal.cpp index e576aed8fb5..bda5694322d 100644 --- a/inference-engine/src/inference_engine/src/cpp_interfaces/interface/ie_iplugin_internal.cpp +++ b/inference-engine/src/inference_engine/src/cpp_interfaces/interface/ie_iplugin_internal.cpp @@ -116,7 +116,7 @@ std::map> const_map_cast(const std::map IInferencePlugin::LoadNetwork( const CNNNetwork& network, const std::map& config, - const std::shared_ptr& context) { + const std::shared_ptr& context) { std::shared_ptr impl; if (nullptr == context) { impl = LoadExeNetworkImpl(network, config); @@ -152,11 +152,11 @@ Parameter IInferencePlugin::GetMetric(const std::string&, const std::map IInferencePlugin::CreateContext(const ParamMap&) { IE_THROW(NotImplemented); } -RemoteContext::Ptr IInferencePlugin::GetDefaultContext(const ParamMap&) { +std::shared_ptr IInferencePlugin::GetDefaultContext(const ParamMap&) { IE_THROW(NotImplemented); } @@ -180,7 +180,7 @@ std::shared_ptr IInferencePlugin::ImportNetwork( std::shared_ptr IInferencePlugin::ImportNetwork( std::istream& networkModel, - const std::shared_ptr& context, + const std::shared_ptr& context, const std::map& config) { IE_THROW(NotImplemented); } @@ -207,7 +207,7 @@ std::shared_ptr IInferencePlugin::LoadExeNetworkImpl std::shared_ptr IInferencePlugin::LoadExeNetworkImpl( const CNNNetwork&, - const std::shared_ptr&, + const std::shared_ptr&, const std::map&) { IE_THROW(NotImplemented); } diff --git a/inference-engine/src/inference_engine/src/cpp_interfaces/interface/ie_iremote_context.cpp b/inference-engine/src/inference_engine/src/cpp_interfaces/interface/ie_iremote_context.cpp new file mode 100644 index 00000000000..8ad2777a007 --- /dev/null +++ b/inference-engine/src/inference_engine/src/cpp_interfaces/interface/ie_iremote_context.cpp @@ -0,0 +1,19 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include + +namespace InferenceEngine { +std::string IRemoteContext::getDeviceName() const noexcept { + return {}; +} + +RemoteBlob::Ptr IRemoteContext::CreateBlob(const TensorDesc&, const ParamMap&) { + IE_THROW(NotImplemented); +} + +ParamMap IRemoteContext::getParams() const { + IE_THROW(NotImplemented); +} +} // namespace InferenceEngine diff --git a/inference-engine/src/inference_engine/src/ie_core.cpp b/inference-engine/src/inference_engine/src/ie_core.cpp index 0c63b75b2bf..9ede317d1cd 100644 --- a/inference-engine/src/inference_engine/src/ie_core.cpp +++ b/inference-engine/src/inference_engine/src/ie_core.cpp @@ -16,6 +16,7 @@ #include "cpp/ie_plugin.hpp" #include "cpp_interfaces/interface/ie_iexecutable_network_internal.hpp" #include "cpp_interfaces/interface/ie_internal_plugin_config.hpp" +#include "cpp_interfaces/interface/ie_iremote_context.hpp" #include "file_utils.h" #include "ie_cache_guard.hpp" #include "ie_cache_manager.hpp" @@ -212,7 +213,7 @@ class CoreImpl : public InferenceEngine::ICore, public std::enable_shared_from_t InferenceEngine::SoExecutableNetworkInternal LoadNetworkImpl(const InferenceEngine::CNNNetwork& network, InferenceEngine::InferencePlugin& plugin, const std::map& parsedConfig, - const InferenceEngine::RemoteContext::Ptr& context, + const InferenceEngine::IRemoteContext::Ptr& context, const std::string& blobID, const std::string& modelPath = std::string(), bool forceDisableCache = false) { @@ -244,7 +245,7 @@ class CoreImpl : public InferenceEngine::ICore, public std::enable_shared_from_t const std::string& blobId, InferenceEngine::InferencePlugin& plugin, const std::map& config, - const InferenceEngine::RemoteContext::Ptr& context, + const std::shared_ptr& context, bool& networkIsImported, const std::string& modelPath = std::string()) { InferenceEngine::SoExecutableNetworkInternal execNetwork; @@ -443,9 +444,10 @@ public: } // TODO: In future this method can be added to ICore interface - InferenceEngine::SoExecutableNetworkInternal LoadNetwork(const InferenceEngine::CNNNetwork& network, - const InferenceEngine::RemoteContext::Ptr& context, - const std::map& config) { + InferenceEngine::SoExecutableNetworkInternal LoadNetwork( + const InferenceEngine::CNNNetwork& network, + const std::shared_ptr& context, + const std::map& config) { OV_ITT_SCOPE(FIRST_INFERENCE, InferenceEngine::itt::domains::IE_LT, "Core::LoadNetwork::RemoteContext"); if (context == nullptr) { IE_THROW() << "Remote context is null"; @@ -994,7 +996,7 @@ ExecutableNetwork Core::LoadNetwork(const CNNNetwork& network, ExecutableNetwork Core::LoadNetwork(const CNNNetwork& network, RemoteContext::Ptr context, const std::map& config) { - auto exec = _impl->LoadNetwork(network, context, config); + auto exec = _impl->LoadNetwork(network, std::dynamic_pointer_cast(context), config); return {exec, exec}; } @@ -1017,7 +1019,9 @@ RemoteContext::Ptr Core::CreateContext(const std::string& deviceName, const Para } auto parsed = core_detail::parseDeviceNameIntoConfig(deviceName, params); - return _impl->GetCPPPluginByName(parsed._deviceName).CreateContext(parsed._config); + InferenceEngine::IRemoteContext::Ptr context = + _impl->GetCPPPluginByName(parsed._deviceName).CreateContext(parsed._config); + return context; } RemoteContext::Ptr Core::GetDefaultContext(const std::string& deviceName) { @@ -1032,7 +1036,9 @@ RemoteContext::Ptr Core::GetDefaultContext(const std::string& deviceName) { } auto parsed = core_detail::parseDeviceNameIntoConfig(deviceName, ParamMap()); - return _impl->GetCPPPluginByName(parsed._deviceName).GetDefaultContext(parsed._config); + InferenceEngine::IRemoteContext::Ptr context = + _impl->GetCPPPluginByName(parsed._deviceName).GetDefaultContext(parsed._config); + return context; } void Core::AddExtension(IExtensionPtr extension, const std::string& deviceName_) { @@ -1106,7 +1112,8 @@ ExecutableNetwork Core::ImportNetwork(std::istream& networkModel, std::string deviceName = device.getDeviceName(); auto parsed = core_detail::parseDeviceNameIntoConfig(deviceName, config); - auto exec = _impl->GetCPPPluginByName(deviceName).ImportNetwork(networkModel, context, parsed._config); + auto exec = _impl->GetCPPPluginByName(deviceName) + .ImportNetwork(networkModel, std::dynamic_pointer_cast(context), parsed._config); return {exec, exec}; } @@ -1250,9 +1257,10 @@ ie::ExecutableNetwork Core::compile_model(const std::string& modelPath, } ie::ExecutableNetwork Core::compile_model(const std::shared_ptr& network, - const ie::RemoteContext::Ptr& context, + const RemoteContext& context, const ConfigMap& config) { - auto exec = _impl->LoadNetwork(ie::CNNNetwork(std::const_pointer_cast(network)), context, config); + auto exec = + _impl->LoadNetwork(ie::CNNNetwork(std::const_pointer_cast(network)), context._impl, config); return {exec, exec}; } @@ -1269,7 +1277,7 @@ ie::ExecutableNetwork Core::import_model(std::istream& networkModel, } ie::ExecutableNetwork Core::import_model(std::istream& networkModel, - const ie::RemoteContext::Ptr& context, + const RemoteContext& context, const ConfigMap& config) { OV_ITT_SCOPED_TASK(ov::itt::domains::IE, "Core::import_model"); @@ -1386,7 +1394,7 @@ void Core::register_plugins(const std::string& xmlConfigFile) { _impl->RegisterPluginsInRegistry(xmlConfigFile); } -ie::RemoteContext::Ptr Core::create_context(const std::string& deviceName, const ie::ParamMap& params) { +RemoteContext Core::create_context(const std::string& deviceName, const ie::ParamMap& params) { if (deviceName.find("HETERO") == 0) { IE_THROW() << "HETERO device does not support remote context"; } @@ -1398,10 +1406,11 @@ ie::RemoteContext::Ptr Core::create_context(const std::string& deviceName, const } auto parsed = core_detail::parseDeviceNameIntoConfig(deviceName, params); - return _impl->GetCPPPluginByName(parsed._deviceName).CreateContext(parsed._config); + auto remoteContext = _impl->GetCPPPluginByName(parsed._deviceName).CreateContext(parsed._config); + return {remoteContext, remoteContext}; } -ie::RemoteContext::Ptr Core::get_default_context(const std::string& deviceName) { +RemoteContext Core::get_default_context(const std::string& deviceName) { if (deviceName.find("HETERO") == 0) { IE_THROW() << "HETERO device does not support remote context"; } @@ -1414,7 +1423,9 @@ ie::RemoteContext::Ptr Core::get_default_context(const std::string& deviceName) auto parsed = core_detail::parseDeviceNameIntoConfig(deviceName, ie::ParamMap()); - return _impl->GetCPPPluginByName(parsed._deviceName).GetDefaultContext(parsed._config); + auto remoteCtx = _impl->GetCPPPluginByName(parsed._deviceName).GetDefaultContext(parsed._config); + + return {remoteCtx, remoteCtx}; } } // namespace runtime diff --git a/inference-engine/src/inference_engine/src/remote_context.cpp b/inference-engine/src/inference_engine/src/remote_context.cpp new file mode 100644 index 00000000000..4c55388ff9c --- /dev/null +++ b/inference-engine/src/inference_engine/src/remote_context.cpp @@ -0,0 +1,43 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "openvino/runtime/remote_context.hpp" + +#include "cpp_interfaces/interface/ie_iremote_context.hpp" +#include "ie_remote_blob.hpp" + +#define REMOTE_CONTEXT_STATEMENT(...) \ + if (_impl == nullptr) \ + IE_THROW(NotAllocated) << "RemoteContext was not initialized."; \ + try { \ + __VA_ARGS__; \ + } catch (...) { \ + ::InferenceEngine::details::Rethrow(); \ + } + +namespace ov { +namespace runtime { + +RemoteContext::RemoteContext(const ie::details::SharedObjectLoader& so, const ie::IRemoteContext::Ptr& impl) + : _so(so), + _impl(impl) { + if (_impl == nullptr) + IE_THROW() << "RemoteContext was not initialized."; +} + +std::string RemoteContext::get_device_name() const { + REMOTE_CONTEXT_STATEMENT(return _impl->getDeviceName()); +} + +std::shared_ptr RemoteContext::create_blob(const ie::TensorDesc& tensorDesc, + const ie::ParamMap& params) { + REMOTE_CONTEXT_STATEMENT(return _impl->CreateBlob(tensorDesc, params)); +} + +ie::ParamMap RemoteContext::get_params() const { + REMOTE_CONTEXT_STATEMENT(return _impl->getParams()); +} + +} // namespace runtime +} // namespace ov diff --git a/inference-engine/src/multi_device/multi_device_exec_network.cpp b/inference-engine/src/multi_device/multi_device_exec_network.cpp index f42c3a22c46..08ff59237e1 100644 --- a/inference-engine/src/multi_device/multi_device_exec_network.cpp +++ b/inference-engine/src/multi_device/multi_device_exec_network.cpp @@ -154,7 +154,7 @@ MultiDeviceExecutableNetwork::~MultiDeviceExecutableNetwork() { _workerRequests.clear(); } -RemoteContext::Ptr MultiDeviceExecutableNetwork::GetContext() const { +std::shared_ptr MultiDeviceExecutableNetwork::GetContext() const { auto devices = [&] { std::lock_guard lock(_mutex); return _devicePriorities; diff --git a/inference-engine/src/multi_device/multi_device_exec_network.hpp b/inference-engine/src/multi_device/multi_device_exec_network.hpp index 3a9516d6c3b..a771ec2531c 100644 --- a/inference-engine/src/multi_device/multi_device_exec_network.hpp +++ b/inference-engine/src/multi_device/multi_device_exec_network.hpp @@ -117,7 +117,7 @@ public: InferenceEngine::IInferRequestInternal::Ptr CreateInferRequest() override; InferenceEngine::IInferRequestInternal::Ptr CreateInferRequestImpl(InferenceEngine::InputsDataMap networkInputs, InferenceEngine::OutputsDataMap networkOutputs) override; - InferenceEngine::RemoteContext::Ptr GetContext() const override; + std::shared_ptr GetContext() const override; ~MultiDeviceExecutableNetwork() override; void ScheduleToWorkerInferRequest(InferenceEngine::Task, DeviceName preferred_device = ""); diff --git a/inference-engine/src/plugin_api/cpp_interfaces/interface/ie_iexecutable_network_internal.hpp b/inference-engine/src/plugin_api/cpp_interfaces/interface/ie_iexecutable_network_internal.hpp index 2dd1086861a..cee656e2f4e 100644 --- a/inference-engine/src/plugin_api/cpp_interfaces/interface/ie_iexecutable_network_internal.hpp +++ b/inference-engine/src/plugin_api/cpp_interfaces/interface/ie_iexecutable_network_internal.hpp @@ -19,7 +19,7 @@ namespace InferenceEngine { class IInferencePlugin; class IInferRequestInternal; -class RemoteContext; +class IRemoteContext; class IVariableStateInternal; /** @@ -125,7 +125,7 @@ public: * @brief Gets the remote context. * @return A reference to a context */ - virtual std::shared_ptr GetContext() const; + virtual std::shared_ptr GetContext() const; protected: ~IExecutableNetworkInternal() = default; diff --git a/inference-engine/src/plugin_api/cpp_interfaces/interface/ie_iplugin_internal.hpp b/inference-engine/src/plugin_api/cpp_interfaces/interface/ie_iplugin_internal.hpp index 1eb16975f65..94d719b9c6b 100644 --- a/inference-engine/src/plugin_api/cpp_interfaces/interface/ie_iplugin_internal.hpp +++ b/inference-engine/src/plugin_api/cpp_interfaces/interface/ie_iplugin_internal.hpp @@ -24,7 +24,7 @@ namespace InferenceEngine { class ICore; class IExecutableNetworkInternal; -class RemoteContext; +class IRemoteContext; class IExtension; /** @@ -143,13 +143,13 @@ public: * @brief Creates an executable network from network object, on specified remote context * @param network A network object acquired from InferenceEngine::Core::ReadNetwork * @param config string-string map of config parameters relevant only for this load operation - * @param context A pointer to plugin context derived from RemoteContext class used to + * @param context A pointer to plugin context derived from IRemoteContext class used to * execute the network * @return Created Executable Network object */ virtual std::shared_ptr LoadNetwork(const CNNNetwork& network, const std::map& config, - const std::shared_ptr& context); + const std::shared_ptr& context); /** * @brief Creates an executable network from model file path @@ -193,14 +193,14 @@ public: * @param[in] params The map of parameters * @return A remote context object */ - virtual std::shared_ptr CreateContext(const ParamMap& params); + virtual std::shared_ptr CreateContext(const ParamMap& params); /** * @brief Provides a default remote context instance if supported by a plugin * @param[in] params The map of parameters * @return The default context. */ - virtual std::shared_ptr GetDefaultContext(const ParamMap& params); + virtual std::shared_ptr GetDefaultContext(const ParamMap& params); /** * @deprecated Use ImportNetwork(std::istream& networkModel, const std::map& config) @@ -232,7 +232,7 @@ public: * @return An Executable network */ virtual std::shared_ptr ImportNetwork(std::istream& networkModel, - const std::shared_ptr& context, + const std::shared_ptr& context, const std::map& config); /** @@ -279,7 +279,7 @@ protected: * resources) * @note The function is used in * InferencePluginInternal::LoadNetwork(const CNNNetwork&, const std::map&, - * RemoteContext::Ptr) which performs common steps first and calls this plugin-dependent method implementation + * IRemoteContext::Ptr) which performs common steps first and calls this plugin-dependent method implementation * after. * @param network A network object * @param context A remote context @@ -288,7 +288,7 @@ protected: */ virtual std::shared_ptr LoadExeNetworkImpl( const CNNNetwork& network, - const std::shared_ptr& context, + const std::shared_ptr& context, const std::map& config); /** diff --git a/inference-engine/src/plugin_api/cpp_interfaces/interface/ie_iremote_context.hpp b/inference-engine/src/plugin_api/cpp_interfaces/interface/ie_iremote_context.hpp new file mode 100644 index 00000000000..361ff67af97 --- /dev/null +++ b/inference-engine/src/plugin_api/cpp_interfaces/interface/ie_iremote_context.hpp @@ -0,0 +1,67 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +/** + * @brief This is a header file for the IE RemoteContext and RemoteBlob classes + * + * @file ie_remote_context.hpp + */ +#pragma once + +#include +#include + +#include "ie_parameter.hpp" +#include "ie_remote_context.hpp" + +namespace InferenceEngine { + +class RemoteBlob; + +class INFERENCE_ENGINE_API_CLASS(IRemoteContext) + : public RemoteContext, + public std::enable_shared_from_this { +public: + /** + * @brief A smart pointer to the IRemoteContext object + */ + using Ptr = std::shared_ptr; + + /** + * @brief Returns name of the device on which underlying object is allocated. + * Abstract method. + * @return A device name string in the same format as that in plugin metric. + */ + std::string getDeviceName() const noexcept override; + + /** + * @brief Allocates memory blob in device memory or wraps user-supplied memory handle + * using the specified tensor description and low-level device-specific parameters. + * Returns a pointer to the object which implements RemoteBlob interface. + * @param tensorDesc Defines the layout and dims of the blob + * @param params Map of the low-level blob object parameters. + * Abstract method. + * @return A pointer to plugin object that implements RemoteBlob interface. + */ + std::shared_ptr CreateBlob(const TensorDesc& tensorDesc, const ParamMap& params = {}) override; + + /** + * @brief Returns a map of device-specific parameters required for low-level + * operations with underlying object. + * Parameters include device/context handles, access flags, + * etc. Contents of the map returned depend on remote execution context that is + * currently set on the device (working scenario). + * Abstract method. + * @return A map of name/parameter elements. + */ + ParamMap getParams() const override; + +protected: + /** + * @brief IRemoteContext destructor + */ + ~IRemoteContext() = default; +}; + +} // namespace InferenceEngine diff --git a/inference-engine/tests/functional/inference_engine/caching_test.cpp b/inference-engine/tests/functional/inference_engine/caching_test.cpp index 4f27b8abaf9..10d952e6e0d 100644 --- a/inference-engine/tests/functional/inference_engine/caching_test.cpp +++ b/inference-engine/tests/functional/inference_engine/caching_test.cpp @@ -17,6 +17,7 @@ #include "details/ie_so_loader.h" #include "ie_metric_helpers.hpp" +#include "cpp_interfaces/interface/ie_iremote_context.hpp" #include "cpp_interfaces/interface/ie_iexecutable_network_internal.hpp" #include "cpp_interfaces/interface/ie_iplugin_internal.hpp" @@ -61,7 +62,7 @@ std::string getTestCaseName(const testing::TestParamInfo(std::get<0>(obj.param)) + "_" + std::get<1>(obj.param); } -class MockRemoteContext : public RemoteContext { +class MockRemoteContext : public IRemoteContext { std::string m_name; public: MockRemoteContext(std::string name): m_name(std::move(name)) {} @@ -96,7 +97,7 @@ public: const std::map& config)); MOCK_METHOD3(LoadExeNetworkImpl, std::shared_ptr(const CNNNetwork& network, - const RemoteContext::Ptr& context, + const IRemoteContext::Ptr& context, const std::map& config)); MOCK_CONST_METHOD0(OnLoadNetworkFromFile, void(void)); @@ -105,7 +106,7 @@ public: const std::map& config)); MOCK_METHOD3(ImportNetwork, IExecutableNetworkInternal::Ptr(std::istream& networkModel, - const RemoteContext::Ptr& context, + const IRemoteContext::Ptr& context, const std::map& config)); MOCK_CONST_METHOD2(QueryNetwork, QueryNetworkResult(const CNNNetwork& network, @@ -113,7 +114,7 @@ public: MOCK_CONST_METHOD2(GetMetric, Parameter(const std::string& name, const std::map& options)); MOCK_METHOD1(SetConfig, void(const std::map& options)); - MOCK_METHOD1(GetDefaultContext, RemoteContext::Ptr(const ParamMap& params)); + MOCK_METHOD1(GetDefaultContext, std::shared_ptr(const ParamMap& params)); }; class MockExecutableNetwork : public IExecutableNetworkInternal { @@ -325,7 +326,7 @@ private: WillByDefault(Return("mock")); ON_CALL(plugin, ImportNetwork(_, _, _)). - WillByDefault(Invoke([&](std::istream &istr, RemoteContext::Ptr, + WillByDefault(Invoke([&](std::istream &istr, const IRemoteContext::Ptr&, const std::map &) { return createMockIExecutableNet(); })); @@ -336,7 +337,7 @@ private: })); ON_CALL(plugin, LoadExeNetworkImpl(_, _, _)). - WillByDefault(Invoke([&](const CNNNetwork &, RemoteContext::Ptr, + WillByDefault(Invoke([&](const CNNNetwork &, const IRemoteContext::Ptr&, const std::map &) { return net; })); @@ -432,7 +433,7 @@ TEST_P(CachingTest, TestLoadCustomImportExport) { EXPECT_CALL(*mockPlugin, GetMetric(METRIC_KEY(IMPORT_EXPORT_SUPPORT), _)).Times(AnyNumber()); EXPECT_CALL(*mockPlugin, GetMetric(METRIC_KEY(DEVICE_ARCHITECTURE), _)).Times(AnyNumber()); ON_CALL(*mockPlugin, ImportNetwork(_, _, _)). - WillByDefault(Invoke([&](std::istream& s, RemoteContext::Ptr, + WillByDefault(Invoke([&](std::istream& s, IRemoteContext::Ptr, const std::map &) { char a[sizeof(customData)]; s.read(a, sizeof(customData)); diff --git a/inference-engine/tests/functional/inference_engine/ov_remote_context_test.cpp b/inference-engine/tests/functional/inference_engine/ov_remote_context_test.cpp new file mode 100644 index 00000000000..2e649082aeb --- /dev/null +++ b/inference-engine/tests/functional/inference_engine/ov_remote_context_test.cpp @@ -0,0 +1,25 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include + +#include + +using namespace ::testing; +using namespace std; + +TEST(RemoteContextOVTests, throwsOnUninitializedReset) { + ov::runtime::RemoteContext ctx; + ASSERT_THROW(ctx.get_device_name(), InferenceEngine::NotAllocated); +} + +TEST(RemoteContextOVTests, throwsOnUninitializedGetname) { + ov::runtime::RemoteContext ctx; + ASSERT_THROW(ctx.create_blob({}, {}), InferenceEngine::NotAllocated); +} + +TEST(RemoteContextOVTests, throwsOnUninitializedGetParams) { + ov::runtime::RemoteContext ctx; + ASSERT_THROW(ctx.get_params(), InferenceEngine::NotAllocated); +} diff --git a/inference-engine/tests/functional/plugin/shared/include/behavior/ov_core_integration.hpp b/inference-engine/tests/functional/plugin/shared/include/behavior/ov_core_integration.hpp index a9b90bd2954..30b3b5873a8 100644 --- a/inference-engine/tests/functional/plugin/shared/include/behavior/ov_core_integration.hpp +++ b/inference-engine/tests/functional/plugin/shared/include/behavior/ov_core_integration.hpp @@ -418,19 +418,6 @@ TEST(OVClassBasicTest, smoke_SetConfigHeteroNoThrow) { ASSERT_FALSE(value); } -// -// ImportNetwork -// - - -TEST_P(OVClassBasicTestP, ImportNetworkWithNullContextThrows) { - SKIP_IF_CURRENT_TEST_IS_DISABLED() - ov::runtime::Core ie = createCoreWithTemplate(); - RemoteContext::Ptr context = nullptr; - std::istringstream stream("None"); - ASSERT_THROW(ie.import_model(stream, context, {}), Exception); -} - // // LoadNetwork // diff --git a/inference-engine/tests/functional/plugin/shared/include/multi/multi_remote_blob_tests.hpp b/inference-engine/tests/functional/plugin/shared/include/multi/multi_remote_blob_tests.hpp index 1dd0c1b07f0..6e9526e47c7 100644 --- a/inference-engine/tests/functional/plugin/shared/include/multi/multi_remote_blob_tests.hpp +++ b/inference-engine/tests/functional/plugin/shared/include/multi/multi_remote_blob_tests.hpp @@ -17,7 +17,7 @@ TEST_P(MultiDevice_SupportTest, canCreateContextThenRequestThenBlobsAndInfer) { auto exec_net = ie->LoadNetwork(net, device_names); if (expected_status) { - InferenceEngine::RemoteContext::Ptr ctx; + std::shared_ptr ctx; ASSERT_NE(ctx = exec_net.GetContext(), nullptr); InferenceEngine::InferRequest req = exec_net.CreateInferRequest(); ASSERT_TRUE(req); diff --git a/inference-engine/tests/ie_test_utils/unit_test_utils/mocks/cpp_interfaces/interface/mock_icore.hpp b/inference-engine/tests/ie_test_utils/unit_test_utils/mocks/cpp_interfaces/interface/mock_icore.hpp index b061c4c3bdc..38fc58dacd5 100644 --- a/inference-engine/tests/ie_test_utils/unit_test_utils/mocks/cpp_interfaces/interface/mock_icore.hpp +++ b/inference-engine/tests/ie_test_utils/unit_test_utils/mocks/cpp_interfaces/interface/mock_icore.hpp @@ -17,14 +17,14 @@ public: MOCK_METHOD3(LoadNetwork, InferenceEngine::SoExecutableNetworkInternal( const InferenceEngine::CNNNetwork&, const std::string&, const std::map&)); MOCK_METHOD3(LoadNetwork, InferenceEngine::SoExecutableNetworkInternal( - const InferenceEngine::CNNNetwork&, const InferenceEngine::RemoteContext::Ptr &, const std::map&)); + const InferenceEngine::CNNNetwork&, const std::shared_ptr &, const std::map&)); MOCK_METHOD3(LoadNetwork, InferenceEngine::SoExecutableNetworkInternal( const std::string &, const std::string &, const std::map&)); MOCK_METHOD3(ImportNetwork, InferenceEngine::SoExecutableNetworkInternal( std::istream&, const std::string&, const std::map&)); MOCK_METHOD3(ImportNetwork, InferenceEngine::SoExecutableNetworkInternal( - std::istream&, const InferenceEngine::RemoteContext::Ptr&, const std::map&)); + std::istream&, const std::shared_ptr&, const std::map&)); MOCK_CONST_METHOD3(QueryNetwork, InferenceEngine::QueryNetworkResult( const InferenceEngine::CNNNetwork&, const std::string&, const std::map&)); diff --git a/inference-engine/tests/ie_test_utils/unit_test_utils/mocks/cpp_interfaces/interface/mock_iexecutable_network_internal.hpp b/inference-engine/tests/ie_test_utils/unit_test_utils/mocks/cpp_interfaces/interface/mock_iexecutable_network_internal.hpp index 434d2c2e4eb..4ceb8f728fe 100644 --- a/inference-engine/tests/ie_test_utils/unit_test_utils/mocks/cpp_interfaces/interface/mock_iexecutable_network_internal.hpp +++ b/inference-engine/tests/ie_test_utils/unit_test_utils/mocks/cpp_interfaces/interface/mock_iexecutable_network_internal.hpp @@ -30,7 +30,7 @@ public: MOCK_METHOD1(SetConfig, void(const std::map &config)); MOCK_CONST_METHOD1(GetConfig, Parameter(const std::string &name)); MOCK_CONST_METHOD1(GetMetric, Parameter(const std::string &name)); - MOCK_CONST_METHOD0(GetContext, RemoteContext::Ptr(void)); + MOCK_CONST_METHOD0(GetContext, std::shared_ptr(void)); void WrapOstreamExport(std::ostream& networkModel) { IExecutableNetworkInternal::Export(networkModel); } diff --git a/inference-engine/tests/ie_test_utils/unit_test_utils/mocks/cpp_interfaces/interface/mock_iinference_plugin.hpp b/inference-engine/tests/ie_test_utils/unit_test_utils/mocks/cpp_interfaces/interface/mock_iinference_plugin.hpp index 36665c81c54..0c45de9b995 100644 --- a/inference-engine/tests/ie_test_utils/unit_test_utils/mocks/cpp_interfaces/interface/mock_iinference_plugin.hpp +++ b/inference-engine/tests/ie_test_utils/unit_test_utils/mocks/cpp_interfaces/interface/mock_iinference_plugin.hpp @@ -30,15 +30,15 @@ public: MOCK_CONST_METHOD2(GetMetric, InferenceEngine::Parameter( const std::string&, const std::map&)); MOCK_METHOD1(CreateContext, - InferenceEngine::RemoteContext::Ptr(const InferenceEngine::ParamMap&)); - MOCK_METHOD1(GetDefaultContext, InferenceEngine::RemoteContext::Ptr(const InferenceEngine::ParamMap&)); + std::shared_ptr(const InferenceEngine::ParamMap&)); + MOCK_METHOD1(GetDefaultContext, std::shared_ptr(const InferenceEngine::ParamMap&)); MOCK_METHOD3(LoadNetwork, std::shared_ptr( const InferenceEngine::CNNNetwork&, const std::map&, - InferenceEngine::RemoteContext::Ptr)); + std::shared_ptr)); MOCK_METHOD2(ImportNetwork, std::shared_ptr( std::istream&, const std::map&)); MOCK_METHOD3(ImportNetwork, std::shared_ptr( - std::istream&, const InferenceEngine::RemoteContext::Ptr&, + std::istream&, const std::shared_ptr&, const std::map&)); MOCK_CONST_METHOD2(QueryNetwork, InferenceEngine::QueryNetworkResult(const InferenceEngine::CNNNetwork&, diff --git a/inference-engine/tests/ie_test_utils/unit_test_utils/mocks/mock_engine/mock_plugin.cpp b/inference-engine/tests/ie_test_utils/unit_test_utils/mocks/mock_engine/mock_plugin.cpp index e6cefc75ea2..2cfa6330ab5 100644 --- a/inference-engine/tests/ie_test_utils/unit_test_utils/mocks/mock_engine/mock_plugin.cpp +++ b/inference-engine/tests/ie_test_utils/unit_test_utils/mocks/mock_engine/mock_plugin.cpp @@ -45,7 +45,7 @@ MockPlugin::LoadNetwork(const CNNNetwork &network, std::shared_ptr MockPlugin::LoadNetwork(const CNNNetwork& network, const std::map& config, - const std::shared_ptr& context) { + const std::shared_ptr& context) { if (_target) { return _target->LoadNetwork(network, config, context); } else { @@ -81,7 +81,7 @@ MockPlugin::ImportNetwork(std::istream& networkModel, std::shared_ptr MockPlugin::ImportNetwork(std::istream& networkModel, - const std::shared_ptr& context, + const std::shared_ptr& context, const std::map& config) { if (_target) { return _target->ImportNetwork(networkModel, context, config); @@ -90,7 +90,7 @@ MockPlugin::ImportNetwork(std::istream& networkModel, } } -std::shared_ptr MockPlugin::GetDefaultContext(const InferenceEngine::ParamMap& params) { +std::shared_ptr MockPlugin::GetDefaultContext(const InferenceEngine::ParamMap& params) { if (_target) { return _target->GetDefaultContext(params); } else { diff --git a/inference-engine/tests/ie_test_utils/unit_test_utils/mocks/mock_engine/mock_plugin.hpp b/inference-engine/tests/ie_test_utils/unit_test_utils/mocks/mock_engine/mock_plugin.hpp index 05becce1fcd..8514bf28c80 100644 --- a/inference-engine/tests/ie_test_utils/unit_test_utils/mocks/mock_engine/mock_plugin.hpp +++ b/inference-engine/tests/ie_test_utils/unit_test_utils/mocks/mock_engine/mock_plugin.hpp @@ -24,7 +24,7 @@ public: std::shared_ptr LoadNetwork(const InferenceEngine::CNNNetwork& network, const std::map& config, - const std::shared_ptr& context) override; + const std::shared_ptr& context) override; std::shared_ptr LoadExeNetworkImpl(const InferenceEngine::CNNNetwork& network, @@ -40,13 +40,13 @@ public: std::shared_ptr ImportNetwork(std::istream& networkModel, - const std::shared_ptr& context, + const std::shared_ptr& context, const std::map& config) override; InferenceEngine::Parameter GetMetric(const std::string& name, const std::map& options) const override; - std::shared_ptr GetDefaultContext(const InferenceEngine::ParamMap& params) override; + std::shared_ptr GetDefaultContext(const InferenceEngine::ParamMap& params) override; InferenceEngine::QueryNetworkResult QueryNetwork(const InferenceEngine::CNNNetwork& network, const std::map& config) const override; From d27161703d04d0f344cb25f153fc78ea892fa56a Mon Sep 17 00:00:00 2001 From: Elizaveta Lobanova Date: Wed, 25 Aug 2021 18:50:42 +0300 Subject: [PATCH 43/76] [GNA] Fixed calculation of input scale factor for POT-quantized model in the case if the first layer after input is activation (#7223) --- inference-engine/src/gna_plugin/gna_plugin.cpp | 4 +++- .../plugin/gna/pass_tests/fq_activation.cpp | 18 ++++++++++-------- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/inference-engine/src/gna_plugin/gna_plugin.cpp b/inference-engine/src/gna_plugin/gna_plugin.cpp index 651bf075b6d..48815f964da 100644 --- a/inference-engine/src/gna_plugin/gna_plugin.cpp +++ b/inference-engine/src/gna_plugin/gna_plugin.cpp @@ -488,7 +488,9 @@ void GNAPlugin::UpdateInputScaleFromNetwork(InferenceEngine::CNNNetwork & networ auto fp32eq = [](float p1, float p2) -> bool { return (std::abs(p1 - p2) <= 0.00001f * std::min(std::abs(p1), std::abs(p2))); }; - float scaleInput = (fqLayer.getLevels() - 1) / (inputRange.second[0] - inputRange.first[0]); + // GNA input is always quantized to int16, so number of levels can't be greater than max uint16 + size_t levels = std::min(fqLayer.getLevels(), static_cast(std::numeric_limits::max())); + float scaleInput = (levels - 1) / (inputRange.second[0] - inputRange.first[0]); auto minAbsVal = std::min(std::abs(inputRange.second[0]), std::abs(inputRange.first[0])); auto maxAbsVal = std::max(std::abs(inputRange.second[0]), std::abs(inputRange.first[0])); if (fp32eq(minAbsVal, 0.0f) && !fp32eq(maxAbsVal, 0.0f)) { diff --git a/inference-engine/tests/functional/plugin/gna/pass_tests/fq_activation.cpp b/inference-engine/tests/functional/plugin/gna/pass_tests/fq_activation.cpp index 9299fceb643..7e352595dcc 100644 --- a/inference-engine/tests/functional/plugin/gna/pass_tests/fq_activation.cpp +++ b/inference-engine/tests/functional/plugin/gna/pass_tests/fq_activation.cpp @@ -25,7 +25,7 @@ typedef std::tuple< std::map, // Configuration std::vector, // Input Shape std::pair, // Input Min and Max - size_t // Levels + std::pair // Levels for input and output FQs > fqActivationParams; namespace LayerTestsDefinitions { @@ -43,7 +43,7 @@ public: std::map configuration; std::vector inputShape; std::pair inputMinMax; - size_t levels = 0; + std::pair levels; std::tie(netPrecision, targetDevice, configuration, inputShape, inputMinMax, levels) = obj.param; std::ostringstream result; @@ -54,7 +54,7 @@ public: } result << "_inputShape=" << CommonTestUtils::vec2str(inputShape); result << "_inputMinMax=(" << inputMinMax.first << ".." << inputMinMax.second << ")"; - result << "_levels=" << levels; + result << "_levels=" << levels.first << "," << levels.second; return result.str(); } @@ -69,20 +69,21 @@ protected: std::vector inputShape; std::pair inputMinMax; - size_t levels = 0; + std::pair levels; std::tie(netPrecision, targetDevice, configuration, inputShape, inputMinMax, levels) = this->GetParam(); auto ngPrc = FuncTestUtils::PrecisionUtils::convertIE2nGraphPrc(netPrecision); + std::tie(inputDataMin, inputDataMax) = inputMinMax; auto inputLowNode = ngraph::builder::makeConstant(ngPrc, { 1 }, { inputMinMax.first }); auto inputHighNode = ngraph::builder::makeConstant(ngPrc, { 1 }, { inputMinMax.second }); auto inputVector = ngraph::builder::makeParams(ngPrc, { inputShape }); auto inputFQNode = std::make_shared(inputVector[0], - inputLowNode, inputHighNode, inputLowNode, inputHighNode, levels); + inputLowNode, inputHighNode, inputLowNode, inputHighNode, levels.first); auto relu = ngraph::builder::makeActivation(inputFQNode, ngraph::element::f32, ngraph::helpers::ActivationTypes::Relu); auto reluFQNode = std::make_shared(relu, - inputLowNode, inputHighNode, inputLowNode, inputHighNode, levels); + inputLowNode, inputHighNode, inputLowNode, inputHighNode, levels.second); ngraph::ResultVector results{ std::make_shared(reluFQNode) }; function = std::make_shared(results, inputVector, "FQActivation"); @@ -118,8 +119,9 @@ const std::vector> inputMinMax = { {-100, 100}, }; -const std::vector levels = { - 65535, +const std::vector> levels = { + {std::numeric_limits::max(), std::numeric_limits::max()}, + {std::numeric_limits::max(), std::numeric_limits::max()} }; INSTANTIATE_TEST_SUITE_P(smoke_fq_activation, FQActivation, From 4a468acd2c0a27d62debab8899935b51990e65d9 Mon Sep 17 00:00:00 2001 From: Nikita Semaev Date: Wed, 25 Aug 2021 21:48:24 +0300 Subject: [PATCH 44/76] [IE TESTS] Max ulong (#6389) * Hiding the problem, Validate() changes 'function' * Adding code to track changes * Report result * Added operation logging * Cancelled the change of the function variable value that causes the bug in the report * Removed logging of each operation to a file * Debugging code removed * Moved debugging under the macros * Reports from commit were deleted * Delete part_report.txt * Delete report.xml * Removed debug code * Correcting the use of unnecessary actions to accomplish these tasks * The name of the function to compile the debug report has changed to saveDebugReport --- .../shared_test_classes/src/single_layer/memory.cpp | 12 ++++++------ .../layer_test_utils/summary.hpp | 9 ++++++++- .../src/layer_test_utils/summary.cpp | 11 +++++++++++ 3 files changed, 25 insertions(+), 7 deletions(-) diff --git a/inference-engine/tests/functional/shared_test_classes/src/single_layer/memory.cpp b/inference-engine/tests/functional/shared_test_classes/src/single_layer/memory.cpp index c059768c4a2..e9902cf80c0 100644 --- a/inference-engine/tests/functional/shared_test_classes/src/single_layer/memory.cpp +++ b/inference-engine/tests/functional/shared_test_classes/src/single_layer/memory.cpp @@ -67,7 +67,6 @@ namespace LayerTestsDefinitions { auto &s = LayerTestsUtils::Summary::getInstance(); s.setDeviceName(targetDevice); - if (FuncTestUtils::SkipTestsConfig::currentTestIsDisabled()) { s.updateOPsStats(function, PassRate::Statuses::SKIPPED); GTEST_SKIP() << "Disabled test due to configuration" << std::endl; @@ -75,6 +74,7 @@ namespace LayerTestsDefinitions { s.updateOPsStats(function, PassRate::Statuses::CRASHED); } + auto func_copy = ngraph::clone_function(*function); try { if (transformation != ngraph::helpers::MemoryTransformation::LOW_LATENCY_V2_REGULAR_API) { LoadNetwork(); @@ -88,16 +88,16 @@ namespace LayerTestsDefinitions { Infer(); Validate(); } - s.updateOPsStats(function, PassRate::Statuses::PASSED); + s.updateOPsStats(func_copy, PassRate::Statuses::PASSED); } catch (const std::runtime_error &re) { - s.updateOPsStats(function, PassRate::Statuses::FAILED); + s.updateOPsStats(func_copy, PassRate::Statuses::FAILED); GTEST_FATAL_FAILURE_(re.what()); } catch (const std::exception &ex) { - s.updateOPsStats(function, PassRate::Statuses::FAILED); + s.updateOPsStats(func_copy, PassRate::Statuses::FAILED); GTEST_FATAL_FAILURE_(ex.what()); } catch (...) { - s.updateOPsStats(function, PassRate::Statuses::FAILED); + s.updateOPsStats(func_copy, PassRate::Statuses::FAILED); GTEST_FATAL_FAILURE_("Unknown failure occurred."); } } @@ -197,7 +197,7 @@ namespace LayerTestsDefinitions { manager.run_passes(function); } else if (transformation == ngraph::helpers::MemoryTransformation::LOW_LATENCY_V2_REGULAR_API) { cnnNetwork = InferenceEngine::CNNNetwork{function}; - InferenceEngine::lowLatency2(cnnNetwork, iteration_count); + InferenceEngine::lowLatency2(cnnNetwork, iteration_count); } } diff --git a/inference-engine/tests/ie_test_utils/functional_test_utils/include/functional_test_utils/layer_test_utils/summary.hpp b/inference-engine/tests/ie_test_utils/functional_test_utils/include/functional_test_utils/layer_test_utils/summary.hpp index 4a608be7341..ba1002a2f5a 100644 --- a/inference-engine/tests/ie_test_utils/functional_test_utils/include/functional_test_utils/layer_test_utils/summary.hpp +++ b/inference-engine/tests/ie_test_utils/functional_test_utils/include/functional_test_utils/layer_test_utils/summary.hpp @@ -92,6 +92,13 @@ public: static Summary &getInstance(); + // #define IE_TEST_DEBUG + + #ifdef IE_TEST_DEBUG + void saveDebugReport(const char* className, const char* opName, unsigned long passed, unsigned long failed, + unsigned long skipped, unsigned long crashed); + #endif //IE_TEST_DEBUG + void saveReport(); static void setExtendReport(bool val) { extendReport = val; } @@ -109,4 +116,4 @@ public: static void setOutputFolder(const std::string &val) { outputFolder = val.c_str(); } }; -} // namespace LayerTestsUtils \ No newline at end of file +} // namespace LayerTestsUtils diff --git a/inference-engine/tests/ie_test_utils/functional_test_utils/src/layer_test_utils/summary.cpp b/inference-engine/tests/ie_test_utils/functional_test_utils/src/layer_test_utils/summary.cpp index 0ffdc8d7950..91d6ee58c43 100644 --- a/inference-engine/tests/ie_test_utils/functional_test_utils/src/layer_test_utils/summary.cpp +++ b/inference-engine/tests/ie_test_utils/functional_test_utils/src/layer_test_utils/summary.cpp @@ -150,6 +150,17 @@ void Summary::updateOPsStats(const std::shared_ptr &function, } } +#ifdef IE_TEST_DEBUG +void Summary::saveDebugReport(const char* className, const char* opName, unsigned long passed, unsigned long failed, + unsigned long skipped, unsigned long crashed) { + std::string outputFilePath = "./part_report.txt"; + std::ofstream file; + file.open(outputFilePath, std::ios_base::app); + file << className << ' ' << opName << ' ' << passed << ' ' << failed << ' ' << skipped << ' ' << crashed << '\n'; + file.close(); +} +#endif //IE_TEST_DEBUG + void Summary::saveReport() { if (isReported) { return; From 0bc991d895d3b03ecfbb3795d966bda83cc15c81 Mon Sep 17 00:00:00 2001 From: Ilya Churaev Date: Thu, 26 Aug 2021 06:45:07 +0300 Subject: [PATCH 45/76] Moved AxisSet, AxisVector, Coordinate, CoordinateDiff to ov (#7237) --- ngraph/core/include/ngraph/axis_set.hpp | 49 +-------------- ngraph/core/include/ngraph/axis_vector.hpp | 43 +------------ ngraph/core/include/ngraph/coordinate.hpp | 42 +------------ .../core/include/ngraph/coordinate_diff.hpp | 45 +------------- .../core/include/openvino/core/axis_set.hpp | 60 +++++++++++++++++++ .../include/openvino/core/axis_vector.hpp | 52 ++++++++++++++++ .../core/include/openvino/core/coordinate.hpp | 51 ++++++++++++++++ .../include/openvino/core/coordinate_diff.hpp | 56 +++++++++++++++++ .../include/ngraph/coordinate_index.hpp | 9 ++- ngraph/core/src/axis_set.cpp | 26 ++++---- ngraph/core/src/axis_vector.cpp | 20 +++---- ngraph/core/src/coordinate.cpp | 22 +++---- ngraph/core/src/coordinate_diff.cpp | 20 +++---- 13 files changed, 275 insertions(+), 220 deletions(-) create mode 100644 ngraph/core/include/openvino/core/axis_set.hpp create mode 100644 ngraph/core/include/openvino/core/axis_vector.hpp create mode 100644 ngraph/core/include/openvino/core/coordinate.hpp create mode 100644 ngraph/core/include/openvino/core/coordinate_diff.hpp diff --git a/ngraph/core/include/ngraph/axis_set.hpp b/ngraph/core/include/ngraph/axis_set.hpp index 9a1c72b8abe..ae513c80818 100644 --- a/ngraph/core/include/ngraph/axis_set.hpp +++ b/ngraph/core/include/ngraph/axis_set.hpp @@ -11,53 +11,8 @@ #include "ngraph/attribute_adapter.hpp" #include "ngraph/ngraph_visibility.hpp" +#include "openvino/core/axis_set.hpp" namespace ngraph { -/// \brief A set of axes. -class AxisSet : public std::set { -public: - NGRAPH_API AxisSet(); - - NGRAPH_API AxisSet(const std::initializer_list& axes); - - NGRAPH_API AxisSet(const std::set& axes); - - NGRAPH_API AxisSet(const std::vector& axes); - - NGRAPH_API AxisSet(const AxisSet& axes); - - NGRAPH_API AxisSet& operator=(const AxisSet& v); - - NGRAPH_API AxisSet& operator=(AxisSet&& v) noexcept; - - NGRAPH_API std::vector to_vector() const; -}; - -NGRAPH_API -std::ostream& operator<<(std::ostream& s, const AxisSet& axis_set); +using ov::AxisSet; } // namespace ngraph - -namespace ov { - -template <> -class NGRAPH_API AttributeAdapter : public ValueAccessor> { -public: - AttributeAdapter(ngraph::AxisSet& value) : m_ref(value) {} - - const std::vector& get() override; - void set(const std::vector& value) override; - static constexpr DiscreteTypeInfo type_info{"AttributeAdapter", 0}; - const DiscreteTypeInfo& get_type_info() const override { - return type_info; - } - operator ngraph::AxisSet&() { - return m_ref; - } - -protected: - ngraph::AxisSet& m_ref; - std::vector m_buffer; - bool m_buffer_valid{false}; -}; - -} // namespace ov diff --git a/ngraph/core/include/ngraph/axis_vector.hpp b/ngraph/core/include/ngraph/axis_vector.hpp index f7215d0c88f..f8c2cf05554 100644 --- a/ngraph/core/include/ngraph/axis_vector.hpp +++ b/ngraph/core/include/ngraph/axis_vector.hpp @@ -10,48 +10,9 @@ #include "ngraph/attribute_adapter.hpp" #include "ngraph/ngraph_visibility.hpp" +#include "openvino/core/axis_vector.hpp" namespace ngraph { /// \brief A vector of axes. -class AxisVector : public std::vector { -public: - NGRAPH_API AxisVector(const std::initializer_list& axes); - - NGRAPH_API AxisVector(const std::vector& axes); - - NGRAPH_API AxisVector(const AxisVector& axes); - - NGRAPH_API explicit AxisVector(size_t n); - - template - AxisVector(InputIterator first, InputIterator last) : std::vector(first, last) {} - - NGRAPH_API AxisVector(); - - NGRAPH_API ~AxisVector(); - - NGRAPH_API AxisVector& operator=(const AxisVector& v); - - NGRAPH_API AxisVector& operator=(AxisVector&& v) noexcept; -}; - -NGRAPH_API -std::ostream& operator<<(std::ostream& s, const AxisVector& axis_vector); +using ov::AxisVector; } // namespace ngraph - -namespace ov { - -template <> -class NGRAPH_API AttributeAdapter - : public IndirectVectorValueAccessor> { -public: - AttributeAdapter(ngraph::AxisVector& value) - : IndirectVectorValueAccessor>(value) {} - - static constexpr DiscreteTypeInfo type_info{"AttributeAdapter", 0}; - const DiscreteTypeInfo& get_type_info() const override { - return type_info; - } -}; - -} // namespace ov diff --git a/ngraph/core/include/ngraph/coordinate.hpp b/ngraph/core/include/ngraph/coordinate.hpp index 56535fdeb18..59c664dc692 100644 --- a/ngraph/core/include/ngraph/coordinate.hpp +++ b/ngraph/core/include/ngraph/coordinate.hpp @@ -10,47 +10,9 @@ #include "ngraph/attribute_adapter.hpp" #include "ngraph/axis_set.hpp" #include "ngraph/shape.hpp" +#include "openvino/core/coordinate.hpp" namespace ngraph { /// \brief Coordinates for a tensor element -class Coordinate : public std::vector { -public: - NGRAPH_API Coordinate(); - NGRAPH_API Coordinate(const std::initializer_list& axes); - - NGRAPH_API Coordinate(const Shape& shape); - - NGRAPH_API Coordinate(const std::vector& axes); - - NGRAPH_API Coordinate(const Coordinate& axes); - - NGRAPH_API Coordinate(size_t n, size_t initial_value = 0); - - NGRAPH_API ~Coordinate(); - - template - Coordinate(InputIterator first, InputIterator last) : std::vector(first, last) {} - - NGRAPH_API Coordinate& operator=(const Coordinate& v); - - NGRAPH_API Coordinate& operator=(Coordinate&& v) noexcept; -}; - -NGRAPH_API -std::ostream& operator<<(std::ostream& s, const Coordinate& coordinate); +using ov::Coordinate; } // namespace ngraph - -namespace ov { -template <> -class NGRAPH_API AttributeAdapter - : public IndirectVectorValueAccessor> { -public: - AttributeAdapter(ngraph::Coordinate& value) - : IndirectVectorValueAccessor>(value) {} - - static constexpr DiscreteTypeInfo type_info{"AttributeAdapter", 0}; - const DiscreteTypeInfo& get_type_info() const override { - return type_info; - } -}; -} // namespace ov diff --git a/ngraph/core/include/ngraph/coordinate_diff.hpp b/ngraph/core/include/ngraph/coordinate_diff.hpp index 77fb5c365ff..21077fe2aa9 100644 --- a/ngraph/core/include/ngraph/coordinate_diff.hpp +++ b/ngraph/core/include/ngraph/coordinate_diff.hpp @@ -10,50 +10,9 @@ #include "ngraph/attribute_adapter.hpp" #include "ngraph/ngraph_visibility.hpp" +#include "openvino/core/coordinate_diff.hpp" namespace ngraph { /// \brief A difference (signed) of tensor element coordinates. -class CoordinateDiff : public std::vector { -public: - NGRAPH_API CoordinateDiff(const std::initializer_list& diffs); - - NGRAPH_API CoordinateDiff(const std::vector& diffs); - - NGRAPH_API CoordinateDiff(const CoordinateDiff& diffs); - - NGRAPH_API explicit CoordinateDiff(size_t n, std::ptrdiff_t initial_value = 0); - - template - CoordinateDiff(InputIterator first, InputIterator last) : std::vector(first, last) {} - - NGRAPH_API ~CoordinateDiff(); - - NGRAPH_API CoordinateDiff(); - - NGRAPH_API CoordinateDiff& operator=(const CoordinateDiff& v); - - NGRAPH_API CoordinateDiff& operator=(CoordinateDiff&& v) noexcept; -}; - -NGRAPH_API -std::ostream& operator<<(std::ostream& s, const CoordinateDiff& coordinate_diff); +using ov::CoordinateDiff; } // namespace ngraph - -namespace ov { - -template <> -class NGRAPH_API AttributeAdapter - : public IndirectVectorValueAccessor> - -{ -public: - AttributeAdapter(ngraph::CoordinateDiff& value) - : IndirectVectorValueAccessor>(value) {} - - static constexpr DiscreteTypeInfo type_info{"AttributeAdapter", 0}; - const DiscreteTypeInfo& get_type_info() const override { - return type_info; - } -}; - -} // namespace ov diff --git a/ngraph/core/include/openvino/core/axis_set.hpp b/ngraph/core/include/openvino/core/axis_set.hpp new file mode 100644 index 00000000000..ea4b93be186 --- /dev/null +++ b/ngraph/core/include/openvino/core/axis_set.hpp @@ -0,0 +1,60 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +#include +#include +#include +#include + +#include "openvino/core/attribute_adapter.hpp" +#include "openvino/core/core_visibility.hpp" + +namespace ov { +/// \brief A set of axes. +class AxisSet : public std::set { +public: + OPENVINO_API AxisSet(); + + OPENVINO_API AxisSet(const std::initializer_list& axes); + + OPENVINO_API AxisSet(const std::set& axes); + + OPENVINO_API AxisSet(const std::vector& axes); + + OPENVINO_API AxisSet(const AxisSet& axes); + + OPENVINO_API AxisSet& operator=(const AxisSet& v); + + OPENVINO_API AxisSet& operator=(AxisSet&& v) noexcept; + + OPENVINO_API std::vector to_vector() const; +}; + +OPENVINO_API +std::ostream& operator<<(std::ostream& s, const AxisSet& axis_set); + +template <> +class OPENVINO_API AttributeAdapter : public ValueAccessor> { +public: + AttributeAdapter(ov::AxisSet& value) : m_ref(value) {} + + const std::vector& get() override; + void set(const std::vector& value) override; + static constexpr DiscreteTypeInfo type_info{"AttributeAdapter", 0}; + const DiscreteTypeInfo& get_type_info() const override { + return type_info; + } + operator ov::AxisSet&() { + return m_ref; + } + +protected: + ov::AxisSet& m_ref; + std::vector m_buffer; + bool m_buffer_valid{false}; +}; + +} // namespace ov diff --git a/ngraph/core/include/openvino/core/axis_vector.hpp b/ngraph/core/include/openvino/core/axis_vector.hpp new file mode 100644 index 00000000000..c545f727fd5 --- /dev/null +++ b/ngraph/core/include/openvino/core/axis_vector.hpp @@ -0,0 +1,52 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +#include +#include +#include + +#include "openvino/core/attribute_adapter.hpp" +#include "openvino/core/core_visibility.hpp" + +namespace ov { +/// \brief A vector of axes. +class AxisVector : public std::vector { +public: + OPENVINO_API AxisVector(const std::initializer_list& axes); + + OPENVINO_API AxisVector(const std::vector& axes); + + OPENVINO_API AxisVector(const AxisVector& axes); + + OPENVINO_API explicit AxisVector(size_t n); + + template + AxisVector(InputIterator first, InputIterator last) : std::vector(first, last) {} + + OPENVINO_API AxisVector(); + + OPENVINO_API ~AxisVector(); + + OPENVINO_API AxisVector& operator=(const AxisVector& v); + + OPENVINO_API AxisVector& operator=(AxisVector&& v) noexcept; +}; + +OPENVINO_API +std::ostream& operator<<(std::ostream& s, const AxisVector& axis_vector); + +template <> +class OPENVINO_API AttributeAdapter : public IndirectVectorValueAccessor> { +public: + AttributeAdapter(AxisVector& value) : IndirectVectorValueAccessor>(value) {} + + static constexpr DiscreteTypeInfo type_info{"AttributeAdapter", 0}; + const DiscreteTypeInfo& get_type_info() const override { + return type_info; + } +}; + +} // namespace ov diff --git a/ngraph/core/include/openvino/core/coordinate.hpp b/ngraph/core/include/openvino/core/coordinate.hpp new file mode 100644 index 00000000000..28dd5196030 --- /dev/null +++ b/ngraph/core/include/openvino/core/coordinate.hpp @@ -0,0 +1,51 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +#include +#include + +#include "ngraph/shape.hpp" +#include "openvino/core/core_visibility.hpp" + +namespace ov { +/// \brief Coordinates for a tensor element +class Coordinate : public std::vector { +public: + OPENVINO_API Coordinate(); + OPENVINO_API Coordinate(const std::initializer_list& axes); + + OPENVINO_API Coordinate(const ngraph::Shape& shape); + + OPENVINO_API Coordinate(const std::vector& axes); + + OPENVINO_API Coordinate(const Coordinate& axes); + + OPENVINO_API Coordinate(size_t n, size_t initial_value = 0); + + OPENVINO_API ~Coordinate(); + + template + Coordinate(InputIterator first, InputIterator last) : std::vector(first, last) {} + + OPENVINO_API Coordinate& operator=(const Coordinate& v); + + OPENVINO_API Coordinate& operator=(Coordinate&& v) noexcept; +}; + +OPENVINO_API +std::ostream& operator<<(std::ostream& s, const Coordinate& coordinate); + +template <> +class OPENVINO_API AttributeAdapter : public IndirectVectorValueAccessor> { +public: + AttributeAdapter(Coordinate& value) : IndirectVectorValueAccessor>(value) {} + + static constexpr DiscreteTypeInfo type_info{"AttributeAdapter", 0}; + const DiscreteTypeInfo& get_type_info() const override { + return type_info; + } +}; +} // namespace ov diff --git a/ngraph/core/include/openvino/core/coordinate_diff.hpp b/ngraph/core/include/openvino/core/coordinate_diff.hpp new file mode 100644 index 00000000000..3f633e67da5 --- /dev/null +++ b/ngraph/core/include/openvino/core/coordinate_diff.hpp @@ -0,0 +1,56 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +#include +#include +#include + +#include "openvino/core/attribute_adapter.hpp" +#include "openvino/core/core_visibility.hpp" + +namespace ov { +/// \brief A difference (signed) of tensor element coordinates. +class CoordinateDiff : public std::vector { +public: + OPENVINO_API CoordinateDiff(const std::initializer_list& diffs); + + OPENVINO_API CoordinateDiff(const std::vector& diffs); + + OPENVINO_API CoordinateDiff(const CoordinateDiff& diffs); + + OPENVINO_API explicit CoordinateDiff(size_t n, std::ptrdiff_t initial_value = 0); + + template + CoordinateDiff(InputIterator first, InputIterator last) : std::vector(first, last) {} + + OPENVINO_API ~CoordinateDiff(); + + OPENVINO_API CoordinateDiff(); + + OPENVINO_API CoordinateDiff& operator=(const CoordinateDiff& v); + + OPENVINO_API CoordinateDiff& operator=(CoordinateDiff&& v) noexcept; +}; + +OPENVINO_API +std::ostream& operator<<(std::ostream& s, const CoordinateDiff& coordinate_diff); + +template <> +class OPENVINO_API AttributeAdapter + : public IndirectVectorValueAccessor> + +{ +public: + AttributeAdapter(CoordinateDiff& value) + : IndirectVectorValueAccessor>(value) {} + + static constexpr DiscreteTypeInfo type_info{"AttributeAdapter", 0}; + const DiscreteTypeInfo& get_type_info() const override { + return type_info; + } +}; + +} // namespace ov diff --git a/ngraph/core/reference/include/ngraph/coordinate_index.hpp b/ngraph/core/reference/include/ngraph/coordinate_index.hpp index 9884c7c70eb..1c0a7ff893c 100644 --- a/ngraph/core/reference/include/ngraph/coordinate_index.hpp +++ b/ngraph/core/reference/include/ngraph/coordinate_index.hpp @@ -5,12 +5,11 @@ #pragma once #include +#include +#include namespace ngraph { -class Coordinate; -class Shape; -} // namespace ngraph -namespace ngraph { std::size_t coordinate_index(const Coordinate& c, const Shape& s); -} + +} // namespace ngraph diff --git a/ngraph/core/src/axis_set.cpp b/ngraph/core/src/axis_set.cpp index fcc623dc646..49988d7b0a9 100644 --- a/ngraph/core/src/axis_set.cpp +++ b/ngraph/core/src/axis_set.cpp @@ -6,38 +6,38 @@ #include "ngraph/util.hpp" -ngraph::AxisSet::AxisSet() : std::set() {} +ov::AxisSet::AxisSet() : std::set() {} -ngraph::AxisSet::AxisSet(const std::initializer_list& axes) : std::set(axes) {} +ov::AxisSet::AxisSet(const std::initializer_list& axes) : std::set(axes) {} -ngraph::AxisSet::AxisSet(const std::set& axes) : std::set(axes) {} +ov::AxisSet::AxisSet(const std::set& axes) : std::set(axes) {} -ngraph::AxisSet::AxisSet(const std::vector& axes) : std::set(axes.begin(), axes.end()) {} +ov::AxisSet::AxisSet(const std::vector& axes) : std::set(axes.begin(), axes.end()) {} -ngraph::AxisSet::AxisSet(const AxisSet& axes) : std::set(axes) {} +ov::AxisSet::AxisSet(const AxisSet& axes) : std::set(axes) {} -ngraph::AxisSet& ngraph::AxisSet::operator=(const AxisSet& v) { +ov::AxisSet& ov::AxisSet::operator=(const AxisSet& v) { static_cast*>(this)->operator=(v); return *this; } -ngraph::AxisSet& ngraph::AxisSet::operator=(AxisSet&& v) noexcept { +ov::AxisSet& ov::AxisSet::operator=(AxisSet&& v) noexcept { static_cast*>(this)->operator=(v); return *this; } -std::vector ngraph::AxisSet::to_vector() const { +std::vector ov::AxisSet::to_vector() const { return std::vector(this->begin(), this->end()); } -std::ostream& ngraph::operator<<(std::ostream& s, const AxisSet& axis_set) { +std::ostream& ov::operator<<(std::ostream& s, const AxisSet& axis_set) { s << "AxisSet{"; s << ngraph::join(axis_set); s << "}"; return s; } -const std::vector& ov::AttributeAdapter::get() { +const std::vector& ov::AttributeAdapter::get() { if (!m_buffer_valid) { m_buffer.clear(); for (auto elt : m_ref) { @@ -48,12 +48,12 @@ const std::vector& ov::AttributeAdapter::get() { return m_buffer; } -void ov::AttributeAdapter::set(const std::vector& value) { - m_ref = ngraph::AxisSet(); +void ov::AttributeAdapter::set(const std::vector& value) { + m_ref = ov::AxisSet(); for (auto elt : value) { m_ref.insert(elt); } m_buffer_valid = false; } -constexpr ov::DiscreteTypeInfo ov::AttributeAdapter::type_info; +constexpr ov::DiscreteTypeInfo ov::AttributeAdapter::type_info; diff --git a/ngraph/core/src/axis_vector.cpp b/ngraph/core/src/axis_vector.cpp index 33052a96496..442ac5899d9 100644 --- a/ngraph/core/src/axis_vector.cpp +++ b/ngraph/core/src/axis_vector.cpp @@ -6,33 +6,33 @@ #include "ngraph/util.hpp" -std::ostream& ngraph::operator<<(std::ostream& s, const AxisVector& axis_vector) { +std::ostream& ov::operator<<(std::ostream& s, const AxisVector& axis_vector) { s << "AxisVector{"; s << ngraph::join(axis_vector); s << "}"; return s; } -ngraph::AxisVector::AxisVector(const std::initializer_list& axes) : std::vector(axes) {} +ov::AxisVector::AxisVector(const std::initializer_list& axes) : std::vector(axes) {} -ngraph::AxisVector::AxisVector(const std::vector& axes) : std::vector(axes) {} +ov::AxisVector::AxisVector(const std::vector& axes) : std::vector(axes) {} -ngraph::AxisVector::AxisVector(const AxisVector& axes) : std::vector(axes) {} +ov::AxisVector::AxisVector(const AxisVector& axes) : std::vector(axes) {} -ngraph::AxisVector::AxisVector(size_t n) : std::vector(n) {} +ov::AxisVector::AxisVector(size_t n) : std::vector(n) {} -ngraph::AxisVector::AxisVector() {} +ov::AxisVector::AxisVector() {} -ngraph::AxisVector::~AxisVector() {} +ov::AxisVector::~AxisVector() {} -ngraph::AxisVector& ngraph::AxisVector::operator=(const AxisVector& v) { +ov::AxisVector& ov::AxisVector::operator=(const AxisVector& v) { static_cast*>(this)->operator=(v); return *this; } -ngraph::AxisVector& ngraph::AxisVector::operator=(AxisVector&& v) noexcept { +ov::AxisVector& ov::AxisVector::operator=(AxisVector&& v) noexcept { static_cast*>(this)->operator=(v); return *this; } -constexpr ov::DiscreteTypeInfo ov::AttributeAdapter::type_info; +constexpr ov::DiscreteTypeInfo ov::AttributeAdapter::type_info; diff --git a/ngraph/core/src/coordinate.cpp b/ngraph/core/src/coordinate.cpp index f1b9c17feca..2a09314dbe5 100644 --- a/ngraph/core/src/coordinate.cpp +++ b/ngraph/core/src/coordinate.cpp @@ -8,36 +8,36 @@ using namespace std; -std::ostream& ngraph::operator<<(std::ostream& s, const Coordinate& coordinate) { +std::ostream& ov::operator<<(std::ostream& s, const Coordinate& coordinate) { s << "Coordinate{"; s << ngraph::join(coordinate); s << "}"; return s; } -ngraph::Coordinate::Coordinate() {} +ov::Coordinate::Coordinate() = default; -ngraph::Coordinate::Coordinate(const std::initializer_list& axes) : std::vector(axes) {} +ov::Coordinate::Coordinate(const std::initializer_list& axes) : std::vector(axes) {} -ngraph::Coordinate::Coordinate(const Shape& shape) +ov::Coordinate::Coordinate(const ngraph::Shape& shape) : std::vector(static_cast&>(shape)) {} -ngraph::Coordinate::Coordinate(const std::vector& axes) : std::vector(axes) {} +ov::Coordinate::Coordinate(const std::vector& axes) : std::vector(axes) {} -ngraph::Coordinate::Coordinate(const Coordinate& axes) : std::vector(axes) {} +ov::Coordinate::Coordinate(const Coordinate& axes) = default; -ngraph::Coordinate::Coordinate(size_t n, size_t initial_value) : std::vector(n, initial_value) {} +ov::Coordinate::Coordinate(size_t n, size_t initial_value) : std::vector(n, initial_value) {} -ngraph::Coordinate::~Coordinate() {} +ov::Coordinate::~Coordinate() = default; -ngraph::Coordinate& ngraph::Coordinate::operator=(const Coordinate& v) { +ov::Coordinate& ov::Coordinate::operator=(const Coordinate& v) { static_cast*>(this)->operator=(v); return *this; } -ngraph::Coordinate& ngraph::Coordinate::operator=(Coordinate&& v) noexcept { +ov::Coordinate& ov::Coordinate::operator=(Coordinate&& v) noexcept { static_cast*>(this)->operator=(v); return *this; } -constexpr ov::DiscreteTypeInfo ov::AttributeAdapter::type_info; +constexpr ov::DiscreteTypeInfo ov::AttributeAdapter::type_info; diff --git a/ngraph/core/src/coordinate_diff.cpp b/ngraph/core/src/coordinate_diff.cpp index 856a4e2ead9..dcbb3abc7e7 100644 --- a/ngraph/core/src/coordinate_diff.cpp +++ b/ngraph/core/src/coordinate_diff.cpp @@ -9,35 +9,35 @@ using namespace std; using namespace ngraph; -std::ostream& ngraph::operator<<(std::ostream& s, const CoordinateDiff& coordinate_diff) { +std::ostream& ov::operator<<(std::ostream& s, const CoordinateDiff& coordinate_diff) { s << "CoordinateDiff{"; s << ngraph::join(coordinate_diff); s << "}"; return s; } -ngraph::CoordinateDiff::CoordinateDiff(const std::initializer_list& diffs) +ov::CoordinateDiff::CoordinateDiff(const std::initializer_list& diffs) : std::vector(diffs) {} -ngraph::CoordinateDiff::CoordinateDiff(const std::vector& diffs) : std::vector(diffs) {} +ov::CoordinateDiff::CoordinateDiff(const std::vector& diffs) : std::vector(diffs) {} -ngraph::CoordinateDiff::CoordinateDiff(const CoordinateDiff& diffs) : std::vector(diffs) {} +ov::CoordinateDiff::CoordinateDiff(const CoordinateDiff& diffs) = default; -ngraph::CoordinateDiff::CoordinateDiff(size_t n, std::ptrdiff_t initial_value) +ov::CoordinateDiff::CoordinateDiff(size_t n, std::ptrdiff_t initial_value) : std::vector(n, initial_value) {} -ngraph::CoordinateDiff::CoordinateDiff() {} +ov::CoordinateDiff::CoordinateDiff() = default; -ngraph::CoordinateDiff::~CoordinateDiff() {} +ov::CoordinateDiff::~CoordinateDiff() = default; -ngraph::CoordinateDiff& ngraph::CoordinateDiff::operator=(const CoordinateDiff& v) { +ov::CoordinateDiff& ov::CoordinateDiff::operator=(const CoordinateDiff& v) { static_cast*>(this)->operator=(v); return *this; } -ngraph::CoordinateDiff& ngraph::CoordinateDiff::operator=(CoordinateDiff&& v) noexcept { +ov::CoordinateDiff& ov::CoordinateDiff::operator=(CoordinateDiff&& v) noexcept { static_cast*>(this)->operator=(v); return *this; } -constexpr ov::DiscreteTypeInfo ov::AttributeAdapter::type_info; +constexpr ov::DiscreteTypeInfo ov::AttributeAdapter::type_info; From e1226cc814239c73167624994123dab3aebe28f0 Mon Sep 17 00:00:00 2001 From: Tomasz Jankowski Date: Thu, 26 Aug 2021 10:08:22 +0200 Subject: [PATCH 46/76] [ONNX] Gather 8 (#7185) --- .../frontend/onnx/frontend/src/op/gather.hpp | 11 +- .../test/models/onnx/gather_float_1D.prototxt | 65 +++++++++++ .../onnx/gather_float_2D_axis_1.prototxt | 71 ++++++++++++ .../onnx/gather_int32_3D_axis_1.prototxt | 77 +++++++++++++ .../onnx/gather_int8_3D_axis_neg_1.prototxt | 77 +++++++++++++ ngraph/test/onnx/onnx_import.in.cpp | 104 ++++++++++++++++++ ngraph/test/runtime/ie/unit_test.manifest | 2 + .../runtime/interpreter/evaluates_map.cpp | 30 +++++ .../runtime/interpreter/opset_int_tbl.hpp | 1 + 9 files changed, 431 insertions(+), 7 deletions(-) create mode 100644 ngraph/test/models/onnx/gather_float_1D.prototxt create mode 100644 ngraph/test/models/onnx/gather_float_2D_axis_1.prototxt create mode 100644 ngraph/test/models/onnx/gather_int32_3D_axis_1.prototxt create mode 100644 ngraph/test/models/onnx/gather_int8_3D_axis_neg_1.prototxt diff --git a/ngraph/frontend/onnx/frontend/src/op/gather.hpp b/ngraph/frontend/onnx/frontend/src/op/gather.hpp index 0c12fedc382..266afd7e0f4 100644 --- a/ngraph/frontend/onnx/frontend/src/op/gather.hpp +++ b/ngraph/frontend/onnx/frontend/src/op/gather.hpp @@ -6,8 +6,8 @@ #include -#include "default_opset.hpp" #include "ngraph/node.hpp" +#include "ngraph/opsets/opset8.hpp" #include "ngraph/validation_util.hpp" #include "onnx_import/core/node.hpp" @@ -21,15 +21,12 @@ inline OutputVector gather(const Node& node) { auto indices = ng_inputs.at(1); auto axis = node.get_attribute_value("axis", 0); - return {std::make_shared(data, - indices, - default_opset::Constant::create(element::i64, Shape{}, {axis}))}; + return {std::make_shared(data, + indices, + default_opset::Constant::create(element::i64, Shape{}, {axis}))}; } } // namespace set_1 - } // namespace op - } // namespace onnx_import - } // namespace ngraph diff --git a/ngraph/test/models/onnx/gather_float_1D.prototxt b/ngraph/test/models/onnx/gather_float_1D.prototxt new file mode 100644 index 00000000000..b0170c32c63 --- /dev/null +++ b/ngraph/test/models/onnx/gather_float_1D.prototxt @@ -0,0 +1,65 @@ +ir_version: 7 +graph { + node { + input: "data" + input: "indices" + output: "output" + name: "gather" + op_type: "Gather" + attribute { + name: "axis" + i: 0 + type: INT + } + } + name: "test-gather8" + input { + name: "data" + type { + tensor_type { + elem_type: 1 + shape { + dim { + dim_value: 3 + } + } + } + } + } + input { + name: "indices" + type { + tensor_type { + elem_type: 7 + shape { + dim { + dim_value: 2 + } + dim { + dim_value: 2 + } + } + } + } + } + output { + name: "output" + type { + tensor_type { + elem_type: 1 + shape { + dim { + dim_value: 2 + } + dim { + dim_value: 2 + } + } + } + } + } +} +opset_import { + domain: "" + version: 13 +} diff --git a/ngraph/test/models/onnx/gather_float_2D_axis_1.prototxt b/ngraph/test/models/onnx/gather_float_2D_axis_1.prototxt new file mode 100644 index 00000000000..fd573601eaf --- /dev/null +++ b/ngraph/test/models/onnx/gather_float_2D_axis_1.prototxt @@ -0,0 +1,71 @@ +ir_version: 7 +graph { + node { + input: "data" + input: "indices" + output: "output" + name: "gather" + op_type: "Gather" + attribute { + name: "axis" + i: 1 + type: INT + } + } + name: "test-gather8" + input { + name: "data" + type { + tensor_type { + elem_type: 1 + shape { + dim { + dim_value: 3 + } + dim { + dim_value: 3 + } + } + } + } + } + input { + name: "indices" + type { + tensor_type { + elem_type: 7 + shape { + dim { + dim_value: 2 + } + dim { + dim_value: 2 + } + } + } + } + } + output { + name: "output" + type { + tensor_type { + elem_type: 1 + shape { + dim { + dim_value: 3 + } + dim { + dim_value: 2 + } + dim { + dim_value: 2 + } + } + } + } + } +} +opset_import { + domain: "" + version: 13 +} diff --git a/ngraph/test/models/onnx/gather_int32_3D_axis_1.prototxt b/ngraph/test/models/onnx/gather_int32_3D_axis_1.prototxt new file mode 100644 index 00000000000..21a5c41758f --- /dev/null +++ b/ngraph/test/models/onnx/gather_int32_3D_axis_1.prototxt @@ -0,0 +1,77 @@ +ir_version: 7 +graph { + node { + input: "data" + input: "indices" + output: "output" + name: "gather" + op_type: "Gather" + attribute { + name: "axis" + i: 1 + type: INT + } + } + name: "test-gather8" + input { + name: "data" + type { + tensor_type { + elem_type: 6 + shape { + dim { + dim_value: 2 + } + dim { + dim_value: 2 + } + dim { + dim_value: 2 + } + } + } + } + } + input { + name: "indices" + type { + tensor_type { + elem_type: 6 + shape { + dim { + dim_value: 4 + } + dim { + dim_value: 1 + } + } + } + } + } + output { + name: "output" + type { + tensor_type { + elem_type: 6 + shape { + dim { + dim_value: 2 + } + dim { + dim_value: 4 + } + dim { + dim_value: 1 + } + dim { + dim_value: 2 + } + } + } + } + } +} +opset_import { + domain: "" + version: 13 +} diff --git a/ngraph/test/models/onnx/gather_int8_3D_axis_neg_1.prototxt b/ngraph/test/models/onnx/gather_int8_3D_axis_neg_1.prototxt new file mode 100644 index 00000000000..2ada8fc0538 --- /dev/null +++ b/ngraph/test/models/onnx/gather_int8_3D_axis_neg_1.prototxt @@ -0,0 +1,77 @@ +ir_version: 7 +graph { + node { + input: "data" + input: "indices" + output: "output" + name: "gather" + op_type: "Gather" + attribute { + name: "axis" + i: -1 + type: INT + } + } + name: "test-gather8" + input { + name: "data" + type { + tensor_type { + elem_type: 3 + shape { + dim { + dim_value: 2 + } + dim { + dim_value: 2 + } + dim { + dim_value: 2 + } + } + } + } + } + input { + name: "indices" + type { + tensor_type { + elem_type: 6 + shape { + dim { + dim_value: 4 + } + dim { + dim_value: 1 + } + } + } + } + } + output { + name: "output" + type { + tensor_type { + elem_type: 3 + shape { + dim { + dim_value: 2 + } + dim { + dim_value: 2 + } + dim { + dim_value: 4 + } + dim { + dim_value: 1 + } + } + } + } + } +} +opset_import { + domain: "" + version: 13 +} diff --git a/ngraph/test/onnx/onnx_import.in.cpp b/ngraph/test/onnx/onnx_import.in.cpp index ae74c4cbe6d..177052530cb 100644 --- a/ngraph/test/onnx/onnx_import.in.cpp +++ b/ngraph/test/onnx/onnx_import.in.cpp @@ -2714,6 +2714,110 @@ NGRAPH_TEST(${BACKEND_NAME}, onnx_model_scatterND_const_i32_indices) { test_case.run(); } +NGRAPH_TEST(${BACKEND_NAME}, onnx_model_gather_float_1D) { + const auto function = + onnx_import::import_onnx_model(file_util::path_join(SERIALIZED_ZOO, "onnx/gather_float_1D.onnx")); + auto test_case = test::TestCase(function); + + // clang-format off + test_case.add_input(Shape{3}, + { 5, 6, 7 }); + test_case.add_input(Shape{2, 2}, + { 0, 1, + 1, 2 }); + test_case.add_expected_output(Shape{2, 2}, + { 5, 6, + 6, 7 }); + // clang-format on + + test_case.run(); +} + +NGRAPH_TEST(${BACKEND_NAME}, onnx_model_gather_int32_3D_axis_1) { + const auto function = + onnx_import::import_onnx_model(file_util::path_join(SERIALIZED_ZOO, "onnx/gather_int32_3D_axis_1.onnx")); + auto test_case = test::TestCase(function); + + // clang-format off + test_case.add_input(Shape{2, 2, 2}, + { 1, 2, + 3, 4, + + 5, 6, + 7, 8 }); + test_case.add_input(Shape{4, 1}, + { 0, + 1, + 1, + 0 }); + test_case.add_expected_output(Shape{2, 4, 1, 2}, + { 1, 2, + 3, 4, + 3, 4, + 1, 2, + + 5, 6, + 7, 8, + 7, 8, + 5, 6 }); + // clang-format on + + test_case.run(); +} + +NGRAPH_TEST(${BACKEND_NAME}, onnx_model_gather_int8_3D_axis_neg_1) { + const auto function = + onnx_import::import_onnx_model(file_util::path_join(SERIALIZED_ZOO, "onnx/gather_int8_3D_axis_neg_1.onnx")); + auto test_case = test::TestCase(function); + + // clang-format off + test_case.add_input(Shape{2, 2, 2}, + { 1, 2, + 3, 4, + + 5, 6, + 7, 8 }); + test_case.add_input(Shape{4, 1}, + { 0, 1, 1, 0 }); + test_case.add_expected_output(Shape{2, 2, 4, 1}, + { 1, 2, 2, 1, + 3, 4, 4, 3, + + 5, 6, 6, 5, + 7, 8, 8, 7 }); + // clang-format on + + test_case.run(); +} + +NGRAPH_TEST(${BACKEND_NAME}, onnx_model_gather_float_2D_neg_indices) { + const auto function = + onnx_import::import_onnx_model(file_util::path_join(SERIALIZED_ZOO, "onnx/gather_float_2D_axis_1.onnx")); + auto test_case = test::TestCase(function); + + // clang-format off + test_case.add_input(Shape{3, 3}, + { 0.0, 0.1, 0.2, + 1.0, 1.1, 1.2, + 2.0, 2.1, 2.2 }); + test_case.add_input(Shape{2, 2}, + { -1, -2, + -3, -2 }); + test_case.add_expected_output(Shape{3, 2, 2}, + { + 0.2, 0.1, + 0.0, 0.1, + + 1.2, 1.1, + 1.0, 1.1, + + 2.2, 2.1, + 2.0, 2.1 }); + // clang-format on + + test_case.run(); +} + NGRAPH_TEST(${BACKEND_NAME}, onnx_model_gather_elements_float_1D) { const auto function = onnx_import::import_onnx_model(file_util::path_join(SERIALIZED_ZOO, "onnx/gather_elements_float_1D.onnx")); diff --git a/ngraph/test/runtime/ie/unit_test.manifest b/ngraph/test/runtime/ie/unit_test.manifest index 88ba3166cb6..04c2983ada5 100644 --- a/ngraph/test/runtime/ie/unit_test.manifest +++ b/ngraph/test/runtime/ie/unit_test.manifest @@ -1597,3 +1597,5 @@ IE_GPU.deformable_convolution_opset8_2D_neg_offsets_groups_and_deforgroups_mask IE_GPU.deformable_convolution_2D_integral_offsets_groups_and_deforgroups IE_GPU.deformable_convolution_opset8_2D_integral_offsets_groups_and_deforgroups +# Not yet implemented - refer PR#6601 +IE_CPU.onnx_model_gather_float_2D_neg_indices diff --git a/ngraph/test/runtime/interpreter/evaluates_map.cpp b/ngraph/test/runtime/interpreter/evaluates_map.cpp index e6a56212f0f..a381faeaa6f 100644 --- a/ngraph/test/runtime/interpreter/evaluates_map.cpp +++ b/ngraph/test/runtime/interpreter/evaluates_map.cpp @@ -37,6 +37,7 @@ #include #include #include +#include #include #include #include @@ -2915,6 +2916,35 @@ namespace return true; } + template + bool evaluate(const shared_ptr& op, + const HostTensorVector& outputs, + const HostTensorVector& inputs) { + using T = typename element_type_traits::value_type; + if (op->get_input_element_type(1) == element::i64) { + runtime::reference::gather(inputs[0]->get_data_ptr(), + inputs[1]->get_data_ptr(), + outputs[0]->get_data_ptr(), + op->get_input_shape(0), + op->get_input_shape(1), + op->get_output_shape(0), + op->get_axis(), + op->get_batch_dims()); + } else if (op->get_input_element_type(1) == element::i32) { + runtime::reference::gather(inputs[0]->get_data_ptr(), + inputs[1]->get_data_ptr(), + outputs[0]->get_data_ptr(), + op->get_input_shape(0), + op->get_input_shape(1), + op->get_output_shape(0), + op->get_axis(), + op->get_batch_dims()); + } else { + throw ngraph_error("Unexpected indices type for Gather operation"); + } + return true; + } + template bool evaluate_node(std::shared_ptr node, const HostTensorVector& outputs, diff --git a/ngraph/test/runtime/interpreter/opset_int_tbl.hpp b/ngraph/test/runtime/interpreter/opset_int_tbl.hpp index 2893e716af5..b24b8676961 100644 --- a/ngraph/test/runtime/interpreter/opset_int_tbl.hpp +++ b/ngraph/test/runtime/interpreter/opset_int_tbl.hpp @@ -99,5 +99,6 @@ NGRAPH_OP(Roll, ngraph::op::v7) NGRAPH_OP(AdaptiveAvgPool, ngraph::op::v8) NGRAPH_OP(AdaptiveMaxPool, ngraph::op::v8) +NGRAPH_OP(Gather, op::v8) NGRAPH_OP(MatrixNms, op::v8) NGRAPH_OP(MulticlassNms, op::v8) From 0e521a1e229f3670e072e9eec1c07e25247fc914 Mon Sep 17 00:00:00 2001 From: Mateusz Bencer Date: Thu, 26 Aug 2021 10:50:53 +0200 Subject: [PATCH 47/76] Use ONNX Frontend instead of ONNX Reader (#7031) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * added get_name * add support to supported_impl * remove debug code * review remarks * changed name to onnx_experimental * fixed test * revert onnx_experimental name * integrate reader and fe api * add unit tests * removed prototxt from model_validator * reader refactor * add supress * Update inference-engine/src/readers/onnx_reader/ie_onnx_reader.cpp Co-authored-by: Tomasz Dołbniak * fix segfaults * removed onnx reader * handle istringstream * wstring support * removed saving path * styles applied * changed name to onnx experimental * Apply suggestions from code review Co-authored-by: Tatiana Savina * skip onnx_experimental frontend in mo.py * add support of wstring paths * fix wstring ctor of InputModelONNX * added NGRAPH_SUPPRESS * make one instance of manager * change onnx_experimental name to onnx * creation frontend manager refactor Co-authored-by: Tomasz Dołbniak Co-authored-by: Tatiana Savina --- cmake/developer_package/plugins/plugins.cmake | 4 +- ...Deep_Learning_Inference_Engine_DevGuide.md | 4 +- docs/IE_DG/inference_engine_intro.md | 4 +- inference-engine/src/CMakeLists.txt | 2 +- .../src/ie_network_reader.cpp | 38 +-- inference-engine/src/readers/CMakeLists.txt | 4 - .../src/readers/onnx_reader/CMakeLists.txt | 39 --- .../readers/onnx_reader/ie_onnx_reader.cpp | 70 ------ .../readers/onnx_reader/ie_onnx_reader.hpp | 45 ---- .../onnx_reader/onnx_model_validator.cpp | 230 ------------------ .../onnx_reader/onnx_model_validator.hpp | 17 -- .../inference_engine/CMakeLists.txt | 2 +- model-optimizer/mo/main.py | 3 + .../frontend_manager/frontend_manager.hpp | 11 + .../frontend_manager/src/frontend_manager.cpp | 2 + .../include/onnx_frontend/frontend.hpp | 2 + ngraph/frontend/onnx/frontend/src/editor.cpp | 25 ++ ngraph/frontend/onnx/frontend/src/editor.hpp | 11 + .../frontend/onnx/frontend/src/frontend.cpp | 108 +++++++- .../onnx/frontend/src/input_model.cpp | 17 ++ .../onnx/frontend/src/input_model.hpp | 9 + .../onnx_common/onnx_model_validator.hpp | 14 ++ .../include/onnx_common/parser.hpp | 3 + .../onnx_common/src/onnx_model_validator.cpp | 219 +++++++++++++++++ .../frontend/onnx/onnx_common/src/parser.cpp | 22 +- .../tests/test_frontend/test_frontend_onnx.py | 15 ++ ngraph/test/frontend/CMakeLists.txt | 4 + ngraph/test/frontend/onnx/CMakeLists.txt | 26 ++ ngraph/test/frontend/onnx/load_from.cpp | 52 ++++ ngraph/test/frontend/onnx/main.cpp | 32 +++ ngraph/test/frontend/onnx/onnx_utils.hpp | 9 + ngraph/test/frontend/onnx/unit_test.manifest | 3 + ngraph/test/onnx/onnx_editor.cpp | 15 ++ ngraph/test/onnx/onnx_import_library.cpp | 2 +- .../deployment_manager/configs/darwin.json | 1 - scripts/deployment_manager/configs/linux.json | 1 - .../deployment_manager/configs/windows.json | 1 - 37 files changed, 626 insertions(+), 440 deletions(-) delete mode 100644 inference-engine/src/readers/onnx_reader/CMakeLists.txt delete mode 100644 inference-engine/src/readers/onnx_reader/ie_onnx_reader.cpp delete mode 100644 inference-engine/src/readers/onnx_reader/ie_onnx_reader.hpp delete mode 100644 inference-engine/src/readers/onnx_reader/onnx_model_validator.cpp delete mode 100644 inference-engine/src/readers/onnx_reader/onnx_model_validator.hpp create mode 100644 ngraph/frontend/onnx/onnx_common/include/onnx_common/onnx_model_validator.hpp create mode 100644 ngraph/frontend/onnx/onnx_common/src/onnx_model_validator.cpp create mode 100644 ngraph/test/frontend/onnx/CMakeLists.txt create mode 100644 ngraph/test/frontend/onnx/load_from.cpp create mode 100644 ngraph/test/frontend/onnx/main.cpp create mode 100644 ngraph/test/frontend/onnx/onnx_utils.hpp create mode 100644 ngraph/test/frontend/onnx/unit_test.manifest diff --git a/cmake/developer_package/plugins/plugins.cmake b/cmake/developer_package/plugins/plugins.cmake index 6210ede333a..cec023f3062 100644 --- a/cmake/developer_package/plugins/plugins.cmake +++ b/cmake/developer_package/plugins/plugins.cmake @@ -112,8 +112,8 @@ function(ie_add_plugin) if(TARGET inference_engine_ir_v7_reader) add_dependencies(${IE_PLUGIN_NAME} inference_engine_ir_v7_reader) endif() - if(TARGET inference_engine_onnx_reader) - add_dependencies(${IE_PLUGIN_NAME} inference_engine_onnx_reader) + if(TARGET onnx_ngraph_frontend) + add_dependencies(${IE_PLUGIN_NAME} onnx_ngraph_frontend) endif() # install rules diff --git a/docs/IE_DG/Deep_Learning_Inference_Engine_DevGuide.md b/docs/IE_DG/Deep_Learning_Inference_Engine_DevGuide.md index 5fc2b3f9102..0f07f550381 100644 --- a/docs/IE_DG/Deep_Learning_Inference_Engine_DevGuide.md +++ b/docs/IE_DG/Deep_Learning_Inference_Engine_DevGuide.md @@ -43,10 +43,10 @@ This library contains the classes to: Starting from 2020.4 release, Inference Engine introduced a concept of `CNNNetwork` reader plugins. Such plugins can be automatically dynamically loaded by Inference Engine in runtime depending on file format: * Linux* OS: - `libinference_engine_ir_reader.so` to read a network from IR - - `libinference_engine_onnx_reader.so` to read a network from ONNX model format + - `onnx_ngraph_frontend.so` to read a network from ONNX model format * Windows* OS: - `inference_engine_ir_reader.dll` to read a network from IR - - `inference_engine_onnx_reader.dll` to read a network from ONNX model format + - `onnx_ngraph_frontend.dll` to read a network from ONNX model format ### Device-Specific Plugin Libraries diff --git a/docs/IE_DG/inference_engine_intro.md b/docs/IE_DG/inference_engine_intro.md index a4c33fd6f85..89d80654fe4 100644 --- a/docs/IE_DG/inference_engine_intro.md +++ b/docs/IE_DG/inference_engine_intro.md @@ -46,10 +46,10 @@ This library contains the classes to: Starting from 2020.4 release, Inference Engine introduced a concept of `CNNNetwork` reader plugins. Such plugins can be automatically dynamically loaded by Inference Engine in runtime depending on file format: * Unix* OS: - `libinference_engine_ir_reader.so` to read a network from IR - - `libinference_engine_onnx_reader.so` to read a network from ONNX model format + - `onnx_ngraph_frontend.so` to read a network from ONNX model format * Windows* OS: - `inference_engine_ir_reader.dll` to read a network from IR - - `inference_engine_onnx_reader.dll` to read a network from ONNX model format + - `onnx_ngraph_frontend.dll` to read a network from ONNX model format ### Device-specific Plugin Libraries ### diff --git a/inference-engine/src/CMakeLists.txt b/inference-engine/src/CMakeLists.txt index 2b53ce68481..4ac1a0da14b 100644 --- a/inference-engine/src/CMakeLists.txt +++ b/inference-engine/src/CMakeLists.txt @@ -54,5 +54,5 @@ add_custom_target(ie_libraries ALL ir_frontend) if(NGRAPH_ONNX_FRONTEND_ENABLE) - add_dependencies(ie_libraries inference_engine_onnx_reader) + add_dependencies(ie_libraries onnx_ngraph_frontend) endif() diff --git a/inference-engine/src/inference_engine/src/ie_network_reader.cpp b/inference-engine/src/inference_engine/src/ie_network_reader.cpp index f3c95ac4ed2..f8c15a4f00d 100644 --- a/inference-engine/src/inference_engine/src/ie_network_reader.cpp +++ b/inference-engine/src/inference_engine/src/ie_network_reader.cpp @@ -96,6 +96,11 @@ namespace { // Extension to plugins creator std::multimap readers; +static ngraph::frontend::FrontEndManager* get_frontend_manager() { + static ngraph::frontend::FrontEndManager manager; + return &manager; +} + void registerReaders() { OV_ITT_SCOPED_TASK(ov::itt::domains::IE, "registerReaders"); static bool initialized = false; @@ -115,14 +120,6 @@ void registerReaders() { return std::make_shared(name, library_name); }; - // try to load ONNX reader if library exists - auto onnxReader = - create_if_exists("ONNX", std::string("inference_engine_onnx_reader") + std::string(IE_BUILD_POSTFIX)); - if (onnxReader) { - readers.emplace("onnx", onnxReader); - readers.emplace("prototxt", onnxReader); - } - // try to load IR reader v10 if library exists auto irReaderv10 = create_if_exists("IRv10", std::string("inference_engine_ir_reader") + std::string(IE_BUILD_POSTFIX)); @@ -174,10 +171,6 @@ CNNNetwork details::ReadNetwork(const std::string& modelPath, #endif // Try to open model file std::ifstream modelStream(model_path, std::ios::binary); - // save path in extensible array of stream - // notice: lifetime of path pointed by pword(0) is limited by current scope - const std::string path_to_save_in_stream = modelPath; - modelStream.pword(0) = const_cast(path_to_save_in_stream.c_str()); if (!modelStream.is_open()) IE_THROW() << "Model file " << modelPath << " cannot be opened!"; @@ -240,7 +233,7 @@ CNNNetwork details::ReadNetwork(const std::string& modelPath, } } // Try to load with FrontEndManager - static ngraph::frontend::FrontEndManager manager; + const auto manager = get_frontend_manager(); ngraph::frontend::FrontEnd::Ptr FE; ngraph::frontend::InputModel::Ptr inputModel; if (!binPath.empty()) { @@ -249,17 +242,17 @@ CNNNetwork details::ReadNetwork(const std::string& modelPath, #else std::string weights_path = binPath; #endif - FE = manager.load_by_model(model_path, weights_path); + FE = manager->load_by_model(model_path, weights_path); if (FE) inputModel = FE->load(model_path, weights_path); } else { - FE = manager.load_by_model(model_path); + FE = manager->load_by_model(model_path); if (FE) inputModel = FE->load(model_path); } if (inputModel) { auto ngFunc = FE->convert(inputModel); - return CNNNetwork(ngFunc); + return CNNNetwork(ngFunc, exts); } IE_THROW() << "Unknown model format! Cannot find reader for model format: " << fileExt << " and read the model: " << modelPath << ". Please check that reader library exists in your PATH."; @@ -282,6 +275,19 @@ CNNNetwork details::ReadNetwork(const std::string& model, return reader->read(modelStream, exts); } } + // Try to load with FrontEndManager + // NOTE: weights argument is ignored + const auto manager = get_frontend_manager(); + ngraph::frontend::FrontEnd::Ptr FE; + ngraph::frontend::InputModel::Ptr inputModel; + FE = manager->load_by_model(&modelStream); + if (FE) + inputModel = FE->load(&modelStream); + if (inputModel) { + auto ngFunc = FE->convert(inputModel); + return CNNNetwork(ngFunc, exts); + } + IE_THROW() << "Unknown model format! Cannot find reader for the model and read it. Please check that reader " "library exists in your PATH."; } diff --git a/inference-engine/src/readers/CMakeLists.txt b/inference-engine/src/readers/CMakeLists.txt index 139a515f3fa..b1864152ade 100644 --- a/inference-engine/src/readers/CMakeLists.txt +++ b/inference-engine/src/readers/CMakeLists.txt @@ -17,7 +17,3 @@ add_cpplint_target(${TARGET_NAME}_cpplint FOR_SOURCES ${reader_api_hpp}) add_subdirectory(ir_reader) add_subdirectory(ir_reader_v7) - -if(NGRAPH_ONNX_FRONTEND_ENABLE) - add_subdirectory(onnx_reader) -endif() diff --git a/inference-engine/src/readers/onnx_reader/CMakeLists.txt b/inference-engine/src/readers/onnx_reader/CMakeLists.txt deleted file mode 100644 index b5b409f99c7..00000000000 --- a/inference-engine/src/readers/onnx_reader/CMakeLists.txt +++ /dev/null @@ -1,39 +0,0 @@ -# Copyright (C) 2018-2021 Intel Corporation -# SPDX-License-Identifier: Apache-2.0 -# - -set(TARGET_NAME "inference_engine_onnx_reader") - -file(GLOB_RECURSE LIBRARY_SRC ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/*.hpp) - -# Create named folders for the sources within the .vcproj -# Empty name lists them directly under the .vcproj - -source_group("src" FILES ${LIBRARY_SRC}) - -# Create module library - -add_library(${TARGET_NAME} MODULE ${LIBRARY_SRC}) - -ie_add_vs_version_file(NAME ${TARGET_NAME} - FILEDESCRIPTION "Inference Engine ONNX reader plugin") - -target_include_directories(${TARGET_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) - -target_compile_definitions(${TARGET_NAME} PRIVATE IMPLEMENT_INFERENCE_ENGINE_PLUGIN) - -target_link_libraries(${TARGET_NAME} PRIVATE inference_engine_reader_api onnx_ngraph_frontend inference_engine) - -ie_add_api_validator_post_build_step(TARGET ${TARGET_NAME}) - -set_target_properties(${TARGET_NAME} PROPERTIES INTERPROCEDURAL_OPTIMIZATION_RELEASE ${ENABLE_LTO}) - -# code style - -add_cpplint_target(${TARGET_NAME}_cpplint FOR_TARGETS ${TARGET_NAME}) - -# install - -install(TARGETS ${TARGET_NAME} - LIBRARY DESTINATION ${IE_CPACK_RUNTIME_PATH} COMPONENT core) diff --git a/inference-engine/src/readers/onnx_reader/ie_onnx_reader.cpp b/inference-engine/src/readers/onnx_reader/ie_onnx_reader.cpp deleted file mode 100644 index 0af45c259ae..00000000000 --- a/inference-engine/src/readers/onnx_reader/ie_onnx_reader.cpp +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright (C) 2018-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#include "ie_onnx_reader.hpp" -#include "onnx_model_validator.hpp" -#include -#include - -using namespace InferenceEngine; - -namespace { -std::string readPathFromStream(std::istream& stream) { - if (stream.pword(0) == nullptr) { - return {}; - } - // read saved path from extensible array - return std::string{static_cast(stream.pword(0))}; -} - -/** - * This helper struct uses RAII to rewind/reset the stream so that it points to the beginning - * of the underlying resource (string, file, ...). It works similarily to std::lock_guard - * which releases a mutex upon destruction. - * - * This makes sure that the stream is always reset (exception, successful and unsuccessful - * model validation). - */ -struct StreamRewinder { - StreamRewinder(std::istream& stream) : m_stream(stream) { - m_stream.seekg(0, m_stream.beg); - } - ~StreamRewinder() { - m_stream.seekg(0, m_stream.beg); - } -private: - std::istream& m_stream; -}; -} // namespace - -bool ONNXReader::supportModel(std::istream& model) const { - StreamRewinder rwd{model}; - - const auto model_path = readPathFromStream(model); - - // this might mean that the model is loaded from a string in memory - // let's try to figure out if it's any of the supported formats - if (model_path.empty()) { - if (!is_valid_model(model, onnx_format{})) { - model.seekg(0, model.beg); - return is_valid_model(model, prototxt_format{}); - } else { - return true; - } - } - - if (model_path.find(".prototxt", 0) != std::string::npos) { - return is_valid_model(model, prototxt_format{}); - } else { - return is_valid_model(model, onnx_format{}); - } -} - -CNNNetwork ONNXReader::read(std::istream& model, const std::vector& exts) const { - return CNNNetwork(ngraph::onnx_import::import_onnx_model(model, readPathFromStream(model)), exts); -} - -INFERENCE_PLUGIN_API(void) InferenceEngine::CreateReader(std::shared_ptr& reader) { - reader = std::make_shared(); -} diff --git a/inference-engine/src/readers/onnx_reader/ie_onnx_reader.hpp b/inference-engine/src/readers/onnx_reader/ie_onnx_reader.hpp deleted file mode 100644 index 7d797a4230a..00000000000 --- a/inference-engine/src/readers/onnx_reader/ie_onnx_reader.hpp +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright (C) 2018-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#pragma once - -#include - -namespace InferenceEngine { - -class ONNXReader: public IReader { -public: - /** - * @brief Checks that reader supports format of the model - * @param model stream with model - * @return true if format is supported - */ - bool supportModel(std::istream& model) const override; - /** - * @brief Reads the model to CNNNetwork - * @param model stream with model - * @param exts vector with extensions - * - * @return CNNNetwork - */ - CNNNetwork read(std::istream& model, const std::vector& exts) const override; - /** - * @brief Reads the model to CNNNetwork - * @param model stream with model - * @param weights blob with binary data - * @param exts vector with extensions - * - * @return CNNNetwork - */ - CNNNetwork read(std::istream& model, const Blob::CPtr& weights, const std::vector& exts) const override { - IE_THROW() << "ONNX reader cannot read model with weights!"; - } - - std::vector getDataFileExtensions() const override { - return {}; - } -}; - -} // namespace InferenceEngine - diff --git a/inference-engine/src/readers/onnx_reader/onnx_model_validator.cpp b/inference-engine/src/readers/onnx_reader/onnx_model_validator.cpp deleted file mode 100644 index ae472990c6a..00000000000 --- a/inference-engine/src/readers/onnx_reader/onnx_model_validator.cpp +++ /dev/null @@ -1,230 +0,0 @@ -// Copyright (C) 2018-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#include "onnx_model_validator.hpp" - -#include -#include -#include -#include -#include - -namespace detail { -namespace onnx { - enum Field { - IR_VERSION = 1, - PRODUCER_NAME = 2, - PRODUCER_VERSION = 3, - DOMAIN_ = 4, // DOMAIN collides with some existing symbol in MSVC thus - underscore - MODEL_VERSION = 5, - DOC_STRING = 6, - GRAPH = 7, - OPSET_IMPORT = 8, - METADATA_PROPS = 14, - TRAINING_INFO = 20 - }; - - enum WireType { - VARINT = 0, - BITS_64 = 1, - LENGTH_DELIMITED = 2, - START_GROUP = 3, - END_GROUP = 4, - BITS_32 = 5 - }; - - // A PB key consists of a field number (defined in onnx.proto) and a type of data that follows this key - using PbKey = std::pair; - - // This pair represents a key found in the encoded model and optional size of the payload - // that follows the key (in bytes). They payload should be skipped for the fast check purposes. - using ONNXField = std::pair; - - bool is_correct_onnx_field(const PbKey& decoded_key) { - static const std::map onnx_fields = { - {IR_VERSION, VARINT}, - {PRODUCER_NAME, LENGTH_DELIMITED}, - {PRODUCER_VERSION, LENGTH_DELIMITED}, - {DOMAIN_, LENGTH_DELIMITED}, - {MODEL_VERSION, VARINT}, - {DOC_STRING, LENGTH_DELIMITED}, - {GRAPH, LENGTH_DELIMITED}, - {OPSET_IMPORT, LENGTH_DELIMITED}, - {METADATA_PROPS, LENGTH_DELIMITED}, - {TRAINING_INFO, LENGTH_DELIMITED}, - }; - - if (!onnx_fields.count(static_cast(decoded_key.first))) { - return false; - } - - return onnx_fields.at(static_cast(decoded_key.first)) == static_cast(decoded_key.second); - } - - /** - * Only 7 bits in each component of a varint count in this algorithm. The components form - * a decoded number when they are concatenated bitwise in a reverse order. For example: - * bytes = [b1, b2, b3, b4] - * varint = b4 ++ b3 ++ b2 ++ b1 <== only 7 bits of each byte should be extracted before concat - * - * b1 b2 - * bytes = [00101100, 00000010] - * b2 b1 - * varint = 0000010 ++ 0101100 = 100101100 => decimal: 300 - * Each consecutive varint byte needs to be left shifted "7 x its position in the vector" - * and bitwise added to the accumulator afterwards. - */ - uint32_t varint_bytes_to_number(const std::vector& bytes) { - uint32_t accumulator = 0u; - - for (size_t i = 0; i < bytes.size(); ++i) { - uint32_t b = bytes[i]; - b <<= 7 * i; - accumulator |= b; - } - - return accumulator; - } - - uint32_t decode_varint(std::istream& model) { - std::vector bytes; - // max 4 bytes for a single value because this function returns a 32-bit long decoded varint - const size_t MAX_VARINT_BYTES = 4u; - // optimization to avoid allocations during push_back calls - bytes.reserve(MAX_VARINT_BYTES); - - char key_component = 0; - model.get(key_component); - - // keep reading all bytes from the stream which have the MSB on - while (key_component & 0x80 && bytes.size() < MAX_VARINT_BYTES) { - // drop the most significant bit - const char component = key_component & ~0x80; - bytes.push_back(component); - model.get(key_component); - } - // add the last byte - the one with MSB off - bytes.push_back(key_component); - - return varint_bytes_to_number(bytes); - } - - PbKey decode_key(const char key) { - // 3 least significant bits - const char wire_type = key & 0b111; - // remaining bits - const char field_number = key >> 3; - return {field_number, wire_type}; - } - - ONNXField decode_next_field(std::istream& model) { - char key = 0; - model.get(key); - - const auto decoded_key = decode_key(key); - - if (!is_correct_onnx_field(decoded_key)) { - throw std::runtime_error{"Incorrect field detected in the processed model"}; - } - - const auto onnx_field = static_cast(decoded_key.first); - - switch (decoded_key.second) { - case VARINT: { - // the decoded varint is the payload in this case but its value doesnt matter - // in the fast check process so we just discard it - decode_varint(model); - return {onnx_field, 0}; - } - case LENGTH_DELIMITED: - // the varint following the key determines the payload length - return {onnx_field, decode_varint(model)}; - case BITS_64: - return {onnx_field, 8}; - case BITS_32: - return {onnx_field, 4}; - case START_GROUP: - case END_GROUP: - throw std::runtime_error{"StartGroup and EndGroup are not used in ONNX models"}; - default: - throw std::runtime_error{"Unknown WireType encountered in the model"}; - } - } - - inline void skip_payload(std::istream& model, uint32_t payload_size) { - model.seekg(payload_size, std::ios::cur); - } -} // namespace onnx - -namespace prototxt { - bool contains_onnx_model_keys(const std::string& model, const size_t expected_keys_num) { - size_t keys_found = 0; - - const std::vector onnx_keys = { - "ir_version", "producer_name", "producer_version", "domain", "model_version", - "doc_string", "graph", "opset_import", "metadata_props", "training_info" - }; - - size_t search_start_pos = 0; - - while (keys_found < expected_keys_num) { - const auto key_finder = [&search_start_pos, &model](const std::string& key) { - const auto key_pos = model.find(key, search_start_pos); - if (key_pos != model.npos) { - // don't search from the beginning each time - search_start_pos = key_pos + key.size(); - return true; - } else { - return false; - } - }; - - const auto found = std::any_of(std::begin(onnx_keys), std::end(onnx_keys), key_finder); - if (!found) { - break; - } else { - ++keys_found; - } - } - - return keys_found == expected_keys_num; - } -} // namespace prototxt -} // namespace detail - -namespace InferenceEngine { - bool is_valid_model(std::istream& model, onnx_format) { - // the model usually starts with a 0x08 byte indicating the ir_version value - // so this checker expects at least 2 valid ONNX keys to be found in the validated model - const unsigned int EXPECTED_FIELDS_FOUND = 2u; - unsigned int valid_fields_found = 0u; - try { - while (!model.eof() && valid_fields_found < EXPECTED_FIELDS_FOUND) { - const auto field = detail::onnx::decode_next_field(model); - - ++valid_fields_found; - - if (field.second > 0) { - detail::onnx::skip_payload(model, field.second); - } - } - - return valid_fields_found == EXPECTED_FIELDS_FOUND; - } catch (...) { - return false; - } - } - - bool is_valid_model(std::istream& model, prototxt_format) { - std::array head_of_file; - - model.seekg(0, model.beg); - model.read(head_of_file.data(), head_of_file.size()); - model.clear(); - model.seekg(0, model.beg); - - return detail::prototxt::contains_onnx_model_keys( - std::string{std::begin(head_of_file), std::end(head_of_file)}, 2); - } -} // namespace InferenceEngine diff --git a/inference-engine/src/readers/onnx_reader/onnx_model_validator.hpp b/inference-engine/src/readers/onnx_reader/onnx_model_validator.hpp deleted file mode 100644 index ad7af077cd7..00000000000 --- a/inference-engine/src/readers/onnx_reader/onnx_model_validator.hpp +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (C) 2018-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#pragma once - -#include - -namespace InferenceEngine { - // 2 empty structs used for tag dispatch below - struct onnx_format {}; - struct prototxt_format {}; - - bool is_valid_model(std::istream& model, onnx_format); - - bool is_valid_model(std::istream& model, prototxt_format); -} // namespace InferenceEngine diff --git a/inference-engine/tests/functional/inference_engine/CMakeLists.txt b/inference-engine/tests/functional/inference_engine/CMakeLists.txt index 56258e51437..d5a9d2fd2d7 100644 --- a/inference-engine/tests/functional/inference_engine/CMakeLists.txt +++ b/inference-engine/tests/functional/inference_engine/CMakeLists.txt @@ -60,7 +60,7 @@ if(NGRAPH_ONNX_FRONTEND_ENABLE) target_compile_definitions(${TARGET_NAME} PRIVATE NGRAPH_ONNX_FRONTEND_ENABLE ONNX_TEST_MODELS="${TEST_MODEL_ZOO}/onnx_reader/models/") - add_dependencies(${TARGET_NAME} inference_engine_onnx_reader) + add_dependencies(${TARGET_NAME} onnx_ngraph_frontend) endif() if(NGRAPH_PDPD_FRONTEND_ENABLE) diff --git a/model-optimizer/mo/main.py b/model-optimizer/mo/main.py index 0747107c8c5..3a9553a2bc0 100644 --- a/model-optimizer/mo/main.py +++ b/model-optimizer/mo/main.py @@ -109,6 +109,9 @@ def prepare_ir(argv: argparse.Namespace): if argv.input_model: if not argv.framework: moc_front_end = fem.load_by_model(argv.input_model) + # skip onnx frontend as not fully supported yet (63050) + if moc_front_end and moc_front_end.get_name() == "onnx": + moc_front_end = None if moc_front_end: argv.framework = moc_front_end.get_name() elif argv.framework in available_moc_front_ends: diff --git a/ngraph/frontend/frontend_manager/include/frontend_manager/frontend_manager.hpp b/ngraph/frontend/frontend_manager/include/frontend_manager/frontend_manager.hpp index 5cc181935ef..6a72fc18fc8 100644 --- a/ngraph/frontend/frontend_manager/include/frontend_manager/frontend_manager.hpp +++ b/ngraph/frontend/frontend_manager/include/frontend_manager/frontend_manager.hpp @@ -5,6 +5,7 @@ #pragma once #include +#include #include #include "frontend.hpp" @@ -107,6 +108,16 @@ public: VariantWrapper(const value_type& value) : VariantImpl(value) {} }; +template <> +class FRONTEND_API VariantWrapper : public VariantImpl { +public: + static constexpr VariantTypeInfo type_info{"Variant::std::istringstream*", 0}; + const VariantTypeInfo& get_type_info() const override { + return type_info; + } + VariantWrapper(const value_type& value) : VariantImpl(value) {} +}; + #if defined(ENABLE_UNICODE_PATH_SUPPORT) && defined(_WIN32) template <> class FRONTEND_API VariantWrapper : public VariantImpl { diff --git a/ngraph/frontend/frontend_manager/src/frontend_manager.cpp b/ngraph/frontend/frontend_manager/src/frontend_manager.cpp index e48403678c6..70f6edd6cd0 100644 --- a/ngraph/frontend/frontend_manager/src/frontend_manager.cpp +++ b/ngraph/frontend/frontend_manager/src/frontend_manager.cpp @@ -375,6 +375,8 @@ std::vector Place::get_consuming_operations(const std::string& outpu constexpr VariantTypeInfo VariantWrapper::type_info; +constexpr VariantTypeInfo VariantWrapper::type_info; + #if defined(ENABLE_UNICODE_PATH_SUPPORT) && defined(_WIN32) constexpr VariantTypeInfo VariantWrapper::type_info; #endif diff --git a/ngraph/frontend/onnx/frontend/include/onnx_frontend/frontend.hpp b/ngraph/frontend/onnx/frontend/include/onnx_frontend/frontend.hpp index 38d0b22975a..412d8837fe9 100644 --- a/ngraph/frontend/onnx/frontend/include/onnx_frontend/frontend.hpp +++ b/ngraph/frontend/onnx/frontend/include/onnx_frontend/frontend.hpp @@ -19,6 +19,8 @@ public: std::shared_ptr convert(InputModel::Ptr model) const override; void convert(std::shared_ptr partially_converted) const override; std::shared_ptr decode(InputModel::Ptr model) const override; + std::string get_name() const override; + bool supported_impl(const std::vector>& variants) const override; protected: InputModel::Ptr load_impl(const std::vector>& params) const override; diff --git a/ngraph/frontend/onnx/frontend/src/editor.cpp b/ngraph/frontend/onnx/frontend/src/editor.cpp index ccbd18b0e1d..0b1ca6d8b2e 100644 --- a/ngraph/frontend/onnx/frontend/src/editor.cpp +++ b/ngraph/frontend/onnx/frontend/src/editor.cpp @@ -11,6 +11,7 @@ #include "detail/subgraph_extraction.hpp" #include "edge_mapper.hpp" +#include "ngraph/file_util.hpp" #include "ngraph/log.hpp" #include "onnx_common/parser.hpp" #include "onnx_common/utils.hpp" @@ -19,6 +20,8 @@ using namespace ngraph; using namespace ngraph::onnx_editor; +NGRAPH_SUPPRESS_DEPRECATED_START + namespace { using namespace ONNX_NAMESPACE; @@ -191,6 +194,14 @@ struct onnx_editor::ONNXModelEditor::Impl { Impl(const std::string& model_path) : m_model_proto{std::make_shared(onnx_common::parse_from_file(model_path))} {} + + Impl(std::istream& model_stream) + : m_model_proto{std::make_shared(onnx_common::parse_from_istream(model_stream))} {} + +#if defined(ENABLE_UNICODE_PATH_SUPPORT) && defined(_WIN32) + Impl(const std::wstring& model_path) + : m_model_proto{std::make_shared(onnx_common::parse_from_file(model_path))} {} +#endif }; onnx_editor::ONNXModelEditor::ONNXModelEditor(const std::string& model_path) @@ -199,6 +210,20 @@ onnx_editor::ONNXModelEditor::ONNXModelEditor(const std::string& model_path) delete impl; }} {} +#if defined(ENABLE_UNICODE_PATH_SUPPORT) && defined(_WIN32) +onnx_editor::ONNXModelEditor::ONNXModelEditor(const std::wstring& model_path) + : m_model_path{file_util::wstring_to_string(model_path)}, + m_pimpl{new ONNXModelEditor::Impl{model_path}, [](Impl* impl) { + delete impl; + }} {} +#endif + +onnx_editor::ONNXModelEditor::ONNXModelEditor(std::istream& model_stream, const std::string& model_path) + : m_model_path{model_path}, + m_pimpl{new ONNXModelEditor::Impl{model_stream}, [](Impl* impl) { + delete impl; + }} {} + const std::string& onnx_editor::ONNXModelEditor::model_path() const { return m_model_path; } diff --git a/ngraph/frontend/onnx/frontend/src/editor.hpp b/ngraph/frontend/onnx/frontend/src/editor.hpp index bec2f1b47e1..0605eb03bb2 100644 --- a/ngraph/frontend/onnx/frontend/src/editor.hpp +++ b/ngraph/frontend/onnx/frontend/src/editor.hpp @@ -31,6 +31,17 @@ public: /// /// \param model_path Path to the file containing the model. ONNXModelEditor(const std::string& model_path); +#if defined(ENABLE_UNICODE_PATH_SUPPORT) && defined(_WIN32) + ONNXModelEditor(const std::wstring& model_path); +#endif + + /// \brief Creates an editor from a model stream. The stream is parsed and loaded + /// into the m_model_proto member variable. + /// + /// \param model_stream The stream containing the model. + /// \param model_path Path to the file containing the model. This information can be used + /// for ONNX external weights feature support. + ONNXModelEditor(std::istream& model_stream, const std::string& path = ""); /// \brief Modifies the in-memory representation of the model by setting /// custom input types for all inputs specified in the provided map. diff --git a/ngraph/frontend/onnx/frontend/src/frontend.cpp b/ngraph/frontend/onnx/frontend/src/frontend.cpp index 8ec3fdf9525..db7eeb7d094 100644 --- a/ngraph/frontend/onnx/frontend/src/frontend.cpp +++ b/ngraph/frontend/onnx/frontend/src/frontend.cpp @@ -4,14 +4,23 @@ #include #include +#include #include #include #include +#include #include +#include "onnx_common/onnx_model_validator.hpp" + using namespace ngraph; using namespace ngraph::frontend; +using VariantString = VariantWrapper; +using VariantWString = VariantWrapper; +using VariantIstreamPtr = VariantWrapper; +using VariantIstringstreamPtr = VariantWrapper; + extern "C" ONNX_FRONTEND_API FrontEndVersion GetAPIVersion() { return OV_FRONTEND_API_VERSION; } @@ -26,12 +35,39 @@ extern "C" ONNX_FRONTEND_API void* GetFrontEndData() { } InputModel::Ptr FrontEndONNX::load_impl(const std::vector>& variants) const { - NGRAPH_CHECK(variants.size() == 1, - "Only one parameter to load function is expected. Got " + std::to_string(variants.size())); - NGRAPH_CHECK(ov::is_type>(variants[0]), - "Parameter to load function need to be a std::string"); - auto path = ov::as_type_ptr>(variants[0])->get(); - return std::make_shared(path); + if (variants.size() == 0) { + return nullptr; + } + if (ov::is_type(variants[0])) { + const auto path = ov::as_type_ptr(variants[0])->get(); + return std::make_shared(path); + } +#if defined(ENABLE_UNICODE_PATH_SUPPORT) && defined(_WIN32) + if (ov::is_type(variants[0])) { + const auto path = ov::as_type_ptr(variants[0])->get(); + return std::make_shared(path); + } +#endif + std::istream* stream = nullptr; + if (ov::is_type(variants[0])) { + stream = ov::as_type_ptr(variants[0])->get(); + } else if (ov::is_type(variants[0])) { + stream = ov::as_type_ptr(variants[0])->get(); + } + if (stream != nullptr) { + if (variants.size() > 1 && ov::is_type(variants[1])) { + const auto path = ov::as_type_ptr(variants[1])->get(); + return std::make_shared(*stream, path); + } +#if defined(ENABLE_UNICODE_PATH_SUPPORT) && defined(_WIN32) + if (variants.size() > 1 && ov::is_type(variants[1])) { + const auto path = ov::as_type_ptr(variants[1])->get(); + return std::make_shared(*stream, path); + } +#endif + return std::make_shared(*stream); + } + return nullptr; } std::shared_ptr FrontEndONNX::convert(InputModel::Ptr model) const { @@ -49,3 +85,63 @@ std::shared_ptr FrontEndONNX::decode(InputModel::Ptr model) co NGRAPH_CHECK(model_onnx != nullptr, "Invalid input model"); return model_onnx->decode(); } + +std::string FrontEndONNX::get_name() const { + return "onnx"; +} + +namespace { +/** + * This helper struct uses RAII to rewind/reset the stream so that it points to the beginning + * of the underlying resource (string, file, and so on). It works similarly to std::lock_guard, + * which releases a mutex upon destruction. + * + * This ensures that the stream is always reset (exception, successful and unsuccessful + * model validation). + */ +struct StreamRewinder { + StreamRewinder(std::istream& stream) : m_stream(stream) { + m_stream.seekg(0, m_stream.beg); + } + ~StreamRewinder() { + m_stream.seekg(0, m_stream.beg); + } + +private: + std::istream& m_stream; +}; +} // namespace + +bool FrontEndONNX::supported_impl(const std::vector>& variants) const { + if (variants.size() == 0) { + return false; + } + std::ifstream model_stream; + if (ov::is_type(variants[0])) { + const auto path = ov::as_type_ptr(variants[0])->get(); + model_stream.open(path, std::ios::in | std::ifstream::binary); + } +#if defined(ENABLE_UNICODE_PATH_SUPPORT) && defined(_WIN32) + else if (ov::is_type(variants[0])) { + const auto path = ov::as_type_ptr(variants[0])->get(); + model_stream.open(path, std::ios::in | std::ifstream::binary); + } +#endif + if (model_stream.is_open()) { + model_stream.seekg(0, model_stream.beg); + const bool is_valid_model = onnx_common::is_valid_model(model_stream); + model_stream.close(); + return is_valid_model; + } + std::istream* stream = nullptr; + if (ov::is_type(variants[0])) { + stream = ov::as_type_ptr(variants[0])->get(); + } else if (ov::is_type(variants[0])) { + stream = ov::as_type_ptr(variants[0])->get(); + } + if (stream != nullptr) { + StreamRewinder rwd{*stream}; + return onnx_common::is_valid_model(*stream); + } + return false; +} diff --git a/ngraph/frontend/onnx/frontend/src/input_model.cpp b/ngraph/frontend/onnx/frontend/src/input_model.cpp index ae0a82f840e..9db743a74b9 100644 --- a/ngraph/frontend/onnx/frontend/src/input_model.cpp +++ b/ngraph/frontend/onnx/frontend/src/input_model.cpp @@ -5,15 +5,32 @@ #include "input_model.hpp" #include +#include #include "place.hpp" using namespace ngraph; using namespace ngraph::frontend; +NGRAPH_SUPPRESS_DEPRECATED_START + InputModelONNX::InputModelONNX(const std::string& path) : m_editor{std::make_shared(path)} {} +#if defined(ENABLE_UNICODE_PATH_SUPPORT) && defined(_WIN32) +InputModelONNX::InputModelONNX(const std::wstring& path) + : m_editor{std::make_shared(path)} {} +#endif + +InputModelONNX::InputModelONNX(std::istream& model_stream) + : m_editor{std::make_shared(model_stream)} {} + +InputModelONNX::InputModelONNX(std::istream& model_stream, const std::string& path) + : m_editor{std::make_shared(model_stream, path)} {} + +InputModelONNX::InputModelONNX(std::istream& model_stream, const std::wstring& path) + : InputModelONNX(model_stream, file_util::wstring_to_string(path)) {} + std::vector InputModelONNX::get_inputs() const { const auto& inputs = m_editor->model_inputs(); std::vector in_places; diff --git a/ngraph/frontend/onnx/frontend/src/input_model.hpp b/ngraph/frontend/onnx/frontend/src/input_model.hpp index 300b5a94d51..2ed2ff0e8e4 100644 --- a/ngraph/frontend/onnx/frontend/src/input_model.hpp +++ b/ngraph/frontend/onnx/frontend/src/input_model.hpp @@ -6,12 +6,21 @@ #include #include +#include namespace ngraph { namespace frontend { class InputModelONNX : public InputModel { public: InputModelONNX(const std::string& path); +#if defined(ENABLE_UNICODE_PATH_SUPPORT) && defined(_WIN32) + InputModelONNX(const std::wstring& path); +#endif + InputModelONNX(std::istream& model_stream); + // The path can be required even if the model is passed as a stream because it is necessary + // for ONNX external data feature + InputModelONNX(std::istream& model_stream, const std::string& path); + InputModelONNX(std::istream& model_stream, const std::wstring& path); std::vector get_inputs() const override; std::vector get_outputs() const override; diff --git a/ngraph/frontend/onnx/onnx_common/include/onnx_common/onnx_model_validator.hpp b/ngraph/frontend/onnx/onnx_common/include/onnx_common/onnx_model_validator.hpp new file mode 100644 index 00000000000..e41bb813459 --- /dev/null +++ b/ngraph/frontend/onnx/onnx_common/include/onnx_common/onnx_model_validator.hpp @@ -0,0 +1,14 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +#include + +namespace ngraph { +namespace onnx_common { + +bool is_valid_model(std::istream& model); +} // namespace onnx_common +} // namespace ngraph diff --git a/ngraph/frontend/onnx/onnx_common/include/onnx_common/parser.hpp b/ngraph/frontend/onnx/onnx_common/include/onnx_common/parser.hpp index 26675840afb..7310f150c5b 100644 --- a/ngraph/frontend/onnx/onnx_common/include/onnx_common/parser.hpp +++ b/ngraph/frontend/onnx/onnx_common/include/onnx_common/parser.hpp @@ -18,6 +18,9 @@ namespace onnx_common { /// /// \return The parsed in-memory representation of the ONNX model ONNX_NAMESPACE::ModelProto parse_from_file(const std::string& file_path); +#if defined(ENABLE_UNICODE_PATH_SUPPORT) && defined(_WIN32) +ONNX_NAMESPACE::ModelProto parse_from_file(const std::wstring& file_path); +#endif /// \brief Parses an ONNX model from a stream (representing for example a file) /// diff --git a/ngraph/frontend/onnx/onnx_common/src/onnx_model_validator.cpp b/ngraph/frontend/onnx/onnx_common/src/onnx_model_validator.cpp new file mode 100644 index 00000000000..82f2b3540fe --- /dev/null +++ b/ngraph/frontend/onnx/onnx_common/src/onnx_model_validator.cpp @@ -0,0 +1,219 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "onnx_common/onnx_model_validator.hpp" + +#include +#include +#include +#include +#include + +namespace detail { +namespace onnx { +enum Field { + IR_VERSION = 1, + PRODUCER_NAME = 2, + PRODUCER_VERSION = 3, + DOMAIN_ = 4, // DOMAIN collides with some existing symbol in MSVC thus - underscore + MODEL_VERSION = 5, + DOC_STRING = 6, + GRAPH = 7, + OPSET_IMPORT = 8, + METADATA_PROPS = 14, + TRAINING_INFO = 20 +}; + +enum WireType { VARINT = 0, BITS_64 = 1, LENGTH_DELIMITED = 2, START_GROUP = 3, END_GROUP = 4, BITS_32 = 5 }; + +// A PB key consists of a field number (defined in onnx.proto) and a type of data that follows this key +using PbKey = std::pair; + +// This pair represents a key found in the encoded model and optional size of the payload +// that follows the key (in bytes). The payload should be skipped for fast check purposes. +using ONNXField = std::pair; + +bool is_correct_onnx_field(const PbKey& decoded_key) { + static const std::map onnx_fields = { + {IR_VERSION, VARINT}, + {PRODUCER_NAME, LENGTH_DELIMITED}, + {PRODUCER_VERSION, LENGTH_DELIMITED}, + {DOMAIN_, LENGTH_DELIMITED}, + {MODEL_VERSION, VARINT}, + {DOC_STRING, LENGTH_DELIMITED}, + {GRAPH, LENGTH_DELIMITED}, + {OPSET_IMPORT, LENGTH_DELIMITED}, + {METADATA_PROPS, LENGTH_DELIMITED}, + {TRAINING_INFO, LENGTH_DELIMITED}, + }; + + if (!onnx_fields.count(static_cast(decoded_key.first))) { + return false; + } + + return onnx_fields.at(static_cast(decoded_key.first)) == static_cast(decoded_key.second); +} + +/** + * Only 7 bits in each component of a varint count in this algorithm. The components form + * a decoded number when they are concatenated bitwise in reverse order. For example: + * bytes = [b1, b2, b3, b4] + * varint = b4 ++ b3 ++ b2 ++ b1 <== only 7 bits of each byte should be extracted before concat + * + * b1 b2 + * bytes = [00101100, 00000010] + * b2 b1 + * varint = 0000010 ++ 0101100 = 100101100 => decimal: 300 + * Each consecutive varint byte needs to be left-shifted "7 x its position in the vector" + * and bitwise added to the accumulator afterward. + */ +uint32_t varint_bytes_to_number(const std::vector& bytes) { + uint32_t accumulator = 0u; + + for (size_t i = 0; i < bytes.size(); ++i) { + uint32_t b = bytes[i]; + b <<= 7 * i; + accumulator |= b; + } + + return accumulator; +} + +uint32_t decode_varint(std::istream& model) { + std::vector bytes; + // max 4 bytes for a single value because this function returns a 32-bit long decoded varint + const size_t MAX_VARINT_BYTES = 4u; + // optimization to avoid allocations during push_back calls + bytes.reserve(MAX_VARINT_BYTES); + + char key_component = 0; + model.get(key_component); + + // keep reading all bytes which have the MSB on from the stream + while (key_component & 0x80 && bytes.size() < MAX_VARINT_BYTES) { + // drop the most significant bit + const char component = key_component & ~0x80; + bytes.push_back(component); + model.get(key_component); + } + // add the last byte - the one with MSB off + bytes.push_back(key_component); + + return varint_bytes_to_number(bytes); +} + +PbKey decode_key(const char key) { + // 3 least significant bits + const char wire_type = key & 0b111; + // remaining bits + const char field_number = key >> 3; + return {field_number, wire_type}; +} + +ONNXField decode_next_field(std::istream& model) { + char key = 0; + model.get(key); + + const auto decoded_key = decode_key(key); + + if (!is_correct_onnx_field(decoded_key)) { + throw std::runtime_error{"Incorrect field detected in the processed model"}; + } + + const auto onnx_field = static_cast(decoded_key.first); + + switch (decoded_key.second) { + case VARINT: { + // the decoded varint is the payload in this case but its value does not matter + // in the fast check process so you can discard it + decode_varint(model); + return {onnx_field, 0}; + } + case LENGTH_DELIMITED: + // the varint following the key determines the payload length + return {onnx_field, decode_varint(model)}; + case BITS_64: + return {onnx_field, 8}; + case BITS_32: + return {onnx_field, 4}; + case START_GROUP: + case END_GROUP: + throw std::runtime_error{"StartGroup and EndGroup are not used in ONNX models"}; + default: + throw std::runtime_error{"Unknown WireType encountered in the model"}; + } +} + +inline void skip_payload(std::istream& model, uint32_t payload_size) { + model.seekg(payload_size, std::ios::cur); +} +} // namespace onnx + +namespace prototxt { +bool contains_onnx_model_keys(const std::string& model, const size_t expected_keys_num) { + size_t keys_found = 0; + + const std::vector onnx_keys = {"ir_version", + "producer_name", + "producer_version", + "domain", + "model_version", + "doc_string", + "graph", + "opset_import", + "metadata_props", + "training_info"}; + + size_t search_start_pos = 0; + + while (keys_found < expected_keys_num) { + const auto key_finder = [&search_start_pos, &model](const std::string& key) { + const auto key_pos = model.find(key, search_start_pos); + if (key_pos != model.npos) { + // don't search from the beginning each time + search_start_pos = key_pos + key.size(); + return true; + } else { + return false; + } + }; + + const auto found = std::any_of(std::begin(onnx_keys), std::end(onnx_keys), key_finder); + if (!found) { + break; + } else { + ++keys_found; + } + } + + return keys_found == expected_keys_num; +} +} // namespace prototxt +} // namespace detail + +namespace ngraph { +namespace onnx_common { +bool is_valid_model(std::istream& model) { + // the model usually starts with a 0x08 byte indicating the ir_version value + // so this checker expects at least 2 valid ONNX keys to be found in the validated model + const unsigned int EXPECTED_FIELDS_FOUND = 2u; + unsigned int valid_fields_found = 0u; + try { + while (!model.eof() && valid_fields_found < EXPECTED_FIELDS_FOUND) { + const auto field = detail::onnx::decode_next_field(model); + + ++valid_fields_found; + + if (field.second > 0) { + detail::onnx::skip_payload(model, field.second); + } + } + + return valid_fields_found == EXPECTED_FIELDS_FOUND; + } catch (...) { + return false; + } +} +} // namespace onnx_common +} // namespace ngraph diff --git a/ngraph/frontend/onnx/onnx_common/src/parser.cpp b/ngraph/frontend/onnx/onnx_common/src/parser.cpp index 03fbc358f22..3cb7f17ebd1 100644 --- a/ngraph/frontend/onnx/onnx_common/src/parser.cpp +++ b/ngraph/frontend/onnx/onnx_common/src/parser.cpp @@ -8,6 +8,8 @@ #include #include +#include + #include "ngraph/except.hpp" namespace ngraph { @@ -19,9 +21,27 @@ ONNX_NAMESPACE::ModelProto parse_from_file(const std::string& file_path) { throw ngraph_error("Could not open the file: " + file_path); }; - return parse_from_istream(file_stream); + auto model_proto = parse_from_istream(file_stream); + file_stream.close(); + return model_proto; } +#if defined(ENABLE_UNICODE_PATH_SUPPORT) && defined(_WIN32) +ONNX_NAMESPACE::ModelProto parse_from_file(const std::wstring& file_path) { + std::ifstream file_stream{file_path, std::ios::in | std::ios::binary}; + + if (!file_stream.is_open()) { + NGRAPH_SUPPRESS_DEPRECATED_START + throw ngraph_error("Could not open the file: " + file_util::wstring_to_string(file_path)); + NGRAPH_SUPPRESS_DEPRECATED_END + }; + + auto model_proto = parse_from_istream(file_stream); + file_stream.close(); + return model_proto; +} +#endif + ONNX_NAMESPACE::ModelProto parse_from_istream(std::istream& model_stream) { if (!model_stream.good()) { model_stream.clear(); diff --git a/ngraph/python/tests/test_frontend/test_frontend_onnx.py b/ngraph/python/tests/test_frontend/test_frontend_onnx.py index 4290c7de2ce..81bb89217fe 100644 --- a/ngraph/python/tests/test_frontend/test_frontend_onnx.py +++ b/ngraph/python/tests/test_frontend/test_frontend_onnx.py @@ -96,3 +96,18 @@ def test_decode_and_convert(): b = np.array([[2, 3], [4, 5]], dtype=np.float32) expected = np.array([[1.5, 5], [10.5, 18]], dtype=np.float32) run_function(decoded_function, a, b, expected=[expected]) + + +def test_load_by_model(): + skip_if_onnx_frontend_is_disabled() + + fe = fem.load_by_model(onnx_model_filename) + assert fe + assert fe.get_name() == "onnx" + model = fe.load(onnx_model_filename) + assert model + decoded_function = fe.decode(model) + assert decoded_function + + assert not fem.load_by_model("test.xx") + assert not fem.load_by_model("onnx.yy") diff --git a/ngraph/test/frontend/CMakeLists.txt b/ngraph/test/frontend/CMakeLists.txt index 67ffb5a992a..901d917edc7 100644 --- a/ngraph/test/frontend/CMakeLists.txt +++ b/ngraph/test/frontend/CMakeLists.txt @@ -7,6 +7,10 @@ if (NGRAPH_PDPD_FRONTEND_ENABLE) add_subdirectory(paddlepaddle) endif() +if (NGRAPH_ONNX_FRONTEND_ENABLE) + add_subdirectory(onnx) +endif() + set(SRC ${CMAKE_CURRENT_SOURCE_DIR}/mock_frontend.cpp) add_library(mock1_ngraph_frontend SHARED ${SRC}) diff --git a/ngraph/test/frontend/onnx/CMakeLists.txt b/ngraph/test/frontend/onnx/CMakeLists.txt new file mode 100644 index 00000000000..d78a8ed4274 --- /dev/null +++ b/ngraph/test/frontend/onnx/CMakeLists.txt @@ -0,0 +1,26 @@ +# Copyright (C) 2018-2021 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 +# + +set(TARGET_NAME "onnx_frontend_tests") + +file(GLOB_RECURSE SRC ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp) + +add_executable(${TARGET_NAME} ${SRC}) + +target_link_libraries(${TARGET_NAME} PRIVATE frontend_shared_test_classes) + +add_clang_format_target(${TARGET_NAME}_clang FOR_TARGETS ${TARGET_NAME}) + +install(TARGETS ${TARGET_NAME} + RUNTIME DESTINATION tests + COMPONENT tests + EXCLUDE_FROM_ALL) + +set(TEST_ONNX_MODELS_DIRNAME ${TEST_MODEL_ZOO}/ngraph/models/onnx) +target_compile_definitions(${TARGET_NAME} PRIVATE -D TEST_ONNX_MODELS_DIRNAME=\"${TEST_ONNX_MODELS_DIRNAME}/\") +set(MANIFEST ${CMAKE_CURRENT_SOURCE_DIR}/unit_test.manifest) +target_compile_definitions(${TARGET_NAME} PRIVATE -D MANIFEST=\"${MANIFEST}\") + +add_dependencies(${TARGET_NAME} onnx_ngraph_frontend) +add_dependencies(${TARGET_NAME} test_model_zoo) diff --git a/ngraph/test/frontend/onnx/load_from.cpp b/ngraph/test/frontend/onnx/load_from.cpp new file mode 100644 index 00000000000..4d98644bc72 --- /dev/null +++ b/ngraph/test/frontend/onnx/load_from.cpp @@ -0,0 +1,52 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// +#include "load_from.hpp" + +#include + +#include +#include + +#include "onnx_utils.hpp" +#include "utils.hpp" + +using namespace ngraph; +using namespace ngraph::frontend; + +using ONNXLoadTest = FrontEndLoadFromTest; + +static LoadFromFEParam getTestData() { + LoadFromFEParam res; + res.m_frontEndName = ONNX_FE; + res.m_modelsPath = std::string(TEST_ONNX_MODELS_DIRNAME); + res.m_file = "external_data/external_data.onnx"; + res.m_stream = "add_abc.onnx"; + return res; +} + +TEST_P(FrontEndLoadFromTest, testLoadFromStreamAndPassPath) { + NGRAPH_SUPPRESS_DEPRECATED_START + const auto path = file_util::path_join(TEST_ONNX_MODELS_DIRNAME, "external_data/external_data.onnx"); + NGRAPH_SUPPRESS_DEPRECATED_END + std::ifstream ifs(path, std::ios::in | std::ios::binary); + ASSERT_TRUE(ifs.is_open()); + std::istream* is = &ifs; + std::vector frontends; + FrontEnd::Ptr fe; + ASSERT_NO_THROW(frontends = m_fem.get_available_front_ends()); + ASSERT_NO_THROW(m_frontEnd = m_fem.load_by_model(is)); + ASSERT_NE(m_frontEnd, nullptr); + + ASSERT_NO_THROW(m_inputModel = m_frontEnd->load(is, path)); + ASSERT_NE(m_inputModel, nullptr); + + std::shared_ptr function; + ASSERT_NO_THROW(function = m_frontEnd->convert(m_inputModel)); + ASSERT_NE(function, nullptr); +} + +INSTANTIATE_TEST_SUITE_P(ONNXLoadTest, + FrontEndLoadFromTest, + ::testing::Values(getTestData()), + FrontEndLoadFromTest::getTestCaseName); diff --git a/ngraph/test/frontend/onnx/main.cpp b/ngraph/test/frontend/onnx/main.cpp new file mode 100644 index 00000000000..3f72a06cf5d --- /dev/null +++ b/ngraph/test/frontend/onnx/main.cpp @@ -0,0 +1,32 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include +#include + +#include "gtest/gtest.h" +#include "utils.hpp" + +std::string get_disabled_tests() { + std::string result = "-"; + const std::string manifest_path = MANIFEST; + std::ifstream manifest_stream(manifest_path); + std::string line; + while (std::getline(manifest_stream, line)) { + if (line.empty()) { + continue; + } + if (line.size() > 0 && line[0] == '#') { + continue; + } + result += ":" + line; + } + manifest_stream.close(); + return result; +} + +int main(int argc, char** argv) { + ::testing::GTEST_FLAG(filter) += get_disabled_tests(); + return FrontEndTestUtils::run_tests(argc, argv); +} diff --git a/ngraph/test/frontend/onnx/onnx_utils.hpp b/ngraph/test/frontend/onnx/onnx_utils.hpp new file mode 100644 index 00000000000..86ce5c94ee5 --- /dev/null +++ b/ngraph/test/frontend/onnx/onnx_utils.hpp @@ -0,0 +1,9 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +#include + +static const std::string ONNX_FE = "onnx_experimental"; diff --git a/ngraph/test/frontend/onnx/unit_test.manifest b/ngraph/test/frontend/onnx/unit_test.manifest new file mode 100644 index 00000000000..790acbe661f --- /dev/null +++ b/ngraph/test/frontend/onnx/unit_test.manifest @@ -0,0 +1,3 @@ +# external weights are not supported for ONNX Frontend +ONNXLoadTest/FrontEndLoadFromTest.testLoadFromTwoFiles/onnx_experimental +ONNXLoadTest/FrontEndLoadFromTest.testLoadFromTwoStreams/onnx_experimental diff --git a/ngraph/test/onnx/onnx_editor.cpp b/ngraph/test/onnx/onnx_editor.cpp index 1e7e36f5dc5..590dc7e9350 100644 --- a/ngraph/test/onnx/onnx_editor.cpp +++ b/ngraph/test/onnx/onnx_editor.cpp @@ -1183,6 +1183,21 @@ NGRAPH_TEST(onnx_editor, values__append_two_initializers_mixed_types) { test_case.run(); } +NGRAPH_TEST(onnx_editor, read_model_from_stream) { + std::string path = file_util::path_join(SERIALIZED_ZOO, "onnx/external_data/external_data.onnx"); + std::ifstream stream{path, std::ios::in | std::ios::binary}; + ASSERT_TRUE(stream.is_open()); + ONNXModelEditor editor{stream, path}; + + auto test_case = test::TestCase(editor.get_function()); + test_case.add_input({1.f, 2.f, 3.f, 4.f}); + test_case.add_expected_output(Shape{2, 2}, {3.f, 6.f, 9.f, 12.f}); + + test_case.run(); + + stream.close(); +} + NGRAPH_TEST(onnx_editor, combined__cut_and_replace_shape) { ONNXModelEditor editor{file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph__inception_head.onnx")}; diff --git a/ngraph/test/onnx/onnx_import_library.cpp b/ngraph/test/onnx/onnx_import_library.cpp index 2180feeac17..61df4cf84e3 100644 --- a/ngraph/test/onnx/onnx_import_library.cpp +++ b/ngraph/test/onnx/onnx_import_library.cpp @@ -15,7 +15,7 @@ NGRAPH_TEST(onnx, check_ir_version_support) { // It appears you've changed the ONNX library version used by nGraph. Please update the value // tested below to make sure it equals the current IR_VERSION enum value defined in ONNX headers // - // You should also check the onnx_reader/onnx_model_validator.cpp file and make sure that + // You should also check the onnx_common/src/onnx_model_validator.cpp file and make sure that // the details::onnx::is_correct_onnx_field() handles any new fields added in the new release // of the ONNX library. Make sure to update the "Field" enum and the function mentioned above. // diff --git a/scripts/deployment_manager/configs/darwin.json b/scripts/deployment_manager/configs/darwin.json index f3581e31cba..09be8f75ed9 100644 --- a/scripts/deployment_manager/configs/darwin.json +++ b/scripts/deployment_manager/configs/darwin.json @@ -21,7 +21,6 @@ "deployment_tools/inference_engine/lib/intel64/libinference_engine_transformations.dylib", "deployment_tools/inference_engine/lib/intel64/libinference_engine_preproc.so", "deployment_tools/inference_engine/lib/intel64/libinference_engine_ir_reader.so", - "deployment_tools/inference_engine/lib/intel64/libinference_engine_onnx_reader.so", "deployment_tools/inference_engine/lib/intel64/libinference_engine_c_api.dylib", "deployment_tools/inference_engine/lib/intel64/libAutoPlugin.so", "deployment_tools/inference_engine/lib/intel64/libHeteroPlugin.so", diff --git a/scripts/deployment_manager/configs/linux.json b/scripts/deployment_manager/configs/linux.json index fd4600abb8e..0c39eeb82a4 100644 --- a/scripts/deployment_manager/configs/linux.json +++ b/scripts/deployment_manager/configs/linux.json @@ -27,7 +27,6 @@ "deployment_tools/inference_engine/lib/intel64/libinference_engine_transformations.so", "deployment_tools/inference_engine/lib/intel64/libinference_engine_preproc.so", "deployment_tools/inference_engine/lib/intel64/libinference_engine_ir_reader.so", - "deployment_tools/inference_engine/lib/intel64/libinference_engine_onnx_reader.so", "deployment_tools/inference_engine/lib/intel64/libinference_engine_c_api.so", "deployment_tools/inference_engine/lib/intel64/libAutoPlugin.so", "deployment_tools/inference_engine/lib/intel64/libHeteroPlugin.so", diff --git a/scripts/deployment_manager/configs/windows.json b/scripts/deployment_manager/configs/windows.json index ba95c29e244..14ceedbff8a 100644 --- a/scripts/deployment_manager/configs/windows.json +++ b/scripts/deployment_manager/configs/windows.json @@ -21,7 +21,6 @@ "deployment_tools/inference_engine/bin/intel64/Release/inference_engine_transformations.dll", "deployment_tools/inference_engine/bin/intel64/Release/inference_engine_preproc.dll", "deployment_tools/inference_engine/bin/intel64/Release/inference_engine_ir_reader.dll", - "deployment_tools/inference_engine/bin/intel64/Release/inference_engine_onnx_reader.dll", "deployment_tools/inference_engine/bin/intel64/Release/inference_engine_c_api.dll", "deployment_tools/inference_engine/bin/intel64/Release/AutoPlugin.dll", "deployment_tools/inference_engine/lib/intel64/Release/HeteroPlugin.dll", From 9ee57fe2333f3ebf0925df115d42cc40647db31b Mon Sep 17 00:00:00 2001 From: Elizaveta Lobanova Date: Thu, 26 Aug 2021 12:56:39 +0300 Subject: [PATCH 48/76] [GNA] Fixed search of the next layer for FQ (#7243) --- .../gna_plugin/optimizer/gna_pass_manager.cpp | 4 +- .../fq_with_multiple_out_connections.cpp | 107 ++++++++++++++++++ 2 files changed, 109 insertions(+), 2 deletions(-) create mode 100644 inference-engine/tests/functional/plugin/gna/pass_tests/fq_with_multiple_out_connections.cpp diff --git a/inference-engine/src/gna_plugin/optimizer/gna_pass_manager.cpp b/inference-engine/src/gna_plugin/optimizer/gna_pass_manager.cpp index b7507e8fbf9..2ec18d3c92b 100644 --- a/inference-engine/src/gna_plugin/optimizer/gna_pass_manager.cpp +++ b/inference-engine/src/gna_plugin/optimizer/gna_pass_manager.cpp @@ -1841,8 +1841,8 @@ void FuseFQIntoWeightsPass::run() { layers_connected_to_fq_count = inputTo.size(); } for (int index = 0; index < layers_connected_to_fq_count; index++) { - auto weightableLayer = CNNNetGetNextLayerSkipCertain(layerBeforeWeightable, 0, index, isNonFunctional).first; - if (!LayerInfo(weightableLayer).isWeightable()) { + auto weightableLayer = CNNNetCheckNextLayerSkipCertain(layerBeforeWeightable, 0, index, true, isNonFunctional).first; + if (!weightableLayer || !LayerInfo(weightableLayer).isWeightable()) { continue; } if (weightableLayer->insData.size() < 2) { diff --git a/inference-engine/tests/functional/plugin/gna/pass_tests/fq_with_multiple_out_connections.cpp b/inference-engine/tests/functional/plugin/gna/pass_tests/fq_with_multiple_out_connections.cpp new file mode 100644 index 00000000000..b0453a20430 --- /dev/null +++ b/inference-engine/tests/functional/plugin/gna/pass_tests/fq_with_multiple_out_connections.cpp @@ -0,0 +1,107 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include +#include +#include +#include +#include + +#include + +#include "common_test_utils/common_utils.hpp" +#include "functional_test_utils/plugin_cache.hpp" +#include "shared_test_classes/base/layer_test_utils.hpp" +#include "functional_test_utils/blob_utils.hpp" +#include "ngraph_functions/utils/ngraph_helpers.hpp" +#include "ngraph_functions/builders.hpp" + +#include "ngraph_functions/pass/convert_prc.hpp" + +typedef std::tuple< + InferenceEngine::Precision, // Network Precision + std::string, // Target Device + std::map // Configuration +> fqWithMultipleOutConnectionsParams; + +namespace LayerTestsDefinitions { + +class FQWithMultipleOutConnections : public testing::WithParamInterface, + public LayerTestsUtils::LayerTestsCommon { +public: + static std::string getTestCaseName(testing::TestParamInfo obj) { + InferenceEngine::Precision netPrecision; + std::string targetDevice; + std::map configuration; + std::tie(netPrecision, targetDevice, configuration) = obj.param; + + std::ostringstream result; + result << "netPRC=" << netPrecision.name() << "_"; + result << "targetDevice=" << targetDevice << "_"; + for (auto const& configItem : configuration) { + result << "_configItem=" << configItem.first << "_" << configItem.second; + } + + return result.str(); + } + +protected: + void SetUp() override { + InferenceEngine::Precision netPrecision; + + std::tie(netPrecision, targetDevice, configuration) = this->GetParam(); + auto ngPrc = FuncTestUtils::PrecisionUtils::convertIE2nGraphPrc(netPrecision); + + const ngraph::Shape shape = {1, 128}; + auto params = ngraph::builder::makeParams(ngPrc, {shape}); + + auto pattern1 = std::make_shared(ngraph::element::Type_t::i64, ngraph::Shape{3}, + ngraph::Shape{1, 2, 64}); + auto reshape1 = std::make_shared(params[0], pattern1, false); + + auto relu1 = std::make_shared(reshape1); + + auto lowNode = ngraph::builder::makeConstant(ngPrc, {1}, { -10.0f }); + auto highNode = ngraph::builder::makeConstant(ngPrc, {1}, { 10.0f }); + auto fq = std::make_shared(relu1, lowNode, highNode, lowNode, highNode, + std::numeric_limits::max()); + + auto pattern2 = std::make_shared(ngraph::element::Type_t::i64, ngraph::Shape{shape.size()}, + shape); + auto reshape2 = std::make_shared(fq, pattern2, false); + + auto relu2 = std::make_shared(fq); + auto reshape3 = std::make_shared(relu2, pattern2, false); + + ngraph::ResultVector results{std::make_shared(reshape2), + std::make_shared(reshape3)}; + function = std::make_shared(results, params, "FQFusionWithMultipleWeights"); + } +}; + +TEST_P(FQWithMultipleOutConnections, CompareWithRefImpl) { + Run(); +}; + +const std::vector netPrecisions = { + InferenceEngine::Precision::FP32, + InferenceEngine::Precision::FP16 +}; + +const std::vector> configs = { + { + {"GNA_DEVICE_MODE", "GNA_SW_EXACT"}, + }, + { + {"GNA_DEVICE_MODE", "GNA_SW_FP32"}, + } +}; + +INSTANTIATE_TEST_SUITE_P(smoke_fq_fusion, FQWithMultipleOutConnections, + ::testing::Combine( + ::testing::ValuesIn(netPrecisions), + ::testing::Values(CommonTestUtils::DEVICE_GNA), + ::testing::ValuesIn(configs)), + FQWithMultipleOutConnections::getTestCaseName); +} // namespace LayerTestsDefinitions \ No newline at end of file From 4ef700c6e4bd8235802b35bcdb7faaeea152d6a4 Mon Sep 17 00:00:00 2001 From: Anton Voronov Date: Thu, 26 Aug 2021 13:38:24 +0300 Subject: [PATCH 49/76] [CPU] fixed convolution outputShape in ConvDWConv fusing (#7239) --- inference-engine/src/mkldnn_plugin/mkldnn_graph.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/inference-engine/src/mkldnn_plugin/mkldnn_graph.cpp b/inference-engine/src/mkldnn_plugin/mkldnn_graph.cpp index 2a41d514b8f..eb6f5fc523b 100644 --- a/inference-engine/src/mkldnn_plugin/mkldnn_graph.cpp +++ b/inference-engine/src/mkldnn_plugin/mkldnn_graph.cpp @@ -1028,6 +1028,8 @@ void MKLDNNGraph::DropDWConvNode(const MKLDNNNodePtr &node) { auto parentConv = parentConvEdge->getParent(); if (!parentConv) return; + parentConv->outputShapes[0] = node->outputShapes[0]; + for (size_t i = 0; i < 1; i++) { auto p_edge = parents[i].lock(); if (!p_edge) continue; From 81c8cd711bb9f8dc48e5f288e77dc0d80cedebd8 Mon Sep 17 00:00:00 2001 From: Piotr Szmelczynski Date: Fri, 27 Aug 2021 05:55:19 +0200 Subject: [PATCH 50/76] Revise logical not (#6942) * update spec * remove backend tests and create op_reference test * add logicalNot to constants * add NGRAPH CHECK for number of inputs and outputs * create type_prop tests * create visitor test * add type_op and visitor tests to CMakeLists * remove backend test from CMakeList * update T to T_BOOL * update outputs part in spec * fix type in the spec * fixed conflicts in CMakeList * update ReferenceLogicalLayerTest to also work with unary logical operator * update logical_not op_reference test to use ReferenceLogicalLayerTest * fix style * fix style * resolve conflict * resolve conflict * remove typo * fix style * Update ReferenceLogicalLayerTest class tto take input as a vector * Create makeLogical function that takes ParameterVector as parameter * update op_reference logical tests to take input as a vector * Replace elem_type with input.type * update getTestCaseName method --- docs/ops/logical/LogicalNot_1.md | 39 ++++++------ .../tests/functional/op_reference/logical.hpp | 34 ++++++----- .../functional/op_reference/logical_and.cpp | 12 ++-- .../functional/op_reference/logical_not.cpp | 37 ++++++++++++ .../functional/op_reference/logical_or.cpp | 12 ++-- .../functional/op_reference/logical_xor.cpp | 12 ++-- .../layer_tests_summary/utils/constants.py | 3 +- .../include/ngraph_functions/builders.hpp | 3 + .../ngraph_functions/src/logical.cpp | 19 +++++- ngraph/core/src/op/not.cpp | 2 + ngraph/test/CMakeLists.txt | 3 +- ngraph/test/backend/logical_not.in.cpp | 59 ------------------- ngraph/test/type_prop/logical_not.cpp | 49 +++++++++++++++ ngraph/test/visitors/op/logical_not.cpp | 9 +++ 14 files changed, 179 insertions(+), 114 deletions(-) create mode 100644 docs/template_plugin/tests/functional/op_reference/logical_not.cpp delete mode 100644 ngraph/test/backend/logical_not.in.cpp create mode 100644 ngraph/test/type_prop/logical_not.cpp create mode 100644 ngraph/test/visitors/op/logical_not.cpp diff --git a/docs/ops/logical/LogicalNot_1.md b/docs/ops/logical/LogicalNot_1.md index 0552da02c7b..9c5f35081cc 100644 --- a/docs/ops/logical/LogicalNot_1.md +++ b/docs/ops/logical/LogicalNot_1.md @@ -6,31 +6,32 @@ **Short description**: *LogicalNot* performs element-wise logical negation operation with given tensor. -**Attributes**: - - No attributes available. - -**Inputs** - -* **1**: An tensor of type *T*. **Required.** - -**Outputs** - -* **1**: The result of element-wise logical negation operation. A tensor of type *T*. - -**Types** - -* *T*: boolean type. - -*LogicalNot* does the following with the input tensor *a*: +**Detailed description**: *LogicalNot* performs element-wise logical negation operation with given tensor, based on the following mathematical formula: \f[ a_{i} = \lnot a_{i} \f] -**Examples** +**Attributes**: *LogicalNot* operation has no attributes. -*Example 1* +**Inputs** + +* **1**: A tensor of type *T_BOOL* and arbitrary shape. **Required.** + +**Outputs** + +* **1**: The result of element-wise logical negation operation. A tensor of type *T_BOOL* and the same shape as input tensor. + +**Types** + +* *T_BOOL*: `boolean`. + +\f[ +a_{i} = \lnot a_{i} +\f] + + +**Example** ```xml diff --git a/docs/template_plugin/tests/functional/op_reference/logical.hpp b/docs/template_plugin/tests/functional/op_reference/logical.hpp index adf8e22f957..ee681f36141 100644 --- a/docs/template_plugin/tests/functional/op_reference/logical.hpp +++ b/docs/template_plugin/tests/functional/op_reference/logical.hpp @@ -18,15 +18,13 @@ namespace LogicalOpsRefTestDefinitions { struct RefLogicalParams { ngraph::helpers::LogicalTypes opType; - Tensor input1; - Tensor input2; + std::vector inputs; Tensor expected; }; struct Builder : ParamsBuilder { REFERENCE_TESTS_ADD_SET_PARAM(Builder, opType); - REFERENCE_TESTS_ADD_SET_PARAM(Builder, input1); - REFERENCE_TESTS_ADD_SET_PARAM(Builder, input2); + REFERENCE_TESTS_ADD_SET_PARAM(Builder, inputs); REFERENCE_TESTS_ADD_SET_PARAM(Builder, expected); }; @@ -34,28 +32,34 @@ class ReferenceLogicalLayerTest : public testing::TestWithParam& obj) { const auto& param = obj.param; std::ostringstream result; result << "LogicalType=" << param.opType << "_"; - result << "inpt_shape1=" << param.input1.shape << "_"; - result << "inpt_shape2=" << param.input2.shape << "_"; - result << "iType=" << param.input1.type << "_"; + for (size_t i =0; i< param.inputs.size(); i++) { + const auto input = param.inputs[i]; + result << "inpt_shape" << i << "=" << input.shape << "_"; + result << "inpt_type" << i << "=" << input.type << "_"; + } result << "oType=" << param.expected.type; return result.str(); } private: - static std::shared_ptr CreateFunction(ngraph::helpers::LogicalTypes op_type, const ngraph::PartialShape& input_shape1, - const ngraph::PartialShape& input_shape2, const ngraph::element::Type& elem_type) { - const auto in1 = std::make_shared(elem_type, input_shape1); - const auto in2 = std::make_shared(elem_type, input_shape2); - const auto logical_op = ngraph::builder::makeLogical(in1, in2, op_type); - return std::make_shared(ngraph::NodeVector {logical_op}, ngraph::ParameterVector {in1, in2}); + static std::shared_ptr CreateFunction(ngraph::helpers::LogicalTypes op_type, const std::vector& inputs) { + ngraph::ParameterVector params_vec; + for (auto& input : inputs) { + params_vec.push_back(std::make_shared(input.type, input.shape)); + } + + const auto logical_op = ngraph::builder::makeLogical(params_vec, op_type); + return std::make_shared(ngraph::NodeVector {logical_op}, ngraph::ParameterVector {params_vec}); } }; } // namespace LogicalOpsRefTestDefinitions diff --git a/docs/template_plugin/tests/functional/op_reference/logical_and.cpp b/docs/template_plugin/tests/functional/op_reference/logical_and.cpp index 0f19bbe50b4..0d1db90e21a 100644 --- a/docs/template_plugin/tests/functional/op_reference/logical_and.cpp +++ b/docs/template_plugin/tests/functional/op_reference/logical_and.cpp @@ -24,18 +24,18 @@ std::vector generateLogicalParams() { std::vector logicalParams { Builder {} .opType(LogicalTypes::LOGICAL_AND) - .input1({{2, 2}, element::boolean, std::vector {true, false, true, false}}) - .input2({{2, 2}, element::boolean, std::vector {false, true, true, false}}) + .inputs({{{2, 2}, element::boolean, std::vector {true, false, true, false}}, + {{2, 2}, element::boolean, std::vector {false, true, true, false}}}) .expected({{2, 2}, element::boolean, std::vector {false, false, true, false}}), Builder {} .opType(LogicalTypes::LOGICAL_AND) - .input1({{2, 1, 2, 1}, element::boolean, std::vector {true, false, true, false}}) - .input2({{1, 1, 2, 1}, element::boolean, std::vector {true, false}}) + .inputs({{{2, 1, 2, 1}, element::boolean, std::vector {true, false, true, false}}, + {{1, 1, 2, 1}, element::boolean, std::vector {true, false}}}) .expected({{2, 1, 2, 1}, element::boolean, std::vector {true, false, true, false}}), Builder {} .opType(LogicalTypes::LOGICAL_AND) - .input1({{3, 4}, element::boolean, std::vector {true, true, true, true, true, false, true, false, false, true, true, true}}) - .input2({{3, 4}, element::boolean, std::vector {true, true, true, true, true, false, true, false, false, true, true, false}}) + .inputs({{{3, 4}, element::boolean, std::vector {true, true, true, true, true, false, true, false, false, true, true, true}}, + {{3, 4}, element::boolean, std::vector {true, true, true, true, true, false, true, false, false, true, true, false}}}) .expected({{3, 4}, element::boolean, std::vector {true, true, true, true, true, false, true, false, false, true, true, false}})}; return logicalParams; } diff --git a/docs/template_plugin/tests/functional/op_reference/logical_not.cpp b/docs/template_plugin/tests/functional/op_reference/logical_not.cpp new file mode 100644 index 00000000000..3bcfa3c6ba8 --- /dev/null +++ b/docs/template_plugin/tests/functional/op_reference/logical_not.cpp @@ -0,0 +1,37 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include + +#include +#include +#include +#include +#include + +#include "logical.hpp" + +using namespace ngraph; +using namespace InferenceEngine; +using LogicalTypes = ngraph::helpers::LogicalTypes; + +namespace reference_tests { +namespace LogicalOpsRefTestDefinitions { +namespace { + +std::vector generateLogicalParams() { + std::vector logicalParams { + Builder {} + .opType(LogicalTypes::LOGICAL_NOT) + .inputs({{{2, 2}, element::boolean, std::vector {true, false, true, false}}}) + .expected({{2, 2}, element::boolean, std::vector {false, true, false, true}})}; + return logicalParams; +} + +INSTANTIATE_TEST_SUITE_P(smoke_LogicalNot_With_Hardcoded_Refs, ReferenceLogicalLayerTest, ::testing::ValuesIn(generateLogicalParams()), + ReferenceLogicalLayerTest::getTestCaseName); + +} // namespace +} // namespace LogicalOpsRefTestDefinitions +} // namespace reference_tests diff --git a/docs/template_plugin/tests/functional/op_reference/logical_or.cpp b/docs/template_plugin/tests/functional/op_reference/logical_or.cpp index 9bd4c61539f..e8c28f24468 100644 --- a/docs/template_plugin/tests/functional/op_reference/logical_or.cpp +++ b/docs/template_plugin/tests/functional/op_reference/logical_or.cpp @@ -24,18 +24,18 @@ std::vector generateLogicalParams() { std::vector logicalParams { Builder {} .opType(LogicalTypes::LOGICAL_OR) - .input1({{2, 2}, element::boolean, std::vector {true, false, true, false}}) - .input2({{2, 2}, element::boolean, std::vector {false, true, true, false}}) + .inputs({{{2, 2}, element::boolean, std::vector {true, false, true, false}}, + {{2, 2}, element::boolean, std::vector {false, true, true, false}}}) .expected({{2, 2}, element::boolean, std::vector {true, true, true, false}}), Builder {} .opType(LogicalTypes::LOGICAL_OR) - .input1({{2, 1, 2, 1}, element::boolean, std::vector {true, false, true, false}}) - .input2({{1, 1, 2, 1}, element::boolean, std::vector {true, false}}) + .inputs({{{2, 1, 2, 1}, element::boolean, std::vector {true, false, true, false}}, + {{1, 1, 2, 1}, element::boolean, std::vector {true, false}}}) .expected({{2, 1, 2, 1}, element::boolean, std::vector {true, false, true, false}}), Builder {} .opType(LogicalTypes::LOGICAL_OR) - .input1({{3, 4}, element::boolean, std::vector {true, true, true, true, true, false, true, false, false, true, true, true}}) - .input2({{3, 4}, element::boolean, std::vector {true, true, true, true, true, true, true, false, false, true, true, false}}) + .inputs({{{3, 4}, element::boolean, std::vector {true, true, true, true, true, false, true, false, false, true, true, true}}, + {{3, 4}, element::boolean, std::vector {true, true, true, true, true, true, true, false, false, true, true, false}}}) .expected({{3, 4}, element::boolean, std::vector {true, true, true, true, true, true, true, false, false, true, true, true}})}; return logicalParams; } diff --git a/docs/template_plugin/tests/functional/op_reference/logical_xor.cpp b/docs/template_plugin/tests/functional/op_reference/logical_xor.cpp index ac30a4c8352..52269ddb894 100644 --- a/docs/template_plugin/tests/functional/op_reference/logical_xor.cpp +++ b/docs/template_plugin/tests/functional/op_reference/logical_xor.cpp @@ -24,18 +24,18 @@ std::vector generateLogicalParams() { std::vector logicalParams { Builder {} .opType(LogicalTypes::LOGICAL_XOR) - .input1({{2, 2}, element::boolean, std::vector {true, false, true, false}}) - .input2({{2, 2}, element::boolean, std::vector {false, true, true, false}}) + .inputs({{{2, 2}, element::boolean, std::vector {true, false, true, false}}, + {{2, 2}, element::boolean, std::vector {false, true, true, false}}}) .expected({{2, 2}, element::boolean, std::vector {true, true, false, false}}), Builder {} .opType(LogicalTypes::LOGICAL_XOR) - .input1({{2, 1, 2, 1}, element::boolean, std::vector {true, false, true, false}}) - .input2({{1, 1, 2, 1}, element::boolean, std::vector {true, false}}) + .inputs({{{2, 1, 2, 1}, element::boolean, std::vector {true, false, true, false}}, + {{1, 1, 2, 1}, element::boolean, std::vector {true, false}}}) .expected({{2, 1, 2, 1}, element::boolean, std::vector {false, false, false, false}}), Builder {} .opType(LogicalTypes::LOGICAL_XOR) - .input1({{3, 4}, element::boolean, std::vector {true, true, true, true, true, false, true, false, false, true, true, true}}) - .input2({{3, 4}, element::boolean, std::vector {true, true, true, true, true, true, true, false, false, true, true, false}}) + .inputs({{{3, 4}, element::boolean, std::vector {true, true, true, true, true, false, true, false, false, true, true, true}}, + {{3, 4}, element::boolean, std::vector {true, true, true, true, true, true, true, false, false, true, true, false}}}) .expected({{3, 4}, element::boolean, std::vector {false, false, false, false, false, true, false, false, false, false, false, true}})}; return logicalParams; } diff --git a/inference-engine/tests/ie_test_utils/functional_test_utils/layer_tests_summary/utils/constants.py b/inference-engine/tests/ie_test_utils/functional_test_utils/layer_tests_summary/utils/constants.py index 7a79d64fa9e..e35678eee29 100644 --- a/inference-engine/tests/ie_test_utils/functional_test_utils/layer_tests_summary/utils/constants.py +++ b/inference-engine/tests/ie_test_utils/functional_test_utils/layer_tests_summary/utils/constants.py @@ -61,7 +61,8 @@ VERIFIED_OP_REFERENCES = [ 'LRN-1', 'LSTMCell-4', 'LSTMSequence-5', - 'LogicalAnd-1' + 'LogicalAnd-1', + 'LogicalNot-1' 'LogicalOr-1' 'LogicalXor-1' 'LogSoftmax-5', diff --git a/inference-engine/tests/ngraph_helpers/ngraph_functions/include/ngraph_functions/builders.hpp b/inference-engine/tests/ngraph_helpers/ngraph_functions/include/ngraph_functions/builders.hpp index 8e70dfdc6d8..54db25a547f 100644 --- a/inference-engine/tests/ngraph_helpers/ngraph_functions/include/ngraph_functions/builders.hpp +++ b/inference-engine/tests/ngraph_helpers/ngraph_functions/include/ngraph_functions/builders.hpp @@ -451,6 +451,9 @@ std::shared_ptr makeLogical(const ngraph::Output &in0, const ngraph::Output &in1, ngraph::helpers::LogicalTypes logicalType); +std::shared_ptr makeLogical(const ngraph::ParameterVector& inputs, + ngraph::helpers::LogicalTypes logicalType); + std::shared_ptr makeDetectionOutput(const ngraph::OutputVector &inputs, const ngraph::op::DetectionOutputAttrs& attrs); diff --git a/inference-engine/tests/ngraph_helpers/ngraph_functions/src/logical.cpp b/inference-engine/tests/ngraph_helpers/ngraph_functions/src/logical.cpp index e21be58f158..784233a5c0a 100644 --- a/inference-engine/tests/ngraph_helpers/ngraph_functions/src/logical.cpp +++ b/inference-engine/tests/ngraph_helpers/ngraph_functions/src/logical.cpp @@ -27,5 +27,22 @@ std::shared_ptr makeLogical(const ngraph::Output &in0, } } +std::shared_ptr makeLogical(const ngraph::ParameterVector& inputs, + ngraph::helpers::LogicalTypes logicalType) { + switch (logicalType) { + case ngraph::helpers::LogicalTypes::LOGICAL_AND: + return std::make_shared(inputs[0], inputs[1]); + case ngraph::helpers::LogicalTypes::LOGICAL_OR: + return std::make_shared(inputs[0], inputs[1]); + case ngraph::helpers::LogicalTypes::LOGICAL_NOT: + return std::make_shared(inputs[0]); + case ngraph::helpers::LogicalTypes::LOGICAL_XOR: + return std::make_shared(inputs[0], inputs[1]); + default: { + throw std::runtime_error("Incorrect type of Logical operation"); + } + } +} + } // namespace builder -} // namespace ngraph \ No newline at end of file +} // namespace ngraph diff --git a/ngraph/core/src/op/not.cpp b/ngraph/core/src/op/not.cpp index a5e196a4f38..26dcc0d7345 100644 --- a/ngraph/core/src/op/not.cpp +++ b/ngraph/core/src/op/not.cpp @@ -9,6 +9,7 @@ #include "ngraph/op/util/elementwise_args.hpp" #include "ngraph/runtime/host_tensor.hpp" #include "ngraph/runtime/reference/not.hpp" +#include "ngraph/validation_util.hpp" using namespace ngraph; using namespace std; @@ -70,6 +71,7 @@ bool evaluate_not(const HostTensorPtr& arg0, const HostTensorPtr& out, const siz bool op::v1::LogicalNot::evaluate(const HostTensorVector& outputs, const HostTensorVector& inputs) const { NGRAPH_OP_SCOPE(v1_LogicalNot_evaluate); + NGRAPH_CHECK(validate_host_tensor_vector(outputs, 1) && validate_host_tensor_vector(inputs, 1)); return notop::evaluate_not(inputs[0], outputs[0], shape_size(get_output_shape(0))); } diff --git a/ngraph/test/CMakeLists.txt b/ngraph/test/CMakeLists.txt index a851e199d73..16ad46af9ed 100644 --- a/ngraph/test/CMakeLists.txt +++ b/ngraph/test/CMakeLists.txt @@ -156,6 +156,7 @@ set(SRC type_prop/idft.cpp type_prop/interpolate.cpp type_prop/logical_and.cpp + type_prop/logical_not.cpp type_prop/logical_or.cpp type_prop/logical_xor.cpp type_prop/lrn.cpp @@ -282,6 +283,7 @@ set(SRC visitors/op/log.cpp visitors/op/logical_and.cpp visitors/op/logical_or.cpp + visitors/op/logical_not.cpp visitors/op/logical_xor.cpp visitors/op/lrn.cpp visitors/op/lstm_cell.cpp @@ -459,7 +461,6 @@ set(MULTI_TEST_SRC backend/interpolate.in.cpp backend/log.in.cpp backend/log_softmax.in.cpp - backend/logical_not.in.cpp backend/lrn.in.cpp backend/matmul.in.cpp backend/matrix_nms.in.cpp diff --git a/ngraph/test/backend/logical_not.in.cpp b/ngraph/test/backend/logical_not.in.cpp deleted file mode 100644 index 4880b4b60d6..00000000000 --- a/ngraph/test/backend/logical_not.in.cpp +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright (C) 2018-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#include -#include -#include -#include -#include -#include - -// clang-format off -#ifdef ${BACKEND_NAME}_FLOAT_TOLERANCE_BITS -#define DEFAULT_FLOAT_TOLERANCE_BITS ${BACKEND_NAME}_FLOAT_TOLERANCE_BITS -#endif - -#ifdef ${BACKEND_NAME}_DOUBLE_TOLERANCE_BITS -#define DEFAULT_DOUBLE_TOLERANCE_BITS ${BACKEND_NAME}_DOUBLE_TOLERANCE_BITS -#endif -// clang-format on - -#include "gtest/gtest.h" -#include "ngraph/ngraph.hpp" -#include "util/engine/test_engines.hpp" -#include "util/test_case.hpp" -#include "util/test_control.hpp" - -NGRAPH_SUPPRESS_DEPRECATED_START - -using namespace std; -using namespace ngraph; - -static string s_manifest = "${MANIFEST}"; -using TestEngine = test::ENGINE_CLASS_NAME(${BACKEND_NAME}); - -NGRAPH_TEST(${BACKEND_NAME}, not) { - Shape shape{2, 2}; - auto A = make_shared(element::boolean, shape); - auto f = make_shared(make_shared(A), ParameterVector{A}); - - std::vector a{1, 0, 1, 0}; - - auto test_case = test::TestCase(f); - test_case.add_input(shape, a); - test_case.add_expected_output(shape, {0, 1, 0, 1}); - test_case.run(); -} - -NGRAPH_TEST(${BACKEND_NAME}, not_i32) { - Shape shape{2, 2}; - auto A = make_shared(element::i32, shape); - auto f = make_shared(make_shared(A), ParameterVector{A}); - - std::vector a{1, 0, 2, 0}; - - auto test_case = test::TestCase(f); - test_case.add_input(shape, a); - test_case.add_expected_output(shape, {0, 1, 0, 1}); -} diff --git a/ngraph/test/type_prop/logical_not.cpp b/ngraph/test/type_prop/logical_not.cpp new file mode 100644 index 00000000000..0a0a8b6d9c4 --- /dev/null +++ b/ngraph/test/type_prop/logical_not.cpp @@ -0,0 +1,49 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "gtest/gtest.h" +#include "ngraph/ngraph.hpp" +#include "util/type_prop.hpp" + +using namespace std; +using namespace ngraph; + +namespace { +void type_check(const ngraph::element::Type& type) { + auto input = make_shared(type, Shape{1, 3, 6}); + auto logical_not = make_shared(input); + + ASSERT_EQ(logical_not->get_element_type(), type); +} +} // namespace + +TEST(type_prop, logical_not_i32) { + type_check(element::i32); +} + +TEST(type_prop, logical_not_i64) { + type_check(element::i64); +} + +TEST(type_prop, logical_not_u32) { + type_check(element::u32); +} + +TEST(type_prop, logical_not_u64) { + type_check(element::u64); +} + +TEST(type_prop, logical_not_f16) { + type_check(element::f16); +} + +TEST(type_prop, logical_not_f32) { + type_check(element::f32); +} + +TEST(type_prop, logical_not_shape_inference) { + auto input = make_shared(element::boolean, Shape{1, 3, 6}); + auto logical_not = make_shared(input); + ASSERT_EQ(logical_not->get_shape(), (Shape{1, 3, 6})); +} diff --git a/ngraph/test/visitors/op/logical_not.cpp b/ngraph/test/visitors/op/logical_not.cpp new file mode 100644 index 00000000000..5ff4dc80b2d --- /dev/null +++ b/ngraph/test/visitors/op/logical_not.cpp @@ -0,0 +1,9 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "unary_ops.hpp" + +using Type = ::testing::Types>; + +INSTANTIATE_TYPED_TEST_SUITE_P(visitor_without_attribute, UnaryOperatorVisitor, Type, UnaryOperatorTypeName); From a81164e1cbf683e0d1665adf56f08e439be01d0f Mon Sep 17 00:00:00 2001 From: Jan Iwaszkiewicz Date: Fri, 27 Aug 2021 10:05:51 +0200 Subject: [PATCH 51/76] Specialized exception if ONNX model is unsupported (#7234) * Add tests * Add new error throw --- .../src/inference_engine/src/ie_network_reader.cpp | 9 +++++---- .../inference_engine/onnx_reader/model_support_tests.cpp | 6 +++--- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/inference-engine/src/inference_engine/src/ie_network_reader.cpp b/inference-engine/src/inference_engine/src/ie_network_reader.cpp index f8c15a4f00d..a624f099dd0 100644 --- a/inference-engine/src/inference_engine/src/ie_network_reader.cpp +++ b/inference-engine/src/inference_engine/src/ie_network_reader.cpp @@ -254,8 +254,9 @@ CNNNetwork details::ReadNetwork(const std::string& modelPath, auto ngFunc = FE->convert(inputModel); return CNNNetwork(ngFunc, exts); } - IE_THROW() << "Unknown model format! Cannot find reader for model format: " << fileExt - << " and read the model: " << modelPath << ". Please check that reader library exists in your PATH."; + IE_THROW(NetworkNotRead) << "Unable to read the model: " << modelPath + << " Please check that model format: " << fileExt + << " is supported and the model is correct."; } CNNNetwork details::ReadNetwork(const std::string& model, @@ -288,8 +289,8 @@ CNNNetwork details::ReadNetwork(const std::string& model, return CNNNetwork(ngFunc, exts); } - IE_THROW() << "Unknown model format! Cannot find reader for the model and read it. Please check that reader " - "library exists in your PATH."; + IE_THROW(NetworkNotRead) + << "Unable to read the model. Please check if the model format is supported and model is correct."; } } // namespace InferenceEngine diff --git a/inference-engine/tests/functional/inference_engine/onnx_reader/model_support_tests.cpp b/inference-engine/tests/functional/inference_engine/onnx_reader/model_support_tests.cpp index 0ed41ca973e..75454a88c3e 100644 --- a/inference-engine/tests/functional/inference_engine/onnx_reader/model_support_tests.cpp +++ b/inference-engine/tests/functional/inference_engine/onnx_reader/model_support_tests.cpp @@ -47,7 +47,7 @@ TEST(ONNXReader_ModelSupported, scrambled_keys) { TEST(ONNXReader_ModelUnsupported, no_graph_field) { // this model contains only 2 fields (it doesn't contain a graph in particular) EXPECT_THROW(InferenceEngine::Core{}.ReadNetwork(model_path("unsupported/no_graph_field.onnx")), - InferenceEngine::Exception); + InferenceEngine::NetworkNotRead); } TEST(ONNXReader_ModelUnsupported, incorrect_onnx_field) { @@ -55,11 +55,11 @@ TEST(ONNXReader_ModelUnsupported, incorrect_onnx_field) { // this test will have to be changed if the number of fields in onnx.proto // (ModelProto message definition) ever reaches 31 or more EXPECT_THROW(InferenceEngine::Core{}.ReadNetwork(model_path("unsupported/incorrect_onnx_field.onnx")), - InferenceEngine::Exception); + InferenceEngine::NetworkNotRead); } TEST(ONNXReader_ModelUnsupported, unknown_wire_type) { // in this model the graph key contains wire type 7 encoded in it - this value is incorrect EXPECT_THROW(InferenceEngine::Core{}.ReadNetwork(model_path("unsupported/unknown_wire_type.onnx")), - InferenceEngine::Exception); + InferenceEngine::NetworkNotRead); } From 148bdf638e202969a7ed551304a1011c55ffeb6a Mon Sep 17 00:00:00 2001 From: Dmitry Kurtaev Date: Fri, 27 Aug 2021 11:18:48 +0300 Subject: [PATCH 52/76] [Docs] CPU_BIND_THREADS -> CPU_BIND_THREAD (#7079) * [Docs] CPU_BIND_THREADS -> CPU_BIND_THREAD * Update docs/optimization_guide/dldt_optimization_guide.md Co-authored-by: Tatiana Savina Co-authored-by: Tatiana Savina --- docs/optimization_guide/dldt_optimization_guide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/optimization_guide/dldt_optimization_guide.md b/docs/optimization_guide/dldt_optimization_guide.md index 3d7b41e7f8c..740f4787061 100644 --- a/docs/optimization_guide/dldt_optimization_guide.md +++ b/docs/optimization_guide/dldt_optimization_guide.md @@ -338,7 +338,7 @@ For inference on the CPU there are multiple threads binding options, see If you are building an app-level pipeline with third-party components like GStreamer*, the general guidance for NUMA machines is as follows: - Whenever possible, use at least one instance of the pipeline per NUMA node: - Pin the _entire_ pipeline instance to the specific NUMA node at the outer-most level (for example, use Kubernetes* and/or `numactl` command with proper settings before actual GStreamer commands). - - Disable any individual pinning by the pipeline components (e.g. set [CPU_BIND_THREADS to 'NO'](../IE_DG/supported_plugins/CPU.md)). + - Disable any individual pinning by the pipeline components (for example, set [CPU_BIND_THREAD to 'NO'](../IE_DG/supported_plugins/CPU.md)). - Limit each instance with respect to number of inference threads. Use [CPU_THREADS_NUM](../IE_DG/supported_plugins/CPU.md) or or other means (e.g. virtualization, Kubernetes*, etc), to avoid oversubscription. - If pinning instancing/pinning of the entire pipeline is not possible or desirable, relax the inference threads pinning to just 'NUMA'. - This is less restrictive compared to the default pinning of threads to cores, yet avoids NUMA penalties. From d0f49fe0c8e82c96ea9a1563ef5cef7d37591230 Mon Sep 17 00:00:00 2001 From: Mikhail Ryzhov Date: Fri, 27 Aug 2021 14:19:18 +0300 Subject: [PATCH 53/76] [GNA] Fixed export/import precisions (#6273) --- .../descriptions/gna_input_desc.hpp | 1 + .../descriptions/gna_output_desc.hpp | 1 + .../src/gna_plugin/gna_model_serial.cpp | 6 ++-- .../src/gna_plugin/gna_plugin.cpp | 34 +++++++++++++++++-- .../src/gna_plugin/gna_plugin.hpp | 1 + .../skip_tests_config.cpp | 3 +- .../src/base/layer_test_utils.cpp | 8 +++++ 7 files changed, 45 insertions(+), 9 deletions(-) diff --git a/inference-engine/src/gna_plugin/descriptions/gna_input_desc.hpp b/inference-engine/src/gna_plugin/descriptions/gna_input_desc.hpp index 555e4ab112e..41f08f0bdde 100644 --- a/inference-engine/src/gna_plugin/descriptions/gna_input_desc.hpp +++ b/inference-engine/src/gna_plugin/descriptions/gna_input_desc.hpp @@ -18,6 +18,7 @@ struct InputDesc { std::unordered_map orientation_in; /// order of scale factors matches inputs order in original topology std::vector inputScaleFactors; + std::vector inputPrecisions; std::map bytes_allocated_for_input; size_t minBytesRequiredForStoreInput(InferenceEngine::CNNLayerPtr); diff --git a/inference-engine/src/gna_plugin/descriptions/gna_output_desc.hpp b/inference-engine/src/gna_plugin/descriptions/gna_output_desc.hpp index eef68a00e81..16237d19ff5 100644 --- a/inference-engine/src/gna_plugin/descriptions/gna_output_desc.hpp +++ b/inference-engine/src/gna_plugin/descriptions/gna_output_desc.hpp @@ -10,6 +10,7 @@ namespace GNAPluginNS { struct OutputDesc { + uint8_t precision; double scale_factor = 1.0; uint32_t num_bytes_per_element = 0; uint32_t num_elements = 0; diff --git a/inference-engine/src/gna_plugin/gna_model_serial.cpp b/inference-engine/src/gna_plugin/gna_model_serial.cpp index e32ded8a9e3..388a3c9d82b 100644 --- a/inference-engine/src/gna_plugin/gna_model_serial.cpp +++ b/inference-engine/src/gna_plugin/gna_model_serial.cpp @@ -831,14 +831,13 @@ std::vector GNAModelSerial::serializeOutputs(cons } uint32_t elementsCount = static_cast(InferenceEngine::details::product(outputDims.begin(), outputDims.end())); InferenceEngine::Layout outputLayout = output.second->getLayout(); - InferenceEngine::Precision::ePrecision outputPrecision = InferenceEngine::Precision::FP32; HeaderLatest::RuntimeEndPoint endPoint(outputsDesc[outputIndex].scale_factor, outputsDesc[outputIndex].ptrs[0], outputsDesc[outputIndex].num_bytes_per_element, elementsCount, outputShape, outputLayout, - outputPrecision, + outputsDesc[outputIndex].precision, outputsDesc[outputIndex].orientation); endPoints.push_back(endPoint); outputIndex++; @@ -866,7 +865,7 @@ std::vector GNAModelSerial::serializeInputs(const uint32_t elementsCount = static_cast(InferenceEngine::details::product(inputDims.begin(), inputDims.end())); intel_dnn_orientation_t orientation = inputDesc->getOrientation(inputName); InferenceEngine::Layout inputLayout = input.second->getLayout(); - InferenceEngine::Precision::ePrecision inputPrecision = InferenceEngine::Precision::FP32; + uint8_t inputPrecision = inputDesc->inputPrecisions.at(inputIndex); HeaderLatest::RuntimeEndPoint endPoint(scaleFactor, descriptor_ptr[0], element_size, @@ -886,7 +885,6 @@ void GNAModelSerial::ImportInputs(std::istream &is, std::shared_ptr inputsDesc, InferenceEngine::InputsDataMap& dataMap) { dataMap.clear(); - for (uint32_t inputIndex = 0; inputIndex < modelHeader.nInputs; inputIndex++) { const std::string& name = (modelHeader.version.major == 2 && modelHeader.version.minor >= 3) ? inputNames.at(inputIndex) : std::string("input" + std::to_string(inputIndex)); diff --git a/inference-engine/src/gna_plugin/gna_plugin.cpp b/inference-engine/src/gna_plugin/gna_plugin.cpp index 48815f964da..4f1b36ab5d5 100644 --- a/inference-engine/src/gna_plugin/gna_plugin.cpp +++ b/inference-engine/src/gna_plugin/gna_plugin.cpp @@ -518,6 +518,33 @@ void GNAPlugin::UpdateInputScaleFromNetwork(InferenceEngine::CNNNetwork & networ } } +void GNAPlugin::UpdateInputsAndOutputsInfoFromNetwork(InferenceEngine::CNNNetwork & network) { + OV_ITT_SCOPED_TASK(itt::domains::GNA_LT, "UpdateInputsAndOutputsInfoFromNetwork"); + + // update inputs + { + InputsDataMap inputs = network.getInputsInfo(); + if (inputsDesc->inputPrecisions.size() != 0) { + inputsDesc->inputPrecisions.clear(); + } + for (const auto input : inputs) { + inputsDesc->inputPrecisions.push_back(input.second->getPrecision().getPrecVal()); + } + } + + // update outputs + { + OutputsDataMap outputs = network.getOutputsInfo(); + outputsDesc.resize(outputs.size()); + + size_t outputIdx = 0; + for (const auto output : outputs) { + outputsDesc[outputIdx].precision = output.second->getPrecision().getPrecVal(); + ++outputIdx; + } + } +} + bool GNAPlugin::TryToInitOutput(int portId, InferenceEngine::CNNLayerPtr layer) { auto initOutput = [this, portId, layer] (intel_dnn_orientation_t orientation, size_t numBytesPerElem, size_t numElem, void* outputPtr) { @@ -759,6 +786,9 @@ void GNAPlugin::LoadNetwork(CNNNetwork & _network) { UpdateGnaQuantModeFromNetwork(network); UpdateInputScaleFromNetwork(network); + // Set input and output information from orginal network + UpdateInputsAndOutputsInfoFromNetwork(network); + if (MustBeConvertedFromNCHWToNHWC(details::CNNNetSortTopologically(network))) { FillInputsAndOutputsTranspositionInfo(network); } @@ -922,7 +952,7 @@ void GNAPlugin::LoadNetwork(CNNNetwork & _network) { inputsDesc->getPtrInputsGlobal(input.first).resize(gnaFlags->gna_lib_async_threads_num); } - // CreatingLayer primitives + // Creating Layer primitives for (auto & layer : sortedNoMem) { graphCompiler.CreateLayerPrimitive(layer); } @@ -940,8 +970,6 @@ void GNAPlugin::LoadNetwork(CNNNetwork & _network) { } /// setting-up output layers information - outputsDesc.resize(outputsDataMap.size()); - int portId = 0; for (auto && outPort : outputsDataMap) { // gets output layer pointer in original topology not in cloned diff --git a/inference-engine/src/gna_plugin/gna_plugin.hpp b/inference-engine/src/gna_plugin/gna_plugin.hpp index 941dc209cea..476106f558e 100644 --- a/inference-engine/src/gna_plugin/gna_plugin.hpp +++ b/inference-engine/src/gna_plugin/gna_plugin.hpp @@ -213,6 +213,7 @@ class GNAPlugin : public InferenceEngine::IInferencePlugin { void UpdateFieldsFromConfig(); void UpdateGnaQuantModeFromNetwork(InferenceEngine::CNNNetwork &); void UpdateInputScaleFromNetwork(InferenceEngine::CNNNetwork &); + void UpdateInputsAndOutputsInfoFromNetwork(InferenceEngine::CNNNetwork &); /** * @brief Tries to init an output on the base of a layer data * @param portId output port identificator diff --git a/inference-engine/tests/functional/plugin/gna/shared_tests_instances/skip_tests_config.cpp b/inference-engine/tests/functional/plugin/gna/shared_tests_instances/skip_tests_config.cpp index c580b6501ff..8305e65ccae 100644 --- a/inference-engine/tests/functional/plugin/gna/shared_tests_instances/skip_tests_config.cpp +++ b/inference-engine/tests/functional/plugin/gna/shared_tests_instances/skip_tests_config.cpp @@ -42,8 +42,7 @@ std::vector disabledTestPatterns() { R"(.*ConvolutionLayerTest.CompareWithRefs.*D=\(3.1\).*)", R"(.*ConstantResultSubgraphTest.*IS=\(2\.3\.4\.5\).*)", R"(.*ConstantResultSubgraphTest.*inPrc=(U8|I8|I32|U64|I64|BOOL).*)", - // TODO: Issue 51528 - R"(.*CachingSupport.*_(u8|i16)_.*)", + // TODO: Issue 57363 (Param -> Result subgraphs) R"(.*smoke_MemoryTest.*LOW_LATENCY.*iteration_count=1_.*)", // TODO: Issue 57368 (accuracy) diff --git a/inference-engine/tests/functional/shared_test_classes/src/base/layer_test_utils.cpp b/inference-engine/tests/functional/shared_test_classes/src/base/layer_test_utils.cpp index 7ba0a1d90b4..af21f3a39b7 100644 --- a/inference-engine/tests/functional/shared_test_classes/src/base/layer_test_utils.cpp +++ b/inference-engine/tests/functional/shared_test_classes/src/base/layer_test_utils.cpp @@ -269,6 +269,14 @@ void LayerTestsCommon::Compare(const InferenceEngine::Blob::Ptr &expected, const Compare(reinterpret_cast(expectedBuffer), reinterpret_cast(actualBuffer), size, 0); break; + case InferenceEngine::Precision::I16: + Compare(reinterpret_cast(expectedBuffer), + reinterpret_cast(actualBuffer), size, 0); + break; + case InferenceEngine::Precision::U8: + Compare(reinterpret_cast(expectedBuffer), + reinterpret_cast(actualBuffer), size, 0); + break; default: FAIL() << "Comparator for " << precision << " precision isn't supported"; } From 4a07a0baaef107cb86b595fd5df101907646f68b Mon Sep 17 00:00:00 2001 From: Mateusz Bencer Date: Sat, 28 Aug 2021 13:48:54 +0200 Subject: [PATCH 54/76] Use ONNX FE instead of ONNX Reader leftovers (#7252) --- .../inference_engine/src/ie_network_reader.cpp | 17 +++++++++-------- .../frontend_manager/frontend_manager.hpp | 10 ---------- .../frontend_manager/src/frontend_manager.cpp | 2 -- ngraph/frontend/onnx/frontend/src/frontend.cpp | 15 ++------------- 4 files changed, 11 insertions(+), 33 deletions(-) diff --git a/inference-engine/src/inference_engine/src/ie_network_reader.cpp b/inference-engine/src/inference_engine/src/ie_network_reader.cpp index a624f099dd0..f9c796c93f1 100644 --- a/inference-engine/src/inference_engine/src/ie_network_reader.cpp +++ b/inference-engine/src/inference_engine/src/ie_network_reader.cpp @@ -96,9 +96,9 @@ namespace { // Extension to plugins creator std::multimap readers; -static ngraph::frontend::FrontEndManager* get_frontend_manager() { +static ngraph::frontend::FrontEndManager& get_frontend_manager() { static ngraph::frontend::FrontEndManager manager; - return &manager; + return manager; } void registerReaders() { @@ -233,7 +233,7 @@ CNNNetwork details::ReadNetwork(const std::string& modelPath, } } // Try to load with FrontEndManager - const auto manager = get_frontend_manager(); + auto& manager = get_frontend_manager(); ngraph::frontend::FrontEnd::Ptr FE; ngraph::frontend::InputModel::Ptr inputModel; if (!binPath.empty()) { @@ -242,11 +242,11 @@ CNNNetwork details::ReadNetwork(const std::string& modelPath, #else std::string weights_path = binPath; #endif - FE = manager->load_by_model(model_path, weights_path); + FE = manager.load_by_model(model_path, weights_path); if (FE) inputModel = FE->load(model_path, weights_path); } else { - FE = manager->load_by_model(model_path); + FE = manager.load_by_model(model_path); if (FE) inputModel = FE->load(model_path); } @@ -264,7 +264,8 @@ CNNNetwork details::ReadNetwork(const std::string& model, const std::vector& exts) { // Register readers if it is needed registerReaders(); - std::istringstream modelStream(model); + std::istringstream modelStringStream(model); + std::istream& modelStream = modelStringStream; assertIfIRv7LikeModel(modelStream); @@ -278,10 +279,10 @@ CNNNetwork details::ReadNetwork(const std::string& model, } // Try to load with FrontEndManager // NOTE: weights argument is ignored - const auto manager = get_frontend_manager(); + auto& manager = get_frontend_manager(); ngraph::frontend::FrontEnd::Ptr FE; ngraph::frontend::InputModel::Ptr inputModel; - FE = manager->load_by_model(&modelStream); + FE = manager.load_by_model(&modelStream); if (FE) inputModel = FE->load(&modelStream); if (inputModel) { diff --git a/ngraph/frontend/frontend_manager/include/frontend_manager/frontend_manager.hpp b/ngraph/frontend/frontend_manager/include/frontend_manager/frontend_manager.hpp index 6a72fc18fc8..ba4183b0b74 100644 --- a/ngraph/frontend/frontend_manager/include/frontend_manager/frontend_manager.hpp +++ b/ngraph/frontend/frontend_manager/include/frontend_manager/frontend_manager.hpp @@ -108,16 +108,6 @@ public: VariantWrapper(const value_type& value) : VariantImpl(value) {} }; -template <> -class FRONTEND_API VariantWrapper : public VariantImpl { -public: - static constexpr VariantTypeInfo type_info{"Variant::std::istringstream*", 0}; - const VariantTypeInfo& get_type_info() const override { - return type_info; - } - VariantWrapper(const value_type& value) : VariantImpl(value) {} -}; - #if defined(ENABLE_UNICODE_PATH_SUPPORT) && defined(_WIN32) template <> class FRONTEND_API VariantWrapper : public VariantImpl { diff --git a/ngraph/frontend/frontend_manager/src/frontend_manager.cpp b/ngraph/frontend/frontend_manager/src/frontend_manager.cpp index 70f6edd6cd0..e48403678c6 100644 --- a/ngraph/frontend/frontend_manager/src/frontend_manager.cpp +++ b/ngraph/frontend/frontend_manager/src/frontend_manager.cpp @@ -375,8 +375,6 @@ std::vector Place::get_consuming_operations(const std::string& outpu constexpr VariantTypeInfo VariantWrapper::type_info; -constexpr VariantTypeInfo VariantWrapper::type_info; - #if defined(ENABLE_UNICODE_PATH_SUPPORT) && defined(_WIN32) constexpr VariantTypeInfo VariantWrapper::type_info; #endif diff --git a/ngraph/frontend/onnx/frontend/src/frontend.cpp b/ngraph/frontend/onnx/frontend/src/frontend.cpp index db7eeb7d094..0a8136db8a6 100644 --- a/ngraph/frontend/onnx/frontend/src/frontend.cpp +++ b/ngraph/frontend/onnx/frontend/src/frontend.cpp @@ -19,7 +19,6 @@ using namespace ngraph::frontend; using VariantString = VariantWrapper; using VariantWString = VariantWrapper; using VariantIstreamPtr = VariantWrapper; -using VariantIstringstreamPtr = VariantWrapper; extern "C" ONNX_FRONTEND_API FrontEndVersion GetAPIVersion() { return OV_FRONTEND_API_VERSION; @@ -48,13 +47,8 @@ InputModel::Ptr FrontEndONNX::load_impl(const std::vector(path); } #endif - std::istream* stream = nullptr; if (ov::is_type(variants[0])) { - stream = ov::as_type_ptr(variants[0])->get(); - } else if (ov::is_type(variants[0])) { - stream = ov::as_type_ptr(variants[0])->get(); - } - if (stream != nullptr) { + const auto stream = ov::as_type_ptr(variants[0])->get(); if (variants.size() > 1 && ov::is_type(variants[1])) { const auto path = ov::as_type_ptr(variants[1])->get(); return std::make_shared(*stream, path); @@ -133,13 +127,8 @@ bool FrontEndONNX::supported_impl(const std::vector>& v model_stream.close(); return is_valid_model; } - std::istream* stream = nullptr; if (ov::is_type(variants[0])) { - stream = ov::as_type_ptr(variants[0])->get(); - } else if (ov::is_type(variants[0])) { - stream = ov::as_type_ptr(variants[0])->get(); - } - if (stream != nullptr) { + const auto stream = ov::as_type_ptr(variants[0])->get(); StreamRewinder rwd{*stream}; return onnx_common::is_valid_model(*stream); } From 6cdd76f7d4fcbb7b59c0dab83040a0aaa24512d6 Mon Sep 17 00:00:00 2001 From: Ilya Churaev Date: Mon, 30 Aug 2021 06:20:22 +0300 Subject: [PATCH 55/76] Moved ngraph::Node to ov namespace (#7240) * Moved ngraph::Node to ov namespace * Fixed code style * Fixed VPU * Fixed GNA * Fixed tests * Added aliases for backward compatibility * Fix clDNN * Try to fix build * Fixed comment * Renamed RTTI macros --- .../src/cldnn_engine/cldnn_program.h | 10 +- .../src/legacy_api/include/legacy/ie_layers.h | 7 +- .../merge_subsequent_dsr_operations.cpp | 2 +- .../transformations/gna_decompose_2d_conv.cpp | 2 +- .../core/include/ngraph/attribute_adapter.hpp | 5 +- .../core/include/ngraph/descriptor/input.hpp | 3 +- .../core/include/ngraph/descriptor/output.hpp | 8 +- ngraph/core/include/ngraph/graph_util.hpp | 3 + ngraph/core/include/ngraph/node.hpp | 649 +--------------- ngraph/core/include/ngraph/node_input.hpp | 109 +-- ngraph/core/include/ngraph/node_output.hpp | 156 +--- ngraph/core/include/ngraph/output_vector.hpp | 10 +- ngraph/core/include/ngraph/rt_info.hpp | 2 + .../include/ngraph/runtime/host_tensor.hpp | 5 +- ngraph/core/include/ngraph/type.hpp | 30 +- ngraph/core/include/ngraph/util.hpp | 5 +- .../core/include/ngraph/validation_util.hpp | 2 + ngraph/core/include/ngraph/variant.hpp | 20 +- .../openvino/core/attribute_visitor.hpp | 14 +- .../openvino/core/descriptor/input.hpp | 26 +- .../openvino/core/descriptor/output.hpp | 18 +- .../openvino/core/descriptor/tensor.hpp | 15 +- ngraph/core/include/openvino/core/node.hpp | 713 ++++++++++++++++++ .../core/include/openvino/core/node_input.hpp | 124 +++ .../include/openvino/core/node_output.hpp | 172 +++++ .../include/openvino/core/node_vector.hpp | 19 + ngraph/core/include/openvino/core/variant.hpp | 6 +- ngraph/core/src/node.cpp | 244 +++--- ngraph/core/src/node_input.cpp | 12 +- ngraph/core/src/node_output.cpp | 12 +- ngraph/core/src/validation_util.cpp | 4 +- ngraph/core/src/variant.cpp | 4 +- ngraph/test/util/test_tools.hpp | 2 +- 33 files changed, 1259 insertions(+), 1154 deletions(-) create mode 100644 ngraph/core/include/openvino/core/node.hpp create mode 100644 ngraph/core/include/openvino/core/node_input.hpp create mode 100644 ngraph/core/include/openvino/core/node_output.hpp create mode 100644 ngraph/core/include/openvino/core/node_vector.hpp diff --git a/inference-engine/src/cldnn_engine/cldnn_program.h b/inference-engine/src/cldnn_engine/cldnn_program.h index cf791870e5e..23b6313cac9 100644 --- a/inference-engine/src/cldnn_engine/cldnn_program.h +++ b/inference-engine/src/cldnn_engine/cldnn_program.h @@ -12,6 +12,7 @@ #include #include +#include #include "cldnn_config.h" @@ -26,15 +27,6 @@ enum class reduce_mode : uint16_t; enum class eltwise_mode : int32_t; } // namespace cldnn -// Forward declarations for ngraph part -namespace ngraph { -class Node; -} // namespace ngraph - -namespace ov { -class DiscreteTypeInfo; -} // namespace ov - #define REGISTER_FACTORY_IMPL(op_version, op_name) \ void __register ## _ ## op_name ## _ ## op_version() { \ Program::RegisterFactory( \ diff --git a/inference-engine/src/legacy_api/include/legacy/ie_layers.h b/inference-engine/src/legacy_api/include/legacy/ie_layers.h index 64fa501966a..7eb2c474597 100644 --- a/inference-engine/src/legacy_api/include/legacy/ie_layers.h +++ b/inference-engine/src/legacy_api/include/legacy/ie_layers.h @@ -22,6 +22,7 @@ #include "ie_common.h" #include "ie_data.h" #include +#include #if defined IMPLEMENT_INFERENCE_ENGINE_API || defined IMPLEMENT_INFERENCE_ENGINE_PLUGIN # define INFERENCE_ENGINE_INTERNAL_CNNLAYER_CLASS(...) INFERENCE_ENGINE_API_CLASS(__VA_ARGS__) @@ -31,12 +32,6 @@ INFERENCE_ENGINE_API_CLASS(__VA_ARGS__) #endif -namespace ngraph { - -class Node; - -} // namespace ngraph - namespace InferenceEngine { /** diff --git a/inference-engine/src/vpu/common/src/ngraph/transformations/merge_subsequent_dsr_operations.cpp b/inference-engine/src/vpu/common/src/ngraph/transformations/merge_subsequent_dsr_operations.cpp index c562cc196c4..89af4c2f5e4 100644 --- a/inference-engine/src/vpu/common/src/ngraph/transformations/merge_subsequent_dsr_operations.cpp +++ b/inference-engine/src/vpu/common/src/ngraph/transformations/merge_subsequent_dsr_operations.cpp @@ -24,7 +24,7 @@ MergeSubsequentDSROperations::MergeSubsequentDSROperations() { auto newDsr = dsr->copy_with_new_inputs({predecessor->input_value(0), dsr->input_value(1)}); newDsr->set_friendly_name(dsr->get_friendly_name()); // replace DSR2 with new so DSR2 will lose all consumers so it will die after pass execution - replace_node(dsr, newDsr); + ngraph::replace_node(dsr, newDsr); // reconnect all DSR1 consumers even with DSR2 which will be destructed so this is no more an issue for (auto &consumer : predecessor->get_output_target_inputs(0)) { consumer.replace_source_output(newDsr); diff --git a/inference-engine/tests/unit/gna/ngraph/transformations/gna_decompose_2d_conv.cpp b/inference-engine/tests/unit/gna/ngraph/transformations/gna_decompose_2d_conv.cpp index c7e9323638e..9861663caf8 100644 --- a/inference-engine/tests/unit/gna/ngraph/transformations/gna_decompose_2d_conv.cpp +++ b/inference-engine/tests/unit/gna/ngraph/transformations/gna_decompose_2d_conv.cpp @@ -664,7 +664,7 @@ std::shared_ptr Decompose(const GraphData& graph_data, C } // We need to put the same name as before for the Convolution layer, so its output can be used as network result std::string conv_result_name = graph_data.last_op_in_sequence_for_replacement->get_friendly_name(); - replace_node(graph_data.last_op_in_sequence_for_replacement, conv_result); + ngraph::replace_node(graph_data.last_op_in_sequence_for_replacement, conv_result); conv_result->set_friendly_name(conv_result_name); return std::make_shared(conv_result); diff --git a/ngraph/core/include/ngraph/attribute_adapter.hpp b/ngraph/core/include/ngraph/attribute_adapter.hpp index 075738a3449..a5267c48e7b 100644 --- a/ngraph/core/include/ngraph/attribute_adapter.hpp +++ b/ngraph/core/include/ngraph/attribute_adapter.hpp @@ -21,10 +21,7 @@ using ov::DirectValueAccessor; using ov::IndirectScalarValueAccessor; -template -A copy_from(B& b) { - return ov::copy_from(b); -} +using ov::copy_from; using ov::IndirectVectorValueAccessor; diff --git a/ngraph/core/include/ngraph/descriptor/input.hpp b/ngraph/core/include/ngraph/descriptor/input.hpp index babcd06e84e..d3ff88346ed 100644 --- a/ngraph/core/include/ngraph/descriptor/input.hpp +++ b/ngraph/core/include/ngraph/descriptor/input.hpp @@ -12,8 +12,7 @@ #include "openvino/core/descriptor/input.hpp" namespace ngraph { -class Node; - +using ov::Node; namespace descriptor { // Describes a tensor that is an input to an op, directly or indirectly via a tuple diff --git a/ngraph/core/include/ngraph/descriptor/output.hpp b/ngraph/core/include/ngraph/descriptor/output.hpp index d4b8bda4394..668ca57baeb 100644 --- a/ngraph/core/include/ngraph/descriptor/output.hpp +++ b/ngraph/core/include/ngraph/descriptor/output.hpp @@ -17,13 +17,7 @@ #include "openvino/core/descriptor/output.hpp" namespace ngraph { -// The forward declaration of Node is needed here because Node has a deque of -// Outputs, and Output is an incomplete type at this point. STL containers of -// incomplete type have undefined behavior according to the C++11 standard, and -// in practice including node.hpp here was causing compilation errors on some -// systems (namely macOS). -class Node; - +using ov::Node; namespace descriptor { // Describes an output tensor of an op using ov::descriptor::Output; diff --git a/ngraph/core/include/ngraph/graph_util.hpp b/ngraph/core/include/ngraph/graph_util.hpp index c2318f1ed04..0fc8ae0221b 100644 --- a/ngraph/core/include/ngraph/graph_util.hpp +++ b/ngraph/core/include/ngraph/graph_util.hpp @@ -456,3 +456,6 @@ bool replace_output_update_name(Output node, const Output& node_inpu NGRAPH_API bool replace_node_update_name(std::shared_ptr target, std::shared_ptr replacement); } // namespace ngraph + +using ngraph::replace_node; +using ngraph::replace_output_update_name; diff --git a/ngraph/core/include/ngraph/node.hpp b/ngraph/core/include/ngraph/node.hpp index e72e1e8e1b1..8d4259f8c34 100644 --- a/ngraph/core/include/ngraph/node.hpp +++ b/ngraph/core/include/ngraph/node.hpp @@ -36,15 +36,11 @@ #include "ngraph/strides.hpp" #include "ngraph/type.hpp" #include "ngraph/variant.hpp" +#include "openvino/core/node.hpp" namespace ngraph { -template -class Input; -template -class Output; - -class Node; +using ov::Node; namespace runtime { class HostTensor; @@ -53,657 +49,44 @@ using HostTensor = runtime::HostTensor; using HostTensorPtr = std::shared_ptr; using HostTensorVector = std::vector; -/// EvaluationContext stores and manages a context (additional parameters, values and -/// environment) for evaluating ngraph::function. -using EvaluationContext = std::map>; - namespace op { -struct AutoBroadcastSpec; namespace v0 { class Result; } } // namespace op -namespace pattern { -class Matcher; -} +using EvaluationContext = std::map>; +using ResultVector = std::vector>; -using ResultVector = std::vector>; +const auto node_validation_failure_loc_string = ov::node_validation_failure_loc_string; +const auto check_single_output_arg = ov::check_single_output_arg; -NGRAPH_API -std::string node_validation_failure_loc_string(const Node* node); +const auto check_single_output_args = ov::check_single_output_args; -const std::shared_ptr& check_single_output_arg(const std::shared_ptr& node, size_t i); -NGRAPH_API -const NodeVector& check_single_output_args(const NodeVector& args); - -const std::shared_ptr& check_single_output_arg(const std::shared_ptr& node, size_t i); - -NGRAPH_API -OutputVector as_output_vector(const NodeVector& args); -NGRAPH_API -NodeVector as_node_vector(const OutputVector& values); -/// Returns a ResultVector referencing values. -NGRAPH_API -ResultVector as_result_vector(const OutputVector& values); +const auto as_output_vector = ov::as_output_vector; +const auto as_node_vector = ov::as_node_vector; +const auto as_result_vector = ov::as_result_vector; /// Alias useful for cloning using NodeMap = std::unordered_map>; -/// \brief Used in evaluator switch statement so that the case type and evaluate call -/// are guaranteed to have the types match. -/// -/// Use this in an evaluate_*() function like this -/// switch (arg0->get_element_type()) -/// { -/// TYPE_CASE(i8)(arg0, arg1, out, broadcast_spec); break; -/// TYPE_CASE(i16)(arg0, arg1, out, broadcast_spec); break; -/// -/// Each TYPE_CASE statement expands like this: -/// case element::Type_t::a: rc = evaluate(arg0, arg1, out, -/// broadcast_spec) -/// -/// \note Don't forget to put a break after each statement or it will fall through and generate -/// a runtime error. - -#define TYPE_CASE(a) \ - case element::Type_t::a: \ - rc = evaluate - /// Nodes are the backbone of the graph of Value dataflow. Every node has /// zero or more nodes as arguments and one value, which is either a tensor /// or a (possibly empty) tuple of values. -class NGRAPH_API Node : public std::enable_shared_from_this { - // For access to m_outputs. - friend class descriptor::Input; - - // For access to m_inputs and m_outputs. - template - friend class Input; - - // For access to m_outputs. - template - friend class Output; - -public: - /// \brief Verifies that attributes and inputs are consistent and computes output shapes - /// and element types. Must be implemented by concrete child classes so that it - /// can be run any number of times. - /// - /// Throws if the node is invalid. - virtual void validate_and_infer_types(); - - // Called in constructors during transition - void constructor_validate_and_infer_types(); - - using type_info_t = DiscreteTypeInfo; - -protected: - /// \brief Construct an unitialized Node - Node() = default; - /// \brief Copying a node - Node(const Node&); - /// \brief Assignment operator - Node& operator=(const Node&); - - /// \brief Construct an unitialized Node - /// \param output_size Number of outputs for this node - Node(size_t output_size); - - /// \brief Constructor for Node subclasses that have metaclasses. - /// \param arguments Output i will connect to input i - /// \param output_size Number of outputs for this node - Node(const OutputVector& arguments, size_t output_size = 1); - /// \brief Moves nodes that would be deleted from inputs to nodes to avoid stack overflows - /// on deep networks. - void safe_delete(NodeVector& nodes, bool recurse); - - /// \brief Marks an input as being relevant or irrelevant to the output shapes of this - /// node. - /// \param i The index of the input to mark as relevant or irrelevant. - /// \param relevant true if the input is relevant to output shapes, false otherwise. - /// - /// This is used by the shape specialization pass to know which nodes must be statically - /// evaluated in order to complete shape specialization. (For example, the shape input of - /// DynReshape must be evaluated statically in order for the output shape to be - /// determined.) By default, all inputs are marked as shape-irrelevant. Overrides of - /// validate_and_infer_types should call this function to mark shape-relevant inputs. - void set_input_is_relevant_to_shape(size_t i, bool relevant = true); - - /// \brief Marks an input as being relevant or irrelevant to the output values of this - /// node. - /// \param i The index of the input to mark as relevant or irrelevant. - /// \param relevant true if the input is relevant to output values, false otherwise. - /// - /// This is used by the shape specialization pass to cut short evaluation in cases where - /// an input value does not actually have any effect on the output value of the node. (As - /// of this writing, the only example of this is ShapeOf.) By default, all inputs are - /// marked as value-relevant. Overrides of validate_and_infer_types should call this - /// function to mark value-irrelevant inputs. - void set_input_is_relevant_to_value(size_t i, bool relevant = true); - -public: - virtual ~Node(); - - virtual bool visit_attributes(AttributeVisitor&) { - return false; - } - /// \returns the autobroadcasr spec - virtual const op::AutoBroadcastSpec& get_autob() const; - - /// \brief Allows to get information about availability of evaluate method for the current - /// operation - // \returns true if evaluate is available - virtual bool has_evaluate() const; - /// \brief Evaluates the op on input_values putting results in output_values - /// \param output_values Tensors for the outputs to compute. One for each result - /// \param input_values Tensors for the inputs. One for each inputs. - /// \returns true if successful - virtual bool evaluate(const HostTensorVector& output_values, const HostTensorVector& input_values) const; - /// \brief Evaluates the op on input_values putting results in output_values - /// \param output_values Tensors for the outputs to compute. One for each result - /// \param input_values Tensors for the inputs. One for each inputs. - /// \param evaluation_context Storage of additional settings and attributes that can be used - /// when evaluating the op. - /// \returns true if successful - virtual bool evaluate(const HostTensorVector& output_values, - const HostTensorVector& input_values, - const EvaluationContext& evaluationContext) const; - virtual bool evaluate_lower(const HostTensorVector& output_values) const; - virtual bool evaluate_upper(const HostTensorVector& output_values) const; - - virtual bool constant_fold(OutputVector& output_values, const OutputVector& inputs_values); - /// \brief Decomposes the FusedOp into a sub-graph consisting of core ngraph ops - /// - /// \return A vector of nodes comprising the sub-graph. The order of output - /// tensors must match the match output tensors of the FusedOp - virtual OutputVector decompose_op() const { - return OutputVector(); - } - /// Returns the NodeTypeInfo for the node's class. - /// During transition to type_info, returns a dummy type_info for Node if the class - /// has not been updated yet. - virtual const type_info_t& get_type_info() const = 0; - const char* get_type_name() const { - return get_type_info().name; - } - /// Sets/replaces the arguments with new arguments. - void set_arguments(const NodeVector& arguments); - /// Sets/replaces the arguments with new arguments. - void set_arguments(const OutputVector& arguments); - /// Sets/replaces the arguments with new arguments. - void set_argument(size_t position, const Output& argument); - - void set_output_type(size_t i, const element::Type& element_type, const PartialShape& pshape); - - /// Sets the number of outputs - void set_output_size(size_t output_size); - - void invalidate_values(); - virtual void revalidate_and_infer_types() { - invalidate_values(); - validate_and_infer_types(); - } - /// \brief Get the string name for the type of the node, such as `Add` or `Multiply`. - /// The class name, must not contain spaces as it is used for codegen. - /// \returns A const reference to the node's type name - virtual std::string description() const; - /// \brief Get the unique name of the node. - /// \returns A const reference to the node's unique name. - const std::string& get_name() const; - - /// \brief Sets a friendly name for a node. This does not overwrite the unique name - /// of the node and is retrieved via get_friendly_name(). Used mainly for debugging. - /// The friendly name may be set exactly once. - /// \param name is the friendly name to set - void set_friendly_name(const std::string& name); - - /// \brief Gets the friendly name for a node. If no friendly name has been set via - /// set_friendly_name then the node's unique name is returned. - /// \returns A const reference to the node's friendly name. - const std::string& get_friendly_name() const; - - virtual bool is_dynamic() const; - size_t get_instance_id() const { - return m_instance_id; - } - /// \brief Writes a description of a node to a stream - /// \param os The stream; should be returned - /// \param depth How many levels of inputs to describe - /// \returns The stream os - virtual std::ostream& write_description(std::ostream& os, uint32_t depth = 0) const; - - /// Get control dependencies registered on the node - const std::vector>& get_control_dependencies() const; - - /// Get nodes dependent on this node - const std::vector& get_control_dependents() const; - - /// This node cannot execute until node executes - void add_control_dependency(std::shared_ptr node); - - /// Remove the dependency of this node on node - void remove_control_dependency(std::shared_ptr node); - - /// Remove all dependencies from this node - void clear_control_dependencies(); - - /// Remove this node as a dependency from all dependent nodes - void clear_control_dependents(); - - /// This node absorbs the control dependencies of source_node - void add_node_control_dependencies(std::shared_ptr source_node); - - /// This node becomes a dependent of every node dependent on source_node - void add_node_control_dependents(std::shared_ptr source_node); - - /// This node's control dependencies are replaced by replacement - void transfer_control_dependents(std::shared_ptr replacement); - - /// Returns the number of outputs from the node. - size_t get_output_size() const; - - /// Returns the element type for output i - const element::Type& get_output_element_type(size_t i) const; - - /// Checks that there is exactly one output and returns its element type - // TODO: deprecate in favor of node->get_output_element_type(0) with a suitable check in - // the calling code, or updates to the calling code if it is making an invalid assumption - // of only one output. - const element::Type& get_element_type() const; - - /// Returns the shape for output i - const Shape& get_output_shape(size_t i) const; - - /// Returns the partial shape for output i - const PartialShape& get_output_partial_shape(size_t i) const; - - /// Return the output to use when converting to an Output with no index specified. - /// Throws when not supported. - Output get_default_output() const; - Output get_default_output(); - - /// Returns the output of the default output, or throws if there is none - virtual size_t get_default_output_index() const; - /// Throws no default - size_t no_default_index() const; - - /// Checks that there is exactly one output and returns its shape - // TODO: deprecate in favor of node->get_output_shape(0) with a suitable check in the - // calling code, or updates to the calling code if it is making an invalid assumption of - // only one output. - const Shape& get_shape() const; - - /// Returns the tensor for output or input i - descriptor::Tensor& get_output_tensor(size_t i) const; - descriptor::Tensor& get_input_tensor(size_t i) const; - - /// Returns the tensor name for output i - NGRAPH_DEPRECATED("The tensor name was deprecated. Use get_output_tensor(i).get_names() instead.") - const std::string& get_output_tensor_name(size_t i) const; - - std::set> get_output_target_inputs(size_t i) const; - - /// Returns the number of inputs for the op - size_t get_input_size() const; - - /// Returns the element type of input i - // TODO: deprecate in favor of node->get_input_element_type(i) - const element::Type& get_input_element_type(size_t i) const; - - /// Returns the shape of input i - // TODO: deprecate in favor of node->get_input_shape(i) - const Shape& get_input_shape(size_t i) const; - - /// Returns the partial shape of input i - // TODO: deprecate in favor of node->get_input_partial_shape(i) - const PartialShape& get_input_partial_shape(size_t i) const; - - /// Returns the tensor name for input i - NGRAPH_DEPRECATED("The tensor name was deprecated. Use get_input_tensor(i).get_names() instead.") - const std::string& get_input_tensor_name(size_t i) const; - - std::unordered_set liveness_new_list; - std::unordered_set liveness_free_list; - - Node* get_input_node_ptr(size_t index) const; - std::shared_ptr get_input_node_shared_ptr(size_t index) const; - Output get_input_source_output(size_t i) const; - -public: - virtual std::shared_ptr clone_with_new_inputs(const OutputVector& inputs) const = 0; - - std::shared_ptr copy_with_new_inputs(const OutputVector& new_args) const; - - std::shared_ptr copy_with_new_inputs(const OutputVector& inputs, - const std::vector>& control_dependencies) const; - - /// True if this and node have one output with same element type and shape - bool has_same_type(std::shared_ptr node) const; - - using RTMap = std::map>; - - RTMap& get_rt_info() { - return m_rt_info; - } - const RTMap& get_rt_info() const { - return m_rt_info; - } - const std::unordered_set& get_provenance_tags() const; - void add_provenance_tag(const std::string& tag); - template - void add_provenance_tags(T tag_set) { - for (auto tag : tag_set) { - add_provenance_tag(tag); - } - } - /// \brief Adds tag_set to this node and all intermediate nodes above base - void add_provenance_tags_above(const OutputVector& base, const std::unordered_set& tag_set); - void remove_provenance_tag(const std::string& tag); - /// \brief Add node to additional nodes that receive tags - void add_provenance_group_member(const std::shared_ptr& node); - /// \brief Remove node to additional nodes that receive tags - void remove_provenance_group_member(const std::shared_ptr& node); - /// \brief Replace current_node with replacement_node and transfer tags - void replace_provenance_group_member(const std::shared_ptr& current_node, - const std::shared_ptr& replacement_node); - /// \return Provenance group nodes - const std::set>& get_provenance_group_members() const; - - /// \brief Add all nodes between this node and nodes in base as additional nodes to receive - /// provenance tags. - std::shared_ptr add_provenance_group_members_above(const OutputVector& base); - - // to be used when nodes are replaced - void merge_provenance_tags_from(const std::shared_ptr& source); - - /// Transfer provenance tags to replacement - void transfer_provenance_tags(const std::shared_ptr& replacement); - - /// Get all the nodes that uses the current node - NodeVector get_users(bool check_is_used = false) const; - - /// \return Version of this node - virtual size_t get_version() const { - return get_type_info().version; - } - - NGRAPH_DEPRECATED("This method is deprecated and will be removed soon.") - virtual std::shared_ptr get_default_value() const { - return nullptr; - } - /// Use instance ids for comparison instead of memory addresses to improve determinism - bool operator<(const Node& other) const { - return m_instance_id < other.m_instance_id; - } - /// \return A vector containing a handle for each of this node's inputs, in order. - // TODO: Rename to get_inputs()? - std::vector> inputs(); - - /// \return A vector containing a handle for each of this node's inputs, in order. - std::vector> inputs() const; - - /// \return A vector containing the values for each input - std::vector> input_values() const; - - /// \return A vector containing a handle for each of this node's outputs, in order. - // TODO: Rename to get_outputs()? - std::vector> outputs(); - - /// \return A vector containing a handle for each of this node's outputs, in order. - std::vector> outputs() const; - - /// \return A handle to the `input_index`th input of this node. - /// \throw std::out_of_range if the node does not have at least `input_index+1` inputs. - Input input(size_t input_index); - - /// \return A handle to the `input_index`th input of this node. - /// \throw std::out_of_range if the node does not have at least `input_index+1` inputs. - Input input(size_t input_index) const; - - Output input_value(size_t input_index) const; - - /// \return A handle to the `output_index`th output of this node. - /// \throw std::out_of_range if the node does not have at least `output_index+1` outputs. - Output output(size_t output_index); - - /// \return A handle to the `output_index`th output of this node. - /// \throw std::out_of_range if the node does not have at least `output_index+1` outputs. - Output output(size_t output_index) const; - - NGRAPH_SUPPRESS_DEPRECATED_START - NGRAPH_DEPRECATED("This method is deprecated and will be removed soon.") - void set_op_annotations(std::shared_ptr op_annotations) { - m_op_annotations = op_annotations; - } - NGRAPH_DEPRECATED("This method is deprecated and will be removed soon.") - std::shared_ptr get_op_annotations() const { - return m_op_annotations; - } - NGRAPH_SUPPRESS_DEPRECATED_END - - virtual bool match_value(pattern::Matcher* matcher, - const Output& pattern_value, - const Output& graph_value); - - virtual bool match_node(pattern::Matcher* matcher, const Output& graph_value); - -private: - descriptor::Input& get_input_descriptor(size_t position); - descriptor::Output& get_output_descriptor(size_t position); - - std::vector m_control_dependents; - std::vector> m_control_dependencies; - std::string m_node_type; - size_t m_instance_id{m_next_instance_id.fetch_add(1)}; - std::string m_friendly_name; - std::string m_unique_name; - static std::atomic m_next_instance_id; - std::unordered_set m_provenance_tags; - std::set> m_provenance_group; - std::deque m_inputs; - std::deque m_outputs; - NGRAPH_SUPPRESS_DEPRECATED_START - std::shared_ptr m_op_annotations; - NGRAPH_SUPPRESS_DEPRECATED_END - std::map> m_rt_info; -}; +using ov::NodeValidationFailure; using NodeTypeInfo = Node::type_info_t; -NGRAPH_API std::ostream& operator<<(std::ostream&, const Node&); -NGRAPH_API std::ostream& operator<<(std::ostream&, const Node*); - -#define _NGRAPH_RTTI_EXPAND(X) X - -/// Helper macro that puts necessary declarations of RTTI block inside a class definition. -/// Should be used in the scope of class that requires type identification besides one provided by -/// C++ RTTI. -/// Recommended to be used for all classes that are inherited from class ngraph::Node to enable -/// pattern -/// matching for them. Accepts necessary type identification details like type of the operation, -/// version and optional parent class. -/// -/// Applying this macro within a class definition provides declaration of type_info static -/// constant for backward compatibility with old RTTI definition for Node, -/// static function get_type_info_static which returns a reference to an object that is equal to -/// type_info but not necessary to the same object, and get_type_info virtual function that -/// overrides Node::get_type_info and returns a reference to the same object that -/// get_type_info_static gives. -/// -/// Use this macro as a public part of the class definition: -/// -/// class MyOp : public Node -/// { -/// public: -/// // Don't use Node as a parent for type_info, it doesn't have any value and -/// prohibited -/// NGRAPH_RTTI_DECLARATION; -/// -/// ... -/// }; -/// -/// class MyInheritedOp : public MyOp -/// { -/// public: -/// NGRAPH_RTTI_DECLARATION; -/// -/// ... -/// }; -/// -/// To complete type identification for a class, use NGRAPH_RTTI_DEFINITION. -/// -#define NGRAPH_RTTI_DECLARATION \ - static const ::ngraph::Node::type_info_t type_info; \ - const ::ngraph::Node::type_info_t& get_type_info() const override; \ - static const ::ngraph::Node::type_info_t& get_type_info_static() - -#define _NGRAPH_RTTI_DEFINITION_COMMON(CLASS) \ - const ::ngraph::Node::type_info_t& CLASS::get_type_info() const { \ - return get_type_info_static(); \ - } \ - const ::ngraph::Node::type_info_t CLASS::type_info = CLASS::get_type_info_static() -#define _NGRAPH_RTTI_DEFINITION_WITH_PARENT(CLASS, TYPE_NAME, _VERSION_INDEX, PARENT_CLASS) \ - const ::ngraph::Node::type_info_t& CLASS::get_type_info_static() { \ - static const ::ngraph::Node::type_info_t type_info_static{TYPE_NAME, \ - _VERSION_INDEX, \ - &PARENT_CLASS::get_type_info_static()}; \ - return type_info_static; \ - } \ - _NGRAPH_RTTI_DEFINITION_COMMON(CLASS) - -#define _NGRAPH_RTTI_DEFINITION_NO_PARENT(CLASS, TYPE_NAME, _VERSION_INDEX) \ - const ::ngraph::Node::type_info_t& CLASS::get_type_info_static() { \ - static const ::ngraph::Node::type_info_t type_info_static{TYPE_NAME, _VERSION_INDEX}; \ - return type_info_static; \ - } \ - _NGRAPH_RTTI_DEFINITION_COMMON(CLASS) - -#define _NGRAPH_RTTI_DEFINITION_SELECTOR(_1, _2, _3, _4, NAME, ...) NAME - -/// Complementary to NGRAPH_RTTI_DECLARATION, this helper macro _defines_ items _declared_ by -/// NGRAPH_RTTI_DECLARATION. -/// Should be used outside the class definition scope in place where ODR is ensured. -/// -/// \param CLASS is a C++ name of the class where corresponding NGRAPH_RTTI_DECLARATION was applied. -/// \param TYPE_NAME a string literal of type const char* that names your class in type -/// identification namespace; -/// It is your choice how to name it, but it should be unique among all -/// NGRAPH_RTTI_DECLARATION-enabled classes that can be -/// used in conjunction with each other in one transformation flow. -/// \param _VERSION_INDEX is an unsigned integer index to distinguish different versions of -/// operations that shares the same TYPE_NAME -/// \param PARENT_CLASS is an optional direct or indirect parent class for this class; define -/// it only in case if there is a need to capture any operation from some group of operations -/// that all derived from some common base class. Don't use Node as a parent, it is a base -/// class -/// for all operations and doesn't provide ability to define some perfect subset of -/// operations. PARENT_CLASS should define RTTI with NGRAPH_RTTI_{DECLARATION/DEFINITION} -/// macros. -/// -/// Examples (see corresponding declarations in NGRAPH_RTTI_DECLARATION description): -/// -/// NGRAPH_RTTI_DEFINITION(MyOp,"MyOp", 1); -/// NGRAPH_RTTI_DEFINITION(MyInheritedOp, "MyInheritedOp", 1, MyOp) -/// -/// For convenience, TYPE_NAME and CLASS name are recommended to be the same. -/// -#define NGRAPH_RTTI_DEFINITION(...) \ - _NGRAPH_RTTI_EXPAND(_NGRAPH_RTTI_DEFINITION_SELECTOR(__VA_ARGS__, \ - _NGRAPH_RTTI_DEFINITION_WITH_PARENT, \ - _NGRAPH_RTTI_DEFINITION_NO_PARENT)(__VA_ARGS__)) - // Like an Output but with a Node* instead of a shared_ptr -struct RawNodeOutput { - RawNodeOutput(const Output& value) : node(value.get_node()), index(value.get_index()) {} - RawNodeOutput(Node* node, size_t index) : node(node), index(index) {} - RawNodeOutput(const RawNodeOutput&) = default; - RawNodeOutput() = default; - RawNodeOutput& operator=(const RawNodeOutput&) = default; - - Node* node; - size_t index{0}; - - operator Output() { - return Output(node->shared_from_this(), index); - } - bool operator==(const RawNodeOutput& other) const { - return node == other.node && index == other.index; - } - bool operator!=(const RawNodeOutput& other) const { - return !(*this == other); - } - bool operator<(const RawNodeOutput& other) const { - return node < other.node || (node == other.node && index < other.index); - } - bool operator>(const RawNodeOutput& other) const { - return node > other.node || (node == other.node && index > other.index); - } - bool operator<=(const RawNodeOutput& other) const { - return !(*this > other); - } - bool operator>=(const RawNodeOutput& other) const { - return !(*this < other); - } -}; +using ov::RawNodeOutput; using RawNodeOutputMap = std::map>; -class NGRAPH_API NodeValidationFailure : public CheckFailure { -public: - NodeValidationFailure(const CheckLocInfo& check_loc_info, const Node* node, const std::string& explanation) - : CheckFailure(check_loc_info, node_validation_failure_loc_string(node), explanation) {} -}; -} // namespace ngraph -#define NODE_VALIDATION_CHECK(node, ...) NGRAPH_CHECK_HELPER(::ngraph::NodeValidationFailure, (node), __VA_ARGS__) +using ov::check_new_args_count; -namespace ngraph { -template -void check_new_args_count(const Node* node, T new_args) { - NODE_VALIDATION_CHECK(node, - new_args.size() == node->input_values().size(), - "clone_with_new_inputs() expected ", - node->input_values().size(), - " argument", - (node->input_values().size() == 1 ? "" : "s"), - " but got ", - new_args.size()); -} +#define NGRAPH_RTTI_DECLARATION OPENVINO_RTTI_DECLARATION + +#define NGRAPH_RTTI_DEFINITION(...) OPENVINO_RTTI_DEFINITION(__VA_ARGS__) } // namespace ngraph - -namespace ov { -/// \brief Visits a reference to a node that has been registered with the visitor. -template <> -class NGRAPH_API AttributeAdapter> : public VisitorAdapter { -public: - AttributeAdapter(std::shared_ptr& value); - - bool visit_attributes(AttributeVisitor& visitor) override; - static constexpr DiscreteTypeInfo type_info{"AttributeAdapter>", 0}; - const DiscreteTypeInfo& get_type_info() const override { - return type_info; - } - -protected: - std::shared_ptr& m_ref; -}; - -template <> -class NGRAPH_API AttributeAdapter : public VisitorAdapter { -public: - AttributeAdapter(ngraph::NodeVector& ref); - - bool visit_attributes(AttributeVisitor& visitor) override; - - static constexpr DiscreteTypeInfo type_info{"AttributeAdapter", 0}; - const DiscreteTypeInfo& get_type_info() const override { - return type_info; - } - -protected: - ngraph::NodeVector& m_ref; -}; - -} // namespace ov diff --git a/ngraph/core/include/ngraph/node_input.hpp b/ngraph/core/include/ngraph/node_input.hpp index 0819e85dba4..51fb4ebc0fc 100644 --- a/ngraph/core/include/ngraph/node_input.hpp +++ b/ngraph/core/include/ngraph/node_input.hpp @@ -12,112 +12,9 @@ #include "ngraph/shape.hpp" #include "ngraph/type/element_type.hpp" #include "ngraph/variant.hpp" +#include "openvino/core/node_input.hpp" namespace ngraph { -class Node; - -template -class Output; - -template -class Input {}; - -/// \brief A handle for one of a node's inputs. -template <> -class NGRAPH_API Input { -public: - /// \brief Constructs a Input. - /// \param node Pointer to the node for the input handle. - /// \param index The index of the input. - Input(Node* node, size_t index); - - /// \return A pointer to the node referenced by this input handle. - Node* get_node() const; - /// \return The index of the input referred to by this input handle. - size_t get_index() const; - /// \return The element type of the input referred to by this input handle. - const element::Type& get_element_type() const; - /// \return The shape of the input referred to by this input handle. - const Shape& get_shape() const; - /// \return The partial shape of the input referred to by this input handle. - const PartialShape& get_partial_shape() const; - /// \return A handle to the output that is connected to this input. - Output get_source_output() const; - /// \return A reference to the tensor descriptor for this input. - descriptor::Tensor& get_tensor() const; - /// \return A shared pointer to the tensor descriptor for this input. - std::shared_ptr get_tensor_ptr() const; - /// \return true if this input is relevant to its node's output shapes; else false. - bool get_is_relevant_to_shapes() const; - /// \return true if this input is relevant to its node's output values; else false. - bool get_is_relevant_to_values() const; - - /// \brief Replaces the source output of this input. - /// \param new_source_output A handle for the output that will replace this input's source. - void replace_source_output(const Output& new_source_output) const; - - /// \return The reference to runtime info map - RTMap& get_rt_info(); - /// \return The constant reference to runtime info map - const RTMap& get_rt_info() const; - - bool operator==(const Input& other) const; - bool operator!=(const Input& other) const; - bool operator<(const Input& other) const; - bool operator>(const Input& other) const; - bool operator<=(const Input& other) const; - bool operator>=(const Input& other) const; - -private: - Node* const m_node; - const size_t m_index; -}; - -/// \brief A handle for one of a node's inputs. -template <> -class NGRAPH_API Input { -public: - /// \brief Constructs a Input. - /// \param node Pointer to the node for the input handle. - /// \param index The index of the input. - Input(const Node* node, size_t index); - - /// \return A pointer to the node referenced by this input handle. - const Node* get_node() const; - /// \return The index of the input referred to by this input handle. - size_t get_index() const; - /// \return The element type of the input referred to by this input handle. - const element::Type& get_element_type() const; - /// \return The shape of the input referred to by this input handle. - const Shape& get_shape() const; - /// \return The partial shape of the input referred to by this input handle. - const PartialShape& get_partial_shape() const; - /// \return A handle to the output that is connected to this input. - Output get_source_output() const; - /// \return A reference to the tensor descriptor for this input. - descriptor::Tensor& get_tensor() const; - /// \return A shared pointer to the tensor descriptor for this input. - std::shared_ptr get_tensor_ptr() const; - /// \return true if this input is relevant to its node's output shapes; else false. - bool get_is_relevant_to_shapes() const; - /// \return true if this input is relevant to its node's output values; else false. - bool get_is_relevant_to_values() const; - - /// \return The constant reference to runtime info map - const RTMap& get_rt_info() const; - - bool operator==(const Input& other) const; - bool operator!=(const Input& other) const; - bool operator<(const Input& other) const; - bool operator>(const Input& other) const; - bool operator<=(const Input& other) const; - bool operator>=(const Input& other) const; - -private: - const Node* const m_node; - const size_t m_index; -}; - -NGRAPH_API std::ostream& operator<<(std::ostream& out, const Input& input); -NGRAPH_API std::ostream& operator<<(std::ostream& out, const Input& input); +using ov::Input; +using ov::Node; } // namespace ngraph diff --git a/ngraph/core/include/ngraph/node_output.hpp b/ngraph/core/include/ngraph/node_output.hpp index 56f3486bcf8..26154e1cd72 100644 --- a/ngraph/core/include/ngraph/node_output.hpp +++ b/ngraph/core/include/ngraph/node_output.hpp @@ -13,159 +13,9 @@ #include "ngraph/shape.hpp" #include "ngraph/type/element_type.hpp" #include "ngraph/variant.hpp" +#include "openvino/core/node_output.hpp" namespace ngraph { -class Node; - -template -class Input; - -template -class Output {}; - -/// \brief A handle for one of a node's outputs. -template <> -class NGRAPH_API Output { -public: - /// \brief Constructs a Output. - /// \param node A pointer to the node for the output handle. - /// \param index The index of the output. - Output(Node* node, size_t index); - - /// \brief Constructs a Output. - /// \param node A `shared_ptr` to the node for the output handle. - /// \param index The index of the output. - /// - /// TODO: Make a plan to deprecate this. - Output(const std::shared_ptr& node, size_t index); - - /// \brief Constructs a Output, referencing the zeroth output of the node. - /// \param node A `shared_ptr` to the node for the output handle. - template - Output(const std::shared_ptr& node) : Output(node ? node->get_default_output() : Output()) {} - - /// A null output - Output() = default; - - void reset(); - - /// This output position for a different node - Output for_node(const std::shared_ptr& node); - /// \return A pointer to the node referred to by this output handle. - Node* get_node() const; - /// \return A `shared_ptr` to the node referred to by this output handle. - /// - /// TODO: Make a plan to deprecate this. - std::shared_ptr get_node_shared_ptr() const; - - /// \return The index of the output referred to by this output handle. - size_t get_index() const; - /// \return A reference to the tensor descriptor for this output. - descriptor::Tensor& get_tensor() const; - /// \return A shared point to the tensor ptr for this output. - std::shared_ptr get_tensor_ptr() const; - /// \return The element type of the output referred to by this output handle. - const element::Type& get_element_type() const; - /// \return The shape of the output referred to by this output handle. - const Shape& get_shape() const; - /// \return The partial shape of the output referred to by this output handle. - const PartialShape& get_partial_shape() const; - - /// \return The reference to runtime info map - RTMap& get_rt_info(); - /// \return The constant reference to runtime info map - const RTMap& get_rt_info() const; - - /// \return A set containing handles for all inputs targeted by the output referenced by - /// this output handle. - std::set> get_target_inputs() const; - - /// \brief Removes a target input from the output referenced by this output handle. - /// \param target_input The target input to remove. - /// - // TODO(amprocte): Investigate whether this really ought to be public. - void remove_target_input(const Input& target_input) const; - - /// \brief Replace all users of this value with replacement - void replace(const Output& replacement); - - bool operator==(const Output& other) const; - bool operator!=(const Output& other) const; - bool operator<(const Output& other) const; - bool operator>(const Output& other) const; - bool operator<=(const Output& other) const; - bool operator>=(const Output& other) const; - -private: - std::shared_ptr m_node; - size_t m_index{0}; -}; - -template <> -class NGRAPH_API Output { -public: - /// \brief Constructs a Output. - /// \param node A pointer to the node for the output handle. - /// \param index The index of the output. - Output(const Node* node, size_t index); - - /// \brief Constructs a Output. - /// \param node A `shared_ptr` to the node for the output handle. - /// \param index The index of the output. - /// - /// TODO: Make a plan to deprecate this. - Output(const std::shared_ptr& node, size_t index); - - /// \brief Constructs a Output, referencing the zeroth output of the node. - /// \param node A `shared_ptr` to the node for the output handle. - template - Output(const std::shared_ptr& node) : Output(node ? node->get_default_output() : Output()) {} - - /// A null output - Output() = default; - - void reset(); - - /// This output position for a different node - Output for_node(const std::shared_ptr& node); - - /// \return A pointer to the node referred to by this output handle. - const Node* get_node() const; - /// \return A `shared_ptr` to the node referred to by this output handle. - /// - /// TODO: Make a plan to deprecate this. - std::shared_ptr get_node_shared_ptr() const; - /// \return The index of the output referred to by this output handle. - size_t get_index() const; - /// \return A reference to the tensor descriptor for this output. - descriptor::Tensor& get_tensor() const; - /// \return A shared point to the tensor ptr for this output. - std::shared_ptr get_tensor_ptr() const; - /// \return The element type of the output referred to by this output handle. - const element::Type& get_element_type() const; - /// \return The shape of the output referred to by this output handle. - const Shape& get_shape() const; - /// \return The partial shape of the output referred to by this output handle. - const PartialShape& get_partial_shape() const; - - /// \return The constant reference to runtime info map - const RTMap& get_rt_info() const; - /// \return A set containing handles for all inputs targeted by the output referenced by - /// this output handle. - std::set> get_target_inputs() const; - - bool operator==(const Output& other) const; - bool operator!=(const Output& other) const; - bool operator<(const Output& other) const; - bool operator>(const Output& other) const; - bool operator<=(const Output& other) const; - bool operator>=(const Output& other) const; - -private: - std::shared_ptr m_node; - size_t m_index{0}; -}; - -NGRAPH_API std::ostream& operator<<(std::ostream& out, const Output& output); -NGRAPH_API std::ostream& operator<<(std::ostream& out, const Output& output); +using ov::Node; +using ov::Output; } // namespace ngraph diff --git a/ngraph/core/include/ngraph/output_vector.hpp b/ngraph/core/include/ngraph/output_vector.hpp index 4a761ac47db..63eaf62388c 100644 --- a/ngraph/core/include/ngraph/output_vector.hpp +++ b/ngraph/core/include/ngraph/output_vector.hpp @@ -7,12 +7,10 @@ #include #include +#include "openvino/core/node_vector.hpp" + namespace ngraph { -class Node; -template -class Output; - -using NodeVector = std::vector>; -using OutputVector = std::vector>; +using NodeVector = ov::NodeVector; +using OutputVector = ov::OutputVector; } // namespace ngraph diff --git a/ngraph/core/include/ngraph/rt_info.hpp b/ngraph/core/include/ngraph/rt_info.hpp index 7d001cddfb0..c858f06f8a5 100644 --- a/ngraph/core/include/ngraph/rt_info.hpp +++ b/ngraph/core/include/ngraph/rt_info.hpp @@ -23,3 +23,5 @@ void copy_runtime_info(const ngraph::NodeVector& from, std::shared_ptr&); + explicit HostTensor(const Output&); explicit HostTensor(const std::shared_ptr& constant); virtual ~HostTensor() override; diff --git a/ngraph/core/include/ngraph/type.hpp b/ngraph/core/include/ngraph/type.hpp index 6980162a3f3..4495aed2b3e 100644 --- a/ngraph/core/include/ngraph/type.hpp +++ b/ngraph/core/include/ngraph/type.hpp @@ -9,31 +9,7 @@ namespace ngraph { using ov::DiscreteTypeInfo; -/// \brief Tests if value is a pointer/shared_ptr that can be statically cast to a -/// Type*/shared_ptr -template -typename std::enable_if< - std::is_convertible()->get_type_info().is_castable(Type::type_info)), bool>::value, - bool>::type -is_type(Value value) { - return ov::is_type(value); -} - -/// Casts a Value* to a Type* if it is of type Type, nullptr otherwise -template -typename std::enable_if(std::declval())), Type*>::value, - Type*>::type -as_type(Value value) { - return ov::as_type(value); -} - -/// Casts a std::shared_ptr to a std::shared_ptr if it is of type -/// Type, nullptr otherwise -template -typename std::enable_if< - std::is_convertible(std::declval())), std::shared_ptr>::value, - std::shared_ptr>::type -as_type_ptr(Value value) { - return ov::as_type_ptr(value); -} +using ov::as_type; +using ov::as_type_ptr; +using ov::is_type; } // namespace ngraph diff --git a/ngraph/core/include/ngraph/util.hpp b/ngraph/core/include/ngraph/util.hpp index 257912d455a..2f4d2c376a4 100644 --- a/ngraph/core/include/ngraph/util.hpp +++ b/ngraph/core/include/ngraph/util.hpp @@ -26,8 +26,11 @@ #include "ngraph/runtime/tensor.hpp" #include "ngraph/shape.hpp" -namespace ngraph { +namespace ov { class Node; +} +namespace ngraph { +using ov::Node; class stopwatch; namespace runtime { diff --git a/ngraph/core/include/ngraph/validation_util.hpp b/ngraph/core/include/ngraph/validation_util.hpp index 84d88b43fd7..560a6c3b164 100644 --- a/ngraph/core/include/ngraph/validation_util.hpp +++ b/ngraph/core/include/ngraph/validation_util.hpp @@ -344,3 +344,5 @@ void infer_conv_backprop_auto_padding(const Shape& input_data_shape, CoordinateDiff& pads_end); } // namespace opset1 } // namespace ngraph + +using ngraph::get_constant_from_source; diff --git a/ngraph/core/include/ngraph/variant.hpp b/ngraph/core/include/ngraph/variant.hpp index 1da8b047988..cf42b298296 100644 --- a/ngraph/core/include/ngraph/variant.hpp +++ b/ngraph/core/include/ngraph/variant.hpp @@ -9,28 +9,18 @@ #include "openvino/core/variant.hpp" +namespace ov { +class Node; +} namespace ngraph { +using ov::Node; using ov::VariantTypeInfo; using ov::Variant; using ov::VariantImpl; using ov::VariantWrapper; -template -inline std::shared_ptr make_variant(const T& p) { - return ov::make_variant(p); -} -template -inline std::shared_ptr make_variant(const char (&s)[N]) { - return ov::make_variant(s); -} - -#if defined(ENABLE_UNICODE_PATH_SUPPORT) && defined(_WIN32) -template -inline std::shared_ptr make_variant(const wchar_t (&s)[N]) { - return ov::make_variant(s); -} -#endif +using ov::make_variant; using ov::RTMap; } // namespace ngraph diff --git a/ngraph/core/include/openvino/core/attribute_visitor.hpp b/ngraph/core/include/openvino/core/attribute_visitor.hpp index fa23b48901f..5d2b3175c8d 100644 --- a/ngraph/core/include/openvino/core/attribute_visitor.hpp +++ b/ngraph/core/include/openvino/core/attribute_visitor.hpp @@ -12,10 +12,8 @@ #include "openvino/core/type.hpp" #include "openvino/core/type/element_type.hpp" -namespace ngraph { -class Node; -} namespace ov { +class Node; class Function; template class ValueAccessor; @@ -126,15 +124,15 @@ public: /// /// No node may be used as an attribute unless it has already been registered with an ID. /// References to nodes are visited with a ValueAccessor of their ID. - virtual void register_node(const std::shared_ptr& node, node_id_t id = invalid_node_id); + virtual void register_node(const std::shared_ptr& node, node_id_t id = invalid_node_id); /// Returns the node with the given id, or nullptr if there is no registered node - virtual std::shared_ptr get_registered_node(node_id_t id); + virtual std::shared_ptr get_registered_node(node_id_t id); /// Returns the id for the node, or -1 if the node is not registered - virtual node_id_t get_registered_node_id(const std::shared_ptr& node); + virtual node_id_t get_registered_node_id(const std::shared_ptr& node); protected: std::vector m_context; - std::unordered_map, node_id_t> m_node_id_map; - std::unordered_map> m_id_node_map; + std::unordered_map, node_id_t> m_node_id_map; + std::unordered_map> m_id_node_map; }; } // namespace ov diff --git a/ngraph/core/include/openvino/core/descriptor/input.hpp b/ngraph/core/include/openvino/core/descriptor/input.hpp index 18a126d042c..437b44f6a60 100644 --- a/ngraph/core/include/openvino/core/descriptor/input.hpp +++ b/ngraph/core/include/openvino/core/descriptor/input.hpp @@ -7,37 +7,35 @@ #include #include +#include "openvino/core/core_visibility.hpp" #include "openvino/core/descriptor/tensor.hpp" #include "openvino/core/variant.hpp" -namespace ngraph { -class Node; -} - namespace ov { +class Node; namespace descriptor { class Output; // Describes a tensor that is an input to an op, directly or indirectly via a tuple -class NGRAPH_API Input { - friend class ngraph::Node; +class OPENVINO_API Input { + friend class ov::Node; public: /// \param node The node that owns this input /// \param index The position of this this tensor in all input tensors /// \param output The output that supplies a value for this input - Input(ngraph::Node* node, size_t index, Output& output); + Input(Node* node, size_t index, Output& output); /// \brief Create an Input that is not connected to an output /// \param node The node that owns this input /// \param index The position of this this tensor in all input tensors - Input(ngraph::Node* node, size_t index); + Input(Node* node, size_t index); ~Input(); /// \return the node that this is an input of - std::shared_ptr get_node() const; + std::shared_ptr get_node() const; /// \return the raw pointer to the node that this is an input of - ngraph::Node* get_raw_pointer_node() const { + Node* get_raw_pointer_node() const { return m_node; } /// \return the position within all supplied tensors of this input @@ -71,7 +69,7 @@ public: /// \brief Replace the current output that supplies a value for this input with output i /// of node - void replace_output(const std::shared_ptr& node, size_t i); + void replace_output(const std::shared_ptr& node, size_t i); /// \brief Replace the current output that supplies a value for this input with output void replace_output(Output& output); /// \brief Remove the output from this input. The node will not be valid until another @@ -114,9 +112,9 @@ protected: std::shared_ptr get_tensor_ptr(); // owner of an argument node (in lieu of m_arguments) - std::shared_ptr m_src_node; - ngraph::Node* m_node; // The node we are an input for - size_t m_index; // Index into all input tensors + std::shared_ptr m_src_node; + Node* m_node; // The node we are an input for + size_t m_index; // Index into all input tensors Output* m_output; RTMap m_rt_info; diff --git a/ngraph/core/include/openvino/core/descriptor/output.hpp b/ngraph/core/include/openvino/core/descriptor/output.hpp index 46ea1fd5269..c4ec21d5ca6 100644 --- a/ngraph/core/include/openvino/core/descriptor/output.hpp +++ b/ngraph/core/include/openvino/core/descriptor/output.hpp @@ -10,37 +10,35 @@ #include #include -#include "ngraph/node_output.hpp" +#include "openvino/core/core_visibility.hpp" #include "openvino/core/descriptor/input.hpp" #include "openvino/core/descriptor/tensor.hpp" +#include "openvino/core/node_output.hpp" #include "openvino/core/variant.hpp" -namespace ngraph { +namespace ov { // The forward declaration of Node is needed here because Node has a deque of // Outputs, and Output is an incomplete type at this point. STL containers of // incomplete type have undefined behavior according to the C++11 standard, and // in practice including node.hpp here was causing compilation errors on some // systems (namely macOS). class Node; -} // namespace ngraph - -namespace ov { namespace descriptor { // Describes an output tensor of an op -class NGRAPH_API Output { +class OPENVINO_API Output { public: Output() : m_node(nullptr), m_index(0), m_tensor(nullptr), m_inputs() {} /// \param node Node that owns this output. /// \param index Position of the output tensor in all output tensors /// \param tensor The tensor where the value will be written - Output(ngraph::Node* node, size_t index, const std::shared_ptr& tensor); + Output(Node* node, size_t index, const std::shared_ptr& tensor); - std::shared_ptr get_node() const; + std::shared_ptr get_node() const; size_t get_index() const { return m_index; } - ngraph::Output get_output() const; + ov::Output get_output() const; std::shared_ptr get_tensor_ptr() const { return m_tensor; } @@ -74,7 +72,7 @@ public: Output& operator=(const Output&) = default; protected: - ngraph::Node* m_node; + Node* m_node; size_t m_index; std::shared_ptr m_tensor; RTMap m_rt_info; diff --git a/ngraph/core/include/openvino/core/descriptor/tensor.hpp b/ngraph/core/include/openvino/core/descriptor/tensor.hpp index b3db6901d5e..cc4c196c3e5 100644 --- a/ngraph/core/include/openvino/core/descriptor/tensor.hpp +++ b/ngraph/core/include/openvino/core/descriptor/tensor.hpp @@ -11,28 +11,25 @@ #include #include "ngraph/shape.hpp" +#include "openvino/core/core_visibility.hpp" #include "openvino/core/partial_shape.hpp" #include "openvino/core/type/element_type.hpp" namespace ngraph { -class Node; - namespace runtime { class HostTensor; } using HostTensorPtr = std::shared_ptr; - } // namespace ngraph + namespace ov { +class Node; namespace descriptor { /// \brief Compile-time descriptor of a first-class value that is a tensor. -class NGRAPH_API Tensor { +class OPENVINO_API Tensor { public: Tensor(const element::Type& element_type, const PartialShape& pshape, const std::string& name); - Tensor(const element::Type& element_type, - const PartialShape& pshape, - ngraph::Node* node, - size_t node_output_number); + Tensor(const element::Type& element_type, const PartialShape& pshape, Node* node, size_t node_output_number); Tensor(const Tensor&) = delete; Tensor& operator=(const Tensor&) = delete; @@ -102,7 +99,7 @@ protected: std::unordered_set m_names; }; -NGRAPH_API +OPENVINO_API std::ostream& operator<<(std::ostream&, const ov::descriptor::Tensor&); } // namespace descriptor } // namespace ov diff --git a/ngraph/core/include/openvino/core/node.hpp b/ngraph/core/include/openvino/core/node.hpp new file mode 100644 index 00000000000..3ba65a5cd78 --- /dev/null +++ b/ngraph/core/include/openvino/core/node.hpp @@ -0,0 +1,713 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ngraph/check.hpp" +#include "ngraph/deprecated.hpp" +#include "ngraph/op/util/attr_types.hpp" +#include "ngraph/op/util/op_annotations.hpp" +#include "ngraph/op/util/variable.hpp" +#include "ngraph/op/util/variable_value.hpp" +#include "ngraph/strides.hpp" +#include "openvino/core/attribute_visitor.hpp" +#include "openvino/core/core_visibility.hpp" +#include "openvino/core/descriptor/input.hpp" +#include "openvino/core/descriptor/output.hpp" +#include "openvino/core/descriptor/tensor.hpp" +#include "openvino/core/node_input.hpp" +#include "openvino/core/node_output.hpp" +#include "openvino/core/node_vector.hpp" +#include "openvino/core/type.hpp" +#include "openvino/core/variant.hpp" + +namespace ngraph { + +namespace runtime { +class HostTensor; +} // namespace runtime + +namespace op { +struct AutoBroadcastSpec; + +namespace v0 { +class Result; +} // namespace v0 +} // namespace op + +namespace pattern { +class Matcher; +} // namespace pattern +} // namespace ngraph + +namespace ov { +using HostTensor = ngraph::runtime::HostTensor; +using HostTensorPtr = std::shared_ptr; +using HostTensorVector = std::vector; + +template +class Input; + +template +class Output; + +class Node; + +/// EvaluationContext stores and manages a context (additional parameters, values and +/// environment) for evaluating ngraph::function. +using EvaluationContext = std::map>; + +using ResultVector = std::vector>; + +OPENVINO_API +std::string node_validation_failure_loc_string(const Node* node); + +OPENVINO_API +const std::shared_ptr& check_single_output_arg(const std::shared_ptr& node, size_t i); +OPENVINO_API +const NodeVector& check_single_output_args(const NodeVector& args); + +OPENVINO_API +OutputVector as_output_vector(const NodeVector& args); +OPENVINO_API +NodeVector as_node_vector(const OutputVector& values); +/// Returns a ResultVector referencing values. +OPENVINO_API +ResultVector as_result_vector(const OutputVector& values); + +/// Alias useful for cloning +using NodeMap = std::unordered_map>; + +/// \brief Used in evaluator switch statement so that the case type and evaluate call +/// are guaranteed to have the types match. +/// +/// Use this in an evaluate_*() function like this +/// switch (arg0->get_element_type()) +/// { +/// TYPE_CASE(i8)(arg0, arg1, out, broadcast_spec); break; +/// TYPE_CASE(i16)(arg0, arg1, out, broadcast_spec); break; +/// ... +/// } +/// +/// Each TYPE_CASE statement expands like this: +/// case element::Type_t::a: rc = evaluate(arg0, arg1, out, +/// broadcast_spec) +/// +/// \note Don't forget to put a break after each statement or it will fall through and generate +/// a runtime error. + +#define TYPE_CASE(a) \ + case element::Type_t::a: \ + rc = evaluate + +/// Nodes are the backbone of the graph of Value dataflow. Every node has +/// zero or more nodes as arguments and one value, which is either a tensor +/// or a (possibly empty) tuple of values. +class OPENVINO_API Node : public std::enable_shared_from_this { + // For access to m_outputs. + friend class descriptor::Input; + + // For access to m_inputs and m_outputs. + template + friend class Input; + + // For access to m_outputs. + template + friend class Output; + +public: + /// \brief Verifies that attributes and inputs are consistent and computes output shapes + /// and element types. Must be implemented by concrete child classes so that it + /// can be run any number of times. + /// + /// Throws if the node is invalid. + virtual void validate_and_infer_types(); + + // Called in constructors during transition + void constructor_validate_and_infer_types(); + + using type_info_t = DiscreteTypeInfo; + +protected: + /// \brief Construct an unitialized Node + Node() = default; + /// \brief Copying a node + Node(const Node&); + /// \brief Assignment operator + Node& operator=(const Node&); + + /// \brief Construct an unitialized Node + /// \param output_size Number of outputs for this node + Node(size_t output_size); + + /// \brief Constructor for Node subclasses that have metaclasses. + /// \param arguments Output i will connect to input i + /// \param output_size Number of outputs for this node + Node(const OutputVector& arguments, size_t output_size = 1); + /// \brief Moves nodes that would be deleted from inputs to nodes to avoid stack overflows + /// on deep networks. + void safe_delete(NodeVector& nodes, bool recurse); + + /// \brief Marks an input as being relevant or irrelevant to the output shapes of this + /// node. + /// \param i The index of the input to mark as relevant or irrelevant. + /// \param relevant true if the input is relevant to output shapes, false otherwise. + /// + /// This is used by the shape specialization pass to know which nodes must be statically + /// evaluated in order to complete shape specialization. (For example, the shape input of + /// DynReshape must be evaluated statically in order for the output shape to be + /// determined.) By default, all inputs are marked as shape-irrelevant. Overrides of + /// validate_and_infer_types should call this function to mark shape-relevant inputs. + void set_input_is_relevant_to_shape(size_t i, bool relevant = true); + + /// \brief Marks an input as being relevant or irrelevant to the output values of this + /// node. + /// \param i The index of the input to mark as relevant or irrelevant. + /// \param relevant true if the input is relevant to output values, false otherwise. + /// + /// This is used by the shape specialization pass to cut short evaluation in cases where + /// an input value does not actually have any effect on the output value of the node. (As + /// of this writing, the only example of this is ShapeOf.) By default, all inputs are + /// marked as value-relevant. Overrides of validate_and_infer_types should call this + /// function to mark value-irrelevant inputs. + void set_input_is_relevant_to_value(size_t i, bool relevant = true); + +public: + virtual ~Node(); + + virtual bool visit_attributes(AttributeVisitor&) { + return false; + } + /// \returns the autobroadcasr spec + virtual const ngraph::op::AutoBroadcastSpec& get_autob() const; + + /// \brief Allows to get information about availability of evaluate method for the current + /// operation + // \returns true if evaluate is available + virtual bool has_evaluate() const; + /// \brief Evaluates the op on input_values putting results in output_values + /// \param output_values Tensors for the outputs to compute. One for each result + /// \param input_values Tensors for the inputs. One for each inputs. + /// \returns true if successful + virtual bool evaluate(const ov::HostTensorVector& output_values, const ov::HostTensorVector& input_values) const; + /// \brief Evaluates the op on input_values putting results in output_values + /// \param output_values Tensors for the outputs to compute. One for each result + /// \param input_values Tensors for the inputs. One for each inputs. + /// \param evaluation_context Storage of additional settings and attributes that can be used + /// when evaluating the op. + /// \returns true if successful + virtual bool evaluate(const ov::HostTensorVector& output_values, + const ov::HostTensorVector& input_values, + const EvaluationContext& evaluationContext) const; + virtual bool evaluate_lower(const ov::HostTensorVector& output_values) const; + virtual bool evaluate_upper(const ov::HostTensorVector& output_values) const; + + virtual bool constant_fold(OutputVector& output_values, const OutputVector& inputs_values); + /// \brief Decomposes the FusedOp into a sub-graph consisting of core ngraph ops + /// + /// \return A vector of nodes comprising the sub-graph. The order of output + /// tensors must match the match output tensors of the FusedOp + virtual OutputVector decompose_op() const { + return OutputVector(); + } + /// Returns the NodeTypeInfo for the node's class. + /// During transition to type_info, returns a dummy type_info for Node if the class + /// has not been updated yet. + virtual const type_info_t& get_type_info() const = 0; + const char* get_type_name() const { + return get_type_info().name; + } + /// Sets/replaces the arguments with new arguments. + void set_arguments(const NodeVector& arguments); + /// Sets/replaces the arguments with new arguments. + void set_arguments(const OutputVector& arguments); + /// Sets/replaces the arguments with new arguments. + void set_argument(size_t position, const Output& argument); + + void set_output_type(size_t i, const element::Type& element_type, const PartialShape& pshape); + + /// Sets the number of outputs + void set_output_size(size_t output_size); + + void invalidate_values(); + virtual void revalidate_and_infer_types() { + invalidate_values(); + validate_and_infer_types(); + } + /// \brief Get the string name for the type of the node, such as `Add` or `Multiply`. + /// The class name, must not contain spaces as it is used for codegen. + /// \returns A const reference to the node's type name + virtual std::string description() const; + /// \brief Get the unique name of the node. + /// \returns A const reference to the node's unique name. + const std::string& get_name() const; + + /// \brief Sets a friendly name for a node. This does not overwrite the unique name + /// of the node and is retrieved via get_friendly_name(). Used mainly for debugging. + /// The friendly name may be set exactly once. + /// \param name is the friendly name to set + void set_friendly_name(const std::string& name); + + /// \brief Gets the friendly name for a node. If no friendly name has been set via + /// set_friendly_name then the node's unique name is returned. + /// \returns A const reference to the node's friendly name. + const std::string& get_friendly_name() const; + + virtual bool is_dynamic() const; + size_t get_instance_id() const { + return m_instance_id; + } + /// \brief Writes a description of a node to a stream + /// \param os The stream; should be returned + /// \param depth How many levels of inputs to describe + /// \returns The stream os + virtual std::ostream& write_description(std::ostream& os, uint32_t depth = 0) const; + + /// Get control dependencies registered on the node + const std::vector>& get_control_dependencies() const; + + /// Get nodes dependent on this node + const std::vector& get_control_dependents() const; + + /// This node cannot execute until node executes + void add_control_dependency(std::shared_ptr node); + + /// Remove the dependency of this node on node + void remove_control_dependency(std::shared_ptr node); + + /// Remove all dependencies from this node + void clear_control_dependencies(); + + /// Remove this node as a dependency from all dependent nodes + void clear_control_dependents(); + + /// This node absorbs the control dependencies of source_node + void add_node_control_dependencies(std::shared_ptr source_node); + + /// This node becomes a dependent of every node dependent on source_node + void add_node_control_dependents(std::shared_ptr source_node); + + /// This node's control dependencies are replaced by replacement + void transfer_control_dependents(std::shared_ptr replacement); + + /// Returns the number of outputs from the node. + size_t get_output_size() const; + + /// Returns the element type for output i + const element::Type& get_output_element_type(size_t i) const; + + /// Checks that there is exactly one output and returns its element type + // TODO: deprecate in favor of node->get_output_element_type(0) with a suitable check in + // the calling code, or updates to the calling code if it is making an invalid assumption + // of only one output. + const element::Type& get_element_type() const; + + /// Returns the shape for output i + const ngraph::Shape& get_output_shape(size_t i) const; + + /// Returns the partial shape for output i + const PartialShape& get_output_partial_shape(size_t i) const; + + /// Return the output to use when converting to an Output with no index specified. + /// Throws when not supported. + Output get_default_output() const; + Output get_default_output(); + + /// Returns the output of the default output, or throws if there is none + virtual size_t get_default_output_index() const; + /// Throws no default + size_t no_default_index() const; + + /// Checks that there is exactly one output and returns its shape + // TODO: deprecate in favor of node->get_output_shape(0) with a suitable check in the + // calling code, or updates to the calling code if it is making an invalid assumption of + // only one output. + const ngraph::Shape& get_shape() const; + + /// Returns the tensor for output or input i + descriptor::Tensor& get_output_tensor(size_t i) const; + descriptor::Tensor& get_input_tensor(size_t i) const; + + /// Returns the tensor name for output i + OPENVINO_DEPRECATED("The tensor name was deprecated. Use get_output_tensor(i).get_names() instead.") + const std::string& get_output_tensor_name(size_t i) const; + + std::set> get_output_target_inputs(size_t i) const; + + /// Returns the number of inputs for the op + size_t get_input_size() const; + + /// Returns the element type of input i + // TODO: deprecate in favor of node->get_input_element_type(i) + const element::Type& get_input_element_type(size_t i) const; + + /// Returns the shape of input i + // TODO: deprecate in favor of node->get_input_shape(i) + const ngraph::Shape& get_input_shape(size_t i) const; + + /// Returns the partial shape of input i + // TODO: deprecate in favor of node->get_input_partial_shape(i) + const PartialShape& get_input_partial_shape(size_t i) const; + + /// Returns the tensor name for input i + OPENVINO_DEPRECATED("The tensor name was deprecated. Use get_input_tensor(i).get_names() instead.") + const std::string& get_input_tensor_name(size_t i) const; + + std::unordered_set liveness_new_list; + std::unordered_set liveness_free_list; + + Node* get_input_node_ptr(size_t index) const; + std::shared_ptr get_input_node_shared_ptr(size_t index) const; + Output get_input_source_output(size_t i) const; + +public: + virtual std::shared_ptr clone_with_new_inputs(const OutputVector& inputs) const = 0; + + std::shared_ptr copy_with_new_inputs(const OutputVector& new_args) const; + + std::shared_ptr copy_with_new_inputs(const OutputVector& inputs, + const std::vector>& control_dependencies) const; + + /// True if this and node have one output with same element type and shape + bool has_same_type(std::shared_ptr node) const; + + using RTMap = std::map>; + + RTMap& get_rt_info() { + return m_rt_info; + } + const RTMap& get_rt_info() const { + return m_rt_info; + } + const std::unordered_set& get_provenance_tags() const; + void add_provenance_tag(const std::string& tag); + template + void add_provenance_tags(T tag_set) { + for (auto tag : tag_set) { + add_provenance_tag(tag); + } + } + /// \brief Adds tag_set to this node and all intermediate nodes above base + void add_provenance_tags_above(const OutputVector& base, const std::unordered_set& tag_set); + void remove_provenance_tag(const std::string& tag); + /// \brief Add node to additional nodes that receive tags + void add_provenance_group_member(const std::shared_ptr& node); + /// \brief Remove node to additional nodes that receive tags + void remove_provenance_group_member(const std::shared_ptr& node); + /// \brief Replace current_node with replacement_node and transfer tags + void replace_provenance_group_member(const std::shared_ptr& current_node, + const std::shared_ptr& replacement_node); + /// \return Provenance group nodes + const std::set>& get_provenance_group_members() const; + + /// \brief Add all nodes between this node and nodes in base as additional nodes to receive + /// provenance tags. + std::shared_ptr add_provenance_group_members_above(const OutputVector& base); + + // to be used when nodes are replaced + void merge_provenance_tags_from(const std::shared_ptr& source); + + /// Transfer provenance tags to replacement + void transfer_provenance_tags(const std::shared_ptr& replacement); + + /// Get all the nodes that uses the current node + NodeVector get_users(bool check_is_used = false) const; + + /// \return Version of this node + virtual size_t get_version() const { + return get_type_info().version; + } + + OPENVINO_DEPRECATED("This method is deprecated and will be removed soon.") + virtual std::shared_ptr get_default_value() const { + return nullptr; + } + /// Use instance ids for comparison instead of memory addresses to improve determinism + bool operator<(const Node& other) const { + return m_instance_id < other.m_instance_id; + } + /// \return A vector containing a handle for each of this node's inputs, in order. + // TODO: Rename to get_inputs()? + std::vector> inputs(); + + /// \return A vector containing a handle for each of this node's inputs, in order. + std::vector> inputs() const; + + /// \return A vector containing the values for each input + std::vector> input_values() const; + + /// \return A vector containing a handle for each of this node's outputs, in order. + // TODO: Rename to get_outputs()? + std::vector> outputs(); + + /// \return A vector containing a handle for each of this node's outputs, in order. + std::vector> outputs() const; + + /// \return A handle to the `input_index`th input of this node. + /// \throw std::out_of_range if the node does not have at least `input_index+1` inputs. + Input input(size_t input_index); + + /// \return A handle to the `input_index`th input of this node. + /// \throw std::out_of_range if the node does not have at least `input_index+1` inputs. + Input input(size_t input_index) const; + + Output input_value(size_t input_index) const; + + /// \return A handle to the `output_index`th output of this node. + /// \throw std::out_of_range if the node does not have at least `output_index+1` outputs. + Output output(size_t output_index); + + /// \return A handle to the `output_index`th output of this node. + /// \throw std::out_of_range if the node does not have at least `output_index+1` outputs. + Output output(size_t output_index) const; + + OPENVINO_SUPPRESS_DEPRECATED_START + OPENVINO_DEPRECATED("This method is deprecated and will be removed soon.") + void set_op_annotations(std::shared_ptr op_annotations) { + m_op_annotations = op_annotations; + } + OPENVINO_DEPRECATED("This method is deprecated and will be removed soon.") + std::shared_ptr get_op_annotations() const { + return m_op_annotations; + } + OPENVINO_SUPPRESS_DEPRECATED_END + + virtual bool match_value(ngraph::pattern::Matcher* matcher, + const Output& pattern_value, + const Output& graph_value); + + virtual bool match_node(ngraph::pattern::Matcher* matcher, const Output& graph_value); + +private: + descriptor::Input& get_input_descriptor(size_t position); + descriptor::Output& get_output_descriptor(size_t position); + + std::vector m_control_dependents; + std::vector> m_control_dependencies; + std::string m_node_type; + size_t m_instance_id{m_next_instance_id.fetch_add(1)}; + std::string m_friendly_name; + std::string m_unique_name; + static std::atomic m_next_instance_id; + std::unordered_set m_provenance_tags; + std::set> m_provenance_group; + std::deque m_inputs; + std::deque m_outputs; + OPENVINO_SUPPRESS_DEPRECATED_START + std::shared_ptr m_op_annotations; + OPENVINO_SUPPRESS_DEPRECATED_END + std::map> m_rt_info; +}; + +using NodeTypeInfo = Node::type_info_t; + +OPENVINO_API std::ostream& operator<<(std::ostream&, const Node&); +OPENVINO_API std::ostream& operator<<(std::ostream&, const Node*); + +#define _OPENVINO_RTTI_EXPAND(X) X + +/// Helper macro that puts necessary declarations of RTTI block inside a class definition. +/// Should be used in the scope of class that requires type identification besides one provided by +/// C++ RTTI. +/// Recommended to be used for all classes that are inherited from class ov::Node to enable +/// pattern +/// matching for them. Accepts necessary type identification details like type of the operation, +/// version and optional parent class. +/// +/// Applying this macro within a class definition provides declaration of type_info static +/// constant for backward compatibility with old RTTI definition for Node, +/// static function get_type_info_static which returns a reference to an object that is equal to +/// type_info but not necessary to the same object, and get_type_info virtual function that +/// overrides Node::get_type_info and returns a reference to the same object that +/// get_type_info_static gives. +/// +/// Use this macro as a public part of the class definition: +/// +/// class MyOp : public Node +/// { +/// public: +/// // Don't use Node as a parent for type_info, it doesn't have any value and +/// prohibited +/// OPENVINO_RTTI_DECLARATION; +/// +/// ... +/// }; +/// +/// class MyInheritedOp : public MyOp +/// { +/// public: +/// OPENVINO_RTTI_DECLARATION; +/// +/// ... +/// }; +/// +/// To complete type identification for a class, use OPENVINO_RTTI_DEFINITION. +/// +#define OPENVINO_RTTI_DECLARATION \ + static const ::ov::Node::type_info_t type_info; \ + const ::ov::Node::type_info_t& get_type_info() const override; \ + static const ::ov::Node::type_info_t& get_type_info_static() + +#define _OPENVINO_RTTI_DEFINITION_COMMON(CLASS) \ + const ::ov::Node::type_info_t& CLASS::get_type_info() const { \ + return get_type_info_static(); \ + } \ + const ::ov::Node::type_info_t CLASS::type_info = CLASS::get_type_info_static() +#define _OPENVINO_RTTI_DEFINITION_WITH_PARENT(CLASS, TYPE_NAME, _VERSION_INDEX, PARENT_CLASS) \ + const ::ov::Node::type_info_t& CLASS::get_type_info_static() { \ + static const ::ov::Node::type_info_t type_info_static{TYPE_NAME, \ + _VERSION_INDEX, \ + &PARENT_CLASS::get_type_info_static()}; \ + return type_info_static; \ + } \ + _OPENVINO_RTTI_DEFINITION_COMMON(CLASS) + +#define _OPENVINO_RTTI_DEFINITION_NO_PARENT(CLASS, TYPE_NAME, _VERSION_INDEX) \ + const ::ov::Node::type_info_t& CLASS::get_type_info_static() { \ + static const ::ov::Node::type_info_t type_info_static{TYPE_NAME, _VERSION_INDEX}; \ + return type_info_static; \ + } \ + _OPENVINO_RTTI_DEFINITION_COMMON(CLASS) + +#define _OPENVINO_RTTI_DEFINITION_SELECTOR(_1, _2, _3, _4, NAME, ...) NAME + +/// Complementary to OPENVINO_RTTI_DECLARATION, this helper macro _defines_ items _declared_ by +/// OPENVINO_RTTI_DECLARATION. +/// Should be used outside the class definition scope in place where ODR is ensured. +/// +/// \param CLASS is a C++ name of the class where corresponding OPENVINO_RTTI_DECLARATION was applied. +/// \param TYPE_NAME a string literal of type const char* that names your class in type +/// identification namespace; +/// It is your choice how to name it, but it should be unique among all +/// OPENVINO_RTTI_DECLARATION-enabled classes that can be +/// used in conjunction with each other in one transformation flow. +/// \param _VERSION_INDEX is an unsigned integer index to distinguish different versions of +/// operations that shares the same TYPE_NAME +/// \param PARENT_CLASS is an optional direct or indirect parent class for this class; define +/// it only in case if there is a need to capture any operation from some group of operations +/// that all derived from some common base class. Don't use Node as a parent, it is a base +/// class +/// for all operations and doesn't provide ability to define some perfect subset of +/// operations. PARENT_CLASS should define RTTI with OPENVINO_RTTI_{DECLARATION/DEFINITION} +/// macros. +/// +/// Examples (see corresponding declarations in OPENVINO_RTTI_DECLARATION description): +/// +/// OPENVINO_RTTI_DEFINITION(MyOp,"MyOp", 1); +/// OPENVINO_RTTI_DEFINITION(MyInheritedOp, "MyInheritedOp", 1, MyOp) +/// +/// For convenience, TYPE_NAME and CLASS name are recommended to be the same. +/// +#define OPENVINO_RTTI_DEFINITION(...) \ + _OPENVINO_RTTI_EXPAND(_OPENVINO_RTTI_DEFINITION_SELECTOR(__VA_ARGS__, \ + _OPENVINO_RTTI_DEFINITION_WITH_PARENT, \ + _OPENVINO_RTTI_DEFINITION_NO_PARENT)(__VA_ARGS__)) + +// Like an Output but with a Node* instead of a shared_ptr +struct RawNodeOutput { + RawNodeOutput(const Output& value) : node(value.get_node()), index(value.get_index()) {} + RawNodeOutput(Node* node, size_t index) : node(node), index(index) {} + RawNodeOutput(const RawNodeOutput&) = default; + RawNodeOutput() = default; + RawNodeOutput& operator=(const RawNodeOutput&) = default; + + Node* node; + size_t index{0}; + + operator Output() { + return Output(node, index); + } + bool operator==(const RawNodeOutput& other) const { + return node == other.node && index == other.index; + } + bool operator!=(const RawNodeOutput& other) const { + return !(*this == other); + } + bool operator<(const RawNodeOutput& other) const { + return node < other.node || (node == other.node && index < other.index); + } + bool operator>(const RawNodeOutput& other) const { + return node > other.node || (node == other.node && index > other.index); + } + bool operator<=(const RawNodeOutput& other) const { + return !(*this > other); + } + bool operator>=(const RawNodeOutput& other) const { + return !(*this < other); + } +}; + +using RawNodeOutputMap = std::map>; + +class OPENVINO_API NodeValidationFailure : public ngraph::CheckFailure { +public: + NodeValidationFailure(const ngraph::CheckLocInfo& check_loc_info, const Node* node, const std::string& explanation) + : CheckFailure(check_loc_info, node_validation_failure_loc_string(node), explanation) {} +}; +} // namespace ov +#define NODE_VALIDATION_CHECK(node, ...) NGRAPH_CHECK_HELPER(::ov::NodeValidationFailure, (node), __VA_ARGS__) + +namespace ov { +template +void check_new_args_count(const Node* node, T new_args) { + NODE_VALIDATION_CHECK(node, + new_args.size() == node->input_values().size(), + "clone_with_new_inputs() expected ", + node->input_values().size(), + " argument", + (node->input_values().size() == 1 ? "" : "s"), + " but got ", + new_args.size()); +} + +} // namespace ov + +namespace ov { +/// \brief Visits a reference to a node that has been registered with the visitor. +template <> +class OPENVINO_API AttributeAdapter> : public VisitorAdapter { +public: + AttributeAdapter(std::shared_ptr& value); + + bool visit_attributes(AttributeVisitor& visitor) override; + static constexpr DiscreteTypeInfo type_info{"AttributeAdapter>", 0}; + const DiscreteTypeInfo& get_type_info() const override { + return type_info; + } + +protected: + std::shared_ptr& m_ref; +}; + +template <> +class OPENVINO_API AttributeAdapter : public VisitorAdapter { +public: + AttributeAdapter(ov::NodeVector& ref); + + bool visit_attributes(AttributeVisitor& visitor) override; + + static constexpr DiscreteTypeInfo type_info{"AttributeAdapter", 0}; + const DiscreteTypeInfo& get_type_info() const override { + return type_info; + } + +protected: + ov::NodeVector& m_ref; +}; + +} // namespace ov diff --git a/ngraph/core/include/openvino/core/node_input.hpp b/ngraph/core/include/openvino/core/node_input.hpp new file mode 100644 index 00000000000..fb6e2cb527c --- /dev/null +++ b/ngraph/core/include/openvino/core/node_input.hpp @@ -0,0 +1,124 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +#include +#include + +#include "ngraph/shape.hpp" +#include "openvino/core/core_visibility.hpp" +#include "openvino/core/descriptor/tensor.hpp" +#include "openvino/core/partial_shape.hpp" +#include "openvino/core/type/element_type.hpp" +#include "openvino/core/variant.hpp" + +namespace ov { +class Node; + +template +class Output; + +template +class Input {}; + +/// \brief A handle for one of a node's inputs. +template <> +class OPENVINO_API Input { +public: + /// \brief Constructs a Input. + /// \param node Pointer to the node for the input handle. + /// \param index The index of the input. + Input(Node* node, size_t index); + + /// \return A pointer to the node referenced by this input handle. + Node* get_node() const; + /// \return The index of the input referred to by this input handle. + size_t get_index() const; + /// \return The element type of the input referred to by this input handle. + const element::Type& get_element_type() const; + /// \return The shape of the input referred to by this input handle. + const ngraph::Shape& get_shape() const; + /// \return The partial shape of the input referred to by this input handle. + const PartialShape& get_partial_shape() const; + /// \return A handle to the output that is connected to this input. + Output get_source_output() const; + /// \return A reference to the tensor descriptor for this input. + descriptor::Tensor& get_tensor() const; + /// \return A shared pointer to the tensor descriptor for this input. + std::shared_ptr get_tensor_ptr() const; + /// \return true if this input is relevant to its node's output shapes; else false. + bool get_is_relevant_to_shapes() const; + /// \return true if this input is relevant to its node's output values; else false. + bool get_is_relevant_to_values() const; + + /// \brief Replaces the source output of this input. + /// \param new_source_output A handle for the output that will replace this input's source. + void replace_source_output(const Output& new_source_output) const; + + /// \return The reference to runtime info map + RTMap& get_rt_info(); + /// \return The constant reference to runtime info map + const RTMap& get_rt_info() const; + + bool operator==(const Input& other) const; + bool operator!=(const Input& other) const; + bool operator<(const Input& other) const; + bool operator>(const Input& other) const; + bool operator<=(const Input& other) const; + bool operator>=(const Input& other) const; + +private: + Node* const m_node; + const size_t m_index; +}; + +/// \brief A handle for one of a node's inputs. +template <> +class OPENVINO_API Input { +public: + /// \brief Constructs a Input. + /// \param node Pointer to the node for the input handle. + /// \param index The index of the input. + Input(const Node* node, size_t index); + + /// \return A pointer to the node referenced by this input handle. + const Node* get_node() const; + /// \return The index of the input referred to by this input handle. + size_t get_index() const; + /// \return The element type of the input referred to by this input handle. + const element::Type& get_element_type() const; + /// \return The shape of the input referred to by this input handle. + const ngraph::Shape& get_shape() const; + /// \return The partial shape of the input referred to by this input handle. + const PartialShape& get_partial_shape() const; + /// \return A handle to the output that is connected to this input. + Output get_source_output() const; + /// \return A reference to the tensor descriptor for this input. + descriptor::Tensor& get_tensor() const; + /// \return A shared pointer to the tensor descriptor for this input. + std::shared_ptr get_tensor_ptr() const; + /// \return true if this input is relevant to its node's output shapes; else false. + bool get_is_relevant_to_shapes() const; + /// \return true if this input is relevant to its node's output values; else false. + bool get_is_relevant_to_values() const; + + /// \return The constant reference to runtime info map + const RTMap& get_rt_info() const; + + bool operator==(const Input& other) const; + bool operator!=(const Input& other) const; + bool operator<(const Input& other) const; + bool operator>(const Input& other) const; + bool operator<=(const Input& other) const; + bool operator>=(const Input& other) const; + +private: + const Node* const m_node; + const size_t m_index; +}; + +OPENVINO_API std::ostream& operator<<(std::ostream& out, const Input& input); +OPENVINO_API std::ostream& operator<<(std::ostream& out, const Input& input); +} // namespace ov diff --git a/ngraph/core/include/openvino/core/node_output.hpp b/ngraph/core/include/openvino/core/node_output.hpp new file mode 100644 index 00000000000..73d9b465982 --- /dev/null +++ b/ngraph/core/include/openvino/core/node_output.hpp @@ -0,0 +1,172 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +#include +#include +#include + +#include "ngraph/shape.hpp" +#include "openvino/core/core_visibility.hpp" +#include "openvino/core/descriptor/tensor.hpp" +#include "openvino/core/partial_shape.hpp" +#include "openvino/core/type/element_type.hpp" +#include "openvino/core/variant.hpp" + +namespace ov { +class Node; + +template +class Input; + +template +class Output {}; + +/// \brief A handle for one of a node's outputs. +template <> +class OPENVINO_API Output { +public: + /// \brief Constructs a Output. + /// \param node A pointer to the node for the output handle. + /// \param index The index of the output. + Output(Node* node, size_t index); + + /// \brief Constructs a Output. + /// \param node A `shared_ptr` to the node for the output handle. + /// \param index The index of the output. + /// + /// TODO: Make a plan to deprecate this. + Output(const std::shared_ptr& node, size_t index); + + /// \brief Constructs a Output, referencing the zeroth output of the node. + /// \param node A `shared_ptr` to the node for the output handle. + template + Output(const std::shared_ptr& node) : Output(node ? node->get_default_output() : Output()) {} + + /// A null output + Output() = default; + + void reset(); + + /// This output position for a different node + Output for_node(const std::shared_ptr& node); + /// \return A pointer to the node referred to by this output handle. + Node* get_node() const; + /// \return A `shared_ptr` to the node referred to by this output handle. + /// + /// TODO: Make a plan to deprecate this. + std::shared_ptr get_node_shared_ptr() const; + + /// \return The index of the output referred to by this output handle. + size_t get_index() const; + /// \return A reference to the tensor descriptor for this output. + descriptor::Tensor& get_tensor() const; + /// \return A shared point to the tensor ptr for this output. + std::shared_ptr get_tensor_ptr() const; + /// \return The element type of the output referred to by this output handle. + const element::Type& get_element_type() const; + /// \return The shape of the output referred to by this output handle. + const ngraph::Shape& get_shape() const; + /// \return The partial shape of the output referred to by this output handle. + const PartialShape& get_partial_shape() const; + + /// \return The reference to runtime info map + RTMap& get_rt_info(); + /// \return The constant reference to runtime info map + const RTMap& get_rt_info() const; + + /// \return A set containing handles for all inputs targeted by the output referenced by + /// this output handle. + std::set> get_target_inputs() const; + + /// \brief Removes a target input from the output referenced by this output handle. + /// \param target_input The target input to remove. + /// + // TODO(amprocte): Investigate whether this really ought to be public. + void remove_target_input(const Input& target_input) const; + + /// \brief Replace all users of this value with replacement + void replace(const Output& replacement); + + bool operator==(const Output& other) const; + bool operator!=(const Output& other) const; + bool operator<(const Output& other) const; + bool operator>(const Output& other) const; + bool operator<=(const Output& other) const; + bool operator>=(const Output& other) const; + +private: + std::shared_ptr m_node; + size_t m_index{0}; +}; + +template <> +class OPENVINO_API Output { +public: + /// \brief Constructs a Output. + /// \param node A pointer to the node for the output handle. + /// \param index The index of the output. + Output(const Node* node, size_t index); + + /// \brief Constructs a Output. + /// \param node A `shared_ptr` to the node for the output handle. + /// \param index The index of the output. + /// + /// TODO: Make a plan to deprecate this. + Output(const std::shared_ptr& node, size_t index); + + /// \brief Constructs a Output, referencing the zeroth output of the node. + /// \param node A `shared_ptr` to the node for the output handle. + template + Output(const std::shared_ptr& node) : Output(node ? node->get_default_output() : Output()) {} + + /// A null output + Output() = default; + + void reset(); + + /// This output position for a different node + Output for_node(const std::shared_ptr& node); + + /// \return A pointer to the node referred to by this output handle. + const Node* get_node() const; + /// \return A `shared_ptr` to the node referred to by this output handle. + /// + /// TODO: Make a plan to deprecate this. + std::shared_ptr get_node_shared_ptr() const; + /// \return The index of the output referred to by this output handle. + size_t get_index() const; + /// \return A reference to the tensor descriptor for this output. + descriptor::Tensor& get_tensor() const; + /// \return A shared point to the tensor ptr for this output. + std::shared_ptr get_tensor_ptr() const; + /// \return The element type of the output referred to by this output handle. + const element::Type& get_element_type() const; + /// \return The shape of the output referred to by this output handle. + const ngraph::Shape& get_shape() const; + /// \return The partial shape of the output referred to by this output handle. + const PartialShape& get_partial_shape() const; + + /// \return The constant reference to runtime info map + const RTMap& get_rt_info() const; + /// \return A set containing handles for all inputs targeted by the output referenced by + /// this output handle. + std::set> get_target_inputs() const; + + bool operator==(const Output& other) const; + bool operator!=(const Output& other) const; + bool operator<(const Output& other) const; + bool operator>(const Output& other) const; + bool operator<=(const Output& other) const; + bool operator>=(const Output& other) const; + +private: + std::shared_ptr m_node; + size_t m_index{0}; +}; + +OPENVINO_API std::ostream& operator<<(std::ostream& out, const Output& output); +OPENVINO_API std::ostream& operator<<(std::ostream& out, const Output& output); +} // namespace ov diff --git a/ngraph/core/include/openvino/core/node_vector.hpp b/ngraph/core/include/openvino/core/node_vector.hpp new file mode 100644 index 00000000000..f76d888e69e --- /dev/null +++ b/ngraph/core/include/openvino/core/node_vector.hpp @@ -0,0 +1,19 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +#include +#include + +namespace ov { + +template +class Output; + +class Node; + +using NodeVector = std::vector>; +using OutputVector = std::vector>; +} // namespace ov diff --git a/ngraph/core/include/openvino/core/variant.hpp b/ngraph/core/include/openvino/core/variant.hpp index b7bcc03a038..2157c4bfa7d 100644 --- a/ngraph/core/include/openvino/core/variant.hpp +++ b/ngraph/core/include/openvino/core/variant.hpp @@ -11,10 +11,8 @@ #include "ngraph/type.hpp" #include "openvino/core/core_visibility.hpp" -namespace ngraph { -class Node; -} namespace ov { +class Node; using VariantTypeInfo = ngraph::DiscreteTypeInfo; class OPENVINO_API Variant { @@ -23,7 +21,7 @@ public: virtual const VariantTypeInfo& get_type_info() const = 0; virtual bool is_copyable() const; - virtual std::shared_ptr init(const std::shared_ptr& node); + virtual std::shared_ptr init(const std::shared_ptr& node); virtual std::shared_ptr merge(const ngraph::NodeVector& nodes); virtual std::string to_string() { return ""; diff --git a/ngraph/core/src/node.cpp b/ngraph/core/src/node.cpp index 96253cf4ba0..17bfa8723ea 100644 --- a/ngraph/core/src/node.cpp +++ b/ngraph/core/src/node.cpp @@ -11,19 +11,18 @@ #include #include "itt.hpp" -#include "ngraph/descriptor/input.hpp" #include "ngraph/graph_util.hpp" #include "ngraph/op/constant.hpp" #include "ngraph/op/parameter.hpp" #include "ngraph/op/result.hpp" #include "ngraph/pattern/matcher.hpp" +#include "openvino/core/descriptor/input.hpp" using namespace std; -using namespace ngraph; -atomic Node::m_next_instance_id(0); +atomic ov::Node::m_next_instance_id(0); -Node::Node(const Node& node) +ov::Node::Node(const Node& node) : m_control_dependents(node.m_control_dependents), m_control_dependencies(node.m_control_dependencies) // skip m_node_type -- will be generated automatically @@ -46,7 +45,7 @@ Node::Node(const Node& node) } } -Node& Node::operator=(const Node& node) { +ov::Node& ov::Node::operator=(const Node& node) { this->m_control_dependents = node.m_control_dependents; this->m_control_dependencies = node.m_control_dependencies; this->m_instance_id = m_next_instance_id.fetch_add(1); @@ -64,16 +63,16 @@ Node& Node::operator=(const Node& node) { return *this; } -Node::Node(size_t output_size) : Node() { +ov::Node::Node(size_t output_size) : Node() { set_output_size(output_size); } -Node::Node(const OutputVector& arguments, size_t output_size) : Node() { +ov::Node::Node(const OutputVector& arguments, size_t output_size) : Node() { set_arguments(arguments); set_output_size(output_size); } -Node::~Node() { +ov::Node::~Node() { for (descriptor::Input& input : m_inputs) { if (input.has_output()) { // This test adds 1 to the actual count, so a count of 2 means this input is the only @@ -90,28 +89,29 @@ Node::~Node() { } } -std::shared_ptr Node::copy_with_new_inputs(const OutputVector& inputs) const { +std::shared_ptr ov::Node::copy_with_new_inputs(const OutputVector& inputs) const { return copy_with_new_inputs(inputs, get_control_dependencies()); } -Output Node::get_default_output() const { +ov::Output ov::Node::get_default_output() const { return output(get_default_output_index()); } -Output Node::get_default_output() { +ov::Output ov::Node::get_default_output() { return output(get_default_output_index()); } -size_t Node::get_default_output_index() const { +size_t ov::Node::get_default_output_index() const { return 0; } -size_t Node::no_default_index() const { +size_t ov::Node::no_default_index() const { NODE_VALIDATION_CHECK(this, false, "Default output not supported"); } -std::shared_ptr Node::copy_with_new_inputs(const OutputVector& inputs, - const std::vector>& control_dependencies) const { +std::shared_ptr ov::Node::copy_with_new_inputs( + const OutputVector& inputs, + const std::vector>& control_dependencies) const { shared_ptr clone = clone_with_new_inputs(inputs); for (auto& cdep : control_dependencies) { clone->add_control_dependency(cdep); @@ -122,7 +122,7 @@ std::shared_ptr Node::copy_with_new_inputs(const OutputVector& inputs, return clone; } -void Node::safe_delete(NodeVector& nodes, bool recurse) { +void ov::Node::safe_delete(NodeVector& nodes, bool recurse) { for (auto& input : m_inputs) { if (input.has_output()) { // This test adds 1 to the actual count, so a count of 2 means this input is the only @@ -144,7 +144,7 @@ void Node::safe_delete(NodeVector& nodes, bool recurse) { } } -void Node::set_arguments(const NodeVector& arguments) { +void ov::Node::set_arguments(const NodeVector& arguments) { OutputVector outputs; for (auto arg : arguments) { for (auto& output : arg->outputs()) { @@ -154,7 +154,7 @@ void Node::set_arguments(const NodeVector& arguments) { set_arguments(outputs); } -void Node::set_arguments(const OutputVector& arguments) { +void ov::Node::set_arguments(const OutputVector& arguments) { // Add this node as a user of each argument. size_t i = 0; for (auto& output : arguments) { @@ -164,14 +164,14 @@ void Node::set_arguments(const OutputVector& arguments) { } } -descriptor::Input& Node::get_input_descriptor(size_t position) { +ov::descriptor::Input& ov::Node::get_input_descriptor(size_t position) { while (m_inputs.size() <= position) { m_inputs.emplace_back(this, m_inputs.size()); } return m_inputs.at(position); } -descriptor::Output& Node::get_output_descriptor(size_t position) { +ov::descriptor::Output& ov::Node::get_output_descriptor(size_t position) { while (m_outputs.size() <= position) { size_t i = m_outputs.size(); auto tensor_descriptor = make_shared(element::dynamic, PartialShape::dynamic(), this, i); @@ -180,17 +180,17 @@ descriptor::Output& Node::get_output_descriptor(size_t position) { return m_outputs[position]; } -void Node::set_argument(size_t position, const Output& argument) { +void ov::Node::set_argument(size_t position, const Output& argument) { auto output_node = argument.get_node(); auto& output_descriptor = output_node->get_output_descriptor(argument.get_index()); get_input_descriptor(position).replace_output(output_descriptor); } -void Node::constructor_validate_and_infer_types() { +void ov::Node::constructor_validate_and_infer_types() { validate_and_infer_types(); } -void Node::set_output_size(size_t n) { +void ov::Node::set_output_size(size_t n) { NGRAPH_CHECK(n >= m_outputs.size(), "shrinking ", m_outputs.size(), " to ", n); for (size_t i = m_outputs.size(); i < n; ++i) { // create the descriptors @@ -198,14 +198,14 @@ void Node::set_output_size(size_t n) { } } -void Node::invalidate_values() { +void ov::Node::invalidate_values() { for (const auto& output : outputs()) output.get_tensor().invalidate_values(); } -void Node::validate_and_infer_types() {} +void ov::Node::validate_and_infer_types() {} -void Node::set_input_is_relevant_to_shape(size_t i, bool relevant) { +void ov::Node::set_input_is_relevant_to_shape(size_t i, bool relevant) { NGRAPH_CHECK(i < m_inputs.size(), "index '", i, @@ -213,7 +213,7 @@ void Node::set_input_is_relevant_to_shape(size_t i, bool relevant) { m_inputs[i].m_is_relevant_to_shape = relevant; } -void Node::set_input_is_relevant_to_value(size_t i, bool relevant) { +void ov::Node::set_input_is_relevant_to_value(size_t i, bool relevant) { NGRAPH_CHECK(i < m_inputs.size(), "index '", i, @@ -221,42 +221,42 @@ void Node::set_input_is_relevant_to_value(size_t i, bool relevant) { m_inputs[i].m_is_relevant_to_value = relevant; } -void Node::set_output_type(size_t i, const element::Type& element_type, const PartialShape& pshape) { +void ov::Node::set_output_type(size_t i, const element::Type& element_type, const PartialShape& pshape) { get_output_descriptor(i).get_tensor_ptr()->set_tensor_type(element_type, pshape); } -std::string Node::description() const { +std::string ov::Node::description() const { return get_type_name(); } -const std::string& Node::get_friendly_name() const { +const std::string& ov::Node::get_friendly_name() const { if (m_friendly_name.empty()) { return get_name(); } return m_friendly_name; } -const std::string& Node::get_name() const { +const std::string& ov::Node::get_name() const { if (m_unique_name.empty()) { const_cast(this)->m_unique_name = description() + "_" + to_string(m_instance_id); } return m_unique_name; } -void Node::set_friendly_name(const string& name) { +void ov::Node::set_friendly_name(const string& name) { m_friendly_name = name; } -void Node::add_provenance_group_member(const shared_ptr& node) { +void ov::Node::add_provenance_group_member(const shared_ptr& node) { m_provenance_group.insert(node); } -void Node::remove_provenance_group_member(const shared_ptr& node) { +void ov::Node::remove_provenance_group_member(const shared_ptr& node) { m_provenance_group.erase(node); } -void Node::replace_provenance_group_member(const shared_ptr& current_node, - const shared_ptr& replacement_node) { +void ov::Node::replace_provenance_group_member(const shared_ptr& current_node, + const shared_ptr& replacement_node) { // Catch up with the current state of the group replacement_node->add_provenance_tags(get_provenance_tags()); if (current_node != nullptr) { @@ -267,11 +267,11 @@ void Node::replace_provenance_group_member(const shared_ptr& current_node, add_provenance_group_member(replacement_node); } -const set>& Node::get_provenance_group_members() const { +const set>& ov::Node::get_provenance_group_members() const { return m_provenance_group; } -shared_ptr Node::add_provenance_group_members_above(const OutputVector& base) { +shared_ptr ov::Node::add_provenance_group_members_above(const OutputVector& base) { set base_set; for (auto& output : base) { Node* node = output.get_node(); @@ -302,7 +302,7 @@ shared_ptr Node::add_provenance_group_members_above(const OutputVector& ba return shared_from_this(); } -void Node::add_provenance_tags_above(const OutputVector& base, const std::unordered_set& tag_set) { +void ov::Node::add_provenance_tags_above(const OutputVector& base, const std::unordered_set& tag_set) { set base_set; for (auto& output : base) { base_set.insert(output.get_node()); @@ -322,73 +322,73 @@ void Node::add_provenance_tags_above(const OutputVector& base, const std::unorde } } -const std::unordered_set& Node::get_provenance_tags() const { +const std::unordered_set& ov::Node::get_provenance_tags() const { return m_provenance_tags; } -void Node::add_provenance_tag(const std::string& tag) { +void ov::Node::add_provenance_tag(const std::string& tag) { m_provenance_tags.insert(tag); for (auto node : m_provenance_group) { node->add_provenance_tag(tag); } } -void Node::remove_provenance_tag(const std::string& tag) { +void ov::Node::remove_provenance_tag(const std::string& tag) { m_provenance_tags.erase(tag); } -void Node::merge_provenance_tags_from(const std::shared_ptr& source) { +void ov::Node::merge_provenance_tags_from(const std::shared_ptr& source) { for (auto& tag : source->get_provenance_tags()) { add_provenance_tag(tag); } } -void Node::transfer_provenance_tags(const shared_ptr& replacement) { +void ov::Node::transfer_provenance_tags(const shared_ptr& replacement) { NGRAPH_SUPPRESS_DEPRECATED_START auto common_args = ngraph::find_common_args(shared_from_this(), replacement); std::set removed_subgraph_tags; - auto set_replacement_prov = [&removed_subgraph_tags](std::shared_ptr node) { - for (auto tag : node->get_provenance_tags()) { + auto set_replacement_prov = [&removed_subgraph_tags](const std::shared_ptr& node) { + for (const auto& tag : node->get_provenance_tags()) { removed_subgraph_tags.insert(tag); } }; - traverse_nodes({shared_from_this()}, set_replacement_prov, common_args); + ngraph::traverse_nodes({shared_from_this()}, set_replacement_prov, common_args); replacement->add_provenance_tags(removed_subgraph_tags); - auto set_prov_new_nodes = [&removed_subgraph_tags](std::shared_ptr node) { + auto set_prov_new_nodes = [&removed_subgraph_tags](const std::shared_ptr& node) { node->add_provenance_tags(removed_subgraph_tags); }; - traverse_nodes({replacement}, set_prov_new_nodes, common_args); + ngraph::traverse_nodes({replacement}, set_prov_new_nodes, common_args); NGRAPH_SUPPRESS_DEPRECATED_END } -Node* Node::get_input_node_ptr(size_t index) const { +ov::Node* ov::Node::get_input_node_ptr(size_t index) const { NGRAPH_CHECK(index < m_inputs.size(), "index '", index, "' out of range in get_argument(size_t index)"); return m_inputs[index].get_output().get_node().get(); } -std::shared_ptr Node::get_input_node_shared_ptr(size_t index) const { +std::shared_ptr ov::Node::get_input_node_shared_ptr(size_t index) const { NGRAPH_CHECK(index < m_inputs.size(), "index '", index, "' out of range in get_argument(size_t index)"); return m_inputs[index].get_output().get_node(); } -Output Node::get_input_source_output(size_t i) const { +ov::Output ov::Node::get_input_source_output(size_t i) const { return input(i).get_source_output(); } -const std::vector>& Node::get_control_dependencies() const { +const std::vector>& ov::Node::get_control_dependencies() const { return m_control_dependencies; } -const std::vector& Node::get_control_dependents() const { +const std::vector& ov::Node::get_control_dependents() const { return m_control_dependents; } -void Node::add_control_dependency(std::shared_ptr node) { +void ov::Node::add_control_dependency(std::shared_ptr node) { if (find(m_control_dependencies.begin(), m_control_dependencies.end(), node) == m_control_dependencies.end()) { m_control_dependencies.push_back(node); if (find(node->m_control_dependents.begin(), node->m_control_dependents.end(), this) == @@ -398,24 +398,24 @@ void Node::add_control_dependency(std::shared_ptr node) { } } -void Node::add_node_control_dependencies(std::shared_ptr source_node) { +void ov::Node::add_node_control_dependencies(std::shared_ptr source_node) { for (auto& node : source_node->get_control_dependencies()) { add_control_dependency(node); } } -void Node::add_node_control_dependents(std::shared_ptr source_node) { +void ov::Node::add_node_control_dependents(std::shared_ptr source_node) { for (Node* node : source_node->get_control_dependents()) { node->add_control_dependency(shared_from_this()); } } -void Node::transfer_control_dependents(std::shared_ptr replacement) { +void ov::Node::transfer_control_dependents(std::shared_ptr replacement) { replacement->add_node_control_dependents(shared_from_this()); clear_control_dependents(); } -void Node::remove_control_dependency(std::shared_ptr node) { +void ov::Node::remove_control_dependency(std::shared_ptr node) { { auto it = find(m_control_dependencies.begin(), m_control_dependencies.end(), node); if (it != m_control_dependencies.end()) { @@ -430,7 +430,7 @@ void Node::remove_control_dependency(std::shared_ptr node) { } } -void Node::clear_control_dependencies() { +void ov::Node::clear_control_dependencies() { for (auto& node : m_control_dependencies) { auto it = find(node->m_control_dependents.begin(), node->m_control_dependents.end(), this); if (it != node->m_control_dependents.end()) { @@ -440,27 +440,27 @@ void Node::clear_control_dependencies() { m_control_dependencies.clear(); } -void Node::clear_control_dependents() { +void ov::Node::clear_control_dependents() { while (!m_control_dependents.empty()) { (*m_control_dependents.begin())->remove_control_dependency(shared_from_this()); } } -const op::AutoBroadcastSpec& Node::get_autob() const { - static op::AutoBroadcastSpec s_spec; +const ngraph::op::AutoBroadcastSpec& ov::Node::get_autob() const { + static ngraph::op::AutoBroadcastSpec s_spec; return s_spec; } -namespace ngraph { +namespace ov { ostream& operator<<(ostream& out, const Node& node) { return node.write_description(out, 1); } ostream& operator<<(ostream& out, const Node* node) { return node->write_description(out, 1); } -} // namespace ngraph +} // namespace ov -std::ostream& Node::write_description(std::ostream& out, uint32_t depth) const { +std::ostream& ov::Node::write_description(std::ostream& out, uint32_t depth) const { if (depth == 0) { out << get_friendly_name(); } else { @@ -481,42 +481,42 @@ std::ostream& Node::write_description(std::ostream& out, uint32_t depth) const { return out; } -size_t Node::get_output_size() const { +size_t ov::Node::get_output_size() const { return m_outputs.size(); } -const element::Type& Node::get_output_element_type(size_t i) const { +const ov::element::Type& ov::Node::get_output_element_type(size_t i) const { NGRAPH_CHECK(i < m_outputs.size(), "index '", i, "' out of range in get_output_element_type(size_t i)"); return m_outputs[i].get_element_type(); } -const element::Type& Node::get_element_type() const { +const ov::element::Type& ov::Node::get_element_type() const { if (get_output_size() != 1) { - throw ngraph_error("get_element_type() must be called on a node with exactly one output."); + throw ngraph::ngraph_error("get_element_type() must be called on a node with exactly one output."); } return get_output_element_type(0); } -const Shape& Node::get_output_shape(size_t i) const { +const ngraph::Shape& ov::Node::get_output_shape(size_t i) const { NGRAPH_CHECK(i < m_outputs.size(), "index '", i, "' out of range in get_output_shape(size_t i)"); return m_outputs[i].get_shape(); } -const PartialShape& Node::get_output_partial_shape(size_t i) const { +const ov::PartialShape& ov::Node::get_output_partial_shape(size_t i) const { NGRAPH_CHECK(i < m_outputs.size(), "index '", i, "' out of range in get_output_partial_shape(size_t i)"); return m_outputs[i].get_partial_shape(); } -const Shape& Node::get_shape() const { +const ngraph::Shape& ov::Node::get_shape() const { if (get_output_size() != 1) { stringstream es; es << "get_shape() must be called on a node with exactly one output (" << description() << ")"; - throw ngraph_error(es); + throw ngraph::ngraph_error(es); } return get_output_shape(0); } -std::set> Node::get_output_target_inputs(size_t i) const { +std::set> ov::Node::get_output_target_inputs(size_t i) const { std::set> result; for (auto& input : m_outputs.at(i).get_inputs()) { @@ -526,49 +526,49 @@ std::set> Node::get_output_target_inputs(size_t i) const { return result; } -descriptor::Tensor& Node::get_output_tensor(size_t i) const { +ov::descriptor::Tensor& ov::Node::get_output_tensor(size_t i) const { NGRAPH_CHECK(i < m_outputs.size(), "index '", i, "' out of range in get_output_tensor(size_t i)"); return m_outputs[i].get_tensor(); } -descriptor::Tensor& Node::get_input_tensor(size_t i) const { +ov::descriptor::Tensor& ov::Node::get_input_tensor(size_t i) const { NGRAPH_CHECK(i < m_inputs.size(), "index '", i, "' out of range in get_input_tensor(size_t i)"); descriptor::Input input = m_inputs[i]; return input.get_tensor(); } -size_t Node::get_input_size() const { +size_t ov::Node::get_input_size() const { return m_inputs.size(); } -const element::Type& Node::get_input_element_type(size_t i) const { +const ov::element::Type& ov::Node::get_input_element_type(size_t i) const { NGRAPH_CHECK(i < m_inputs.size(), "index '", i, "' out of range in get_input_element_type(size_t i)"); return m_inputs[i].get_element_type(); } -const Shape& Node::get_input_shape(size_t i) const { +const ngraph::Shape& ov::Node::get_input_shape(size_t i) const { NGRAPH_CHECK(i < m_inputs.size(), "index '", i, "' out of range in get_input_shape(size_t i)"); return m_inputs[i].get_shape(); } -const PartialShape& Node::get_input_partial_shape(size_t i) const { +const ov::PartialShape& ov::Node::get_input_partial_shape(size_t i) const { NGRAPH_CHECK(i < m_inputs.size(), "index '", i, "' out of range in get_input_partial_shape(size_t i)"); return m_inputs[i].get_partial_shape(); } NGRAPH_SUPPRESS_DEPRECATED_START -const string& Node::get_input_tensor_name(size_t i) const { +const string& ov::Node::get_input_tensor_name(size_t i) const { NGRAPH_CHECK(i < m_inputs.size(), "index '", i, "' out of range in get_input_tensor_name(size_t i)"); return m_inputs[i].get_tensor().get_name(); } -const string& Node::get_output_tensor_name(size_t i) const { +const string& ov::Node::get_output_tensor_name(size_t i) const { NGRAPH_CHECK(i < m_outputs.size(), "index '", i, "' out of range in get_output_tensor_name(size_t i)"); return m_outputs[i].get_tensor().get_name(); } NGRAPH_SUPPRESS_DEPRECATED_END -bool Node::has_same_type(std::shared_ptr node) const { +bool ov::Node::has_same_type(std::shared_ptr node) const { if (get_output_size() != node->get_output_size()) { return false; } @@ -581,12 +581,12 @@ bool Node::has_same_type(std::shared_ptr node) const { return true; } -NodeVector Node::get_users(bool check_is_used) const { +ov::NodeVector ov::Node::get_users(bool check_is_used) const { NodeVector result; for (auto output : outputs()) { for (auto input : output.get_target_inputs()) { Node* input_node = input.get_node(); - if (!check_is_used || is_used(input_node)) { + if (!check_is_used || ngraph::is_used(input_node)) { result.push_back(input_node->shared_from_this()); } } @@ -594,25 +594,25 @@ NodeVector Node::get_users(bool check_is_used) const { return result; } -std::string ngraph::node_validation_failure_loc_string(const Node* node) { +std::string ov::node_validation_failure_loc_string(const Node* node) { std::stringstream ss; ss << "While validating node '" << *node << "' with friendly_name '" << node->get_friendly_name() << '\''; return ss.str(); } -const std::shared_ptr& ngraph::check_single_output_arg(const std::shared_ptr& node, size_t i) { +const std::shared_ptr& ov::check_single_output_arg(const std::shared_ptr& node, size_t i) { NGRAPH_CHECK(node->get_output_size() == 1, "Argument ", i, node, " must produce exactly one value."); return node; } -const NodeVector& ngraph::check_single_output_args(const NodeVector& args) { +const ov::NodeVector& ov::check_single_output_args(const NodeVector& args) { for (size_t i = 0; i < args.size(); ++i) { ngraph::check_single_output_arg(args.at(i), i); } return args; } -OutputVector ngraph::as_output_vector(const NodeVector& args) { +ov::OutputVector ov::as_output_vector(const NodeVector& args) { OutputVector output_vector; for (auto arg : args) { output_vector.push_back(arg); @@ -620,7 +620,7 @@ OutputVector ngraph::as_output_vector(const NodeVector& args) { return output_vector; } -NodeVector ngraph::as_node_vector(const OutputVector& values) { +ov::NodeVector ov::as_node_vector(const OutputVector& values) { NodeVector node_vector; for (auto& value : values) { node_vector.emplace_back(value.get_node_shared_ptr()); @@ -628,17 +628,19 @@ NodeVector ngraph::as_node_vector(const OutputVector& values) { return node_vector; } -ResultVector ngraph::as_result_vector(const OutputVector& values) { +ov::ResultVector ov::as_result_vector(const OutputVector& values) { ResultVector result; for (auto value : values) { shared_ptr node = value.get_node_shared_ptr(); - result.push_back(ov::is_type(node) ? ov::as_type_ptr(node) - : make_shared(value)); + result.push_back(ov::is_type(node) ? ov::as_type_ptr(node) + : make_shared(value)); } return result; } -bool Node::match_value(pattern::Matcher* matcher, const Output& pattern_value, const Output& graph_value) { +bool ov::Node::match_value(ngraph::pattern::Matcher* matcher, + const Output& pattern_value, + const Output& graph_value) { if (pattern_value.get_index() != graph_value.get_index() || (matcher->is_strict_mode() && (!pattern_value.get_element_type().compatible(graph_value.get_element_type()) || @@ -648,7 +650,7 @@ bool Node::match_value(pattern::Matcher* matcher, const Output& pattern_va return match_node(matcher, graph_value); } -bool Node::match_node(pattern::Matcher* matcher, const Output& graph_value) { +bool ov::Node::match_node(ngraph::pattern::Matcher* matcher, const Output& graph_value) { matcher->add_node(graph_value); // Check if a type of a given node, which produces graph_value, matches the type of `this` node // or `this` node type is an ancestor of that node type. It is not the exact matching, types of @@ -669,7 +671,7 @@ bool Node::match_node(pattern::Matcher* matcher, const Output& graph_value // default implementation for the node to check if it contains partial shape // we will override this method, for the Op's which depends on additional shape // attribute to determine if node contains partial shape or not -bool Node::is_dynamic() const { +bool ov::Node::is_dynamic() const { for (size_t i = 0; i < get_input_size(); i++) { if (get_input_partial_shape(i).is_dynamic()) { return true; @@ -678,7 +680,7 @@ bool Node::is_dynamic() const { return false; } -Input Node::input(size_t input_index) { +ov::Input ov::Node::input(size_t input_index) { if (input_index >= m_inputs.size()) { throw out_of_range("node input index is out of range"); } @@ -686,11 +688,11 @@ Input Node::input(size_t input_index) { return Input(this, input_index); } -Output Node::input_value(size_t input_index) const { +ov::Output ov::Node::input_value(size_t input_index) const { return input(input_index).get_source_output(); } -Input Node::input(size_t input_index) const { +ov::Input ov::Node::input(size_t input_index) const { if (input_index >= m_inputs.size()) { throw out_of_range("node input index is out of range"); } @@ -698,7 +700,7 @@ Input Node::input(size_t input_index) const { return Input(this, input_index); } -Output Node::output(size_t output_index) { +ov::Output ov::Node::output(size_t output_index) { // All nodes will have at least 1 output if (output_index > 0 && output_index >= m_outputs.size()) { throw out_of_range("node output index is out of range"); @@ -707,7 +709,7 @@ Output Node::output(size_t output_index) { return Output(this, output_index); } -Output Node::output(size_t output_index) const { +ov::Output ov::Node::output(size_t output_index) const { // All nodes will have at least 1 output if (output_index > 0 && output_index >= m_outputs.size()) { throw out_of_range("node output index is out of range"); @@ -716,7 +718,7 @@ Output Node::output(size_t output_index) const { return Output(this, output_index); } -vector> Node::inputs() { +vector> ov::Node::inputs() { vector> result; for (size_t i = 0; i < get_input_size(); i++) { @@ -726,7 +728,7 @@ vector> Node::inputs() { return result; } -vector> Node::input_values() const { +vector> ov::Node::input_values() const { vector> result; for (size_t i = 0; i < get_input_size(); i++) { @@ -736,7 +738,7 @@ vector> Node::input_values() const { return result; } -vector> Node::inputs() const { +vector> ov::Node::inputs() const { vector> result; for (size_t i = 0; i < get_input_size(); i++) { @@ -746,7 +748,7 @@ vector> Node::inputs() const { return result; } -vector> Node::outputs() { +vector> ov::Node::outputs() { vector> result; for (size_t i = 0; i < get_output_size(); i++) { @@ -756,7 +758,7 @@ vector> Node::outputs() { return result; } -vector> Node::outputs() const { +vector> ov::Node::outputs() const { vector> result; for (size_t i = 0; i < get_output_size(); i++) { @@ -766,41 +768,41 @@ vector> Node::outputs() const { return result; } -bool Node::has_evaluate() const { +bool ov::Node::has_evaluate() const { return false; } -bool Node::evaluate(const HostTensorVector& output_values, const HostTensorVector& input_values) const { +bool ov::Node::evaluate(const HostTensorVector& output_values, const HostTensorVector& input_values) const { return false; } -bool Node::evaluate(const HostTensorVector& output_values, - const HostTensorVector& input_values, - const EvaluationContext& evaluationContext) const { +bool ov::Node::evaluate(const HostTensorVector& output_values, + const HostTensorVector& input_values, + const EvaluationContext& evaluationContext) const { return evaluate(output_values, input_values); } -bool Node::evaluate_lower(const HostTensorVector& output_values) const { +bool ov::Node::evaluate_lower(const HostTensorVector& output_values) const { const auto& inputs = input_values(); bool dyn_inputs = std::any_of(inputs.begin(), inputs.end(), [](const Output& output) { return !output.get_tensor().has_and_set_bound(); }); if (dyn_inputs) return false; - return default_lower_bound_evaluator(this, output_values); + return ngraph::default_lower_bound_evaluator(this, output_values); } -bool Node::evaluate_upper(const HostTensorVector& output_values) const { +bool ov::Node::evaluate_upper(const HostTensorVector& output_values) const { const auto& inputs = input_values(); bool dyn_inputs = std::any_of(inputs.begin(), inputs.end(), [](const Output& output) { return !output.get_tensor().has_and_set_bound(); }); if (dyn_inputs) return false; - return default_upper_bound_evaluator(this, output_values); + return ngraph::default_upper_bound_evaluator(this, output_values); } -bool Node::constant_fold(OutputVector& output_values, const OutputVector& input_values) { +bool ov::Node::constant_fold(OutputVector& output_values, const OutputVector& input_values) { OV_ITT_SCOPED_TASK(ov::itt::domains::nGraph, "Node::constant_fold"); if (m_rt_info.count("DISABLED_CONSTANT_FOLDING")) { @@ -809,15 +811,15 @@ bool Node::constant_fold(OutputVector& output_values, const OutputVector& input_ // If all the inputs are constants, try to evaluate the outputs bool all_constants = std::all_of(input_values.begin(), input_values.end(), [](const Output& input) { - return ov::as_type_ptr(input.get_node_shared_ptr()); + return ov::as_type_ptr(input.get_node_shared_ptr()); }); if (!all_constants) return false; HostTensorVector input_tensors; for (const auto& input : input_values) { - auto host_tensor = - make_shared(ov::as_type_ptr(input.get_node_shared_ptr())); + auto host_tensor = make_shared( + ov::as_type_ptr(input.get_node_shared_ptr())); input_tensors.push_back(host_tensor); } HostTensorVector output_tensors; @@ -828,7 +830,7 @@ bool Node::constant_fold(OutputVector& output_values, const OutputVector& input_ } if (evaluate(output_tensors, input_tensors)) { for (size_t i = 0; i < output_tensors.size(); ++i) { - output_values[i] = make_shared(output_tensors[i]); + output_values[i] = make_shared(output_tensors[i]); } return true; } diff --git a/ngraph/core/src/node_input.cpp b/ngraph/core/src/node_input.cpp index 53b85be01c2..5c6a45ab837 100644 --- a/ngraph/core/src/node_input.cpp +++ b/ngraph/core/src/node_input.cpp @@ -2,11 +2,11 @@ // SPDX-License-Identifier: Apache-2.0 // -#include "ngraph/node_input.hpp" +#include "openvino/core/node_input.hpp" -#include "ngraph/node.hpp" +#include "openvino/core/node.hpp" -namespace ngraph { +namespace ov { Input::Input(Node* node, size_t index) : m_node(node), m_index(index) {} Node* Input::get_node() const { @@ -19,7 +19,7 @@ const element::Type& Input::get_element_type() const { return m_node->get_input_element_type(m_index); } -const Shape& Input::get_shape() const { +const ngraph::Shape& Input::get_shape() const { return m_node->get_input_shape(m_index); } const PartialShape& Input::get_partial_shape() const { @@ -95,7 +95,7 @@ size_t Input::get_index() const { const element::Type& Input::get_element_type() const { return m_node->get_input_element_type(m_index); } -const Shape& Input::get_shape() const { +const ngraph::Shape& Input::get_shape() const { return m_node->get_input_shape(m_index); } const PartialShape& Input::get_partial_shape() const { @@ -153,4 +153,4 @@ std::ostream& operator<<(std::ostream& out, const Input& input) { return input.get_node()->write_description(out, 0) << ".input(" << input.get_index() << "):" << input.get_element_type() << input.get_partial_shape(); } -} // namespace ngraph +} // namespace ov diff --git a/ngraph/core/src/node_output.cpp b/ngraph/core/src/node_output.cpp index 752b24a9565..fcd2285956e 100644 --- a/ngraph/core/src/node_output.cpp +++ b/ngraph/core/src/node_output.cpp @@ -2,13 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 // -#include "ngraph/node_output.hpp" +#include "openvino/core/node_output.hpp" #include "ngraph/log.hpp" -#include "ngraph/node.hpp" #include "ngraph/variant.hpp" +#include "openvino/core/node.hpp" -namespace ngraph { +namespace ov { Output::Output(Node* node, size_t index) : m_node(node->shared_from_this()), m_index(index) {} Output::Output(const std::shared_ptr& node, size_t index) : m_node(node), m_index(index) {} @@ -39,7 +39,7 @@ std::shared_ptr Output::get_tensor_ptr() const { const element::Type& Output::get_element_type() const { return m_node->get_output_element_type(m_index); } -const Shape& Output::get_shape() const { +const ngraph::Shape& Output::get_shape() const { return m_node->get_output_shape(m_index); } const PartialShape& Output::get_partial_shape() const { @@ -128,7 +128,7 @@ std::shared_ptr Output::get_tensor_ptr() const { const element::Type& Output::get_element_type() const { return m_node->get_output_element_type(m_index); } -const Shape& Output::get_shape() const { +const ngraph::Shape& Output::get_shape() const { return m_node->get_output_shape(m_index); } const PartialShape& Output::get_partial_shape() const { @@ -172,4 +172,4 @@ std::ostream& operator<<(std::ostream& out, const Output& output) { return output.get_node()->write_description(out, 0) << "[" << output.get_index() << "]:" << output.get_element_type() << output.get_partial_shape(); } -} // namespace ngraph +} // namespace ov diff --git a/ngraph/core/src/validation_util.cpp b/ngraph/core/src/validation_util.cpp index c5585e87013..3db696721a6 100644 --- a/ngraph/core/src/validation_util.cpp +++ b/ngraph/core/src/validation_util.cpp @@ -1150,9 +1150,9 @@ bool ngraph::could_propagate(const Output& output, std::vector& ord auto current_node = nodes_to_calculate.front(); nodes_to_calculate.pop_front(); - if (current_node->inputs().empty() && !ov::is_type(current_node)) + if (current_node->inputs().empty() && !is_type(current_node)) status = false; - else if (!ov::is_type(current_node) && !ov::is_type(current_node)) { + else if (!is_type(current_node) && !is_type(current_node)) { // not a leaf, not a shape_of -- continue to search for (const auto& input_value : current_node->input_values()) { const auto& input_node = input_value.get_node(); diff --git a/ngraph/core/src/variant.cpp b/ngraph/core/src/variant.cpp index d09688cff3e..a2086989bdf 100644 --- a/ngraph/core/src/variant.cpp +++ b/ngraph/core/src/variant.cpp @@ -4,13 +4,15 @@ #include "ngraph/variant.hpp" +#include "ngraph/node.hpp" + using namespace ngraph; // Define variant for std::string constexpr VariantTypeInfo VariantWrapper::type_info; constexpr VariantTypeInfo VariantWrapper::type_info; -Variant::~Variant() {} +Variant::~Variant() = default; std::shared_ptr Variant::init(const std::shared_ptr& node) { return nullptr; diff --git a/ngraph/test/util/test_tools.hpp b/ngraph/test/util/test_tools.hpp index 6f1260717d5..bd2a6ac1c7b 100644 --- a/ngraph/test/util/test_tools.hpp +++ b/ngraph/test/util/test_tools.hpp @@ -20,11 +20,11 @@ #include "ngraph/runtime/host_tensor.hpp" #include "ngraph/runtime/tensor.hpp" #include "ngraph/type/element_type_traits.hpp" +#include "ngraph/node.hpp" #include "runtime/backend.hpp" namespace ngraph { - class Node; class TestOpMultiOut : public op::Op { public: From 4622f2f15dce8a68e55af45b13ac90a6af5d160d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karol=20Trzci=C5=84ski?= Date: Mon, 30 Aug 2021 09:26:59 +0200 Subject: [PATCH 56/76] IE: Fix Windows compilation on MSVC (#7206) `Win32` may be undefined when MSVC is used, see: https://docs.microsoft.com/en-us/cpp/preprocessor/predefined-macros?redirectedfrom=MSDN&view=msvc-160 Signed-off-by: Karol Trzcinski --- .../src/inference_engine/src/compilation_context.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/inference-engine/src/inference_engine/src/compilation_context.cpp b/inference-engine/src/inference_engine/src/compilation_context.cpp index ed787235e1b..30baa04b9d1 100644 --- a/inference-engine/src/inference_engine/src/compilation_context.cpp +++ b/inference-engine/src/inference_engine/src/compilation_context.cpp @@ -7,7 +7,7 @@ #include #include -#ifndef WIN32 +#ifndef _WIN32 # include #endif #include @@ -23,7 +23,7 @@ #include "transformations/rt_info/primitives_priority_attribute.hpp" #include "transformations/serialize.hpp" -#ifdef WIN32 +#ifdef _WIN32 # define stat _stat #endif From 4a9ac22787455d911c8d5db9c304ded987c73340 Mon Sep 17 00:00:00 2001 From: Bartosz Lesniewski Date: Mon, 30 Aug 2021 12:47:30 +0200 Subject: [PATCH 57/76] Revise ScatterElementsUpdate Op (#7162) * Use ngraph rtti macros * Add visitor test * Add SSLT * Add hardcoded refs tests for ScatterElementsUpdate * Add ScatterElementsUpdate to trusted ops list * Add i16 case to backend tests * Add typed testcase generation, check for all supported types * Remove redundant parameters from generateScatterParams --- .../op_reference/scatter_elements_update.cpp | 176 ++++++++++++++++++ .../single_layer/scatter_elements_update.cpp | 51 +++++ .../layer_tests_summary/utils/constants.py | 1 + .../ngraph/op/scatter_elements_update.hpp | 6 +- .../core/src/op/scatter_elements_update.cpp | 2 +- ngraph/test/CMakeLists.txt | 1 + .../visitors/op/scatter_elements_update.cpp | 28 +++ 7 files changed, 260 insertions(+), 5 deletions(-) create mode 100644 docs/template_plugin/tests/functional/op_reference/scatter_elements_update.cpp create mode 100644 inference-engine/tests/functional/inference_engine/serialization/single_layer/scatter_elements_update.cpp create mode 100644 ngraph/test/visitors/op/scatter_elements_update.cpp diff --git a/docs/template_plugin/tests/functional/op_reference/scatter_elements_update.cpp b/docs/template_plugin/tests/functional/op_reference/scatter_elements_update.cpp new file mode 100644 index 00000000000..3d844bfcf6d --- /dev/null +++ b/docs/template_plugin/tests/functional/op_reference/scatter_elements_update.cpp @@ -0,0 +1,176 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include + +#include +#include +#include +#include +#include + +#include "base_reference_test.hpp" + +using namespace reference_tests; +using namespace ngraph; +using namespace InferenceEngine; + +namespace { +struct ScatterElementsUpdateParams { + ScatterElementsUpdateParams(const Tensor& paramData, + const Tensor& paramIndices, + const Tensor& paramUpdates, + const Tensor& paramAxis, + const Tensor& paramExpected) + : input(paramData), + indices(paramIndices), + updates(paramUpdates), + axis(paramAxis), + expected(paramExpected) {} + + Tensor input; + Tensor indices; + Tensor updates; + Tensor axis; + Tensor expected; +}; + +class ReferenceScatterElementsUpdateLayerTest : public testing::TestWithParam, + public CommonReferenceTest { +public: + void SetUp() override { + auto params = GetParam(); + function = CreateFunction(params); + inputData = {params.input.data, + params.indices.data, + params.updates.data, + params.axis.data}; + refOutData = {params.expected.data}; + } + static std::string getTestCaseName(const testing::TestParamInfo& obj) { + auto param = obj.param; + std::ostringstream result; + result << "data_sh=" << param.input.shape; + result << "_data_pr=" << param.input.type; + result << "_indx_sh=" << param.indices.shape; + result << "_indx_pr=" << param.indices.type; + result << "_updt_sh=" << param.updates.shape; + result << "_updt_pr=" << param.updates.type; + result << "_axis_sh=" << param.axis.shape; + result << "_axis_pr=" << param.axis.type; + return result.str(); + } +private: + static std::shared_ptr CreateFunction(const ScatterElementsUpdateParams& params) { + const auto A = std::make_shared(params.input.type, params.input.shape); + const auto B = std::make_shared(params.indices.type, params.indices.shape); + const auto C = std::make_shared(params.updates.type, params.updates.shape); + const auto D = std::make_shared(params.axis.type, params.axis.shape); + auto scatterElts = std::make_shared(A, B, C, D); + return std::make_shared(NodeVector{scatterElts}, ParameterVector{A, B, C, D}); + } +}; + +TEST_P(ReferenceScatterElementsUpdateLayerTest, CompareWithHardcodedRefs) { + Exec(); +} + +template +std::vector generateScatterParams() { + using T = typename element_type_traits::value_type; + using T_INT = typename element_type_traits::value_type; + std::vector scatterParams{ + // axis = 0 + ScatterElementsUpdateParams(Tensor({2, 2}, element::Type(ET), std::vector{1, 2, 3, 4}), // input + Tensor({2, 2}, element::Type(ET_IND), std::vector{1, 1, 0, 0}), // indices + Tensor({2, 2}, element::Type(ET), std::vector{10, 20, 30, 40}), // updates + Tensor({1}, element::Type(ET_IND), std::vector{0}), // axis + Tensor({2, 2}, element::Type(ET), std::vector{30, 40, 10, 20})), // expected + // axis = 1 + ScatterElementsUpdateParams(Tensor({2, 1}, element::Type(ET), std::vector{1, 2}), // input + Tensor({2, 1}, element::Type(ET_IND), std::vector{0, 0}), // indices + Tensor({2, 1}, element::Type(ET), std::vector{10, 20}), // updates + Tensor({1}, element::Type(ET_IND), std::vector{1}), // axis + Tensor({2, 1}, element::Type(ET), std::vector{10, 20})), // expected + }; + return scatterParams; +} + +std::vector generateScatterCombinedParams() { + const std::vector> scatterTypeParams{ + // i16 + generateScatterParams(), + generateScatterParams(), + generateScatterParams(), + generateScatterParams(), + generateScatterParams(), + generateScatterParams(), + generateScatterParams(), + generateScatterParams(), + // i32 + generateScatterParams(), + generateScatterParams(), + generateScatterParams(), + generateScatterParams(), + generateScatterParams(), + generateScatterParams(), + generateScatterParams(), + generateScatterParams(), + // i64 + generateScatterParams(), + generateScatterParams(), + generateScatterParams(), + generateScatterParams(), + generateScatterParams(), + generateScatterParams(), + generateScatterParams(), + generateScatterParams(), + // u32 + generateScatterParams(), + generateScatterParams(), + generateScatterParams(), + generateScatterParams(), + generateScatterParams(), + generateScatterParams(), + generateScatterParams(), + generateScatterParams(), + // u64 + generateScatterParams(), + generateScatterParams(), + generateScatterParams(), + generateScatterParams(), + generateScatterParams(), + generateScatterParams(), + generateScatterParams(), + generateScatterParams(), + // f16 + generateScatterParams(), + generateScatterParams(), + generateScatterParams(), + generateScatterParams(), + generateScatterParams(), + generateScatterParams(), + generateScatterParams(), + generateScatterParams(), + // f32 + generateScatterParams(), + generateScatterParams(), + generateScatterParams(), + generateScatterParams(), + generateScatterParams(), + generateScatterParams(), + generateScatterParams(), + generateScatterParams(), + }; + std::vector combinedParams; + for (const auto& params : scatterTypeParams) { + combinedParams.insert(combinedParams.end(), params.begin(), params.end()); + } + return combinedParams; +} +INSTANTIATE_TEST_SUITE_P(smoke_ScatterEltsUpdate_With_Hardcoded_Refs, + ReferenceScatterElementsUpdateLayerTest, + ::testing::ValuesIn(generateScatterCombinedParams()), + ReferenceScatterElementsUpdateLayerTest::getTestCaseName); +} // namespace diff --git a/inference-engine/tests/functional/inference_engine/serialization/single_layer/scatter_elements_update.cpp b/inference-engine/tests/functional/inference_engine/serialization/single_layer/scatter_elements_update.cpp new file mode 100644 index 00000000000..b41246eace7 --- /dev/null +++ b/inference-engine/tests/functional/inference_engine/serialization/single_layer/scatter_elements_update.cpp @@ -0,0 +1,51 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include +#include + +#include "shared_test_classes/single_layer/scatter_elements_update.hpp" +#include "common_test_utils/test_constants.hpp" + +using namespace LayerTestsDefinitions; +using namespace ngraph::opset3; + +namespace { +TEST_P(ScatterElementsUpdateLayerTest, Serialize) { + Serialize(); +} +// map> +std::map, std::map, std::vector>> axesShapeInShape { + {{10, 12, 15}, {{{1, 2, 4}, {0, 1, 2}}, {{2, 2, 2}, {-1, -2, -3}}}}, + {{15, 9, 8, 12}, {{{1, 2, 2, 2}, {0, 1, 2, 3}}, {{1, 2, 1, 4}, {-1, -2, -3, -4}}}}, + {{9, 9, 8, 8, 11, 10}, {{{1, 2, 1, 2, 1, 2}, {5, -3}}}}, +}; +// index value should not be random data +const std::vector> idxValue = { + {1, 0, 4, 6, 2, 3, 7, 5} +}; + +const std::vector inputPrecisions = { + InferenceEngine::Precision::FP32, + InferenceEngine::Precision::FP16, + InferenceEngine::Precision::I32, +}; + +const std::vector idxPrecisions = { + InferenceEngine::Precision::I32, + InferenceEngine::Precision::I64, +}; + +const auto ScatterEltUpdateCases = ::testing::Combine( + ::testing::ValuesIn(ScatterElementsUpdateLayerTest::combineShapes(axesShapeInShape)), + ::testing::ValuesIn(idxValue), + ::testing::ValuesIn(inputPrecisions), + ::testing::ValuesIn(idxPrecisions), + ::testing::Values(CommonTestUtils::DEVICE_CPU) +); + +INSTANTIATE_TEST_SUITE_P(smoke_ScatterEltsUpdateSerialization, ScatterElementsUpdateLayerTest, + ScatterEltUpdateCases, ScatterElementsUpdateLayerTest::getTestCaseName); + +} // namespace diff --git a/inference-engine/tests/ie_test_utils/functional_test_utils/layer_tests_summary/utils/constants.py b/inference-engine/tests/ie_test_utils/functional_test_utils/layer_tests_summary/utils/constants.py index e35678eee29..d40dc40480c 100644 --- a/inference-engine/tests/ie_test_utils/functional_test_utils/layer_tests_summary/utils/constants.py +++ b/inference-engine/tests/ie_test_utils/functional_test_utils/layer_tests_summary/utils/constants.py @@ -105,6 +105,7 @@ VERIFIED_OP_REFERENCES = [ 'ReverseSequence-1', 'Round-5', 'SpaceToDepth-1', + 'ScatterElementsUpdate-3', 'ScatterNDUpdate-4', 'Select-1', 'ShapeOf-1', diff --git a/ngraph/core/include/ngraph/op/scatter_elements_update.hpp b/ngraph/core/include/ngraph/op/scatter_elements_update.hpp index e49ed049750..78847c2a33e 100644 --- a/ngraph/core/include/ngraph/op/scatter_elements_update.hpp +++ b/ngraph/core/include/ngraph/op/scatter_elements_update.hpp @@ -15,10 +15,8 @@ namespace op { namespace v3 { class NGRAPH_API ScatterElementsUpdate : public Op { public: - static constexpr NodeTypeInfo type_info{"ScatterElementsUpdate", 3}; - const NodeTypeInfo& get_type_info() const override { - return type_info; - } + NGRAPH_RTTI_DECLARATION; + ScatterElementsUpdate() = default; /// \brief Constructs a ScatterElementsUpdate node diff --git a/ngraph/core/src/op/scatter_elements_update.cpp b/ngraph/core/src/op/scatter_elements_update.cpp index b4880bbb74b..46275a703f4 100644 --- a/ngraph/core/src/op/scatter_elements_update.cpp +++ b/ngraph/core/src/op/scatter_elements_update.cpp @@ -13,7 +13,7 @@ using namespace ngraph; using namespace std; -constexpr NodeTypeInfo op::v3::ScatterElementsUpdate::type_info; +NGRAPH_RTTI_DEFINITION(op::ScatterElementsUpdate, "ScatterElementsUpdate", 3); op::v3::ScatterElementsUpdate::ScatterElementsUpdate(const Output& data, const Output& indices, diff --git a/ngraph/test/CMakeLists.txt b/ngraph/test/CMakeLists.txt index 16ad46af9ed..ec621a10509 100644 --- a/ngraph/test/CMakeLists.txt +++ b/ngraph/test/CMakeLists.txt @@ -330,6 +330,7 @@ set(SRC visitors/op/rnn_cell.cpp visitors/op/roi_pooling.cpp visitors/op/round.cpp + visitors/op/scatter_elements_update.cpp visitors/op/select.cpp visitors/op/space_to_depth.cpp visitors/op/selu.cpp diff --git a/ngraph/test/visitors/op/scatter_elements_update.cpp b/ngraph/test/visitors/op/scatter_elements_update.cpp new file mode 100644 index 00000000000..fdceae95925 --- /dev/null +++ b/ngraph/test/visitors/op/scatter_elements_update.cpp @@ -0,0 +1,28 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "gtest/gtest.h" +#include "ngraph/ngraph.hpp" +#include "ngraph/op/util/attr_types.hpp" +#include "ngraph/opsets/opset3.hpp" +#include "util/visitor.hpp" + +using namespace ngraph; +using ngraph::test::NodeBuilder; +using ngraph::test::ValueMap; + +TEST(attributes, scatter_elements_update) { + NodeBuilder::get_ops().register_factory(); + + auto data = std::make_shared(element::f32, Shape{2, 4, 5, 7}); + auto indices = std::make_shared(element::i16, Shape{2, 2, 2, 2}); + auto updates = std::make_shared(element::f32, Shape{2, 2, 2, 2}); + auto axis = std::make_shared(element::i16, Shape{}); + + auto scatter = std::make_shared(data, indices, updates, axis); + NodeBuilder builder(scatter); + + const auto expected_attr_count = 0; + EXPECT_EQ(builder.get_value_map_size(), expected_attr_count); +} From b235f5e4523496400c777d165a99eb3d495c5a06 Mon Sep 17 00:00:00 2001 From: Vladimir Paramuzov Date: Mon, 30 Aug 2021 18:47:57 +0300 Subject: [PATCH 58/76] [GPU] Fixed default device id (#7155) --- .../src/cldnn_engine/cldnn_config.h | 2 +- .../shared_tests_instances/behavior/config.cpp | 7 +++++++ .../plugin/shared/include/behavior/config.hpp | 18 ++++++++++++++++++ 3 files changed, 26 insertions(+), 1 deletion(-) diff --git a/inference-engine/src/cldnn_engine/cldnn_config.h b/inference-engine/src/cldnn_engine/cldnn_config.h index 873c01e2188..8ff47846da8 100644 --- a/inference-engine/src/cldnn_engine/cldnn_config.h +++ b/inference-engine/src/cldnn_engine/cldnn_config.h @@ -30,7 +30,7 @@ struct Config { tuningConfig(), graph_dumps_dir(""), sources_dumps_dir(""), - device_id(""), + device_id("0"), kernels_cache_dir(""), n_threads(std::max(static_cast(1), std::thread::hardware_concurrency())), enable_loop_unrolling(true) { diff --git a/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/behavior/config.cpp b/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/behavior/config.cpp index 22a13191dc5..8061224764c 100644 --- a/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/behavior/config.cpp +++ b/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/behavior/config.cpp @@ -97,6 +97,13 @@ namespace { ::testing::ValuesIn(conf)), CorrectConfigAPITests::getTestCaseName); + INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, DefaultValuesConfigTests, + ::testing::Combine( + ::testing::ValuesIn(netPrecisions), + ::testing::Values(CommonTestUtils::DEVICE_GPU), + ::testing::ValuesIn(conf)), + CorrectConfigAPITests::getTestCaseName); + INSTANTIATE_TEST_SUITE_P(smoke_GPU_BehaviorTests, CorrectConfigAPITests, ::testing::Combine( ::testing::ValuesIn(netPrecisions), diff --git a/inference-engine/tests/functional/plugin/shared/include/behavior/config.hpp b/inference-engine/tests/functional/plugin/shared/include/behavior/config.hpp index dec8961c85f..3f9b8dcdf2f 100644 --- a/inference-engine/tests/functional/plugin/shared/include/behavior/config.hpp +++ b/inference-engine/tests/functional/plugin/shared/include/behavior/config.hpp @@ -133,6 +133,24 @@ namespace BehaviorTestsDefinitions { ASSERT_EQ(std::find(supportedOptions.cbegin(), supportedOptions.cend(), key), supportedOptions.cend()); } + using DefaultValuesConfigTests = BehaviorTestsUtils::BehaviorTestsBasic; + + TEST_P(DefaultValuesConfigTests, CanSetDefaultValueBackToPlugin) { + // Skip test according to plugin specific disabledTestPatterns() (if any) + SKIP_IF_CURRENT_TEST_IS_DISABLED() + InferenceEngine::CNNNetwork cnnNet(function); + InferenceEngine::Parameter metric; + ASSERT_NO_THROW(metric = ie->GetMetric(targetDevice, METRIC_KEY(SUPPORTED_CONFIG_KEYS))); + std::vector keys = metric; + + for (auto& key : keys) { + InferenceEngine::Parameter configValue; + ASSERT_NO_THROW(configValue = ie->GetConfig(targetDevice, key)); + + ASSERT_NO_THROW(ie->SetConfig({{ key, configValue.as()}}, targetDevice)); + } + } + using IncorrectConfigTests = BehaviorTestsUtils::BehaviorTestsBasic; TEST_P(IncorrectConfigTests, SetConfigWithIncorrectKey) { From 1eea4a5e0b168017398fe83575b0f17f5b3081c1 Mon Sep 17 00:00:00 2001 From: Evgeny Kotov Date: Tue, 31 Aug 2021 11:03:11 +0300 Subject: [PATCH 59/76] Unroll Tensor Iterator using ngraph pass (#7205) * use ngraph-based unroll-ti as default * use isNgraphPassesUsed for legacy code * code review fixes * code review fixes --- inference-engine/src/gna_plugin/gna_plugin.cpp | 13 +++++-------- .../src/subgraph/memory_LSTMCell.cpp | 3 ++- .../src/subgraph/multiple_LSTMCell.cpp | 6 ++++-- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/inference-engine/src/gna_plugin/gna_plugin.cpp b/inference-engine/src/gna_plugin/gna_plugin.cpp index 4f1b36ab5d5..bc566df0f09 100644 --- a/inference-engine/src/gna_plugin/gna_plugin.cpp +++ b/inference-engine/src/gna_plugin/gna_plugin.cpp @@ -750,11 +750,6 @@ void GNAPlugin::LoadNetwork(CNNNetwork & _network) { manager.register_pass(); const auto& pass_config = manager.get_pass_config(); - pass_config->set_callback( - [](const std::shared_ptr &node) -> bool { - // UnrollTI transformation is disabled by default, is turned on by LowLatency transformation - return node->get_rt_info().count("UNROLL_TI") == 0; - }); pass_config->disable(); pass_config->disable(); pass_config->disable(); @@ -798,10 +793,12 @@ void GNAPlugin::LoadNetwork(CNNNetwork & _network) { auto run_passes = [&] (const CNNNetwork& network, bool runBeforeCopy, bool lowPrecision) { auto passes = make_shared(PassManagerSettings{runBeforeCopy, lowPrecision}, network); passes->registerPass(); - passes->registerPass(); - passes->registerPass(); - if (!isNgraphPassesUsed) + if (!isNgraphPassesUsed) { + passes->registerPass(); + passes->registerPass(); passes->registerPass(); + } + passes->registerPass(); // fake quantisation aware passes diff --git a/inference-engine/tests/functional/shared_test_classes/src/subgraph/memory_LSTMCell.cpp b/inference-engine/tests/functional/shared_test_classes/src/subgraph/memory_LSTMCell.cpp index 29177461671..2baa728a189 100644 --- a/inference-engine/tests/functional/shared_test_classes/src/subgraph/memory_LSTMCell.cpp +++ b/inference-engine/tests/functional/shared_test_classes/src/subgraph/memory_LSTMCell.cpp @@ -104,7 +104,7 @@ namespace SubgraphTestsDefinitions { // TI construction auto tensor_iterator = std::make_shared(); tensor_iterator->set_body(body); - tensor_iterator->set_invariant_input(X, permute_in); + tensor_iterator->set_sliced_input(X, permute_in, 0, 1, 1, -1, 0); tensor_iterator->set_merged_input(H_t, hidden_memory_read, H_o); tensor_iterator->set_merged_input(C_t, cell_memory_read, C_o); @@ -130,6 +130,7 @@ namespace SubgraphTestsDefinitions { SinkVector{cell_memory_write, hidden_memory_write}, input_parameter, "TI_with_memory"); + tensor_iterator->validate_and_infer_types(); } void MemoryLSTMCellTest::switchToNgraphFriendlyModel() { diff --git a/inference-engine/tests/functional/shared_test_classes/src/subgraph/multiple_LSTMCell.cpp b/inference-engine/tests/functional/shared_test_classes/src/subgraph/multiple_LSTMCell.cpp index 09f8020df41..a3a131eb5b2 100644 --- a/inference-engine/tests/functional/shared_test_classes/src/subgraph/multiple_LSTMCell.cpp +++ b/inference-engine/tests/functional/shared_test_classes/src/subgraph/multiple_LSTMCell.cpp @@ -106,9 +106,10 @@ void MultipleLSTMCellTest::SetUp() { // TI construction auto tensor_iterator = std::make_shared(); tensor_iterator->set_body(body); - tensor_iterator->set_invariant_input(X, permute_in); + tensor_iterator->set_sliced_input(X, permute_in, 0, 1, 1, -1, 0); tensor_iterator->set_merged_input(H_t, hidden_memory_read, H_o); tensor_iterator->set_merged_input(C_t, cell_memory_read, C_o); + tensor_iterator->validate_and_infer_types(); auto out_unsqueeze = tensor_iterator->get_iter_value(unsqueeze_o, -1); auto out_hidden = tensor_iterator->get_iter_value(H_o, -1); @@ -165,9 +166,10 @@ void MultipleLSTMCellTest::SetUp() { // TI construction auto tensor_iterator_2 = std::make_shared(); tensor_iterator_2->set_body(body_2); - tensor_iterator_2->set_invariant_input(X_2, inbetween_squeeze); + tensor_iterator_2->set_sliced_input(X_2, inbetween_squeeze, 0, 1, 1, -1, 0); tensor_iterator_2->set_merged_input(H_t_2, hidden_memory_2_read, H_o_2); tensor_iterator_2->set_merged_input(C_t_2, cell_memory_2_read, C_o_2); + tensor_iterator_2->validate_and_infer_types(); auto out_unsqueeze_2 = tensor_iterator_2->get_iter_value(unsqueeze_o_2, -1); auto out_hidden_2 = tensor_iterator_2->get_iter_value(H_o_2, -1); From 82442c83247db93bb128bc965e1f6fe3eebd9f00 Mon Sep 17 00:00:00 2001 From: Vladislav Golubev Date: Tue, 31 Aug 2021 13:50:54 +0300 Subject: [PATCH 60/76] [LPT] SubMulToMulAdd transformation: naming fix (#7195) * [LPT] SubMulToMulAddTransformation: naming fix * [LPT] Refactoring and legacy code removed * [TESTS] SubMulToMulAdd: added check on unique friendly names --- .../src/clamp.cpp | 33 +++-------- .../src/depth_to_space.cpp | 3 +- .../src/fold_fake_quantize.cpp | 2 +- .../src/max_pool.cpp | 2 +- .../low_precision_transformations/src/mvn.cpp | 10 +--- .../src/normalize_l2.cpp | 9 +-- .../src/strided_slice.cpp | 22 +++----- .../src/subtract.cpp | 8 +-- .../src/subtract_multiply_to_multiply_add.cpp | 1 + .../layer_transformation.cpp | 55 +++++-------------- .../layer_transformation.hpp | 29 +--------- ...ultiply_to_multiply_add_transformation.cpp | 3 + .../src/common/builders.cpp | 3 + 13 files changed, 52 insertions(+), 128 deletions(-) diff --git a/inference-engine/src/low_precision_transformations/src/clamp.cpp b/inference-engine/src/low_precision_transformations/src/clamp.cpp index da1b462697d..4c1c10efade 100644 --- a/inference-engine/src/low_precision_transformations/src/clamp.cpp +++ b/inference-engine/src/low_precision_transformations/src/clamp.cpp @@ -32,35 +32,14 @@ ClampTransformation::ClampTransformation(const Params& params) : LayerTransforma } bool ClampTransformation::transform(TransformationContext& context, ngraph::pattern::Matcher& m) { - auto subWithTheSameValues = [](std::shared_ptr sub) { - if (sub == nullptr) { - return false; - } - - auto constant = ov::as_type_ptr(sub->get_input_node_shared_ptr(1)); - if (constant == nullptr) { - const auto convert = sub->get_input_node_shared_ptr(1); - if (!ov::is_type(convert)) { - return false; - } - constant = ov::as_type_ptr(convert->get_input_node_shared_ptr(0)); - } - - if (constant == nullptr) { - return false; - } - - return NetworkHelper::isScalarLike(constant); - }; - if (!canBeTransformed(context, m.get_match_root())) { return false; } - std::shared_ptr clamp = NetworkHelper::separateInStandaloneBranch(m.get_match_root()); + const std::shared_ptr clamp = NetworkHelper::separateInStandaloneBranch(m.get_match_root()); const FakeQuantizeDequantization dequantization = NetworkHelper::getDequantization(clamp); - const bool moveSubtract = subWithTheSameValues(dequantization.subtract); + const bool moveSubtract = dequantization.subtract == nullptr ? false : NetworkHelper::isScalarLike(dequantization.subtractConstant); // issue #43136 if (!moveSubtract && (dequantization.subtract != nullptr)) { return false; @@ -74,7 +53,7 @@ bool ClampTransformation::transform(TransformationContext& context, ngraph::patt double max = newClamp->get_max(); if (dequantization.multiply != nullptr) { - double scale = ov::as_type_ptr(dequantization.multiply->get_input_node_shared_ptr(1))->cast_vector()[0]; + double scale = dequantization.multiplyConstant->cast_vector()[0]; if (scale < 0.0) { std::swap(min, max); } @@ -83,14 +62,16 @@ bool ClampTransformation::transform(TransformationContext& context, ngraph::patt } if (dequantization.subtract != nullptr && moveSubtract) { - double shift = ov::as_type_ptr(dequantization.subtractConstant)->cast_vector()[0]; + double shift = dequantization.subtractConstant->cast_vector()[0]; min += shift; max += shift; } - replacement = std::make_shared(newClamp->get_input_source_output(0), min, max); + replacement = std::make_shared(newClamp->input_value(0), min, max); } + replace_node(newClamp, replacement); + replacement->set_friendly_name(newClamp->get_friendly_name()); element::Type outputClampType = dequantization.multiply ? dequantization.multiply->get_output_element_type(0) : diff --git a/inference-engine/src/low_precision_transformations/src/depth_to_space.cpp b/inference-engine/src/low_precision_transformations/src/depth_to_space.cpp index 3e66bfd0e04..b5de8dd661c 100644 --- a/inference-engine/src/low_precision_transformations/src/depth_to_space.cpp +++ b/inference-engine/src/low_precision_transformations/src/depth_to_space.cpp @@ -51,8 +51,7 @@ bool DepthToSpaceTransformation::canBeTransformed(const TransformationContext& c const FakeQuantizeDequantization dequantization = NetworkHelper::getDequantization(layer); if (dequantization.multiply != nullptr) { - auto multiplyConst = ov::as_type_ptr(dequantization.multiply->get_input_node_shared_ptr(1)); - if (!NetworkHelper::isScalarLike(multiplyConst)) { + if (!NetworkHelper::isScalarLike(dequantization.multiplyConstant)) { return false; } } diff --git a/inference-engine/src/low_precision_transformations/src/fold_fake_quantize.cpp b/inference-engine/src/low_precision_transformations/src/fold_fake_quantize.cpp index 5eb0797123e..63f01f92c4f 100644 --- a/inference-engine/src/low_precision_transformations/src/fold_fake_quantize.cpp +++ b/inference-engine/src/low_precision_transformations/src/fold_fake_quantize.cpp @@ -43,7 +43,7 @@ bool FoldFakeQuantizeTransformation::transform(TransformationContext& context, n } const auto constantShape = fakeQuantize->input(1).get_partial_shape(); - if (constantShape.is_dynamic() || constantShape.rank().is_dynamic()) { + if (constantShape.is_dynamic()) { return false; } diff --git a/inference-engine/src/low_precision_transformations/src/max_pool.cpp b/inference-engine/src/low_precision_transformations/src/max_pool.cpp index 8cdfbfc7c5a..ee49df50fae 100644 --- a/inference-engine/src/low_precision_transformations/src/max_pool.cpp +++ b/inference-engine/src/low_precision_transformations/src/max_pool.cpp @@ -43,7 +43,7 @@ bool MaxPoolTransformation::canBeTransformed(const TransformationContext& contex return false; } - const std::vector scales = ov::as_type_ptr(dequantization.multiply->get_input_node_shared_ptr(1))->cast_vector(); + const std::vector scales = dequantization.multiplyConstant->cast_vector(); if (std::any_of(scales.begin(), scales.end(), [](const float value) { return value < 0.0; })) { return false; } diff --git a/inference-engine/src/low_precision_transformations/src/mvn.cpp b/inference-engine/src/low_precision_transformations/src/mvn.cpp index 383688c2f2f..4be1cf58b9d 100644 --- a/inference-engine/src/low_precision_transformations/src/mvn.cpp +++ b/inference-engine/src/low_precision_transformations/src/mvn.cpp @@ -79,8 +79,7 @@ bool MVNTransformation::canBeTransformed(const TransformationContext& context, s } } - const auto scalesConst = ov::as_type_ptr(NetworkHelper::getConstantInput(mvn->get_input_node_shared_ptr(0))); - bool isScalarScales = NetworkHelper::isScalarLike(scalesConst); + bool isScalarScales = NetworkHelper::isScalarLike(dequantization.multiplyConstant); AxisSet reduction_axes; if (ov::is_type(mvn)) { @@ -128,12 +127,9 @@ bool MVNTransformation::transform(TransformationContext &context, ngraph::patter } FakeQuantizeDequantization dequantization = NetworkHelper::getDequantization(mvn); - auto scalesConst = ov::as_type_ptr(dequantization.multiply->get_input_node_shared_ptr(1)); - if (scalesConst == nullptr) { - scalesConst = ov::as_type_ptr(dequantization.multiply->get_input_node_shared_ptr(0)); - } + const auto scalesConst = dequantization.multiplyConstant; - auto newScalesConst = scalesConst; + auto newScalesConst = dequantization.multiplyConstant; const auto type = scalesConst->get_output_element_type(0); if (normalizeVariance) { switch (type) { diff --git a/inference-engine/src/low_precision_transformations/src/normalize_l2.cpp b/inference-engine/src/low_precision_transformations/src/normalize_l2.cpp index d7ca932335b..9cf39cb1003 100644 --- a/inference-engine/src/low_precision_transformations/src/normalize_l2.cpp +++ b/inference-engine/src/low_precision_transformations/src/normalize_l2.cpp @@ -59,15 +59,12 @@ bool NormalizeL2Transformation::canBeTransformed(const TransformationContext& co return false; } - if (NetworkHelper::getDequantization(operation).subtract != nullptr) { + const auto dequantization = NetworkHelper::getDequantization(operation); + if (dequantization.subtract != nullptr) { return false; } - const std::shared_ptr multiply = operation->get_input_node_shared_ptr(0); - auto scalesConst = ov::as_type_ptr(multiply->get_input_node_shared_ptr(1)); - if (scalesConst == nullptr) { - scalesConst = ov::as_type_ptr(multiply->get_input_node_shared_ptr(0)); - } + const auto scalesConst = dequantization.multiplyConstant; if (scalesConst == nullptr) { return false; } diff --git a/inference-engine/src/low_precision_transformations/src/strided_slice.cpp b/inference-engine/src/low_precision_transformations/src/strided_slice.cpp index 470e7aec2fc..12744e330ce 100644 --- a/inference-engine/src/low_precision_transformations/src/strided_slice.cpp +++ b/inference-engine/src/low_precision_transformations/src/strided_slice.cpp @@ -16,7 +16,7 @@ namespace low_precision { NGRAPH_RTTI_DEFINITION(ngraph::pass::low_precision::StridedSliceTransformation, "StridedSliceTransformation", 0); -std::shared_ptr stridedSliceDeqConstant( +std::shared_ptr stridedSliceDeqConstant( const std::shared_ptr strSlice, const std::shared_ptr dequantizaitonConstant) { auto constant = ov::as_type_ptr(dequantizaitonConstant); @@ -71,7 +71,7 @@ std::shared_ptr stridedSliceDeqConstant( stridedSlice->get_shrink_axis_mask(), stridedSlice->get_ellipsis_mask()); - return NetworkHelper::toScalarIfPossible(result); + return ov::as_type_ptr(NetworkHelper::toScalarIfPossible(result)); } StridedSliceTransformation::StridedSliceTransformation(const Params& params) : LayerTransformation(params) { @@ -95,21 +95,17 @@ bool StridedSliceTransformation::transform(TransformationContext& context, ngrap } const auto stridedSlice = NetworkHelper::separateInStandaloneBranch(m.get_match_root()); - const auto dequantization = NetworkHelper::getDequantization(stridedSlice); + auto dequantization = NetworkHelper::getDequantization(stridedSlice); if (dequantization.subtract) { - const auto subConst = NetworkHelper::getConstantInput(dequantization.subtract); - const size_t subConstIdx = NetworkHelper::getChildInputIndex(subConst, dequantization.subtract); - - const auto newSubConst = stridedSliceDeqConstant(stridedSlice, subConst); - dequantization.subtract->set_argument(subConstIdx, newSubConst); + const auto newSubConst = stridedSliceDeqConstant(stridedSlice, dequantization.subtractConstant); + replace_node(dequantization.subtractConstant, newSubConst); + dequantization.subtractConstant = newSubConst; } - const auto mulConst = NetworkHelper::getConstantInput(dequantization.multiply); - const size_t mulConstIdx = NetworkHelper::getChildInputIndex(mulConst, dequantization.multiply); - - const auto newMulConst = stridedSliceDeqConstant(stridedSlice, mulConst); - dequantization.multiply->set_argument(mulConstIdx, newMulConst); + const auto newMulConst = stridedSliceDeqConstant(stridedSlice, dequantization.multiplyConstant); + replace_node(dequantization.multiplyConstant, newMulConst); + dequantization.multiplyConstant = newMulConst; moveDequantizationAfter(context, stridedSlice, NetworkHelper::getDequantization(stridedSlice), false); return true; diff --git a/inference-engine/src/low_precision_transformations/src/subtract.cpp b/inference-engine/src/low_precision_transformations/src/subtract.cpp index 83569ef8dc2..46e2245bcb3 100644 --- a/inference-engine/src/low_precision_transformations/src/subtract.cpp +++ b/inference-engine/src/low_precision_transformations/src/subtract.cpp @@ -49,7 +49,7 @@ bool SubtractTransformation::transform(TransformationContext& context, ngraph::p const ngraph::element::Type originalPrecision = subtract->get_output_element_type(0); - const FakeQuantizeDequantization dequantization = ngraph::pass::low_precision::NetworkHelper::getDequantization(subtract); + const FakeQuantizeDequantization dequantization = NetworkHelper::getDequantization(subtract); if (dequantization.multiply != nullptr) { // before: Y = X * SC - SH, after: Y = (X - SH') * SC // X * SC - SH = X * SC - SH' * SC @@ -63,7 +63,7 @@ bool SubtractTransformation::transform(TransformationContext& context, ngraph::p std::shared_ptr newMultiply = dequantization.multiply->copy_with_new_inputs({ newSubtract, - dequantization.multiply->input_value(1) + dequantization.multiplyConstant }); replace_node(subtract, newMultiply); @@ -73,9 +73,7 @@ bool SubtractTransformation::transform(TransformationContext& context, ngraph::p if (dequantization.subtract != nullptr) { std::shared_ptr newSubtract = ov::as_type_ptr(subtract->copy_with_new_inputs({ dequantization.subtract->get_input_node_shared_ptr(0), - ngraph::pass::low_precision::fold( - subtract->get_input_node_shared_ptr(1), - dequantization.subtract->get_input_node_shared_ptr(1)) + fold(subtract->get_input_node_shared_ptr(1), dequantization.subtractConstant) })); replace_node(subtract, newSubtract); diff --git a/inference-engine/src/low_precision_transformations/src/subtract_multiply_to_multiply_add.cpp b/inference-engine/src/low_precision_transformations/src/subtract_multiply_to_multiply_add.cpp index 895a502f178..b604323be9c 100644 --- a/inference-engine/src/low_precision_transformations/src/subtract_multiply_to_multiply_add.cpp +++ b/inference-engine/src/low_precision_transformations/src/subtract_multiply_to_multiply_add.cpp @@ -126,6 +126,7 @@ bool SubtractMultiplyToMultiplyAddTransformation::transform(TransformationContex } } + lastPrevious = lastNew.get_node_shared_ptr(); lastNew = std::make_shared>( std::vector{element::f32, element::f32}, std::vector{precisionAfterDequantization}, diff --git a/inference-engine/tests/functional/inference_engine/lp_transformations/layer_transformation.cpp b/inference-engine/tests/functional/inference_engine/lp_transformations/layer_transformation.cpp index d316adab1e3..2a31f228c5e 100644 --- a/inference-engine/tests/functional/inference_engine/lp_transformations/layer_transformation.cpp +++ b/inference-engine/tests/functional/inference_engine/lp_transformations/layer_transformation.cpp @@ -87,46 +87,6 @@ pass::low_precision::LayerTransformation::Params TestTransformationParams::toPar params.deqPrecision); } -//TestTransformationParams LayerTransformation::createParamsU8U8() { -// return low_precision::LayerTransformation::Params( -// true, -// low_precision::LayerTransformation::QuantizedTensorAlignment::UpdateLevel, -// low_precision::LayerTransformation::QuantizedTensorAlignment::None, -// true, -// { ngraph::element::u8 }, -// { ngraph::element::u8 }); -//} -// -//TestTransformationParams LayerTransformation::createParamsU8I8() { -// return low_precision::LayerTransformation::Params( -// true, -// low_precision::LayerTransformation::QuantizedTensorAlignment::UpdateLevel, -// low_precision::LayerTransformation::QuantizedTensorAlignment::None, -// true, -// { ngraph::element::u8 }, -// { ngraph::element::i8 }); -//} -// -//TestTransformationParams LayerTransformation::createParamsI8I8() { -// return low_precision::LayerTransformation::Params( -// true, -// low_precision::LayerTransformation::QuantizedTensorAlignment::UpdateLevel, -// low_precision::LayerTransformation::QuantizedTensorAlignment::None, -// true, -// { ngraph::element::i8 }, -// { ngraph::element::i8 }); -//} -// -//TestTransformationParams LayerTransformation::createParamsU8I8AndI8() { -// return low_precision::LayerTransformation::Params( -// true, -// low_precision::LayerTransformation::QuantizedTensorAlignment::UpdateLevel, -// low_precision::LayerTransformation::QuantizedTensorAlignment::None, -// true, -// { ngraph::element::u8, ngraph::element::i8 }, -// { ngraph::element::i8 }); -//} - std::string LayerTransformation::toString(const TestTransformationParams& params) { std::ostringstream result; result << @@ -199,3 +159,18 @@ ngraph::builder::subgraph::DequantizationOperations LayerTransformation::toDequa return ngraph::builder::subgraph::DequantizationOperations(convert, subtract, multiply); } + +bool LayerTransformation::allNamesAreUnique(const std::shared_ptr& function) { + const auto& ops = function->get_ops(); + std::set opNames; + for (const auto& op : ops) { + auto it = opNames.find(op->get_friendly_name()); + if (it != opNames.end()) { + return false; + } + + opNames.insert(op->get_friendly_name()); + } + + return true; +} diff --git a/inference-engine/tests/functional/inference_engine/lp_transformations/layer_transformation.hpp b/inference-engine/tests/functional/inference_engine/lp_transformations/layer_transformation.hpp index 374eb6d265a..d704936eecf 100644 --- a/inference-engine/tests/functional/inference_engine/lp_transformations/layer_transformation.hpp +++ b/inference-engine/tests/functional/inference_engine/lp_transformations/layer_transformation.hpp @@ -47,33 +47,6 @@ struct TestTransformationParams { bool deconvolutionSpecificChannelsRatio; }; -/* -TestTransformationParams& setSupportAsymmetricQuantization(const bool supportAsymmetricQuantization) { - this->supportAsymmetricQuantization = supportAsymmetricQuantization; - return *this; - } - - TestTransformationParams& setPrecisionsOnActivations(const std::vector& precisionsOnActivations) { - this->precisionsOnActivations = precisionsOnActivations; - return *this; - } - - TestTransformationParams& setPrecisionsOnWeights(const std::vector& precisionsOnWeights) { - this->precisionsOnWeights = precisionsOnWeights; - return *this; - } - - TestTransformationParams& setSupport3DTensorOnActivations(const bool support3DTensorOnActivations) { - this->support3DTensorOnActivations = support3DTensorOnActivations; - return *this; - } - - TestTransformationParams& setDeconvolutionSpecificChannelsRatio(const bool deconvolutionSpecificChannelsRatio) { - this->deconvolutionSpecificChannelsRatio = deconvolutionSpecificChannelsRatio; - return *this; - } -*/ - class LayerTransformation : public CommonTestUtils::TestsCommon { public: static TestTransformationParams createParamsU8U8(); @@ -91,6 +64,8 @@ public: static builder::subgraph::DequantizationOperations toDequantizationOperations( const pass::low_precision::FakeQuantizeDequantization& dequantization); + static bool allNamesAreUnique(const std::shared_ptr& function); + template static NodeVector get(std::shared_ptr function) { NodeVector foundNodes; diff --git a/inference-engine/tests/functional/inference_engine/lp_transformations/subtract_multiply_to_multiply_add_transformation.cpp b/inference-engine/tests/functional/inference_engine/lp_transformations/subtract_multiply_to_multiply_add_transformation.cpp index d4a71e496c8..79f0eca2163 100644 --- a/inference-engine/tests/functional/inference_engine/lp_transformations/subtract_multiply_to_multiply_add_transformation.cpp +++ b/inference-engine/tests/functional/inference_engine/lp_transformations/subtract_multiply_to_multiply_add_transformation.cpp @@ -103,6 +103,9 @@ public: TEST_P(SubtractMultiplyToMultiplyAddTransformation, CompareFunctions) { actualFunction->validate_nodes_and_infer_types(); auto res = compare_functions(referenceFunction, actualFunction, true, true); + + // issue #63030 + ASSERT_TRUE(LayerTransformation::allNamesAreUnique(actualFunction)) << "Not all names are unique"; ASSERT_TRUE(res.first) << res.second; } diff --git a/inference-engine/tests/ngraph_helpers/lpt_ngraph_functions/src/common/builders.cpp b/inference-engine/tests/ngraph_helpers/lpt_ngraph_functions/src/common/builders.cpp index c6153dffa2d..cf2e6a4d517 100644 --- a/inference-engine/tests/ngraph_helpers/lpt_ngraph_functions/src/common/builders.cpp +++ b/inference-engine/tests/ngraph_helpers/lpt_ngraph_functions/src/common/builders.cpp @@ -28,6 +28,7 @@ std::shared_ptr makeDequantization( std::make_shared(data, dequantizationOperations.convert.outPrecision) : std::make_shared(data, dequantizationOperations.convert.outPrecision); NetworkHelper::copyInfo({ data.get_node_shared_ptr(), convert }, convert); + convert->set_friendly_name(data.get_node_shared_ptr()->get_friendly_name() + "/DequantizationConvert"); parent = convert; } @@ -120,6 +121,7 @@ std::shared_ptr makeDequantization( } } + subtract->set_friendly_name(data.get_node_shared_ptr()->get_friendly_name() + "/DequantizationSubtract"); ngraph::pass::low_precision::NetworkHelper::setOutDataPrecision(subtract, dequantizationOperations.subtract.outPrecision); } if (!dequantizationOperations.subtract.addDequantizationAttribute) { @@ -140,6 +142,7 @@ std::shared_ptr makeDequantization( if (!dequantizationOperations.multiply.empty()) { auto const newMultiply = makeMultiply(parent, dequantizationOperations.multiply); NetworkHelper::copyInfo({ data.get_node_shared_ptr(), newMultiply }, newMultiply); + newMultiply->set_friendly_name(data.get_node_shared_ptr()->get_friendly_name() + "/DequantizationMultiply"); parent = newMultiply; } From 494aaef6ae86f0dc3beea5f9f34186f66d0f55d8 Mon Sep 17 00:00:00 2001 From: Roman Kazantsev Date: Tue, 31 Aug 2021 15:43:38 +0300 Subject: [PATCH 61/76] Suppress obsolete MO parameters (#7276) Signed-off-by: Roman Kazantsev --- model-optimizer/mo/utils/cli_parser.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/model-optimizer/mo/utils/cli_parser.py b/model-optimizer/mo/utils/cli_parser.py index bbfdbcfdfed..3e89843ef54 100644 --- a/model-optimizer/mo/utils/cli_parser.py +++ b/model-optimizer/mo/utils/cli_parser.py @@ -334,9 +334,7 @@ def get_common_cli_parser(parser: argparse.ArgumentParser = None): 'Use --input option to specify a value for freezing.', default=None) common_group.add_argument('--generate_deprecated_IR_V7', - help='Force to generate deprecated IR V7 with layers from old IR specification.', - action=IgnoredAction, - default=False) + help=argparse.SUPPRESS, action=IgnoredAction, default=False) common_group.add_argument('--static_shape', help='Enables IR generation for fixed input shape (folding `ShapeOf` operations and ' 'shape-calculating sub-graphs to `Constant`). Changing model input shape using ' @@ -358,8 +356,7 @@ def get_common_cli_parser(parser: argparse.ArgumentParser = None): help='Use the configuration file with transformations description.', action=CanonicalizePathCheckExistenceAction) common_group.add_argument('--legacy_ir_generation', - help='Use legacy IR serialization engine', - action=DeprecatedStoreTrue, default=False) + help=argparse.SUPPRESS, action=DeprecatedStoreTrue, default=False) return parser From 781c1aecffecfd8b6d890c5a849cf482019297f1 Mon Sep 17 00:00:00 2001 From: Vladimir Paramuzov Date: Tue, 31 Aug 2021 18:45:56 +0300 Subject: [PATCH 62/76] Revert "[GPU] Fixed default device id (#7155)" (#7308) This reverts commit b235f5e4523496400c777d165a99eb3d495c5a06. --- .../src/cldnn_engine/cldnn_config.h | 2 +- .../shared_tests_instances/behavior/config.cpp | 7 ------- .../plugin/shared/include/behavior/config.hpp | 18 ------------------ 3 files changed, 1 insertion(+), 26 deletions(-) diff --git a/inference-engine/src/cldnn_engine/cldnn_config.h b/inference-engine/src/cldnn_engine/cldnn_config.h index 8ff47846da8..873c01e2188 100644 --- a/inference-engine/src/cldnn_engine/cldnn_config.h +++ b/inference-engine/src/cldnn_engine/cldnn_config.h @@ -30,7 +30,7 @@ struct Config { tuningConfig(), graph_dumps_dir(""), sources_dumps_dir(""), - device_id("0"), + device_id(""), kernels_cache_dir(""), n_threads(std::max(static_cast(1), std::thread::hardware_concurrency())), enable_loop_unrolling(true) { diff --git a/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/behavior/config.cpp b/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/behavior/config.cpp index 8061224764c..22a13191dc5 100644 --- a/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/behavior/config.cpp +++ b/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/behavior/config.cpp @@ -97,13 +97,6 @@ namespace { ::testing::ValuesIn(conf)), CorrectConfigAPITests::getTestCaseName); - INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, DefaultValuesConfigTests, - ::testing::Combine( - ::testing::ValuesIn(netPrecisions), - ::testing::Values(CommonTestUtils::DEVICE_GPU), - ::testing::ValuesIn(conf)), - CorrectConfigAPITests::getTestCaseName); - INSTANTIATE_TEST_SUITE_P(smoke_GPU_BehaviorTests, CorrectConfigAPITests, ::testing::Combine( ::testing::ValuesIn(netPrecisions), diff --git a/inference-engine/tests/functional/plugin/shared/include/behavior/config.hpp b/inference-engine/tests/functional/plugin/shared/include/behavior/config.hpp index 3f9b8dcdf2f..dec8961c85f 100644 --- a/inference-engine/tests/functional/plugin/shared/include/behavior/config.hpp +++ b/inference-engine/tests/functional/plugin/shared/include/behavior/config.hpp @@ -133,24 +133,6 @@ namespace BehaviorTestsDefinitions { ASSERT_EQ(std::find(supportedOptions.cbegin(), supportedOptions.cend(), key), supportedOptions.cend()); } - using DefaultValuesConfigTests = BehaviorTestsUtils::BehaviorTestsBasic; - - TEST_P(DefaultValuesConfigTests, CanSetDefaultValueBackToPlugin) { - // Skip test according to plugin specific disabledTestPatterns() (if any) - SKIP_IF_CURRENT_TEST_IS_DISABLED() - InferenceEngine::CNNNetwork cnnNet(function); - InferenceEngine::Parameter metric; - ASSERT_NO_THROW(metric = ie->GetMetric(targetDevice, METRIC_KEY(SUPPORTED_CONFIG_KEYS))); - std::vector keys = metric; - - for (auto& key : keys) { - InferenceEngine::Parameter configValue; - ASSERT_NO_THROW(configValue = ie->GetConfig(targetDevice, key)); - - ASSERT_NO_THROW(ie->SetConfig({{ key, configValue.as()}}, targetDevice)); - } - } - using IncorrectConfigTests = BehaviorTestsUtils::BehaviorTestsBasic; TEST_P(IncorrectConfigTests, SetConfigWithIncorrectKey) { From e6482037aa657797c83b007648e841d1db9ec49d Mon Sep 17 00:00:00 2001 From: Denis Orlov Date: Tue, 31 Aug 2021 19:50:27 +0300 Subject: [PATCH 63/76] [GNA] Include documentation for GNA3 QoS (#7046) (#7302) * [GNA] Include documentation for GNA3 QoS * Fix according to review * Fix the driver version --- docs/IE_DG/supported_plugins/GNA.md | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/docs/IE_DG/supported_plugins/GNA.md b/docs/IE_DG/supported_plugins/GNA.md index e37fbc646f1..ce124072b06 100644 --- a/docs/IE_DG/supported_plugins/GNA.md +++ b/docs/IE_DG/supported_plugins/GNA.md @@ -86,7 +86,7 @@ Intel® GNA essentially operates in the low-precision mode, which represents a m Unlike other plugins supporting low-precision execution, the GNA plugin can calculate quantization factors at the model loading time, so you can run a model without calibration using the [Post-Training Optimizaton Tool](@ref pot_README). However, this mode may not provide satisfactory accuracy because the internal quantization algorithm is based on heuristics which may or may not be efficient, depending on the model and dynamic range of input data. -Starting with 2021.4 release of OpenVINO, GNA plugin users are encouraged to use the [POT API Usage sample for GNA](@ref pot_sample_speech_README) to get a model with quantization hints based on statistics for the provided dataset. +Starting with 2021.4 release of OpenVINO™, GNA plugin users are encouraged to use the [POT API Usage sample for GNA](@ref pot_sample_speech_README) to get a model with quantization hints based on statistics for the provided dataset. ## Execution Modes @@ -97,6 +97,7 @@ Starting with 2021.4 release of OpenVINO, GNA plugin users are encouraged to use | `GNA_HW` | Uses Intel® GNA if available, otherwise raises an error. | | `GNA_SW` | *Deprecated*. Executes the GNA-compiled graph on CPU performing calculations in the same precision as the Intel® GNA, but not in the bit-exact mode. | | `GNA_SW_EXACT` | Executes the GNA-compiled graph on CPU performing calculations in the same precision as the Intel® GNA in the bit-exact mode. | +| `GNA_HW_WITH_SW_FBACK` | Uses Intel® GNA if available, otherwise raises an error. If the HW queue is not empty, automatically falls back to CPU in the bit-exact mode. | | `GNA_SW_FP32` | Executes the GNA-compiled graph on CPU but substitutes parameters and calculations from low precision to floating point (`FP32`). | ## Supported Configuration Parameters @@ -189,6 +190,19 @@ executableNet.SetConfig(newConfig); ``` 2. Resubmit and switch back to GNA_HW expecting that the competing application has finished. +> **NOTE:** This method is deprecated since a new automatic QoS mode has been introduced in 2021.4.1 release of OpenVINO™ (see below). + +## GNA3 Automatic QoS Feature on Windows* + +Starting with 2021.4.1 release of OpenVINO and 03.00.00.1363 version of Windows* GNA driver, a new execution mode (GNA_HW_WITH_SW_FBACK) is introduced +to assure that workloads satisfy real-time execution. In this mode, the GNA driver automatically falls back on CPU for a particular infer request +if the HW queue is not empty, so there is no need for explicitly switching between GNA and CPU. + +**NOTE:** Due to the "first come - first served" nature of GNA driver and the QoS feature, this mode may lead to increased CPU consumption +if there are several clients using GNA simultaneously. +Even a lightweight competing infer request which has not been cleared at the time when the user's GNA client process makes its request, +can cause the user's request to be executed on CPU, thereby unnecessarily increasing CPU utilization and power. + ## See Also * [Supported Devices](Supported_Devices.md) From 2b1637f28d111c6de11d7926b5f26af64ce6ff18 Mon Sep 17 00:00:00 2001 From: Ilya Churaev Date: Wed, 1 Sep 2021 08:17:11 +0300 Subject: [PATCH 64/76] Deprecate nGraph API to don't include it to public API (#7171) * Deprecate stopwatch * Deprecate some utils * Deprecate versions * Moved slice_plan from the top level * Fixed build * Deprecate more old structures * Fixed linux build --- ngraph/core/include/ngraph/distributed.hpp | 2 + ngraph/core/include/ngraph/evaluator.hpp | 5 +- .../core/include/ngraph/factory_adapter.hpp | 5 +- ngraph/core/include/ngraph/ngraph.hpp | 9 ++- .../include/ngraph/op/util/slice_plan.hpp | 56 +++++++++++++++++++ ngraph/core/include/ngraph/slice_plan.hpp | 49 +--------------- ngraph/core/include/ngraph/util.hpp | 35 +++++++++--- .../reference/src/coordinate_transform.cpp | 2 + ngraph/core/src/distributed.cpp | 3 + ngraph/core/src/ngraph.cpp | 2 + ngraph/core/src/op/constant.cpp | 2 + ngraph/core/src/op/transpose.cpp | 2 + ngraph/core/src/{ => op/util}/slice_plan.cpp | 0 ngraph/core/src/pass/manager.cpp | 4 +- ngraph/core/src/runtime/aligned_buffer.cpp | 2 + ngraph/core/src/runtime/host_tensor.cpp | 4 ++ ngraph/core/src/type.cpp | 2 + ngraph/core/src/util.cpp | 1 + ngraph/core/src/validation_util.cpp | 1 + ngraph/test/bfloat16.cpp | 2 + .../runtime/interpreter/int_executable.hpp | 43 +++++++------- 21 files changed, 147 insertions(+), 84 deletions(-) create mode 100644 ngraph/core/include/ngraph/op/util/slice_plan.hpp rename ngraph/core/src/{ => op/util}/slice_plan.cpp (100%) diff --git a/ngraph/core/include/ngraph/distributed.hpp b/ngraph/core/include/ngraph/distributed.hpp index f36c318cf05..ed4a0e84c80 100644 --- a/ngraph/core/include/ngraph/distributed.hpp +++ b/ngraph/core/include/ngraph/distributed.hpp @@ -21,8 +21,10 @@ enum class Type { MAX, }; +NGRAPH_SUPPRESS_DEPRECATED_START NGRAPH_API std::ostream& operator<<(std::ostream& out, const Type& obj); +NGRAPH_SUPPRESS_DEPRECATED_END } // namespace reduction } // namespace ngraph diff --git a/ngraph/core/include/ngraph/evaluator.hpp b/ngraph/core/include/ngraph/evaluator.hpp index 63ba4826a26..d67110fffb5 100644 --- a/ngraph/core/include/ngraph/evaluator.hpp +++ b/ngraph/core/include/ngraph/evaluator.hpp @@ -8,6 +8,7 @@ #include #include +#include "ngraph/deprecated.hpp" #include "ngraph/node.hpp" #include "ngraph/shape.hpp" #include "ngraph/type/element_type_traits.hpp" @@ -17,7 +18,8 @@ namespace ngraph { /// /// template -class Evaluator { +class NGRAPH_DEPRECATED("This class is deprecated and will be removed soon.") Evaluator { + NGRAPH_SUPPRESS_DEPRECATED_START public: /// \brief values we compute for outputs using value_map = std::map; @@ -172,5 +174,6 @@ protected: op_handler_map m_handlers; op_handler m_default_handler; value_map& m_value_map; + NGRAPH_SUPPRESS_DEPRECATED_END }; } // namespace ngraph diff --git a/ngraph/core/include/ngraph/factory_adapter.hpp b/ngraph/core/include/ngraph/factory_adapter.hpp index a465857129f..6ae19e5a473 100644 --- a/ngraph/core/include/ngraph/factory_adapter.hpp +++ b/ngraph/core/include/ngraph/factory_adapter.hpp @@ -6,11 +6,14 @@ #include "ngraph/attribute_adapter.hpp" #include "ngraph/attribute_visitor.hpp" +#include "ngraph/deprecated.hpp" #include "ngraph/factory.hpp" namespace ngraph { template -class FactoryAttributeAdapter : public VisitorAdapter { + +class NGRAPH_DEPRECATED("This class is deprecated and will be removed soon.") FactoryAttributeAdapter + : public VisitorAdapter { public: FactoryAttributeAdapter(std::shared_ptr& ref) : m_ref(ref) {} diff --git a/ngraph/core/include/ngraph/ngraph.hpp b/ngraph/core/include/ngraph/ngraph.hpp index 38a8365f8a6..a759eae29b6 100644 --- a/ngraph/core/include/ngraph/ngraph.hpp +++ b/ngraph/core/include/ngraph/ngraph.hpp @@ -10,13 +10,19 @@ #include +#include "ngraph/deprecated.hpp" + #ifdef IN_NGRAPH_LIBRARY # error("ngraph.hpp is for external use only") #endif #include -extern "C" NGRAPH_API const char* get_ngraph_version_string(); +// clang-format off +extern "C" NGRAPH_API +NGRAPH_DEPRECATED("This method is deprecated and will be removed soon") +const char* get_ngraph_version_string(); +// clang-format on namespace ngraph { /// \brief Function to query parsed version information of the version of ngraph which @@ -30,6 +36,7 @@ namespace ngraph { /// /// \note Throws a runtime_error if there is an error during parsing NGRAPH_API +NGRAPH_DEPRECATED("This method is deprecated and will be removed soon") void get_version(size_t& major, size_t& minor, size_t& patch, std::string& extra); } // namespace ngraph diff --git a/ngraph/core/include/ngraph/op/util/slice_plan.hpp b/ngraph/core/include/ngraph/op/util/slice_plan.hpp new file mode 100644 index 00000000000..cd636450d1e --- /dev/null +++ b/ngraph/core/include/ngraph/op/util/slice_plan.hpp @@ -0,0 +1,56 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +#include + +#include "ngraph/axis_set.hpp" +#include "ngraph/shape.hpp" + +namespace ngraph { +// +// In various places, like ConstantFolding, it is +// useful to transform DynSlice by converting it to a sequence of ops: +// +// Slice (to do the basic slicing) +// | +// v +// Reshape (non-transposing, to handle shrinks) +// | +// v +// Reverse (to emulate backwards stride) +// +// (The Reshape, Reverse, or both may be omitted if they would just be +// identities.) +// +// A SlicePlan is used to collect parameters for these ops. +// +struct NGRAPH_API SlicePlan { + // Parameters for the Slice + std::vector begins; + std::vector ends; + std::vector strides; + + // Shapes coming into, and going out of, the Reshape. + Shape reshape_in_shape; + Shape reshape_out_shape; + + // Parameters for the Reverse + AxisSet reverse_axes; + + bool operator==(const SlicePlan& other) const; + bool operator!=(const SlicePlan& other) const; +}; + +SlicePlan NGRAPH_API make_slice_plan(const Shape& input_shape, + const std::vector& begins, + const std::vector& ends, + const std::vector& strides, + const AxisSet& lower_bounds_mask, + const AxisSet& upper_bounds_mask, + const AxisSet& new_axis_mask, + const AxisSet& shrink_axis_mask, + const AxisSet& ellipsis_mask); +} // namespace ngraph diff --git a/ngraph/core/include/ngraph/slice_plan.hpp b/ngraph/core/include/ngraph/slice_plan.hpp index cd636450d1e..2f6eb7f0041 100644 --- a/ngraph/core/include/ngraph/slice_plan.hpp +++ b/ngraph/core/include/ngraph/slice_plan.hpp @@ -6,51 +6,4 @@ #include -#include "ngraph/axis_set.hpp" -#include "ngraph/shape.hpp" - -namespace ngraph { -// -// In various places, like ConstantFolding, it is -// useful to transform DynSlice by converting it to a sequence of ops: -// -// Slice (to do the basic slicing) -// | -// v -// Reshape (non-transposing, to handle shrinks) -// | -// v -// Reverse (to emulate backwards stride) -// -// (The Reshape, Reverse, or both may be omitted if they would just be -// identities.) -// -// A SlicePlan is used to collect parameters for these ops. -// -struct NGRAPH_API SlicePlan { - // Parameters for the Slice - std::vector begins; - std::vector ends; - std::vector strides; - - // Shapes coming into, and going out of, the Reshape. - Shape reshape_in_shape; - Shape reshape_out_shape; - - // Parameters for the Reverse - AxisSet reverse_axes; - - bool operator==(const SlicePlan& other) const; - bool operator!=(const SlicePlan& other) const; -}; - -SlicePlan NGRAPH_API make_slice_plan(const Shape& input_shape, - const std::vector& begins, - const std::vector& ends, - const std::vector& strides, - const AxisSet& lower_bounds_mask, - const AxisSet& upper_bounds_mask, - const AxisSet& new_axis_mask, - const AxisSet& shrink_axis_mask, - const AxisSet& ellipsis_mask); -} // namespace ngraph +#include "ngraph/op/util/slice_plan.hpp" diff --git a/ngraph/core/include/ngraph/util.hpp b/ngraph/core/include/ngraph/util.hpp index 2f4d2c376a4..d5a85793e5f 100644 --- a/ngraph/core/include/ngraph/util.hpp +++ b/ngraph/core/include/ngraph/util.hpp @@ -34,8 +34,6 @@ using ov::Node; class stopwatch; namespace runtime { -class Backend; -class Value; class Tensor; } // namespace runtime @@ -60,8 +58,10 @@ std::string vector_to_string(const T& v) { } NGRAPH_API +NGRAPH_DEPRECATED("This method is deprecated and will be removed soon") size_t hash_combine(const std::vector& list); NGRAPH_API +NGRAPH_DEPRECATED("This method is deprecated and will be removed soon") void dump(std::ostream& out, const void*, size_t); NGRAPH_API std::string to_lower(const std::string& s); @@ -73,6 +73,7 @@ NGRAPH_API std::vector split(const std::string& s, char delimiter, bool trim = false); template +NGRAPH_DEPRECATED("This method is deprecated and will be removed soon") std::string locale_string(T x) { std::stringstream ss; ss.imbue(std::locale("")); @@ -80,7 +81,7 @@ std::string locale_string(T x) { return ss.str(); } -class NGRAPH_API stopwatch { +class NGRAPH_API NGRAPH_DEPRECATED("It is obsolete structure and will be removed soon") stopwatch { public: void start() { if (m_active == false) { @@ -122,6 +123,7 @@ private: /// Parses a string containing a literal of the underlying type. template +NGRAPH_DEPRECATED("This method is deprecated and will be removed soon") T parse_string(const std::string& s) { T result; std::stringstream ss; @@ -140,26 +142,33 @@ T parse_string(const std::string& s) { /// template specializations for float and double to handle INFINITY, -INFINITY /// and NaN values. template <> +NGRAPH_DEPRECATED("This method is deprecated and will be removed soon") NGRAPH_API float parse_string(const std::string& s); template <> +NGRAPH_DEPRECATED("This method is deprecated and will be removed soon") NGRAPH_API double parse_string(const std::string& s); /// template specializations for int8_t and uint8_t to handle the fact that default /// implementation ends up treating values as characters so that the number "0" turns into /// the parsed value 48, which is it's ASCII value template <> +NGRAPH_DEPRECATED("This method is deprecated and will be removed soon") NGRAPH_API int8_t parse_string(const std::string& s); template <> +NGRAPH_DEPRECATED("This method is deprecated and will be removed soon") NGRAPH_API uint8_t parse_string(const std::string& s); /// Parses a list of strings containing literals of the underlying type. template +NGRAPH_DEPRECATED("This method is deprecated and will be removed soon") std::vector parse_string(const std::vector& ss) { + NGRAPH_SUPPRESS_DEPRECATED_START std::vector result(ss.size()); std::transform(ss.begin(), ss.end(), result.begin(), [](const std::string& s) { return parse_string(s); }); return result; + NGRAPH_SUPPRESS_DEPRECATED_END } template @@ -168,30 +177,41 @@ T ceil_div(const T& x, const T& y) { } template +NGRAPH_DEPRECATED("This method is deprecated and will be removed soon") T subtract_or_zero(T x, T y) { return y > x ? 0 : x - y; } NGRAPH_API +NGRAPH_DEPRECATED("This method is deprecated and will be removed soon") void* ngraph_malloc(size_t size); NGRAPH_API +NGRAPH_DEPRECATED("This method is deprecated and will be removed soon") void ngraph_free(void*); NGRAPH_API size_t round_up(size_t size, size_t alignment); + +NGRAPH_DEPRECATED("This method is deprecated and will be removed soon") bool is_valid_permutation(ngraph::AxisVector permutation, ngraph::Rank rank = Rank::dynamic()); template +NGRAPH_DEPRECATED("This method is deprecated and will be removed soon") T apply_permutation(T input, ngraph::AxisVector order); -extern template NGRAPH_API AxisVector apply_permutation(AxisVector input, AxisVector order); +extern template NGRAPH_API NGRAPH_DEPRECATED("This method is deprecated and will be removed soon") + AxisVector apply_permutation(AxisVector input, AxisVector order); -extern template NGRAPH_API Coordinate apply_permutation(Coordinate input, AxisVector order); +extern template NGRAPH_API NGRAPH_DEPRECATED("This method is deprecated and will be removed soon") + Coordinate apply_permutation(Coordinate input, AxisVector order); -extern template NGRAPH_API Strides apply_permutation(Strides input, AxisVector order); +extern template NGRAPH_API NGRAPH_DEPRECATED("This method is deprecated and will be removed soon") Strides + apply_permutation(Strides input, AxisVector order); -extern template NGRAPH_API Shape apply_permutation(Shape input, AxisVector order); +extern template NGRAPH_API NGRAPH_DEPRECATED("This method is deprecated and will be removed soon") Shape + apply_permutation(Shape input, AxisVector order); template <> +NGRAPH_DEPRECATED("This method is deprecated and will be removed soon") NGRAPH_API PartialShape apply_permutation(PartialShape input, AxisVector order); NGRAPH_API @@ -317,6 +337,7 @@ private: /// /// \note Throws a runtime_error if there is an error during parsing NGRAPH_API +NGRAPH_DEPRECATED("This method is deprecated and will be removed soon") void parse_version_string(std::string version, size_t& major, size_t& minor, size_t& patch, std::string& extra); template diff --git a/ngraph/core/reference/src/coordinate_transform.cpp b/ngraph/core/reference/src/coordinate_transform.cpp index 84a9639d6c8..0acfedfb1e5 100644 --- a/ngraph/core/reference/src/coordinate_transform.cpp +++ b/ngraph/core/reference/src/coordinate_transform.cpp @@ -123,8 +123,10 @@ CoordinateTransform::CoordinateTransform(const Shape& source_shape, std::vector padded_upper_bounds; for (size_t i = 0; i < m_n_axes; i++) { + NGRAPH_SUPPRESS_DEPRECATED_START std::ptrdiff_t padded_upper_bound = subtract_or_zero(source_shape[i], size_t(1)) * target_dilation_strides[i] + 1 + target_padding_below[i] + target_padding_above[i]; + NGRAPH_SUPPRESS_DEPRECATED_END if (padded_upper_bound < 0) { std::stringstream ss; diff --git a/ngraph/core/src/distributed.cpp b/ngraph/core/src/distributed.cpp index 5849ef9d2b5..52058275052 100644 --- a/ngraph/core/src/distributed.cpp +++ b/ngraph/core/src/distributed.cpp @@ -7,6 +7,9 @@ #include "ngraph/log.hpp" #include "ngraph/type.hpp" +NGRAPH_SUPPRESS_DEPRECATED_START +using namespace ngraph; + namespace ov { template <> EnumNames& EnumNames::get() { diff --git a/ngraph/core/src/ngraph.cpp b/ngraph/core/src/ngraph.cpp index 7f6687cdd15..69e0d84d0da 100644 --- a/ngraph/core/src/ngraph.cpp +++ b/ngraph/core/src/ngraph.cpp @@ -15,7 +15,9 @@ extern "C" NGRAPH_API const char* get_ngraph_version_string() { namespace ngraph { NGRAPH_API void get_version(size_t& major, size_t& minor, size_t& patch, std::string& extra) { + NGRAPH_SUPPRESS_DEPRECATED_START string version = NGRAPH_VERSION_NUMBER; ngraph::parse_version_string(version, major, minor, patch, extra); + NGRAPH_SUPPRESS_DEPRECATED_END } } // namespace ngraph diff --git a/ngraph/core/src/op/constant.cpp b/ngraph/core/src/op/constant.cpp index becbd1c91d1..763f508d16d 100644 --- a/ngraph/core/src/op/constant.cpp +++ b/ngraph/core/src/op/constant.cpp @@ -56,6 +56,7 @@ op::Constant::Constant(const shared_ptr& tensor) { op::Constant::Constant(const element::Type& type, const Shape& shape, const std::vector& values) : Constant(type, shape) { + NGRAPH_SUPPRESS_DEPRECATED_START NODE_VALIDATION_CHECK(this, values.size() == shape_size(m_shape) || values.size() == 1, "Did not get the expected number of literals for a constant of shape ", @@ -182,6 +183,7 @@ op::Constant::Constant(const element::Type& type, const Shape& shape, const std: } m_all_elements_bitwise_identical = are_all_data_elements_bitwise_identical(); } + NGRAPH_SUPPRESS_DEPRECATED_END } op::Constant::Constant(const element::Type& type, const Shape& shape) : m_element_type(type), m_shape(shape) { diff --git a/ngraph/core/src/op/transpose.cpp b/ngraph/core/src/op/transpose.cpp index 8d7d3cfa84a..e0c9bd37a74 100644 --- a/ngraph/core/src/op/transpose.cpp +++ b/ngraph/core/src/op/transpose.cpp @@ -42,6 +42,7 @@ void op::v1::Transpose::validate_and_infer_types() { set_input_is_relevant_to_shape(1); + NGRAPH_SUPPRESS_DEPRECATED_START if (const auto& input_const = get_constant_from_source(input_value(1))) { auto permutation = input_const->get_axis_vector_val(); if (permutation.empty()) { @@ -58,6 +59,7 @@ void op::v1::Transpose::validate_and_infer_types() { } else { set_output_type(0, get_input_element_type(0), PartialShape::dynamic(arg_shape.rank())); } + NGRAPH_SUPPRESS_DEPRECATED_END } shared_ptr op::v1::Transpose::clone_with_new_inputs(const OutputVector& new_args) const { diff --git a/ngraph/core/src/slice_plan.cpp b/ngraph/core/src/op/util/slice_plan.cpp similarity index 100% rename from ngraph/core/src/slice_plan.cpp rename to ngraph/core/src/op/util/slice_plan.cpp diff --git a/ngraph/core/src/pass/manager.cpp b/ngraph/core/src/pass/manager.cpp index 5aeb9180670..613ec73bff3 100644 --- a/ngraph/core/src/pass/manager.cpp +++ b/ngraph/core/src/pass/manager.cpp @@ -46,6 +46,7 @@ pass::Manager::~Manager() {} pass::Manager::Manager(std::shared_ptr pass_config) : m_pass_config(std::move(pass_config)) {} void pass::Manager::run_passes(shared_ptr func) { + NGRAPH_SUPPRESS_DEPRECATED_START OV_ITT_SCOPED_TASK(ov::itt::domains::nGraph, "pass::Manager::run_passes"); static bool profile_enabled = getenv_bool("NGRAPH_PROFILE_PASS_ENABLE"); @@ -67,7 +68,6 @@ void pass::Manager::run_passes(shared_ptr func) { pass_timer.start(); - NGRAPH_SUPPRESS_DEPRECATED_START if (auto matcher_pass = dynamic_pointer_cast(pass)) { // This checks is to skip the graph transformation when the graph pass relies on // static shape but the function state is dynamic. @@ -106,7 +106,6 @@ void pass::Manager::run_passes(shared_ptr func) { function_changed |= node_pass->run_on_node(n); } } - NGRAPH_SUPPRESS_DEPRECATED_END if (m_visualize) { // visualizations and serializations will be named after the outermost function @@ -131,4 +130,5 @@ void pass::Manager::run_passes(shared_ptr func) { if (profile_enabled) { cout << "passes done in " << overall_timer.get_milliseconds() << "ms\n"; } + NGRAPH_SUPPRESS_DEPRECATED_END } diff --git a/ngraph/core/src/runtime/aligned_buffer.cpp b/ngraph/core/src/runtime/aligned_buffer.cpp index b901bc99204..5bac0a083b6 100644 --- a/ngraph/core/src/runtime/aligned_buffer.cpp +++ b/ngraph/core/src/runtime/aligned_buffer.cpp @@ -15,6 +15,7 @@ using namespace std; runtime::AlignedBuffer::AlignedBuffer() : m_allocated_buffer(nullptr), m_aligned_buffer(nullptr), m_byte_size(0) {} runtime::AlignedBuffer::AlignedBuffer(size_t byte_size, size_t alignment) : m_byte_size(byte_size) { + NGRAPH_SUPPRESS_DEPRECATED_START m_byte_size = std::max(1, byte_size); size_t allocation_size = m_byte_size + alignment; m_allocated_buffer = static_cast(ngraph_malloc(allocation_size)); @@ -24,6 +25,7 @@ runtime::AlignedBuffer::AlignedBuffer(size_t byte_size, size_t alignment) : m_by if (mod != 0) { m_aligned_buffer += (alignment - mod); } + NGRAPH_SUPPRESS_DEPRECATED_END } runtime::AlignedBuffer::AlignedBuffer(AlignedBuffer&& other) diff --git a/ngraph/core/src/runtime/host_tensor.cpp b/ngraph/core/src/runtime/host_tensor.cpp index afa347f95ab..7c146736ea6 100644 --- a/ngraph/core/src/runtime/host_tensor.cpp +++ b/ngraph/core/src/runtime/host_tensor.cpp @@ -42,6 +42,7 @@ runtime::HostTensor::HostTensor(const Output& value) NGRAPH_SUPPRESS_DEPRECATED_END void runtime::HostTensor::allocate_buffer() { + NGRAPH_SUPPRESS_DEPRECATED_START NGRAPH_CHECK(get_partial_shape().is_static(), "Attempt to allocate buffer for tensor with partial shape: ", get_partial_shape()); @@ -63,6 +64,7 @@ void runtime::HostTensor::allocate_buffer() { m_aligned_buffer_pool = (allocated_buffer_pool + alignment - mod); } } + NGRAPH_SUPPRESS_DEPRECATED_END } NGRAPH_SUPPRESS_DEPRECATED_START @@ -78,9 +80,11 @@ void runtime::HostTensor::initialize(const std::shared_ptr& co } runtime::HostTensor::~HostTensor() { + NGRAPH_SUPPRESS_DEPRECATED_START if (m_allocated_buffer_pool != nullptr) { ngraph_free(m_allocated_buffer_pool); } + NGRAPH_SUPPRESS_DEPRECATED_END } void* runtime::HostTensor::get_data_ptr() { diff --git a/ngraph/core/src/type.cpp b/ngraph/core/src/type.cpp index 5cf8c29b61a..5456fb8d1e4 100644 --- a/ngraph/core/src/type.cpp +++ b/ngraph/core/src/type.cpp @@ -8,9 +8,11 @@ namespace std { size_t std::hash::operator()(const ngraph::DiscreteTypeInfo& k) const { + NGRAPH_SUPPRESS_DEPRECATED_START size_t name_hash = hash()(string(k.name)); size_t version_hash = hash()(k.version); // don't use parent for hash calculation, it is not a part of type (yet) return ngraph::hash_combine(vector{name_hash, version_hash}); + NGRAPH_SUPPRESS_DEPRECATED_END } } // namespace std diff --git a/ngraph/core/src/util.cpp b/ngraph/core/src/util.cpp index 3a448189a13..4dcf3abb220 100644 --- a/ngraph/core/src/util.cpp +++ b/ngraph/core/src/util.cpp @@ -22,6 +22,7 @@ #include "ngraph/partial_shape.hpp" #include "ngraph/shape.hpp" +NGRAPH_SUPPRESS_DEPRECATED_START using namespace std; using namespace ngraph; diff --git a/ngraph/core/src/validation_util.cpp b/ngraph/core/src/validation_util.cpp index 3db696721a6..ff69f511059 100644 --- a/ngraph/core/src/validation_util.cpp +++ b/ngraph/core/src/validation_util.cpp @@ -23,6 +23,7 @@ #include "ngraph/type/element_type_traits.hpp" #include "ngraph/util.hpp" +NGRAPH_SUPPRESS_DEPRECATED_START using namespace std; using namespace ngraph; diff --git a/ngraph/test/bfloat16.cpp b/ngraph/test/bfloat16.cpp index 31040bebf1e..1546d147d9b 100644 --- a/ngraph/test/bfloat16.cpp +++ b/ngraph/test/bfloat16.cpp @@ -139,6 +139,7 @@ TEST(bfloat16, numeric_limits) { } TEST(benchmark, bfloat16) { + NGRAPH_SUPPRESS_DEPRECATED_START size_t buffer_size = 128 * 3 * 224 * 224; ngraph::runtime::AlignedBuffer data(buffer_size * sizeof(float), 4096); float* f = static_cast(data.get_ptr()); @@ -197,6 +198,7 @@ TEST(benchmark, bfloat16) { timer.stop(); NGRAPH_INFO << "float to bfloat16 round to nearest even " << timer.get_milliseconds() << "ms"; } + NGRAPH_SUPPRESS_DEPRECATED_END } TEST(bfloat16, assigns) { diff --git a/ngraph/test/runtime/interpreter/int_executable.hpp b/ngraph/test/runtime/interpreter/int_executable.hpp index 8c901cd93c5..d7df9c6a0d2 100644 --- a/ngraph/test/runtime/interpreter/int_executable.hpp +++ b/ngraph/test/runtime/interpreter/int_executable.hpp @@ -7,11 +7,11 @@ #include #include #include +#include #include #include #include -#include #include "backend.hpp" #include "int_backend_visibility.hpp" #include "ngraph/ops.hpp" @@ -22,25 +22,20 @@ #include "ngraph/runtime/reference/tensor_iterator.hpp" #include "ngraph/runtime/tensor.hpp" -namespace ngraph -{ - namespace runtime - { - namespace interpreter - { - class INTBackend; - class INTExecutable; - } // namespace interpreter - } // namespace runtime -} // namespace ngraph +namespace ngraph { +namespace runtime { +namespace interpreter { +class INTBackend; +class INTExecutable; +} // namespace interpreter +} // namespace runtime +} // namespace ngraph -class INTERPRETER_BACKEND_API ngraph::runtime::interpreter::INTExecutable : public Executable -{ +class INTERPRETER_BACKEND_API ngraph::runtime::interpreter::INTExecutable : public Executable { friend class INTBackend; public: - INTExecutable(const std::shared_ptr& function, - bool enable_performance_collection = false); + INTExecutable(const std::shared_ptr& function, bool enable_performance_collection = false); bool call(const std::vector>& outputs, const std::vector>& inputs) override; @@ -53,11 +48,11 @@ public: std::shared_ptr create_output_tensor(size_t output_index) override; - std::vector> - create_input_tensor(size_t input_index, size_t pipeline_depth) override; + std::vector> create_input_tensor(size_t input_index, + size_t pipeline_depth) override; - std::vector> - create_output_tensor(size_t output_index, size_t pipeline_depth) override; + std::vector> create_output_tensor(size_t output_index, + size_t pipeline_depth) override; protected: std::shared_ptr get_parameter(size_t index) const; @@ -69,13 +64,13 @@ protected: bool m_nan_check_enabled = false; bool m_performance_counters_enabled = false; std::shared_ptr m_function; + NGRAPH_SUPPRESS_DEPRECATED_START std::unordered_map, stopwatch> m_timer_map; + NGRAPH_SUPPRESS_DEPRECATED_END std::vector> m_nodes; - static void perform_nan_check(const std::vector>&, - const Node* op = nullptr); - struct InfoForNMS5 - { + static void perform_nan_check(const std::vector>&, const Node* op = nullptr); + struct InfoForNMS5 { int64_t max_output_boxes_per_class; float iou_threshold; float score_threshold; From b7deb11d6aa488647746c606e5f244c9dfc654d4 Mon Sep 17 00:00:00 2001 From: Edward Shogulin Date: Wed, 1 Sep 2021 09:59:29 +0300 Subject: [PATCH 65/76] [LPT] Legacy restrictions removal: dequantization operations (#6974) * [LPT] Legacy restrictions removal: dequantization operations * [LPT] not used tests removal --- .../src/compilation_context.cpp | 4 - ...convert_mul_add_to_scaleshift_or_power.cpp | 23 +- .../convert_mul_or_add_finally.cpp | 84 +---- .../common/dequantization_op.hpp | 138 ------- .../include/low_precision/network_helper.hpp | 2 - .../subtract_multiply_to_multiply_add.hpp | 26 -- .../low_precision_transformations/src/add.cpp | 11 +- .../src/concat.cpp | 7 +- .../src/convolution.cpp | 7 +- .../src/convolution_backprop_data.cpp | 6 +- .../src/eltwise_base_transformation.cpp | 6 - .../src/fake_quantize.cpp | 1 - .../src/low_precision.cpp | 2 - .../src/mat_mul.cpp | 5 +- .../src/multiply.cpp | 7 +- .../low_precision_transformations/src/mvn.cpp | 5 +- .../src/network_helper.cpp | 48 +-- .../src/normalize_l2.cpp | 3 +- .../src/split.cpp | 5 +- .../src/subtract_multiply_to_multiply_add.cpp | 176 --------- .../src/mkldnn_plugin/mkldnn_plugin.cpp | 13 - .../rt_info/dequantization_attribute.hpp | 78 ---- ...convert_constant_folding_on_const_path.cpp | 1 - .../rt_info/dequantization_attribute.cpp | 57 --- ...lly_transformation_with_dequantization.cpp | 117 ------ .../group_convolution_transformation.cpp | 2 +- .../layer_transformation.cpp | 6 +- .../low_precision_transformations_test.cpp | 1 - ..._to_scaleshift_or_power_transformation.cpp | 147 -------- ...ultiply_to_multiply_add_transformation.cpp | 356 ------------------ ...sformations_after_split_transformation.cpp | 8 +- .../mul_add_conversion_test.cpp | 6 - .../src/fuse_scaleshift_and_fakequantize.cpp | 5 +- .../lpt_ngraph_functions/common/builders.hpp | 3 - .../common/dequantization_operations.hpp | 16 +- .../lpt_ngraph_functions/src/add_function.cpp | 2 +- .../src/common/builders.cpp | 115 ++---- .../src/common/dequantization_operations.cpp | 32 +- ...d_finally_with_dequantization_function.cpp | 7 +- .../convolution_backprop_data_function.cpp | 1 - .../src/convolution_function.cpp | 5 +- ...h_multi_parent_dequantization_function.cpp | 4 +- .../src/fake_quantize_function.cpp | 1 - .../src/group_convolution_function.cpp | 1 - ...ul_add_to_scaleshift_or_power_function.cpp | 11 +- .../src/multiply_function.cpp | 11 +- .../src/normalize_l2_function.cpp | 1 - .../src/precision_propagation_function.cpp | 2 +- .../src/reshape_fully_connected_function.cpp | 1 - ...ract_multiply_to_multiply_add_function.cpp | 5 +- .../ie_compilation_context_test.cpp | 13 - 51 files changed, 115 insertions(+), 1479 deletions(-) delete mode 100644 inference-engine/src/low_precision_transformations/include/low_precision/common/dequantization_op.hpp delete mode 100644 inference-engine/src/low_precision_transformations/include/low_precision/subtract_multiply_to_multiply_add.hpp delete mode 100644 inference-engine/src/low_precision_transformations/src/subtract_multiply_to_multiply_add.cpp delete mode 100644 inference-engine/src/transformations/include/transformations/rt_info/dequantization_attribute.hpp delete mode 100644 inference-engine/src/transformations/src/transformations/rt_info/dequantization_attribute.cpp delete mode 100644 inference-engine/tests/functional/inference_engine/lp_transformations/convert_mul_or_add_finally_transformation_with_dequantization.cpp delete mode 100644 inference-engine/tests/functional/inference_engine/lp_transformations/mul_add_to_scaleshift_or_power_transformation.cpp delete mode 100644 inference-engine/tests/functional/inference_engine/lp_transformations/subtract_multiply_to_multiply_add_transformation.cpp diff --git a/inference-engine/src/inference_engine/src/compilation_context.cpp b/inference-engine/src/inference_engine/src/compilation_context.cpp index 30baa04b9d1..de956bdcd92 100644 --- a/inference-engine/src/inference_engine/src/compilation_context.cpp +++ b/inference-engine/src/inference_engine/src/compilation_context.cpp @@ -18,7 +18,6 @@ #include "ie_itt.hpp" #include "ngraph/opsets/opset6.hpp" #include "ngraph/variant.hpp" -#include "transformations/rt_info/dequantization_attribute.hpp" #include "transformations/rt_info/fused_names_attribute.hpp" #include "transformations/rt_info/primitives_priority_attribute.hpp" #include "transformations/serialize.hpp" @@ -121,9 +120,6 @@ std::string NetworkCompilationContext::computeHash(const CNNNetwork& network, } else if (auto intData = std::dynamic_pointer_cast>(rtMapData.second)) { seed = hash_combine(seed, intData->get()); - } else if (auto deq = std::dynamic_pointer_cast>( - rtMapData.second)) { - seed = hash_combine(seed, deq->get().getDequantizationAttr()); } else if (auto fNames = std::dynamic_pointer_cast>(rtMapData.second)) { seed = hash_combine(seed, fNames->get().getNames()); diff --git a/inference-engine/src/legacy_api/src/transformations/convert_opset1_to_legacy/convert_mul_add_to_scaleshift_or_power.cpp b/inference-engine/src/legacy_api/src/transformations/convert_opset1_to_legacy/convert_mul_add_to_scaleshift_or_power.cpp index de8bf432af6..4fddc712722 100644 --- a/inference-engine/src/legacy_api/src/transformations/convert_opset1_to_legacy/convert_mul_add_to_scaleshift_or_power.cpp +++ b/inference-engine/src/legacy_api/src/transformations/convert_opset1_to_legacy/convert_mul_add_to_scaleshift_or_power.cpp @@ -145,16 +145,13 @@ ngraph::pass::ConvertMulAddToScaleShiftOrPower::ConvertMulAddToScaleShiftOrPower const auto output_shape = add_node->get_output_partial_shape(0); const auto output_shape_rank = output_shape.rank().get_length(); - bool is_dequantization = - (add_node->get_rt_info().count("DEQUANTIZATION") != 0 || mul_node->get_rt_info().count("DEQUANTIZATION") != 0); - if (res1 == CONVERSION_RESULT::NONE || res2 == CONVERSION_RESULT::NONE || - ((res1 == CONVERSION_RESULT::SCALE_SHIFT || res2 == CONVERSION_RESULT::SCALE_SHIFT) && !is_dequantization && output_shape_rank < 4)) { + ((res1 == CONVERSION_RESULT::SCALE_SHIFT || res2 == CONVERSION_RESULT::SCALE_SHIFT) && output_shape_rank < 4)) { return false; } // TODO: in case if scale and shift constants has equal values the best way is to convert them to Power - if (res1 == CONVERSION_RESULT::SCALE_SHIFT || res2 == CONVERSION_RESULT::SCALE_SHIFT || is_dequantization) { + if (res1 == CONVERSION_RESULT::SCALE_SHIFT || res2 == CONVERSION_RESULT::SCALE_SHIFT) { NodeVector new_ops; auto weights_in = ngraph::op::util::normalize_constant(const_weights_node, output_shape); @@ -162,23 +159,11 @@ ngraph::pass::ConvertMulAddToScaleShiftOrPower::ConvertMulAddToScaleShiftOrPower new_ops.push_back(weights_in); new_ops.push_back(biases_in); - if (is_dequantization) { - const Shape data_shape = data_node.get_shape(); - Shape broadcasted_shape = std::vector(data_shape.size(), 1ul); - broadcasted_shape[1] = data_shape[1]; - - weights_in = ngraph::op::util::broadcastTo(weights_in, broadcasted_shape); - new_ops.push_back(weights_in); - - biases_in = ngraph::op::util::broadcastTo(biases_in, broadcasted_shape); - new_ops.push_back(biases_in); - } - - if (res1 == CONVERSION_RESULT::POWER && !is_dequantization) { + if (res1 == CONVERSION_RESULT::POWER) { weights_in = ngraph::op::util::broadcastTo(weights_in, biases_in->get_shape()); new_ops.push_back(weights_in); } - if (res2 == CONVERSION_RESULT::POWER && !is_dequantization) { + if (res2 == CONVERSION_RESULT::POWER) { biases_in = ngraph::op::util::broadcastTo(biases_in, weights_in->get_shape()); new_ops.push_back(biases_in); } diff --git a/inference-engine/src/legacy_api/src/transformations/convert_opset1_to_legacy/convert_mul_or_add_finally.cpp b/inference-engine/src/legacy_api/src/transformations/convert_opset1_to_legacy/convert_mul_or_add_finally.cpp index 0ad0b349996..78819f61b64 100644 --- a/inference-engine/src/legacy_api/src/transformations/convert_opset1_to_legacy/convert_mul_or_add_finally.cpp +++ b/inference-engine/src/legacy_api/src/transformations/convert_opset1_to_legacy/convert_mul_or_add_finally.cpp @@ -125,70 +125,14 @@ ngraph::matcher_pass_callback get_callback() { auto res = check_constant(const_node, data_node.get_partial_shape()); - auto checkElementwise = [](const std::shared_ptr& elementwise) -> bool { - const ngraph::PartialShape partialShape = elementwise->get_input_partial_shape(0); - if (partialShape.is_dynamic()) { - return false; - } - - std::shared_ptr constant = ngraph::as_type_ptr(elementwise->get_input_node_shared_ptr(1)); - if (constant == nullptr) { - constant = ngraph::as_type_ptr(elementwise->get_input_node_shared_ptr(0)); - } - if (constant == nullptr) { - return false; - } - - const ngraph::Shape constShape = constant->get_output_shape(0); - const ngraph::Shape shape = partialShape.to_shape(); - - if (constShape.size() == 1ul && constShape[0] != 1 && constShape[0] != shape[1]) { - return false; - } - - if ((constShape.size() > 5ul)) { - return false; - } - - if ((constShape.size() <= 1ul) || (std::all_of(constShape.begin(), constShape.end(), [](const size_t value) { return value == 1ul; }))) { - return true; - } - - if (constShape.size() == shape.size()) { - if ((constShape[0] != 1ul) || (constShape[1] != shape[1])) { - return false; - } - for (size_t i = 2ul; i < constShape.size(); ++i) { - if (constShape[i] != 1ul) { - return false; - } - } - } else if (constShape.size() == (shape.size() - 1)) { - if (constShape[0] != shape[1]) { - return false; - } - for (size_t i = 1ul; i < constShape.size(); ++i) { - if (constShape[i] != 1ul) { - return false; - } - } - } else { - return false; - } - - return true; - }; - - bool is_dequantization = (lin_op->get_rt_info().count("DEQUANTIZATION") != 0) && checkElementwise(lin_op); - - if (!is_dequantization && (res == CONVERSION_RESULT::NONE || (res == CONVERSION_RESULT::SCALE_SHIFT && output_shape_rank < 4))) { + if (res == CONVERSION_RESULT::NONE || (res == CONVERSION_RESULT::SCALE_SHIFT && output_shape_rank < 4)) { return convert_to_eltwise(lin_op, lin_op->input(0).get_source_output(), lin_op->input(1).get_source_output()); } // TODO: if all values in Constant are equal the best way is to convert this Eltwise to Power - if (res == CONVERSION_RESULT::SCALE_SHIFT || is_dequantization) { + if (res == CONVERSION_RESULT::SCALE_SHIFT) { auto weights_et = const_node->get_element_type(); auto weights_shape = const_node->get_shape(); @@ -198,14 +142,6 @@ ngraph::matcher_pass_callback get_callback() { auto weights = ngraph::opset1::Constant::create(weights_et, weights_shape, {1}); auto weights_in = ngraph::op::util::normalize_constant(weights, output_shape); auto biases_in = ngraph::op::util::normalize_constant(const_node, output_shape); - if (is_dequantization) { - const ngraph::Shape data_shape = data_node.get_shape(); - ngraph::Shape broadcasted_shape = std::vector(data_shape.size(), 1ul); - broadcasted_shape[1] = data_shape[1]; - - weights_in = ngraph::op::util::broadcastTo(weights_in, broadcasted_shape); - biases_in = ngraph::op::util::broadcastTo(biases_in, broadcasted_shape); - } scaleshift = std::make_shared(data_node, weights_in, biases_in); } else if (std::is_same()) { std::shared_ptr new_const_node = std::make_shared( @@ -215,27 +151,11 @@ ngraph::matcher_pass_callback get_callback() { auto weights = ngraph::opset1::Constant::create(weights_et, weights_shape, {1}); auto weights_in = ngraph::op::util::normalize_constant(weights, output_shape); auto biases_in = new_const_node; - if (is_dequantization) { - const ngraph::Shape data_shape = data_node.get_shape(); - ngraph::Shape broadcasted_shape = std::vector(data_shape.size(), 1ul); - broadcasted_shape[1] = data_shape[1]; - - weights_in = ngraph::op::util::broadcastTo(weights_in, broadcasted_shape); - biases_in = ngraph::op::util::broadcastTo(biases_in, broadcasted_shape); - } scaleshift = std::make_shared(data_node, weights_in, biases_in); } else if (std::is_same()) { auto bias = ngraph::opset1::Constant::create(weights_et, weights_shape, {0}); auto weights_in = ngraph::op::util::normalize_constant(const_node, output_shape); auto biases_in = ngraph::op::util::normalize_constant(bias, output_shape); - if (is_dequantization) { - const ngraph::Shape data_shape = data_node.get_shape(); - ngraph::Shape broadcasted_shape = std::vector(data_shape.size(), 1ul); - broadcasted_shape[1] = data_shape[1]; - - weights_in = ngraph::op::util::broadcastTo(weights_in, broadcasted_shape); - biases_in = ngraph::op::util::broadcastTo(biases_in, broadcasted_shape); - } scaleshift = std::make_shared(data_node, weights_in, biases_in); } else { return false; diff --git a/inference-engine/src/low_precision_transformations/include/low_precision/common/dequantization_op.hpp b/inference-engine/src/low_precision_transformations/include/low_precision/common/dequantization_op.hpp deleted file mode 100644 index 46b739959d6..00000000000 --- a/inference-engine/src/low_precision_transformations/include/low_precision/common/dequantization_op.hpp +++ /dev/null @@ -1,138 +0,0 @@ -// Copyright (C) 2018-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#pragma once - -#include -#include -#include -#include - -#include -#include -#include - -#include "low_precision/lpt_visibility.hpp" -#include "transformations/rt_info/dequantization_attribute.hpp" - -namespace ngraph { -namespace pass { -namespace low_precision { - -// template -// class LP_TRANSFORMATIONS_API DequantizationOp : public BaseOp2 { -// public: -// template -// DequantizationOp(Args&&... args) : BaseOp2(std::forward(args)...) { -// init(); -// } -// -// std::shared_ptr clone_with_new_inputs(const OutputVector& inputs) const override { -// std::shared_ptr cloned = BaseOp2::clone_with_new_inputs(inputs); -// auto& rtInfo = cloned->get_rt_info(); -// rtInfo = get_rt_info(); -// -// return cloned; -// } -// -// protected: -// void init() { -// auto& rtInfo = get_rt_info(); -// rtInfo["DEQUANTIZATION"] = std::make_shared>(""); -// } -// }; -// -// using DequantizationConvert = DequantizationOp; -// using DequantizationSubtract = DequantizationOp; -// using DequantizationMultiply = DequantizationOp; - -namespace { -void initRuntimeInfo(ngraph::Node& operation) { - auto& rtInfo = operation.get_rt_info(); - rtInfo["DEQUANTIZATION"] = std::make_shared>(DequantizationAttr()); -} - -// #include -// ngraph::copy_runtime_info(from, to); -void copyRuntimeInfo(const ngraph::Node& from, ngraph::Node& to) { - const auto& rtInfoFrom = from.get_rt_info(); - auto& rtInfoTo = to.get_rt_info(); - rtInfoTo = rtInfoFrom; -} - -} // namespace - -class LP_TRANSFORMATIONS_API DequantizationConvert : public ngraph::opset1::Convert { -public: - DequantizationConvert(const ngraph::Output& arg, const ngraph::element::Type& destination_type) : - ngraph::opset1::Convert(arg, destination_type) { - initRuntimeInfo(*this); - } - - std::shared_ptr clone_with_new_inputs(const OutputVector& inputs) const override { - std::shared_ptr cloned = ngraph::opset1::Convert::clone_with_new_inputs(inputs); - copyRuntimeInfo(*this, *cloned); - return cloned; - } -}; - -class LP_TRANSFORMATIONS_API DequantizationSubtract : public ngraph::opset1::Subtract { -public: - DequantizationSubtract( - const ngraph::Output& arg0, - const ngraph::Output& arg1, - const ngraph::op::AutoBroadcastSpec& auto_broadcast = ngraph::op::AutoBroadcastSpec(ngraph::op::AutoBroadcastType::NUMPY)) : - ngraph::opset1::Subtract(arg0, arg1, auto_broadcast) { - initRuntimeInfo(*this); - } - - std::shared_ptr clone_with_new_inputs(const OutputVector& inputs) const override { - std::shared_ptr cloned = ngraph::opset1::Subtract::clone_with_new_inputs(inputs); - copyRuntimeInfo(*this, *cloned); - return cloned; - } -}; - -class LP_TRANSFORMATIONS_API DequantizationMultiply : public ngraph::opset1::Multiply { -public: - DequantizationMultiply( - const Output& arg0, - const Output& arg1, - const ngraph::op::AutoBroadcastSpec& auto_broadcast = ngraph::op::AutoBroadcastSpec(ngraph::op::AutoBroadcastType::NUMPY)) : - ngraph::opset1::Multiply(arg0, arg1, auto_broadcast) { - initRuntimeInfo(*this); - } - - DequantizationMultiply(const ngraph::opset1::Multiply& multiply) : - ngraph::opset1::Multiply(multiply) { - initRuntimeInfo(*this); - } - - std::shared_ptr clone_with_new_inputs(const OutputVector& inputs) const override { - std::shared_ptr cloned = ngraph::opset1::Multiply::clone_with_new_inputs(inputs); - copyRuntimeInfo(*this, *cloned); - return cloned; - } -}; - -class LP_TRANSFORMATIONS_API DequantizationAdd : public ngraph::opset1::Add { -public: - DequantizationAdd( - const ngraph::Output& arg0, - const ngraph::Output& arg1, - const ngraph::op::AutoBroadcastSpec& auto_broadcast = ngraph::op::AutoBroadcastSpec(ngraph::op::AutoBroadcastType::NUMPY)) : - ngraph::opset1::Add(arg0, arg1, auto_broadcast) { - initRuntimeInfo(*this); - } - - std::shared_ptr clone_with_new_inputs(const OutputVector& inputs) const override { - std::shared_ptr cloned = ngraph::opset1::Add::clone_with_new_inputs(inputs); - copyRuntimeInfo(*this, *cloned); - return cloned; - } -}; - -} // namespace low_precision -} // namespace pass -} // namespace ngraph diff --git a/inference-engine/src/low_precision_transformations/include/low_precision/network_helper.hpp b/inference-engine/src/low_precision_transformations/include/low_precision/network_helper.hpp index ca80b580b0b..1f1ba432408 100644 --- a/inference-engine/src/low_precision_transformations/include/low_precision/network_helper.hpp +++ b/inference-engine/src/low_precision_transformations/include/low_precision/network_helper.hpp @@ -86,8 +86,6 @@ public: static void copyInfo(const std::shared_ptr& source, const std::shared_ptr& target); - static void cleanRunTimeInfo(const std::shared_ptr& layer); - static bool isScalarLike(std::shared_ptr constant); static bool isZero(std::shared_ptr constant); diff --git a/inference-engine/src/low_precision_transformations/include/low_precision/subtract_multiply_to_multiply_add.hpp b/inference-engine/src/low_precision_transformations/include/low_precision/subtract_multiply_to_multiply_add.hpp deleted file mode 100644 index cee4f4f5d62..00000000000 --- a/inference-engine/src/low_precision_transformations/include/low_precision/subtract_multiply_to_multiply_add.hpp +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright (C) 2018-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#pragma once - -#include -#include "low_precision/layer_transformation.hpp" -#include "low_precision/eltwise_base_transformation.hpp" - -namespace ngraph { -namespace pass { -namespace low_precision { - -class LP_TRANSFORMATIONS_API SubtractMultiplyToMultiplyAddTransformation : public LayerTransformation { -public: - NGRAPH_RTTI_DECLARATION; - SubtractMultiplyToMultiplyAddTransformation(const Params& params = Params()); - bool transform(TransformationContext& context, ngraph::pattern::Matcher &m) override; - bool canBeTransformed(const TransformationContext& context, std::shared_ptr layer) const override; - bool isPrecisionPreserved(std::shared_ptr layer) const noexcept override; -}; - -} // namespace low_precision -} // namespace pass -} // namespace ngraph diff --git a/inference-engine/src/low_precision_transformations/src/add.cpp b/inference-engine/src/low_precision_transformations/src/add.cpp index c09a22783a6..da720928ff7 100644 --- a/inference-engine/src/low_precision_transformations/src/add.cpp +++ b/inference-engine/src/low_precision_transformations/src/add.cpp @@ -14,7 +14,6 @@ #include "ngraph_ops/type_relaxed.hpp" #include "low_precision/common/ie_lpt_exception.hpp" -#include "low_precision/common/dequantization_op.hpp" #include "low_precision/network_helper.hpp" namespace ngraph { @@ -54,7 +53,7 @@ std::shared_ptr replaceToSubtract(const std::shared_ptr& auto constant = fold(add->input_value(constBranchIndex)); auto constOutput = constant->output(0); - const auto subtract = std::make_shared>( + const auto subtract = std::make_shared>( std::vector{element::f32, element::f32}, std::vector{ op->get_output_element_type(0) }, ngraph::op::TemporaryReplaceOutputType(add->input_value(dataBranchIndex), element::f32).get(), @@ -80,7 +79,7 @@ std::shared_ptr fuseWithSubtract(const std::shared_ptr& add->get_input_node_shared_ptr(0)->input_value(1), add->input_value(1)); - const auto newSubtract = std::make_shared>( + const auto newSubtract = std::make_shared>( std::vector{element::f32, element::f32}, std::vector{ op->get_output_element_type(0) }, ngraph::op::TemporaryReplaceOutputType(add->get_input_node_shared_ptr(0)->input_value(0), element::f32).get(), @@ -201,10 +200,10 @@ bool AddTransformation::transform(TransformationContext& context, ngraph::patter // newMultiply inputs[emptyPathIndex] = dequantizationEmptyPath.data; - inputs[fullPathIndex] = std::make_shared( + inputs[fullPathIndex] = std::make_shared( newSubtractFullPathValues == nullptr ? fullPathInput : - std::make_shared( + std::make_shared( // precision on branch with dequantization operations can be different with dequantization precision, // for example: FP16 model with FP32 dequantization fullPathInput.get_element_type() != newSubtractFullPathValues->get_element_type() ? @@ -217,7 +216,7 @@ bool AddTransformation::transform(TransformationContext& context, ngraph::patter std::vector{element::f32, element::f32}, std::vector{ element::f32 }, ngraph::op::TemporaryReplaceOutputType(inputs[0], element::f32).get(), ngraph::op::TemporaryReplaceOutputType(inputs[1], element::f32).get()); - newMultiply = std::make_shared>( + newMultiply = std::make_shared>( std::vector{element::f32, element::f32}, std::vector{ add->get_output_element_type(0) }, ngraph::op::TemporaryReplaceOutputType(newAddOrSubtract, element::f32).get(), ngraph::op::TemporaryReplaceOutputType(multiplyEmptyPathValues, element::f32).get()); diff --git a/inference-engine/src/low_precision_transformations/src/concat.cpp b/inference-engine/src/low_precision_transformations/src/concat.cpp index b17846446a1..ae95a834d7d 100644 --- a/inference-engine/src/low_precision_transformations/src/concat.cpp +++ b/inference-engine/src/low_precision_transformations/src/concat.cpp @@ -14,7 +14,6 @@ #include "low_precision/common/fake_quantize_dequantization.hpp" #include "low_precision/common/ie_lpt_exception.hpp" -#include "low_precision/common/dequantization_op.hpp" #include "low_precision/network_helper.hpp" namespace ngraph { @@ -144,7 +143,7 @@ bool ConcatTransformation::transform(TransformationContext& context, ngraph::pat // concatenation axis is 1 if (!subtractNodes.empty()) { - const auto subtract = std::make_shared( + const auto subtract = std::make_shared( lastDequantization, NetworkHelper::toScalarIfPossible(subtractNodes.size() == 1ul ? subtractNodes[0] : @@ -155,8 +154,8 @@ bool ConcatTransformation::transform(TransformationContext& context, ngraph::pat } if (!multiplyNodes.empty()) { - const auto multiply = std::make_shared>( - DequantizationMultiply( + const auto multiply = std::make_shared>( + opset1::Multiply( lastDequantization, NetworkHelper::toScalarIfPossible(multiplyNodes.size() == 1ul ? multiplyNodes[0] : diff --git a/inference-engine/src/low_precision_transformations/src/convolution.cpp b/inference-engine/src/low_precision_transformations/src/convolution.cpp index 344c9ba90ac..9a0c0e40474 100644 --- a/inference-engine/src/low_precision_transformations/src/convolution.cpp +++ b/inference-engine/src/low_precision_transformations/src/convolution.cpp @@ -13,7 +13,6 @@ #include #include #include "low_precision/network_helper.hpp" -#include "low_precision/common/dequantization_op.hpp" namespace ngraph { namespace pass { @@ -84,9 +83,7 @@ bool ConvolutionTransformation::transform(TransformationContext &context, ngraph { std::shared_ptr subtract; if (dequantization.subtract != nullptr) { - NetworkHelper::cleanRunTimeInfo(dequantization.subtract->shared_from_this()); auto optimizedSubtract = NetworkHelper::optimizeSubtract(dequantization.subtract); - if (optimizedSubtract == nullptr) { optimizedSubtract = dequantization.subtract; } @@ -174,7 +171,7 @@ bool ConvolutionTransformation::transform(TransformationContext &context, ngraph } NetworkHelper::copyInfo(convolution, relaxedNewConvolution); - std::shared_ptr newMultiplyAfter = std::make_shared>( + std::shared_ptr newMultiplyAfter = std::make_shared>( std::vector{ deqPrecision, deqPrecision }, std::vector{ dequantization.multiply->get_output_element_type(0) }, ngraph::op::TemporaryReplaceOutputType(relaxedNewConvolution, deqPrecision).get(), @@ -244,7 +241,7 @@ bool ConvolutionTransformation::transform(TransformationContext &context, ngraph }); NetworkHelper::copyInfo(convolution, newConvolution); - auto newMultiplyAfter = std::make_shared( + auto newMultiplyAfter = std::make_shared( newConvolution, foldConvert( fold_reshape( diff --git a/inference-engine/src/low_precision_transformations/src/convolution_backprop_data.cpp b/inference-engine/src/low_precision_transformations/src/convolution_backprop_data.cpp index 1054149e836..7802a498a0e 100644 --- a/inference-engine/src/low_precision_transformations/src/convolution_backprop_data.cpp +++ b/inference-engine/src/low_precision_transformations/src/convolution_backprop_data.cpp @@ -13,7 +13,6 @@ #include #include #include "low_precision/network_helper.hpp" -#include "low_precision/common/dequantization_op.hpp" namespace ngraph { namespace pass { @@ -100,7 +99,6 @@ bool ConvolutionBackpropDataTransformation::transform(TransformationContext &con FakeQuantizeDequantization dequantization = NetworkHelper::getDequantization(convolutionBackpropData); { if (dequantization.subtract != nullptr) { - NetworkHelper::cleanRunTimeInfo(dequantization.subtract->shared_from_this()); NetworkHelper::optimizeSubtract(dequantization.subtract); } @@ -117,7 +115,7 @@ bool ConvolutionBackpropDataTransformation::transform(TransformationContext &con std::vector{deqPrecision, deqPrecision}, std::vector{deqPrecision}); - const auto newMultiplyAfter = std::make_shared>( + const auto newMultiplyAfter = std::make_shared>( std::vector{ deqPrecision, deqPrecision }, std::vector{ dequantization.multiply->get_output_element_type(0) }, ngraph::op::TemporaryReplaceOutputType(relaxedConvolutionBackpropData, deqPrecision).get(), @@ -155,7 +153,7 @@ bool ConvolutionBackpropDataTransformation::transform(TransformationContext &con auto inputs = convolutionBackpropData->input_values(); inputs[1] = multiplyFromWeights->input_value(0); - auto newMultiplyAfter = std::make_shared( + auto newMultiplyAfter = std::make_shared( convolutionBackpropData->copy_with_new_inputs(inputs), foldConvert( fold_reshape( diff --git a/inference-engine/src/low_precision_transformations/src/eltwise_base_transformation.cpp b/inference-engine/src/low_precision_transformations/src/eltwise_base_transformation.cpp index b2ae84b19f9..ddde3eb3456 100644 --- a/inference-engine/src/low_precision_transformations/src/eltwise_base_transformation.cpp +++ b/inference-engine/src/low_precision_transformations/src/eltwise_base_transformation.cpp @@ -41,12 +41,6 @@ bool EltwiseBaseTransformation::canBeTransformed(const TransformationContext& co return false; } - if ((ov::as_type_ptr(operation->get_input_node_shared_ptr(0)) || - ov::as_type_ptr(operation->get_input_node_shared_ptr(1))) && - !FakeQuantizeDequantization::checkElementwise(operation)) { - NetworkHelper::cleanRunTimeInfo(operation); - } - FakeQuantizeDequantization dequantization1 = pass::low_precision::NetworkHelper::getDequantization(operation, 0ul); FakeQuantizeDequantization dequantization2 = pass::low_precision::NetworkHelper::getDequantization(operation, 1ul); if ((dequantization1.empty() || ((dequantization1.multiply != nullptr) && !FakeQuantizeDequantization::checkElementwise(dequantization1.multiply))) && diff --git a/inference-engine/src/low_precision_transformations/src/fake_quantize.cpp b/inference-engine/src/low_precision_transformations/src/fake_quantize.cpp index cab841e3bc5..b731ed22a63 100644 --- a/inference-engine/src/low_precision_transformations/src/fake_quantize.cpp +++ b/inference-engine/src/low_precision_transformations/src/fake_quantize.cpp @@ -204,7 +204,6 @@ std::shared_ptr FakeQuantizeTransformation::fuseElementwis replace_node(fakeQuantize, newFakeQuantize); ngraph::copy_runtime_info({ fakeQuantize, eltwise }, newFakeQuantize); newFakeQuantize->set_friendly_name(fakeQuantize->get_friendly_name()); - NetworkHelper::cleanRunTimeInfo(newFakeQuantize); return newFakeQuantize; } diff --git a/inference-engine/src/low_precision_transformations/src/low_precision.cpp b/inference-engine/src/low_precision_transformations/src/low_precision.cpp index be040eb122a..ca34f0e8c77 100644 --- a/inference-engine/src/low_precision_transformations/src/low_precision.cpp +++ b/inference-engine/src/low_precision_transformations/src/low_precision.cpp @@ -75,7 +75,6 @@ #include "low_precision/fuse_subtract_to_fake_quantize.hpp" #include "low_precision/fuse_multiply_to_fake_quantize.hpp" #include "low_precision/multiply_to_group_convolution.hpp" -#include "low_precision/subtract_multiply_to_multiply_add.hpp" NGRAPH_RTTI_DEFINITION(ngraph::pass::low_precision::LowPrecision, "LowPrecision", 0); @@ -245,7 +244,6 @@ bool ngraph::pass::low_precision::LowPrecision::run_on_function(std::shared_ptr< cleanup->add_matcher( params, OperationPrecisionRestriction::getPrecisionsByOperationType(precisionRestrictions)); - manager.register_pass(params); manager.register_pass(params); manager.register_pass(); diff --git a/inference-engine/src/low_precision_transformations/src/mat_mul.cpp b/inference-engine/src/low_precision_transformations/src/mat_mul.cpp index 64816e8c541..6b0a1cdfeca 100644 --- a/inference-engine/src/low_precision_transformations/src/mat_mul.cpp +++ b/inference-engine/src/low_precision_transformations/src/mat_mul.cpp @@ -13,7 +13,6 @@ #include #include "low_precision/network_helper.hpp" -#include "low_precision/common/dequantization_op.hpp" using namespace ngraph; using namespace ngraph::pass; @@ -114,7 +113,7 @@ bool MatMulTransformation::transform(TransformationContext &context, ngraph::pat newMatMul->get_transpose_a(), newMatMul->get_transpose_b())); - const auto newSubtract = std::make_shared(newMatMul, newSubConst); + const auto newSubtract = std::make_shared(newMatMul, newSubConst); newSubtract->set_friendly_name(newMatMul->get_friendly_name() + "/DequantizationSubtract"); copy_runtime_info({ newSubtract, matMul }, newSubtract); @@ -160,7 +159,7 @@ bool MatMulTransformation::transform(TransformationContext &context, ngraph::pat mulConst1, foldConvert(mulConst2, element::f32))); - const auto newMultiply = std::make_shared>( + const auto newMultiply = std::make_shared>( std::vector{ deqPrecision, deqPrecision }, std::vector{ dequantization1.multiply->get_output_element_type(0) }, ngraph::op::TemporaryReplaceOutputType(parent, deqPrecision).get(), diff --git a/inference-engine/src/low_precision_transformations/src/multiply.cpp b/inference-engine/src/low_precision_transformations/src/multiply.cpp index c5a468cf21c..cf15d24dc02 100644 --- a/inference-engine/src/low_precision_transformations/src/multiply.cpp +++ b/inference-engine/src/low_precision_transformations/src/multiply.cpp @@ -15,7 +15,6 @@ #include #include "low_precision/common/ie_lpt_exception.hpp" -#include "low_precision/common/dequantization_op.hpp" #include "low_precision/network_helper.hpp" namespace ngraph { @@ -95,10 +94,6 @@ bool MultiplyTransformation::transform(TransformationContext& context, ngraph::p NetworkHelper::copyInfo(multiplyParent.get_node_shared_ptr(), newMultiply); NetworkHelper::copyInfo(multiply, newMultiply); - - if (!FakeQuantizeDequantization::checkElementwise(newMultiply)) { - NetworkHelper::cleanRunTimeInfo(newMultiply); - } } else { const int emptyPathIndex = fullPathIndex == 0 ? 1 : 0; @@ -135,7 +130,7 @@ bool MultiplyTransformation::transform(TransformationContext& context, ngraph::p std::shared_ptr newMultiplyValuesFullPath = fold(multiplyValuesEmptyPath, multiplyValuesFullPath); OutputVector inputs{ {}, {} }; inputs[emptyPathIndex] = dequantizationEmptyPath.data; - inputs[fullPathIndex] = std::make_shared( + inputs[fullPathIndex] = std::make_shared( dequantizationFullPath.subtract == nullptr ? (dequantizationFullPath.convert == nullptr ? dequantizationFullPath.data : dequantizationFullPath.convert) : diff --git a/inference-engine/src/low_precision_transformations/src/mvn.cpp b/inference-engine/src/low_precision_transformations/src/mvn.cpp index 4be1cf58b9d..093747a68b6 100644 --- a/inference-engine/src/low_precision_transformations/src/mvn.cpp +++ b/inference-engine/src/low_precision_transformations/src/mvn.cpp @@ -16,7 +16,6 @@ #include "ngraph/type/element_type.hpp" #include "ngraph/type/element_type_traits.hpp" #include "low_precision/network_helper.hpp" -#include "low_precision/common/dequantization_op.hpp" #include "ngraph/opsets/opset6.hpp" @@ -155,8 +154,8 @@ bool MVNTransformation::transform(TransformationContext &context, ngraph::patter NetworkHelper::setOutDataPrecisionForTypeRelaxed(newMVN, deqPrecision); NetworkHelper::copyInfo(mvn, newMVN); - auto newMultiply = std::make_shared>( - DequantizationMultiply(newMVN, newScalesConst), + auto newMultiply = std::make_shared>( + opset1::Multiply(newMVN, newScalesConst), mvn->get_output_element_type(0)); ngraph::copy_runtime_info({ mvn, newMultiply }, newMultiply); diff --git a/inference-engine/src/low_precision_transformations/src/network_helper.cpp b/inference-engine/src/low_precision_transformations/src/network_helper.cpp index 6b4bda9da54..c45e80e0b27 100644 --- a/inference-engine/src/low_precision_transformations/src/network_helper.cpp +++ b/inference-engine/src/low_precision_transformations/src/network_helper.cpp @@ -18,7 +18,6 @@ #include #include "low_precision/common/ie_lpt_exception.hpp" -#include "low_precision/common/dequantization_op.hpp" #include "low_precision/layer_transformation.hpp" #include "low_precision/rt_info/precision_preserved_attribute.hpp" #include "low_precision/rt_info/intervals_alignment_attribute.hpp" @@ -290,7 +289,7 @@ std::shared_ptr NetworkHelper::swapMultiplyAndAdd(std::shared_ptr>( + auto newMultiply = std::make_shared>( std::vector{element::f32, element::f32}, std::vector{ multiply->get_output_element_type(0) }, ngraph::op::TemporaryReplaceOutputType(newAdd, element::f32).get(), @@ -354,14 +353,6 @@ void NetworkHelper::copyInfo(const std::shared_ptr& source, const std::sha copyInfo(std::vector>{ source }, std::vector>{ target }); } -void NetworkHelper::cleanRunTimeInfo(const std::shared_ptr& layer) { - auto& rt_info = layer->get_rt_info(); - auto attributeIter = rt_info.find("DEQUANTIZATION"); - if (rt_info.find("DEQUANTIZATION") != rt_info.end()) { - rt_info.erase(attributeIter); - } -} - bool NetworkHelper::isScalarLike(std::shared_ptr constant) { // ticket #48857 // return constant->get_all_data_elements_bitwise_identical(); @@ -1068,12 +1059,12 @@ std::tuple, std::shared_ptr> NetworkHelper::decompos THROW_IE_LPT_EXCEPTION(*newFQ) << "unexpected operation type"; } - convert2 = std::make_shared(convert, element::f32); + convert2 = std::make_shared(convert, element::f32); convert2->set_friendly_name(convert->get_friendly_name() + "/DequantizationConvert"); ngraph::copy_runtime_info({ newFQ, convert2 }, convert2); } else { if (newFQ->get_output_element_type(0) != element::f32) { - convert2 = std::make_shared(newFQ, element::f32); + convert2 = std::make_shared(newFQ, element::f32); convert2->set_friendly_name(newFQ->get_friendly_name() + "/DequantizationConvert"); ngraph::copy_runtime_info({ newFQ, convert2 }, convert2); } @@ -1082,14 +1073,14 @@ std::tuple, std::shared_ptr> NetworkHelper::decompos // TODO: why type relaxed? const std::shared_ptr sub = shift == nullptr ? nullptr : - std::make_shared>(convert2 == nullptr ? newFQ : convert2, shift); + std::make_shared>(convert2 == nullptr ? newFQ : convert2, shift); if (sub != nullptr) { sub->set_friendly_name(newFQ->get_friendly_name() + "/DequantizationSubtract"); ngraph::copy_runtime_info({ newFQ, sub }, sub); } const auto dequantize = - std::make_shared>( + std::make_shared>( std::vector{ element::f32, element::f32 }, std::vector{ fq->get_output_element_type(0) }, ngraph::op::TemporaryReplaceOutputType(sub == nullptr ? (convert2 == nullptr ? newFQ : convert2) : sub, element::f32).get(), @@ -1143,20 +1134,20 @@ FakeQuantizeDequantization NetworkHelper::makeDequantization( } std::shared_ptr parent = input; - std::shared_ptr convert; + std::shared_ptr convert; if (precision == deqPrecision) { convert = nullptr; } else { - convert = std::make_shared( + convert = std::make_shared( parent, deqPrecision); parent = convert; } - std::shared_ptr subtract; + std::shared_ptr subtract; std::shared_ptr subtractConstant; if (std::abs(dequantizationSub) > 1e-6) { - subtract = std::make_shared>( + subtract = std::make_shared>( parent, std::make_shared(deqPrecision, ngraph::Shape({}), std::vector({ dequantizationSub }))); subtract->set_output_type(0, deqPrecision, subtract->get_output_partial_shape(0)); @@ -1165,8 +1156,8 @@ FakeQuantizeDequantization NetworkHelper::makeDequantization( // mandatory auto multiplyConstant = std::make_shared(deqPrecision, ngraph::Shape({}), std::vector({ dequantizationMul })); - auto multiply = std::make_shared>( - DequantizationMultiply(parent, multiplyConstant), + auto multiply = std::make_shared>( + opset1::Multiply(parent, multiplyConstant), originalPrecision); return FakeQuantizeDequantization(input, convert, subtract, nullptr, subtractConstant, multiply, multiplyConstant); @@ -1220,7 +1211,7 @@ FakeQuantizeDequantization NetworkHelper::createDequantizationFromFakeQuantize( std::shared_ptr convert; if (updatePrecision || (parent->output(0).get_element_type() != deqPrecision)) { - convert = std::make_shared(parent, deqPrecision); + convert = std::make_shared(parent, deqPrecision); parent = convert; } else { convert = nullptr; @@ -1228,13 +1219,13 @@ FakeQuantizeDequantization NetworkHelper::createDequantizationFromFakeQuantize( std::shared_ptr subtract; if (shift != nullptr) { - subtract = make_shared>(parent, shift); + subtract = make_shared>(parent, shift); subtract->set_output_type(0, deqPrecision, subtract->get_output_partial_shape(0)); parent = subtract; } else { subtract = nullptr; } - const std::shared_ptr multiply = std::make_shared(parent, scale); + const std::shared_ptr multiply = std::make_shared(parent, scale); multiply->set_output_type(0, fq->get_output_element_type(0), multiply->get_output_partial_shape(0)); return FakeQuantizeDequantization(fq, convert, subtract, nullptr, shift, multiply, scale); @@ -1591,7 +1582,7 @@ NetworkHelper::InsertDequantizationResult NetworkHelper::moveDequantizationAfter const auto convertOutputPrecision = dequantization.convert != nullptr ? dequantization.convert->get_output_element_type(0) : deqPrecision; - parent = std::make_shared(parent, convertOutputPrecision); + parent = std::make_shared(parent, convertOutputPrecision); ngraph::copy_runtime_info({ newOperation, parent }, parent); } @@ -1605,7 +1596,7 @@ NetworkHelper::InsertDequantizationResult NetworkHelper::moveDequantizationAfter dequantization.subtractConstant->get_element_type(); } - parent = std::make_shared>( + parent = std::make_shared>( std::vector{element::f32, element::f32}, std::vector{ element::f32 }, ngraph::op::TemporaryReplaceOutputType(parent, element::f32).get(), ngraph::op::TemporaryReplaceOutputType( @@ -1614,7 +1605,7 @@ NetworkHelper::InsertDequantizationResult NetworkHelper::moveDequantizationAfter foldConvert(dequantization.subtractConstant, parentPrecision), element::f32).get()); ngraph::copy_runtime_info({ newOperation, parent }, parent); } else { - parent = std::make_shared(parent, dequantization.subtractConvert); + parent = std::make_shared(parent, dequantization.subtractConvert); ngraph::copy_runtime_info({ newOperation, parent }, parent); } } @@ -1628,8 +1619,8 @@ NetworkHelper::InsertDequantizationResult NetworkHelper::moveDequantizationAfter ", multiply dequantization constant " << multiplyConstant->get_friendly_name() << ":" << multiplyConstant->get_element_type(); } - parent = std::make_shared>( - DequantizationMultiply(parent, + parent = std::make_shared>( + opset1::Multiply(parent, multiplyConstant->output(0).get_element_type() == parentPrecision ? multiplyConstant : foldConvert(multiplyConstant->output(0), parentPrecision)), @@ -1639,7 +1630,6 @@ NetworkHelper::InsertDequantizationResult NetworkHelper::moveDequantizationAfter replace_node(operation, parent); if ((!moveSubtract) && (dequantization.convert != nullptr) && (dequantization.subtract != nullptr)) { - NetworkHelper::cleanRunTimeInfo(dequantization.subtract); // issue #43088 // NetworkHelper::optimizeElementwise(dequantization.subtract); } diff --git a/inference-engine/src/low_precision_transformations/src/normalize_l2.cpp b/inference-engine/src/low_precision_transformations/src/normalize_l2.cpp index 9cf39cb1003..4e2b361324e 100644 --- a/inference-engine/src/low_precision_transformations/src/normalize_l2.cpp +++ b/inference-engine/src/low_precision_transformations/src/normalize_l2.cpp @@ -14,7 +14,6 @@ #include "ngraph/type/element_type.hpp" #include "ngraph/type/element_type_traits.hpp" #include "low_precision/network_helper.hpp" -#include "low_precision/common/dequantization_op.hpp" using namespace ngraph; using namespace ngraph::pass; @@ -135,7 +134,7 @@ bool NormalizeL2Transformation::transform(TransformationContext &context, ngraph normalize->get_eps_mode()); NetworkHelper::copyInfo(normalize, newNormalize); - auto newMultiply = std::make_shared>( + auto newMultiply = std::make_shared>( std::vector{ element::f32, element::f32 }, std::vector{normalize->get_output_element_type(0)}, ngraph::op::TemporaryReplaceOutputType(newNormalize, element::f32).get(), diff --git a/inference-engine/src/low_precision_transformations/src/split.cpp b/inference-engine/src/low_precision_transformations/src/split.cpp index eabe1f7e45e..141549dd582 100644 --- a/inference-engine/src/low_precision_transformations/src/split.cpp +++ b/inference-engine/src/low_precision_transformations/src/split.cpp @@ -8,7 +8,6 @@ #include #include "low_precision/network_helper.hpp" -#include "low_precision/common/dequantization_op.hpp" namespace ngraph { namespace pass { @@ -91,12 +90,12 @@ bool SplitTransformation::transform(TransformationContext& context, ngraph::patt } if (dequantization.subtract) { - const auto subtract = std::make_shared(parent, splitedSub[i]); + const auto subtract = std::make_shared(parent, splitedSub[i]); copy_runtime_info({ newSplit, subtract }, subtract); parent = subtract; } - const auto multiply = std::make_shared>(parent, splitedMul[i]); + const auto multiply = std::make_shared>(parent, splitedMul[i]); NetworkHelper::setOutDataPrecisionForTypeRelaxed(multiply, dequantization.multiply->get_output_element_type(0)); copy_runtime_info({ newSplit, multiply }, multiply); diff --git a/inference-engine/src/low_precision_transformations/src/subtract_multiply_to_multiply_add.cpp b/inference-engine/src/low_precision_transformations/src/subtract_multiply_to_multiply_add.cpp deleted file mode 100644 index b604323be9c..00000000000 --- a/inference-engine/src/low_precision_transformations/src/subtract_multiply_to_multiply_add.cpp +++ /dev/null @@ -1,176 +0,0 @@ -// Copyright (C) 2018-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#include "low_precision/subtract_multiply_to_multiply_add.hpp" - -#include -#include -#include - -#include -#include "low_precision/common/ie_lpt_exception.hpp" -#include "low_precision/network_helper.hpp" -#include "low_precision/common/dequantization_op.hpp" - -namespace ngraph { -namespace pass { -namespace low_precision { - -NGRAPH_RTTI_DEFINITION(ngraph::pass::low_precision::SubtractMultiplyToMultiplyAddTransformation, "SubtractMultiplyToMultiplyAddTransformation", 0); - -SubtractMultiplyToMultiplyAddTransformation::SubtractMultiplyToMultiplyAddTransformation(const Params& params) : LayerTransformation(params) { - auto matcher = pattern::wrap_type(); - - ngraph::graph_rewrite_callback callback = [this](pattern::Matcher& m) { - auto op = m.get_match_root(); - if (transformation_callback(op)) { - return false; - } - return transform(*context, m); - }; - - auto m = std::make_shared(matcher, "SubtractMultiplyToMultiplyAddTransformation"); - this->register_matcher(m, callback); -} - -FakeQuantizeDequantization get(const std::shared_ptr node) { - Output dataNode = node; - - const std::shared_ptr multiply = ov::is_type( - dataNode.get_node_shared_ptr()->get_input_node_shared_ptr(1)) ? - ov::as_type_ptr(dataNode.get_node_shared_ptr()) : - nullptr; - std::shared_ptr multiplyConstant; - if (multiply != nullptr) { - FakeQuantizeDequantization::fillDequantizationParams(multiply, multiplyConstant); - dataNode = multiply->get_input_source_output(0); - } - - const std::shared_ptr subtract = (dataNode.get_node_shared_ptr()->get_input_size() > 1ul) - && ov::is_type(dataNode.get_node_shared_ptr()->get_input_node_ptr(1)) ? - ov::as_type_ptr(dataNode.get_node_shared_ptr()) : - nullptr; - std::shared_ptr subtractConvert; - std::shared_ptr subtractConstant; - if (subtract != nullptr) { - FakeQuantizeDequantization::fillDequantizationParams(subtract, subtractConvert, subtractConstant); - dataNode = subtract->get_input_source_output(0); - } - - const std::shared_ptr convert = ov::as_type_ptr(dataNode.get_node_shared_ptr()); - if (convert != nullptr) { - dataNode = convert->get_input_source_output(0); - } - - return FakeQuantizeDequantization(dataNode, convert, subtract, subtractConvert, subtractConstant, multiply, multiplyConstant); -} - -bool SubtractMultiplyToMultiplyAddTransformation::transform(TransformationContext& context, ngraph::pattern::Matcher &m) { - auto multiply = m.get_match_root(); - if (!canBeTransformed(context, multiply)) { - return false; - } - - multiply = NetworkHelper::separateInStandaloneBranch(multiply); - FakeQuantizeDequantization dequantization = get(multiply); - - const element::Type precisionBeforeDequantization = dequantization.convert == nullptr ? - (dequantization.subtract == nullptr ? - dequantization.multiply->get_input_element_type(0) : - dequantization.subtract->get_input_element_type(0)) : - dequantization.convert->get_input_element_type(0); - - const element::Type precisionAfterDequantization = dequantization.multiply->get_output_element_type(0); - - if (dequantization.empty()) { - return false; - } - - auto lastNew = dequantization.data; - element::Type lastNewPrecision = precisionBeforeDequantization; - std::shared_ptr lastPrevious = dequantization.multiply != nullptr ? - std::dynamic_pointer_cast(dequantization.multiply) : - dequantization.subtract; - - { - const std::shared_ptr multiplyConstant = dequantization.multiply->get_input_node_shared_ptr(1); - - lastNew = std::make_shared>( - std::vector{element::f32, element::f32}, - std::vector{deqPrecision}, - ngraph::op::TemporaryReplaceOutputType(lastNew, element::f32).get(), - ngraph::op::TemporaryReplaceOutputType(multiplyConstant, element::f32).get()); - - if (dequantization.multiply != nullptr) { - auto lastNewPtr = lastNew.get_node_shared_ptr(); - NetworkHelper::copyInfo(dequantization.multiply, lastNewPtr); - } - - lastNewPrecision = deqPrecision; - } - - if (dequantization.subtract != nullptr) { - std::shared_ptr originalSubtractConstant = dequantization.subtract->get_input_node_shared_ptr(1); - - std::shared_ptr subtractConstant = fold( - fold( - foldConvert(originalSubtractConstant, deqPrecision), - std::make_shared(deqPrecision, Shape{}, std::vector{ -1.f })), - foldConvert(dequantization.multiply->get_input_node_shared_ptr(1), deqPrecision)); - - if (ov::is_type(subtractConstant)) { - std::shared_ptr constant = ov::as_type_ptr(subtractConstant); - if (NetworkHelper::isScalarLike(constant)) { - subtractConstant = NetworkHelper::toScalar(constant); - } - } - - lastPrevious = lastNew.get_node_shared_ptr(); - lastNew = std::make_shared>( - std::vector{element::f32, element::f32}, - std::vector{precisionAfterDequantization}, - ngraph::op::TemporaryReplaceOutputType(lastNew, element::f32).get(), - ngraph::op::TemporaryReplaceOutputType(subtractConstant, element::f32).get()); - - auto lastNewPtr = lastNew.get_node_shared_ptr(); - NetworkHelper::copyInfo(dequantization.subtract, lastNewPtr); - - lastNewPrecision = precisionAfterDequantization; - } else { - NetworkHelper::setOutDataPrecision(ov::as_type_ptr(lastNew.get_node_shared_ptr()), precisionAfterDequantization); - } - - const std::shared_ptr lastOriginal = dequantization.multiply == nullptr ? - std::dynamic_pointer_cast(dequantization.subtract) : - dequantization.multiply; - const std::shared_ptr lastNewPtr = lastNew.get_node_shared_ptr(); - replace_node(lastOriginal, lastNewPtr); - - updateOutput(context, lastNewPtr, lastPrevious); - return true; -} - -bool SubtractMultiplyToMultiplyAddTransformation::canBeTransformed(const TransformationContext& context, std::shared_ptr op) const { - FakeQuantizeDequantization dequantization = get(op); - if (dequantization.empty() || (dequantization.multiply == nullptr)) { - return false; - } - - if (((dequantization.subtract == nullptr) || (!dequantization.subtract->get_rt_info().count("DEQUANTIZATION"))) && - (!dequantization.multiply->get_rt_info().count("DEQUANTIZATION"))) { - return false; - } - - return - ((dequantization.subtract == nullptr) || FakeQuantizeDequantization::checkElementwise(dequantization.subtract)) && - FakeQuantizeDequantization::checkElementwise(dequantization.multiply); -} - -bool SubtractMultiplyToMultiplyAddTransformation::isPrecisionPreserved(std::shared_ptr layer) const noexcept { - return false; -} - -} // namespace low_precision -} // namespace pass -} // namespace ngraph diff --git a/inference-engine/src/mkldnn_plugin/mkldnn_plugin.cpp b/inference-engine/src/mkldnn_plugin/mkldnn_plugin.cpp index 29820837762..ed42651a738 100644 --- a/inference-engine/src/mkldnn_plugin/mkldnn_plugin.cpp +++ b/inference-engine/src/mkldnn_plugin/mkldnn_plugin.cpp @@ -375,19 +375,6 @@ static void Transformation(CNNNetwork& clonedNetwork, const Config& conf) { std::string errMsg; return MKLDNNFakeQuantizeNode::isSupportedOperation(node, errMsg); }); - postLPTPassManager.get_pass_config()->set_callback([](const_node_ptr &node) -> bool { - if (auto mul_op = std::dynamic_pointer_cast(node)) { - auto add_op = std::dynamic_pointer_cast(mul_op->get_input_node_shared_ptr(0)); - auto constant = std::dynamic_pointer_cast(mul_op->get_input_node_shared_ptr(1)); - bool is_dequantization = mul_op->get_rt_info().count("DEQUANTIZATION") != 0; - if (add_op && constant && is_dequantization) { - return ngraph::is_type(add_op->get_input_node_shared_ptr(0)) || - ngraph::is_type(add_op->get_input_node_shared_ptr(0)) || - ngraph::is_type(add_op->get_input_node_shared_ptr(0)); - } - } - return false; - }); postLPTPassManager.get_pass_config()->set_callback([](const_node_ptr &node) -> bool { // UnrollTI transformation is disabled by default, is turned on by LowLatency transformation return node->get_rt_info().count("UNROLL_TI") == 0; diff --git a/inference-engine/src/transformations/include/transformations/rt_info/dequantization_attribute.hpp b/inference-engine/src/transformations/include/transformations/rt_info/dequantization_attribute.hpp deleted file mode 100644 index 9b9b0747bc9..00000000000 --- a/inference-engine/src/transformations/include/transformations/rt_info/dequantization_attribute.hpp +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright (C) 2018-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -/** - * @brief Defines fused names attribute - * @file fused_names_attribute.hpp - */ - -#include -#include -#include -#include -#include - -#include -#include -#include - - -namespace ngraph { - -/** - * @ingroup ie_runtime_attr_api - * @brief Dequantization class represents runtime info attribute that indicates - * whether the operation is dequantization - */ -class TRANSFORMATIONS_API DequantizationAttr { -private: - std::string dequantization_attribute; - -public: - /** - * A default constructor - */ - DequantizationAttr() = default; - - /** - * @brief Constructs a new object consisting of a single name * - * @param[in] name The name - */ - explicit DequantizationAttr(const std::string& name) : dequantization_attribute(name) {} - - /** - * @brief return string with dequantization value - */ - std::string getDequantizationAttr() const; -}; -/** - * @ingroup ie_runtime_attr_api - * @brief getDequantization return string with dequantization value - * @param[in] node The node will be used to get Dequantization attribute - */ -TRANSFORMATIONS_API std::string getDequantization(const std::shared_ptr& node); - -} // namespace ngraph - -namespace ov { - -extern template class TRANSFORMATIONS_API VariantImpl; - -template<> -class TRANSFORMATIONS_API VariantWrapper : public VariantImpl { -public: - static constexpr VariantTypeInfo type_info{"DEQUANTIZATION", 0}; - - const VariantTypeInfo &get_type_info() const override { - return type_info; - } - - VariantWrapper(const value_type &value) : VariantImpl(value) {} - - std::shared_ptr merge(const ngraph::NodeVector & nodes) override; - - std::shared_ptr init(const std::shared_ptr & node) override; -}; - -} // namespace ov diff --git a/inference-engine/src/transformations/src/transformations/low_precision/disable_convert_constant_folding_on_const_path.cpp b/inference-engine/src/transformations/src/transformations/low_precision/disable_convert_constant_folding_on_const_path.cpp index 15dc27bada2..8096a9ac6bc 100644 --- a/inference-engine/src/transformations/src/transformations/low_precision/disable_convert_constant_folding_on_const_path.cpp +++ b/inference-engine/src/transformations/src/transformations/low_precision/disable_convert_constant_folding_on_const_path.cpp @@ -13,7 +13,6 @@ #include #include #include -#include "transformations/rt_info/dequantization_attribute.hpp" using namespace ngraph; diff --git a/inference-engine/src/transformations/src/transformations/rt_info/dequantization_attribute.cpp b/inference-engine/src/transformations/src/transformations/rt_info/dequantization_attribute.cpp deleted file mode 100644 index c2858c6d8f5..00000000000 --- a/inference-engine/src/transformations/src/transformations/rt_info/dequantization_attribute.cpp +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright (C) 2018-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#include -#include -#include -#include -#include - -#include -#include - -#include "transformations/rt_info/dequantization_attribute.hpp" - -using namespace ov; -using namespace ngraph; - -std::string DequantizationAttr::getDequantizationAttr() const { - return dequantization_attribute; -} - -std::string ngraph::getDequantization(const std::shared_ptr& node) { - const auto& rtInfo = node->get_rt_info(); - using getDequantizationWrapper = VariantWrapper; - - if (!rtInfo.count(getDequantizationWrapper::type_info.name)) return ""; - - const auto& attr = rtInfo.at(getDequantizationWrapper::type_info.name); - DequantizationAttr pp = ov::as_type_ptr(attr)->get(); - return pp.getDequantizationAttr(); -} - -template class ov::VariantImpl; - -constexpr VariantTypeInfo VariantWrapper::type_info; - -std::shared_ptr VariantWrapper::merge(const ngraph::NodeVector & nodes) { - std::set dequantizations; - - for (auto& node : nodes) { - std::string pp = getDequantization(node); - if (!pp.empty()) dequantizations.insert(pp); - } - - std::string final_primitives_priority; - if (dequantizations.size() == 0) { - final_primitives_priority = ""; - } else { - final_primitives_priority = *dequantizations.begin(); - } - return std::make_shared>(DequantizationAttr(final_primitives_priority)); -} - -std::shared_ptr VariantWrapper::init(const std::shared_ptr & node) { - return std::make_shared>(DequantizationAttr(node->get_friendly_name())); -} diff --git a/inference-engine/tests/functional/inference_engine/lp_transformations/convert_mul_or_add_finally_transformation_with_dequantization.cpp b/inference-engine/tests/functional/inference_engine/lp_transformations/convert_mul_or_add_finally_transformation_with_dequantization.cpp deleted file mode 100644 index e0091e57153..00000000000 --- a/inference-engine/tests/functional/inference_engine/lp_transformations/convert_mul_or_add_finally_transformation_with_dequantization.cpp +++ /dev/null @@ -1,117 +0,0 @@ -// Copyright (C) 2018-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#include "layer_transformation.hpp" - -#include -#include -#include - -#include - -#include -#include -#include -#include - -#include "common_test_utils/ngraph_test_utils.hpp" - -#include "lpt_ngraph_functions/convert_mul_or_add_finally_with_dequantization_function.hpp" - -using namespace testing; -using namespace ngraph::pass; - -namespace { - -inline std::ostream& operator<<(std::ostream& os, const std::vector& values) { - os << "{ "; - for (size_t i = 0; i < values.size(); ++i) { - os << values[i]; - if (i != (values.size() - 1ul)) { - os << ", "; - } - } - os << " }"; - return os; -} - -class ConvertMulOrAddFinallyTransformationWithDequantizationTestValues { -public: - std::vector multiplyConstValues; - ngraph::Shape inputShape; - ngraph::element::Type inputPrecision; - TestTransformationParams params; -}; - -using TestValuesType = ConvertMulOrAddFinallyTransformationWithDequantizationTestValues; - -class ConvertMulOrAddFinallyTransformationWithDequantization : public LayerTransformation, public testing::WithParamInterface { -public: - void SetUp() override { - using namespace ngraph::builder::subgraph; - const ConvertMulOrAddFinallyTransformationWithDequantizationTestValues testValues = GetParam(); - - actualFunction = ConvertMulOrAddWithDequantizationFunction::getOriginal(testValues.inputShape, - testValues.inputPrecision, - testValues.multiplyConstValues); - - ngraph::pass::Manager manager; - manager.register_pass(); - manager.register_pass(); - - manager.run_passes(actualFunction); - - referenceFunction = ConvertMulOrAddWithDequantizationFunction::getReference(testValues.inputShape, - testValues.inputPrecision, - testValues.multiplyConstValues); - } - - static std::string getTestCaseName(testing::TestParamInfo obj) { - const ConvertMulOrAddFinallyTransformationWithDequantizationTestValues testValues = obj.param; - std::ostringstream result; - result << LayerTransformation::getTestCaseNameByParams(testValues.inputPrecision, testValues.inputShape, testValues.params) << "_" << - testValues.multiplyConstValues; - return result.str(); - } -}; - -TEST_P(ConvertMulOrAddFinallyTransformationWithDequantization, CompareFunctions) { - actualFunction->validate_nodes_and_infer_types(); - auto res = compare_functions(referenceFunction, actualFunction, true, true, true); - ASSERT_TRUE(res.first) << res.second; -} - -std::vector testValues = { - { - { -1.0 }, - { 1, 1000 }, - ngraph::element::f32, - LayerTransformation::createParamsU8I8() - }, - { - { 128.0 }, - { 1, 10 }, - ngraph::element::f32, - LayerTransformation::createParamsU8I8() - }, - { - { -64.5 }, - { 1, 10 }, - ngraph::element::i8, - LayerTransformation::createParamsU8I8() - }, - { - { 1.2 }, - { 1, 100 }, - ngraph::element::u8, - LayerTransformation::createParamsI8I8() - } -}; - -INSTANTIATE_TEST_SUITE_P( - smoke_LPT, - ConvertMulOrAddFinallyTransformationWithDequantization, - ::testing::ValuesIn(testValues), - ConvertMulOrAddFinallyTransformationWithDequantization::getTestCaseName); -} // namespace diff --git a/inference-engine/tests/functional/inference_engine/lp_transformations/group_convolution_transformation.cpp b/inference-engine/tests/functional/inference_engine/lp_transformations/group_convolution_transformation.cpp index 1426ed6fe63..782a72105b2 100644 --- a/inference-engine/tests/functional/inference_engine/lp_transformations/group_convolution_transformation.cpp +++ b/inference-engine/tests/functional/inference_engine/lp_transformations/group_convolution_transformation.cpp @@ -471,7 +471,7 @@ const std::vector testValuesGroupConv = { 1, ngraph::element::i8, false, - {"DEQUANTIZATION", "DISABLED_CONSTANT_FOLDING"} + {"DISABLED_CONSTANT_FOLDING"} }, {} }, diff --git a/inference-engine/tests/functional/inference_engine/lp_transformations/layer_transformation.cpp b/inference-engine/tests/functional/inference_engine/lp_transformations/layer_transformation.cpp index 2a31f228c5e..2e51501dec0 100644 --- a/inference-engine/tests/functional/inference_engine/lp_transformations/layer_transformation.cpp +++ b/inference-engine/tests/functional/inference_engine/lp_transformations/layer_transformation.cpp @@ -139,10 +139,6 @@ ngraph::builder::subgraph::DequantizationOperations LayerTransformation::toDequa ngraph::builder::subgraph::DequantizationOperations::Multiply multiply; { - const bool addDequantizationAttribute = dequantization.multiply != nullptr ? - dequantization.multiply->get_rt_info().count("DEQUANTIZATION") != 0 : - true; - const size_t constantIndex = dequantization.multiplyConstant && dequantization.multiply ? ngraph::pass::low_precision::NetworkHelper::getChildInputIndex(dequantization.multiplyConstant, dequantization.multiply) : 0ul; @@ -152,7 +148,7 @@ ngraph::builder::subgraph::DequantizationOperations LayerTransformation::toDequa dequantization.multiplyConstant->cast_vector(), dequantization.multiplyConstant->output(0).get_element_type(), dequantization.multiplyConstant->output(0).get_shape(), - addDequantizationAttribute, + false, constantIndex) : ngraph::builder::subgraph::DequantizationOperations::Multiply(); } diff --git a/inference-engine/tests/functional/inference_engine/lp_transformations/low_precision_transformations_test.cpp b/inference-engine/tests/functional/inference_engine/lp_transformations/low_precision_transformations_test.cpp index 3849c941bd5..82e2ed20204 100644 --- a/inference-engine/tests/functional/inference_engine/lp_transformations/low_precision_transformations_test.cpp +++ b/inference-engine/tests/functional/inference_engine/lp_transformations/low_precision_transformations_test.cpp @@ -8,7 +8,6 @@ #include "low_precision/convolution.hpp" #include "low_precision/mat_mul.hpp" #include "low_precision/fuse_convert.hpp" -#include "low_precision/subtract_multiply_to_multiply_add.hpp" using namespace ::testing; using namespace ngraph::pass::low_precision; diff --git a/inference-engine/tests/functional/inference_engine/lp_transformations/mul_add_to_scaleshift_or_power_transformation.cpp b/inference-engine/tests/functional/inference_engine/lp_transformations/mul_add_to_scaleshift_or_power_transformation.cpp deleted file mode 100644 index 3a9348f6ab6..00000000000 --- a/inference-engine/tests/functional/inference_engine/lp_transformations/mul_add_to_scaleshift_or_power_transformation.cpp +++ /dev/null @@ -1,147 +0,0 @@ -// Copyright (C) 2018-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#include "layer_transformation.hpp" - -#include -#include -#include - -#include - -#include -#include -#include -#include -#include - -#include "common_test_utils/ngraph_test_utils.hpp" -#include "lpt_ngraph_functions/common/dequantization_operations.hpp" -#include "lpt_ngraph_functions/common/add.hpp" -#include "lpt_ngraph_functions/mul_add_to_scaleshift_or_power_function.hpp" - -using namespace testing; -using namespace ngraph; -using namespace ngraph::pass; - -namespace { - -class MulAddToScaleshiftOrPowerParams { -public: - TestTransformationParams params; - ngraph::builder::subgraph::DequantizationOperations::Multiply mulValues; - ngraph::builder::subgraph::Add addValues; - ngraph::element::Type precisionAfterOperation; -}; - -typedef std::tuple < - ngraph::element::Type, - bool, - ngraph::Shape, - MulAddToScaleshiftOrPowerParams -> MulAddToScaleshiftOrPowerTestValues; - -inline std::ostream& operator<<(std::ostream& os, const std::vector& values) { - os << "{ "; - for (size_t i = 0; i < values.size(); ++i) { - os << values[i]; - if (i != (values.size() - 1ul)) { - os << ", "; - } - } - os << " }"; - return os; -} - - -class MulAddToScaleshiftOrPowerTransformation : - public LayerTransformation, - public testing::WithParamInterface { -public: - void SetUp() override { - const auto inputPrecision = std::get<0>(GetParam()); - const auto isDequantization = std::get<1>(GetParam()); - const auto inputShape = std::get<2>(GetParam()); - const auto testValues = std::get<3>(GetParam()); - - actualFunction = ngraph::builder::subgraph::MulAddToScaleshiftOrPowerFunction::getOriginal( - inputPrecision, - inputShape, - isDequantization, - testValues.mulValues, - testValues.addValues); - - ngraph::pass::Manager manager; - manager.register_pass(); - manager.register_pass(); - manager.run_passes(actualFunction); - - referenceFunction = ngraph::builder::subgraph::MulAddToScaleshiftOrPowerFunction::getReference( - inputPrecision, - inputShape, - isDequantization, - testValues.mulValues, - testValues.addValues, - testValues.precisionAfterOperation); - } - - static std::string getTestCaseName(testing::TestParamInfo obj) { - const auto inputPrecision = std::get<0>(obj.param); - const auto isDequantization = std::get<1>(obj.param); - const auto inputShape = std::get<2>(obj.param); - const auto testValues = std::get<3>(obj.param); - - std::ostringstream result; - result << toString(testValues.params) << "_" << inputPrecision << "_" << inputShape << "_" - << testValues.mulValues.values << "_" << testValues.addValues.values << (isDequantization ? "_ScaleShift_" : "_Power_") - << testValues.precisionAfterOperation; - return result.str(); - } -}; - -TEST_P(MulAddToScaleshiftOrPowerTransformation, CompareFunctions) { - actualFunction->validate_nodes_and_infer_types(); - auto res = compare_functions(referenceFunction, actualFunction, true, true, true); - ASSERT_TRUE(res.first) << res.second; -} - -const std::vector precision = { - ngraph::element::i32, - ngraph::element::f32, - ngraph::element::u8, - ngraph::element::i8, -}; - -const std::vector isDequantization = { false, true }; - -const std::vector inputShape = { - { 1, 3, 9, 9 }, - { 4, 3, 9, 9 } -}; - -const std::vector testValues = { - { - LayerTransformation::createParamsU8I8(), - { 0.1f }, - { 128.f }, - ngraph::element::f32 - }, - { - LayerTransformation::createParamsU8I8(), - { 0.1f }, - { -128.f }, - ngraph::element::f32 - } -}; - -INSTANTIATE_TEST_SUITE_P( - smoke_LPT, - MulAddToScaleshiftOrPowerTransformation, - ::testing::Combine( - ::testing::ValuesIn(precision), - ::testing::ValuesIn(isDequantization), - ::testing::ValuesIn(inputShape), - ::testing::ValuesIn(testValues)), - MulAddToScaleshiftOrPowerTransformation::getTestCaseName); -} // namespace diff --git a/inference-engine/tests/functional/inference_engine/lp_transformations/subtract_multiply_to_multiply_add_transformation.cpp b/inference-engine/tests/functional/inference_engine/lp_transformations/subtract_multiply_to_multiply_add_transformation.cpp deleted file mode 100644 index 79f0eca2163..00000000000 --- a/inference-engine/tests/functional/inference_engine/lp_transformations/subtract_multiply_to_multiply_add_transformation.cpp +++ /dev/null @@ -1,356 +0,0 @@ -// Copyright (C) 2018-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#include "layer_transformation.hpp" - -#include -#include -#include - -#include - -#include -#include -#include "low_precision/subtract_multiply_to_multiply_add.hpp" - -#include "common_test_utils/ngraph_test_utils.hpp" -#include "simple_low_precision_transformer.hpp" -#include "lpt_ngraph_functions/subtract_multiply_to_multiply_add_function.hpp" - -using namespace testing; -using namespace ngraph; -using namespace ngraph::pass; -using namespace ngraph::builder::subgraph; - -namespace { - -class SubtractMultiplyToMultiplyAddTransformationTestValues { -public: - class Actual { - public: - ngraph::element::Type precisionBefore; - DequantizationOperations dequantization; - ngraph::element::Type precisionAfter; - }; - class Expected { - public: - ngraph::element::Type precisionBefore; - DequantizationOperations dequantization; - ngraph::element::Type precisionAfter; - Multiply multiply; - Add add; - }; - TestTransformationParams params; - Actual actual; - Expected expected; -}; - -typedef std::tuple< - ngraph::PartialShape, - SubtractMultiplyToMultiplyAddTransformationTestValues> SubtractMultiplyToMultiplyAddTransformationParams; - -class SubtractMultiplyToMultiplyAddTransformation : - public LayerTransformation, - public testing::WithParamInterface { -public: - void SetUp() override { - const ngraph::PartialShape inputShape = std::get<0>(GetParam()); - SubtractMultiplyToMultiplyAddTransformationTestValues testValues = std::get<1>(GetParam()); - - actualFunction = SubtractMultiplyToMultiplyAddFunction::getOriginal( - inputShape, - testValues.actual.precisionBefore, - testValues.actual.dequantization, - testValues.actual.precisionAfter); - - SimpleLowPrecisionTransformer transform; - transform.add(testValues.params); - transform.transform(actualFunction); - - referenceFunction = SubtractMultiplyToMultiplyAddFunction::getReference( - inputShape, - testValues.expected.precisionBefore, - testValues.expected.dequantization, - testValues.expected.precisionAfter, - testValues.expected.multiply, - testValues.expected.add); - } - - static std::string getTestCaseName(testing::TestParamInfo obj) { - const ngraph::PartialShape inputShape = std::get<0>(obj.param); - SubtractMultiplyToMultiplyAddTransformationTestValues testValues = std::get<1>(obj.param); - - std::ostringstream result; - result << - inputShape << "_" << - testValues.actual.precisionBefore << "_" << - testValues.actual.dequantization << "_" << - testValues.actual.precisionAfter << "_" << - testValues.expected.precisionBefore << "_" << - testValues.expected.dequantization << "_" << - testValues.expected.precisionAfter << "_" << - testValues.expected.multiply.values << "_" << - testValues.expected.multiply.constantShape << "_" << - testValues.expected.multiply.outPrecision << "_" << - testValues.expected.add.values << "_" << - testValues.expected.add.constantShape << "_" << - testValues.expected.add.outPrecision; - return result.str(); - } -}; - -TEST_P(SubtractMultiplyToMultiplyAddTransformation, CompareFunctions) { - actualFunction->validate_nodes_and_infer_types(); - auto res = compare_functions(referenceFunction, actualFunction, true, true); - - // issue #63030 - ASSERT_TRUE(LayerTransformation::allNamesAreUnique(actualFunction)) << "Not all names are unique"; - ASSERT_TRUE(res.first) << res.second; -} - -namespace testValues1 { -const std::vector inputShapes = { - {1, 3, 299, 299}, - {Dimension::dynamic(), 3, Dimension::dynamic(), Dimension::dynamic()} -}; - -const std::vector testValues = { - // Multiply {} -> Multiply + Subtract {1x3x1x1} - { - LayerTransformation::createParamsU8I8(), - { - ngraph::element::f32, - {{}, {}, {0.1f}}, - ngraph::element::f32, - }, - { - ngraph::element::f32, - {}, - ngraph::element::f32, - {{0.1f}, {ngraph::element::f32}}, - {} - }, - }, - // Multiply {} -> Multiply + Subtract {1x3x1x1} - { - LayerTransformation::createParamsU8I8(), - { - ngraph::element::f32, - {{}, {}, {{0.1f, 0.2f, 0.3f}}}, - ngraph::element::f32, - }, - { - ngraph::element::f32, - {}, - ngraph::element::f32, - {{0.1f, 0.2f, 0.3f}, {ngraph::element::f32}}, - {} - }, - }, - // FP32 Subtract + Multiply {} -> Multiply + Subtract {1x3x1x1} - { - LayerTransformation::createParamsU8I8(), - { - ngraph::element::f32, - {{ngraph::element::f32}, {{128.f, 128.f / 2.f, 128.f / 4.f}}, {0.1f}}, - ngraph::element::f32, - }, - { - ngraph::element::f32, - {}, - ngraph::element::f32, - {{0.1f}, {ngraph::element::f32}}, - {{-12.8f, -12.8f / 2.f, -12.8f / 4.f}, {ngraph::element::f32}} - }, - }, - // FP32 Subtract + Multiply {} -> Multiply + Subtract {1x3x1x1} - { - LayerTransformation::createParamsU8I8(), - { - ngraph::element::f32, - {{ngraph::element::f32}, {128}, {0.1f}}, - ngraph::element::f32, - }, - { - ngraph::element::f32, - {}, - ngraph::element::f32, - {{0.1f}, {ngraph::element::f32}}, - {{-12.8f}, {ngraph::element::f32}} - }, - }, - // U8 Multiply {} -> Multiply + Subtract {1x3x1x1} - { - LayerTransformation::createParamsU8I8(), - { - ngraph::element::u8, - {{ngraph::element::f32}, {}, {0.1f}}, - ngraph::element::f32, - }, - { - ngraph::element::u8, - {}, - ngraph::element::u8, - {{0.1f}, {ngraph::element::f32}}, - {} - }, - }, - // U8 Subtract + Multiply {} -> Multiply + Subtract {1x3x1x1} - { - LayerTransformation::createParamsU8I8(), - { - ngraph::element::u8, - {{ngraph::element::f32}, {128}, {0.1f}}, - ngraph::element::f32, - }, - { - ngraph::element::u8, - {}, - ngraph::element::u8, - {{0.1f}, {ngraph::element::f32}}, - {{-12.8f}, {ngraph::element::f32}} - }, - }, - // empty - { - LayerTransformation::createParamsU8I8(), - { - ngraph::element::u8, - {{ngraph::element::f32}, {128}, {}}, - ngraph::element::f32, - }, - { - ngraph::element::u8, - {{ngraph::element::f32}, {128}, {}}, - ngraph::element::u8, - {}, - {} - }, - }, - // empty - { - LayerTransformation::createParamsU8I8(), - { - ngraph::element::f32, - {}, - ngraph::element::f32, - }, - { - ngraph::element::f32, - {}, - ngraph::element::f32, - {}, - {} - }, - }, -}; - -INSTANTIATE_TEST_SUITE_P( - smoke_LPT, - SubtractMultiplyToMultiplyAddTransformation, - ::testing::Combine( - ::testing::ValuesIn(inputShapes), - ::testing::ValuesIn(testValues)), - SubtractMultiplyToMultiplyAddTransformation::getTestCaseName); -} // namespace testValues1 - -namespace testValues2 { -const std::vector inputShapes = { - {2, 5, 2, 2} -}; - -const std::vector testValues = { - // FP32 Multiply {5x1x1} -> Multiply + Subtract {1x5x1x1} - { - LayerTransformation::createParamsU8I8(), - { - ngraph::element::f32, - {{}, {}, {{0.1f, 0.2f, 0.3f, 0.4f, 0.5f}, ngraph::element::f32, {5, 1, 1}}}, - ngraph::element::f32, - }, - { - ngraph::element::f32, - {}, - ngraph::element::f32, - {{0.1f, 0.2f, 0.3f, 0.4f, 0.5f}, {ngraph::element::f32}, {5, 1, 1}}, - {} - }, - }, - // FP32 Multiply {5x1x2} - { - LayerTransformation::createParamsU8I8(), - { - ngraph::element::f32, - {{}, {}, {{0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f, 0.9f, 1.f}, ngraph::element::f32, {5, 1, 2}}}, - ngraph::element::f32, - }, - { - ngraph::element::f32, - {{}, {}, {{0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f, 0.9f, 1.f}, ngraph::element::f32, {5, 1, 2}}}, - ngraph::element::f32, - {}, - {} - }, - }, -}; - -INSTANTIATE_TEST_SUITE_P( - smoke_LPT, - SubtractMultiplyToMultiplyAddTransformation, - ::testing::Combine( - ::testing::ValuesIn(inputShapes), - ::testing::ValuesIn(testValues)), - SubtractMultiplyToMultiplyAddTransformation::getTestCaseName); -} // namespace testValues2 - -namespace testValues3 { -const std::vector inputShapesWithDynamicChannels = { - {Dimension::dynamic(), Dimension::dynamic(), Dimension::dynamic(), Dimension::dynamic()}, - PartialShape::dynamic() -}; - -const std::vector testValues = { - // Multiply {} -> Multiply + Subtract {1x3x1x1} - { - LayerTransformation::createParamsU8I8(), - { - ngraph::element::f32, - {{}, {}, {0.1f}}, - ngraph::element::f32, - }, - { - ngraph::element::f32, - {}, - ngraph::element::f32, - {{0.1f}, {ngraph::element::f32}}, - {} - }, - }, - // Multiply {} -> Multiply + Subtract {1x3x1x1} - { - LayerTransformation::createParamsU8I8(), - { - ngraph::element::f32, - {{}, {}, {{0.1f, 0.2f, 0.3f}}}, - ngraph::element::f32, - }, - { - ngraph::element::f32, - {{}, {}, {{0.1f, 0.2f, 0.3f}}}, - ngraph::element::f32, - {}, - {} - }, - }, -}; - -INSTANTIATE_TEST_SUITE_P( - smoke_LPT, - SubtractMultiplyToMultiplyAddTransformation, - ::testing::Combine( - ::testing::ValuesIn(inputShapesWithDynamicChannels), - ::testing::ValuesIn(testValues)), - SubtractMultiplyToMultiplyAddTransformation::getTestCaseName); -} // namespace testValues3 -} // namespace diff --git a/inference-engine/tests/functional/inference_engine/lp_transformations/transformations_after_split_transformation.cpp b/inference-engine/tests/functional/inference_engine/lp_transformations/transformations_after_split_transformation.cpp index 678592ae601..b7d092c6269 100644 --- a/inference-engine/tests/functional/inference_engine/lp_transformations/transformations_after_split_transformation.cpp +++ b/inference-engine/tests/functional/inference_engine/lp_transformations/transformations_after_split_transformation.cpp @@ -39,7 +39,6 @@ #include "low_precision/fuse_subtract_to_fake_quantize.hpp" #include "low_precision/fuse_multiply_to_fake_quantize.hpp" #include "low_precision/multiply_to_group_convolution.hpp" -#include "low_precision/subtract_multiply_to_multiply_add.hpp" #include "lpt_ngraph_functions/transformations_after_split_function.hpp" #include "common_test_utils/ngraph_test_utils.hpp" @@ -149,10 +148,6 @@ void getTransformerWithTransformationByName( transformer.add(params); return; } - if (name == "SubtractMultiplyToMultiplyAddTransformation") { - transformer.add(params); - return; - } throw std::runtime_error("unexpected transformation name"); } @@ -210,8 +205,7 @@ const std::vector transformationNames = { "FuseConvertTransformation", "FuseSubtractToFakeQuantizeTransformation", "FuseMultiplyToFakeQuantizeTransformation", - "MultiplyToGroupConvolutionTransformation", - "SubtractMultiplyToMultiplyAddTransformation", + "MultiplyToGroupConvolutionTransformation" }; INSTANTIATE_TEST_SUITE_P( diff --git a/inference-engine/tests/functional/inference_engine/transformations/mul_add_conversion_test.cpp b/inference-engine/tests/functional/inference_engine/transformations/mul_add_conversion_test.cpp index 8da572786cd..daef677eaa7 100644 --- a/inference-engine/tests/functional/inference_engine/transformations/mul_add_conversion_test.cpp +++ b/inference-engine/tests/functional/inference_engine/transformations/mul_add_conversion_test.cpp @@ -70,15 +70,9 @@ public: ngraph::Output last = input; if (!mul_const.skip) { last = std::make_shared(last, create_constant(mul_const.shape, mul_const.value)); - if (is_dequantization) { - ngraph::builder::subgraph::addDequantizationAttribute(last.get_node_shared_ptr()); - } } if (!add_const.skip) { last = std::make_shared(last, create_constant(add_const.shape, add_const.value)); - if (is_dequantization) { - ngraph::builder::subgraph::addDequantizationAttribute(last.get_node_shared_ptr()); - } } last = std::make_shared(last); return std::make_shared(ngraph::NodeVector{last.get_node_shared_ptr()}, ngraph::ParameterVector{input}); diff --git a/inference-engine/tests/functional/plugin/cpu/subgraph_tests/src/fuse_scaleshift_and_fakequantize.cpp b/inference-engine/tests/functional/plugin/cpu/subgraph_tests/src/fuse_scaleshift_and_fakequantize.cpp index b2974883220..675636f4468 100644 --- a/inference-engine/tests/functional/plugin/cpu/subgraph_tests/src/fuse_scaleshift_and_fakequantize.cpp +++ b/inference-engine/tests/functional/plugin/cpu/subgraph_tests/src/fuse_scaleshift_and_fakequantize.cpp @@ -5,7 +5,6 @@ #include "shared_test_classes/base/layer_test_utils.hpp" #include "test_utils/cpu_test_utils.hpp" #include "ngraph_functions/builders.hpp" -#include "low_precision/common/dequantization_op.hpp" using namespace ngraph; using FuncTestUtils::PrecisionUtils::convertIE2nGraphPrc; @@ -58,10 +57,10 @@ protected: const auto param = std::make_shared(inputPrecision, inputShape); Shape constShape = Shape(inputShape.size(), 1); constShape[1] = scaleShift.second.size(); - const auto subtract = std::make_shared( + const auto subtract = std::make_shared( param, std::make_shared(inputPrecision, constShape, scaleShift.second)); - const auto multiply = std::make_shared( + const auto multiply = std::make_shared( param, std::make_shared(inputPrecision, constShape, scaleShift.first)); Shape inConstShape = Shape(inputShape.size(), 1); diff --git a/inference-engine/tests/ngraph_helpers/lpt_ngraph_functions/include/lpt_ngraph_functions/common/builders.hpp b/inference-engine/tests/ngraph_helpers/lpt_ngraph_functions/include/lpt_ngraph_functions/common/builders.hpp index cda84be9b22..9d8183efc0e 100644 --- a/inference-engine/tests/ngraph_helpers/lpt_ngraph_functions/include/lpt_ngraph_functions/common/builders.hpp +++ b/inference-engine/tests/ngraph_helpers/lpt_ngraph_functions/include/lpt_ngraph_functions/common/builders.hpp @@ -10,7 +10,6 @@ #include #include "ngraph_ops/type_relaxed.hpp" -#include "low_precision/common/dequantization_op.hpp" #include "low_precision/rt_info/intervals_alignment_attribute.hpp" #include "low_precision/rt_info/quantization_alignment_attribute.hpp" #include "low_precision/network_helper.hpp" @@ -95,8 +94,6 @@ std::shared_ptr makeFakeQuantizeTypeRelaxed( const ngraph::element::Type constantPrecision, const FakeQuantizeOnDataWithConstant& fqOnData); -std::shared_ptr addDequantizationAttribute(const std::shared_ptr& op); - template void addAttribute(std::vector> nodes, Args&& ... args) { const auto attribute = std::make_shared>( diff --git a/inference-engine/tests/ngraph_helpers/lpt_ngraph_functions/include/lpt_ngraph_functions/common/dequantization_operations.hpp b/inference-engine/tests/ngraph_helpers/lpt_ngraph_functions/include/lpt_ngraph_functions/common/dequantization_operations.hpp index 79ef40d7e3d..6bcd7ef7f82 100644 --- a/inference-engine/tests/ngraph_helpers/lpt_ngraph_functions/include/lpt_ngraph_functions/common/dequantization_operations.hpp +++ b/inference-engine/tests/ngraph_helpers/lpt_ngraph_functions/include/lpt_ngraph_functions/common/dequantization_operations.hpp @@ -16,7 +16,7 @@ public: class Convert { public: Convert(); - Convert(const ngraph::element::Type outPrecision, const bool addDeqAttr = true); + Convert(const ngraph::element::Type outPrecision, const bool toRemove = true); bool empty() const noexcept; bool equal(const DequantizationOperations::Convert& value) const noexcept; bool operator==(const Convert& value) const noexcept { @@ -32,14 +32,14 @@ public: class Subtract { public: Subtract(); - Subtract(const float value, const bool addDeqAttr = true); - Subtract(const std::vector& values, const bool addDeqAttr = true); - Subtract(const std::vector& values, const ngraph::element::Type outPrecision, const bool addDeqAttr = true); + Subtract(const float value, const bool toRemove = true); + Subtract(const std::vector& values); + Subtract(const std::vector& values, const ngraph::element::Type outPrecision); Subtract( const std::vector& values, const ngraph::element::Type outPrecision, const ngraph::Shape& constantShape, - const bool addDequantizationAttribute = true, + const bool toRemove = false, const size_t constantIndex = 1ul, const ngraph::element::Type constantPrecision = ngraph::element::undefined, const bool addConvert = false, @@ -59,7 +59,6 @@ public: ngraph::element::Type outPrecision = ngraph::element::undefined; ngraph::Shape constantShape; bool constantShapeIsDefined = false; - bool addDequantizationAttribute = true; size_t constantIndex = 1ul; ngraph::element::Type constantPrecision = ngraph::element::undefined; bool addConvert = false; @@ -80,7 +79,7 @@ public: const std::vector& values, const ngraph::element::Type outPrecision, const ngraph::Shape& constantShape, - const bool addDequantizationAttribute = true, + const bool toRemove = false, const size_t constantIndex = 1ul, const ngraph::element::Type constantPrecision = ngraph::element::undefined); bool empty() const noexcept; @@ -94,7 +93,6 @@ public: ngraph::element::Type outPrecision = ngraph::element::undefined; ngraph::Shape constantShape; bool constantShapeIsDefined = false; - bool addDequantizationAttribute = true; size_t constantIndex = 1ul; ngraph::element::Type constantPrecision = ngraph::element::undefined; @@ -128,7 +126,6 @@ inline std::ostream& operator<<(std::ostream& out, const DequantizationOperation subtract.outPrecision << "_" << subtract.constantShape << "_" << subtract.constantShapeIsDefined << "_" << - subtract.addDequantizationAttribute << "_" << subtract.constantIndex << "_" << subtract.constantPrecision << "_" << subtract.addConvert; @@ -140,7 +137,6 @@ inline std::ostream& operator<<(std::ostream& out, const DequantizationOperation multiply.outPrecision << "_" << multiply.constantShape << "_" << multiply.constantShapeIsDefined << "_" << - multiply.addDequantizationAttribute << "_" << multiply.constantIndex << "_" << multiply.constantPrecision; } diff --git a/inference-engine/tests/ngraph_helpers/lpt_ngraph_functions/src/add_function.cpp b/inference-engine/tests/ngraph_helpers/lpt_ngraph_functions/src/add_function.cpp index 77c1bcac6fe..430b34f35df 100644 --- a/inference-engine/tests/ngraph_helpers/lpt_ngraph_functions/src/add_function.cpp +++ b/inference-engine/tests/ngraph_helpers/lpt_ngraph_functions/src/add_function.cpp @@ -300,7 +300,7 @@ std::shared_ptr AddFunction::getReference( std::vector{ element::f32 }, ngraph::op::TemporaryReplaceOutputType(dequantizationOp1, element::f32).get(), ngraph::op::TemporaryReplaceOutputType(dequantizationOp2, element::f32).get())) : - std::make_shared>( + std::make_shared>( std::vector{ element::f32, element::f32 }, std::vector{ element::f32 }, ngraph::op::TemporaryReplaceOutputType(dequantizationOp1, element::f32).get(), diff --git a/inference-engine/tests/ngraph_helpers/lpt_ngraph_functions/src/common/builders.cpp b/inference-engine/tests/ngraph_helpers/lpt_ngraph_functions/src/common/builders.cpp index cf2e6a4d517..b1c9395ce95 100644 --- a/inference-engine/tests/ngraph_helpers/lpt_ngraph_functions/src/common/builders.cpp +++ b/inference-engine/tests/ngraph_helpers/lpt_ngraph_functions/src/common/builders.cpp @@ -16,7 +16,7 @@ namespace ngraph { namespace builder { namespace subgraph { - using namespace ngraph::pass::low_precision; +using namespace ngraph::pass::low_precision; std::shared_ptr makeDequantization( const Output& data, @@ -24,9 +24,7 @@ std::shared_ptr makeDequantization( Output parent = data; if (!dequantizationOperations.convert.empty()) { - std::shared_ptr convert = dequantizationOperations.convert.addDequantizationAttribute ? - std::make_shared(data, dequantizationOperations.convert.outPrecision) : - std::make_shared(data, dequantizationOperations.convert.outPrecision); + auto convert = std::make_shared(data, dequantizationOperations.convert.outPrecision); NetworkHelper::copyInfo({ data.get_node_shared_ptr(), convert }, convert); convert->set_friendly_name(data.get_node_shared_ptr()->get_friendly_name() + "/DequantizationConvert"); parent = convert; @@ -80,53 +78,28 @@ std::shared_ptr makeDequantization( (((dequantizationOperations.subtract.constantPrecision == element::undefined) || (dequantizationOperations.subtract.constantPrecision == parent.get_element_type())) || dequantizationOperations.subtract.addConvert)) { - if (dequantizationOperations.subtract.constantIndex == 1ul) { - subtract = dequantizationOperations.subtract.addDequantizationAttribute ? - std::make_shared(parent, subtractConst) : - std::make_shared(parent, subtractConst); - } else { - subtract = dequantizationOperations.subtract.addDequantizationAttribute ? - std::make_shared(subtractConst, parent) : - std::make_shared(subtractConst, parent); - } + subtract = dequantizationOperations.subtract.constantIndex == 1ul ? + std::make_shared(parent, subtractConst) : + subtract = std::make_shared(subtractConst, parent); } else { - // TODO: use templates - if (dequantizationOperations.subtract.addDequantizationAttribute) { - if (dequantizationOperations.subtract.constantIndex == 1ul) { - subtract = std::make_shared>( - std::vector{element::f32, element::f32}, - std::vector{ element::f32 }, - ngraph::op::TemporaryReplaceOutputType(parent, element::f32).get(), - ngraph::op::TemporaryReplaceOutputType(subtractConst, element::f32).get()); - } else { - subtract = std::make_shared>( - std::vector{element::f32, element::f32}, - std::vector{ element::f32 }, - ngraph::op::TemporaryReplaceOutputType(subtractConst, element::f32).get(), - ngraph::op::TemporaryReplaceOutputType(parent, element::f32).get()); - } + if (dequantizationOperations.subtract.constantIndex == 1ul) { + subtract = std::make_shared>( + std::vector{element::f32, element::f32}, + std::vector{ element::f32 }, + ngraph::op::TemporaryReplaceOutputType(parent, element::f32).get(), + ngraph::op::TemporaryReplaceOutputType(subtractConst, element::f32).get()); } else { - if (dequantizationOperations.subtract.constantIndex == 1ul) { - subtract = std::make_shared>( - std::vector{element::f32, element::f32}, - std::vector{ element::f32 }, - ngraph::op::TemporaryReplaceOutputType(parent, element::f32).get(), - ngraph::op::TemporaryReplaceOutputType(subtractConst, element::f32).get()); - } else { - subtract = std::make_shared>( - std::vector{element::f32, element::f32}, - std::vector{ element::f32 }, - ngraph::op::TemporaryReplaceOutputType(subtractConst, element::f32).get(), - ngraph::op::TemporaryReplaceOutputType(parent, element::f32).get()); - } + subtract = std::make_shared>( + std::vector{element::f32, element::f32}, + std::vector{ element::f32 }, + ngraph::op::TemporaryReplaceOutputType(subtractConst, element::f32).get(), + ngraph::op::TemporaryReplaceOutputType(parent, element::f32).get()); } subtract->set_friendly_name(data.get_node_shared_ptr()->get_friendly_name() + "/DequantizationSubtract"); ngraph::pass::low_precision::NetworkHelper::setOutDataPrecision(subtract, dequantizationOperations.subtract.outPrecision); } - if (!dequantizationOperations.subtract.addDequantizationAttribute) { - ngraph::pass::low_precision::NetworkHelper::cleanRunTimeInfo(subtract); - } + NetworkHelper::copyInfo({ data.get_node_shared_ptr(), subtract }, subtract); if (!dequantizationOperations.subtract.attributes.empty()) { @@ -179,15 +152,9 @@ std::shared_ptr makeMultiply(const Output& parent, const Dequantizat shape, values); - if (multiply.addDequantizationAttribute) { - newMultiply = multiply.constantIndex == 1ul ? - std::make_shared(parent, constant) : - std::make_shared(constant, parent); - } else { - newMultiply = multiply.constantIndex == 1ul ? - std::make_shared(parent, constant) : - std::make_shared(constant, parent); - } + newMultiply = multiply.constantIndex == 1ul ? + std::make_shared(parent, constant) : + std::make_shared(constant, parent); } else { const std::shared_ptr constant = std::make_shared( multiply.constantPrecision != element::undefined ? @@ -197,31 +164,17 @@ std::shared_ptr makeMultiply(const Output& parent, const Dequantizat values); // TODO: use templates - if (multiply.addDequantizationAttribute) { - newMultiply = multiply.constantIndex == 1ul ? - std::make_shared>( - std::vector{element::f32, element::f32}, - std::vector{ multiply.outPrecision }, - ngraph::op::TemporaryReplaceOutputType(parent, element::f32).get(), - ngraph::op::TemporaryReplaceOutputType(constant, element::f32).get()) : - std::make_shared>( - std::vector{element::f32, element::f32}, - std::vector{ multiply.outPrecision }, - ngraph::op::TemporaryReplaceOutputType(constant, element::f32).get(), - ngraph::op::TemporaryReplaceOutputType(parent, element::f32).get()); - } else { - newMultiply = multiply.constantIndex == 1ul ? - std::make_shared>( - std::vector{element::f32, element::f32}, - std::vector{ multiply.outPrecision }, - ngraph::op::TemporaryReplaceOutputType(parent, element::f32).get(), - ngraph::op::TemporaryReplaceOutputType(constant, element::f32).get()) : - std::make_shared>( - std::vector{element::f32, element::f32}, - std::vector{ multiply.outPrecision }, - ngraph::op::TemporaryReplaceOutputType(constant, element::f32).get(), - ngraph::op::TemporaryReplaceOutputType(parent, element::f32).get()); - } + newMultiply = multiply.constantIndex == 1ul ? + std::make_shared>( + std::vector{element::f32, element::f32}, + std::vector{ multiply.outPrecision }, + ngraph::op::TemporaryReplaceOutputType(parent, element::f32).get(), + ngraph::op::TemporaryReplaceOutputType(constant, element::f32).get()) : + std::make_shared>( + std::vector{element::f32, element::f32}, + std::vector{ multiply.outPrecision }, + ngraph::op::TemporaryReplaceOutputType(constant, element::f32).get(), + ngraph::op::TemporaryReplaceOutputType(parent, element::f32).get()); } return newMultiply; @@ -345,12 +298,6 @@ std::shared_ptr makeFakeQuantizeTypeRelaxed( fqOnData.outputPrecision == ngraph::element::undefined ? constantPrecision : fqOnData.outputPrecision); } -std::shared_ptr addDequantizationAttribute(const std::shared_ptr& op) { - auto& rtInfo = op->get_rt_info(); - rtInfo["DEQUANTIZATION"] = std::make_shared>(DequantizationAttr()); - return op; -} - void addAttributes(std::vector> nodes, std::vector> attributes) { for (const auto& node : nodes) { for (const auto& attribute : attributes) { diff --git a/inference-engine/tests/ngraph_helpers/lpt_ngraph_functions/src/common/dequantization_operations.cpp b/inference-engine/tests/ngraph_helpers/lpt_ngraph_functions/src/common/dequantization_operations.cpp index e5da339d912..474476b500e 100644 --- a/inference-engine/tests/ngraph_helpers/lpt_ngraph_functions/src/common/dequantization_operations.cpp +++ b/inference-engine/tests/ngraph_helpers/lpt_ngraph_functions/src/common/dequantization_operations.cpp @@ -14,10 +14,9 @@ DequantizationOperations::Convert::Convert() : outPrecision(ngraph::element::undefined) {} -DequantizationOperations::Convert::Convert(const ngraph::element::Type outPrecision, const bool addDeqAttr) : +DequantizationOperations::Convert::Convert(const ngraph::element::Type outPrecision, const bool toRemove) : isEmpty(false), - outPrecision(outPrecision), - addDequantizationAttribute(addDeqAttr) + outPrecision(outPrecision) {} bool DequantizationOperations::Convert::empty() const noexcept { @@ -34,37 +33,34 @@ DequantizationOperations::Subtract::Subtract() : constantShapeIsDefined(false) {} -DequantizationOperations::Subtract::Subtract(const float value, const bool addDeqAttr) : +DequantizationOperations::Subtract::Subtract(const float value, const bool toRemove) : isEmpty(false), values({ value }), outPrecision(ngraph::element::undefined), - constantShapeIsDefined(false), - addDequantizationAttribute(addDeqAttr) { + constantShapeIsDefined(false) { } -DequantizationOperations::Subtract::Subtract(const std::vector& values, const bool addDeqAttr) : +DequantizationOperations::Subtract::Subtract(const std::vector& values) : isEmpty(values.empty()), values(values), outPrecision(ngraph::element::undefined), - constantShapeIsDefined(false), - addDequantizationAttribute(addDeqAttr) { + constantShapeIsDefined(false) { } -DequantizationOperations::Subtract::Subtract(const std::vector& values, - const ngraph::element::Type outPrecision, - const bool addDeqAttr) : +DequantizationOperations::Subtract::Subtract( + const std::vector& values, + const ngraph::element::Type outPrecision) : isEmpty(false), values(values), outPrecision(outPrecision), - constantShapeIsDefined(false), - addDequantizationAttribute(addDeqAttr) { + constantShapeIsDefined(false) { } DequantizationOperations::Subtract::Subtract( const std::vector& values, const ngraph::element::Type outPrecision, const ngraph::Shape& constantShape, - const bool addDequantizationAttribute, + const bool toRemove, const size_t constantIndex, const ngraph::element::Type constantPrecision, const bool addConvert, @@ -75,7 +71,6 @@ DequantizationOperations::Subtract::Subtract( outPrecision(outPrecision), constantShape(constantShape), constantShapeIsDefined(true), - addDequantizationAttribute(addDequantizationAttribute), constantIndex(constantIndex), constantPrecision(constantPrecision), addConvert(addConvert), @@ -93,7 +88,6 @@ bool DequantizationOperations::Subtract::equal(const DequantizationOperations::S (outPrecision == value.outPrecision) && (constantShape == value.constantShape) && (constantShapeIsDefined == value.constantShapeIsDefined) && - (addDequantizationAttribute == value.addDequantizationAttribute) && (constantIndex == value.constantIndex); } @@ -133,14 +127,13 @@ DequantizationOperations::Multiply::Multiply( const std::vector& values, const ngraph::element::Type outPrecision, const ngraph::Shape& constantShape, - const bool addDequantizationAttribute, + const bool toRemove, const size_t constantIndex, ngraph::element::Type constantPrecision) : isEmpty(false), values(values), outPrecision(outPrecision), constantShape(constantShape), - addDequantizationAttribute(addDequantizationAttribute), constantIndex(constantIndex), constantPrecision(constantPrecision), constantShapeIsDefined(true) { @@ -155,7 +148,6 @@ bool DequantizationOperations::Multiply::equal(const DequantizationOperations::M (values == value.values) && (outPrecision == value.outPrecision) && (constantShape == value.constantShape) && - (addDequantizationAttribute == value.addDequantizationAttribute) && (constantIndex == value.constantIndex) && (constantPrecision == value.constantPrecision) && (constantShapeIsDefined == value.constantShapeIsDefined); diff --git a/inference-engine/tests/ngraph_helpers/lpt_ngraph_functions/src/convert_mul_or_add_finally_with_dequantization_function.cpp b/inference-engine/tests/ngraph_helpers/lpt_ngraph_functions/src/convert_mul_or_add_finally_with_dequantization_function.cpp index 648837f703f..f51053d4ab6 100644 --- a/inference-engine/tests/ngraph_helpers/lpt_ngraph_functions/src/convert_mul_or_add_finally_with_dequantization_function.cpp +++ b/inference-engine/tests/ngraph_helpers/lpt_ngraph_functions/src/convert_mul_or_add_finally_with_dequantization_function.cpp @@ -14,7 +14,6 @@ #include "lpt_ngraph_functions/common/builders.hpp" #include "low_precision/network_helper.hpp" #include -#include "low_precision/common/dequantization_op.hpp" namespace ngraph { namespace builder { @@ -36,8 +35,9 @@ std::shared_ptr ConvertMulOrAddWithDequantizationFunction::get std::vector{}); - const auto multiply = std::make_shared(relu, - std::make_shared(element::f32, inputShape, multiplyConst)); + const auto multiply = std::make_shared( + relu, + std::make_shared(element::f32, inputShape, multiplyConst)); multiply->set_friendly_name("output"); @@ -62,7 +62,6 @@ std::shared_ptr ConvertMulOrAddWithDequantizationFunction::get const auto weights = std::make_shared(element::f32, inputShape, multiplyConst); const auto bias = std::make_shared(element::f32, inputShape, 0.0); std::shared_ptr scaleShift = std::make_shared(relu, weights, bias); - addDequantizationAttribute(scaleShift); scaleShift->set_friendly_name("output"); diff --git a/inference-engine/tests/ngraph_helpers/lpt_ngraph_functions/src/convolution_backprop_data_function.cpp b/inference-engine/tests/ngraph_helpers/lpt_ngraph_functions/src/convolution_backprop_data_function.cpp index b7462c602b6..c609062aae8 100644 --- a/inference-engine/tests/ngraph_helpers/lpt_ngraph_functions/src/convolution_backprop_data_function.cpp +++ b/inference-engine/tests/ngraph_helpers/lpt_ngraph_functions/src/convolution_backprop_data_function.cpp @@ -13,7 +13,6 @@ #include "lpt_ngraph_functions/common/fake_quantize_on_data.hpp" #include "lpt_ngraph_functions/common/dequantization_operations.hpp" #include "lpt_ngraph_functions/common/builders.hpp" -#include "low_precision/common/dequantization_op.hpp" #include "low_precision/network_helper.hpp" using namespace ngraph::pass::low_precision; diff --git a/inference-engine/tests/ngraph_helpers/lpt_ngraph_functions/src/convolution_function.cpp b/inference-engine/tests/ngraph_helpers/lpt_ngraph_functions/src/convolution_function.cpp index 5c512508455..1d2dc22bb86 100644 --- a/inference-engine/tests/ngraph_helpers/lpt_ngraph_functions/src/convolution_function.cpp +++ b/inference-engine/tests/ngraph_helpers/lpt_ngraph_functions/src/convolution_function.cpp @@ -13,7 +13,6 @@ #include "lpt_ngraph_functions/common/fake_quantize_on_data.hpp" #include "lpt_ngraph_functions/common/dequantization_operations.hpp" #include "lpt_ngraph_functions/common/builders.hpp" -#include "low_precision/common/dequantization_op.hpp" #include "low_precision/network_helper.hpp" using namespace ngraph::pass::low_precision; @@ -106,7 +105,7 @@ std::shared_ptr ConvolutionFunction::getOriginalWithIncorrectW fakeQuantizeOnWeights.inputLowValues, fakeQuantizeOnWeights.inputHighValues, fakeQuantizeOnWeights.outputLowValues, fakeQuantizeOnWeights.outputHighValues); - const auto subtract = isCorrect ? nullptr : std::make_shared(fqOnWeights, + const auto subtract = isCorrect ? nullptr : std::make_shared(fqOnWeights, std::make_shared(ngraph::element::f32, Shape{1, 1, 1, 1}, 3.0f)); const auto convolution = std::make_shared( @@ -148,7 +147,7 @@ std::shared_ptr ConvolutionFunction::getOriginalWithIncorrectW fakeQuantizeOnWeights.inputLowValues, fakeQuantizeOnWeights.inputHighValues, fakeQuantizeOnWeights.outputLowValues, fakeQuantizeOnWeights.outputHighValues); - const auto subtract = isCorrect ? nullptr : std::make_shared(fqOnWeights, + const auto subtract = isCorrect ? nullptr : std::make_shared(fqOnWeights, std::make_shared(precision, Shape{ 1, 1, 1, 1 }, 3.0f)); const auto convolution = std::make_shared( diff --git a/inference-engine/tests/ngraph_helpers/lpt_ngraph_functions/src/elementwise_with_multi_parent_dequantization_function.cpp b/inference-engine/tests/ngraph_helpers/lpt_ngraph_functions/src/elementwise_with_multi_parent_dequantization_function.cpp index 3ad0d8cb9e2..5479e585f27 100644 --- a/inference-engine/tests/ngraph_helpers/lpt_ngraph_functions/src/elementwise_with_multi_parent_dequantization_function.cpp +++ b/inference-engine/tests/ngraph_helpers/lpt_ngraph_functions/src/elementwise_with_multi_parent_dequantization_function.cpp @@ -26,7 +26,7 @@ std::shared_ptr ElementwiseWithMultiParentDequantizationFuncti const auto input1_1 = std::make_shared(precision1, inputShape); const auto input1_2 = std::make_shared(precision1, ngraph::Shape({ inputShape[0], inputShape[1], 1, 1 })); const std::shared_ptr multiply1 = std::make_shared>( - DequantizationMultiply( + opset1::Multiply( ngraph::op::TemporaryReplaceOutputType(input1_1, element::f32).get(), ngraph::op::TemporaryReplaceOutputType(input1_2, element::f32).get()), std::vector{element::f32, element::f32}, @@ -37,7 +37,7 @@ std::shared_ptr ElementwiseWithMultiParentDequantizationFuncti const auto input2_1 = std::make_shared(precision1, inputShape); const auto input2_2 = std::make_shared(precision1, ngraph::Shape({ inputShape[0], inputShape[1], 1, 1 })); const std::shared_ptr multiply2 = std::make_shared>( - DequantizationMultiply( + opset1::Multiply( ngraph::op::TemporaryReplaceOutputType(input2_1, element::f32).get(), ngraph::op::TemporaryReplaceOutputType(input2_2, element::f32).get()), std::vector{element::f32, element::f32}, diff --git a/inference-engine/tests/ngraph_helpers/lpt_ngraph_functions/src/fake_quantize_function.cpp b/inference-engine/tests/ngraph_helpers/lpt_ngraph_functions/src/fake_quantize_function.cpp index 4ec0851d800..a0441772afb 100644 --- a/inference-engine/tests/ngraph_helpers/lpt_ngraph_functions/src/fake_quantize_function.cpp +++ b/inference-engine/tests/ngraph_helpers/lpt_ngraph_functions/src/fake_quantize_function.cpp @@ -7,7 +7,6 @@ #include #include "ngraph_ops/type_relaxed.hpp" #include "ngraph_functions/subgraph_builders.hpp" -#include "low_precision/common/dequantization_op.hpp" #include "low_precision/network_helper.hpp" #include "lpt_ngraph_functions/common/builders.hpp" diff --git a/inference-engine/tests/ngraph_helpers/lpt_ngraph_functions/src/group_convolution_function.cpp b/inference-engine/tests/ngraph_helpers/lpt_ngraph_functions/src/group_convolution_function.cpp index f9bc892c8d0..fb6f82696cb 100644 --- a/inference-engine/tests/ngraph_helpers/lpt_ngraph_functions/src/group_convolution_function.cpp +++ b/inference-engine/tests/ngraph_helpers/lpt_ngraph_functions/src/group_convolution_function.cpp @@ -13,7 +13,6 @@ #include "lpt_ngraph_functions/common/fake_quantize_on_data.hpp" #include "lpt_ngraph_functions/common/dequantization_operations.hpp" #include "lpt_ngraph_functions/common/builders.hpp" -#include "low_precision/common/dequantization_op.hpp" using namespace ngraph::opset1; using namespace ngraph::pass::low_precision; diff --git a/inference-engine/tests/ngraph_helpers/lpt_ngraph_functions/src/mul_add_to_scaleshift_or_power_function.cpp b/inference-engine/tests/ngraph_helpers/lpt_ngraph_functions/src/mul_add_to_scaleshift_or_power_function.cpp index 52946be7c46..eaa31273f12 100644 --- a/inference-engine/tests/ngraph_helpers/lpt_ngraph_functions/src/mul_add_to_scaleshift_or_power_function.cpp +++ b/inference-engine/tests/ngraph_helpers/lpt_ngraph_functions/src/mul_add_to_scaleshift_or_power_function.cpp @@ -7,7 +7,6 @@ #include #include "ngraph_ops/type_relaxed.hpp" #include "low_precision/network_helper.hpp" -#include "low_precision/common/dequantization_op.hpp" #include #include @@ -28,20 +27,15 @@ namespace subgraph { const auto input = std::make_shared(precision, inputShape); const auto mulConst = ngraph::op::Constant::create(ngraph::element::f32, mulValues.constantShape, mulValues.values); - const auto mul = std::make_shared>( + const auto mul = std::make_shared>( std::vector{element::f32, element::f32}, std::vector{ element::f32 }, ngraph::op::TemporaryReplaceOutputType(input, element::f32).get(), ngraph::op::TemporaryReplaceOutputType(mulConst, element::f32).get()); const auto addConst = ngraph::op::Constant::create(ngraph::element::f32, addValues.constantShape, addValues.values); - const auto add = std::make_shared(mul, addConst); + const auto add = std::make_shared(mul, addConst); add->set_friendly_name("add"); - if (!isDequantization) { - ngraph::pass::low_precision::NetworkHelper::cleanRunTimeInfo(mul); - ngraph::pass::low_precision::NetworkHelper::cleanRunTimeInfo(add); - } - ngraph::ResultVector results{ std::make_shared(add) }; return std::make_shared(results, ngraph::ParameterVector{ input }, "MulAddToScaleshiftOrPowerFunction"); } @@ -62,7 +56,6 @@ namespace subgraph { std::shared_ptr lastNode; if (isDequantization) { std::shared_ptr scaleshift = std::make_shared(input, weights, biases, precisionAfterOperation); - addDequantizationAttribute(scaleshift); scaleshift->set_friendly_name("add"); lastNode = scaleshift; } else { diff --git a/inference-engine/tests/ngraph_helpers/lpt_ngraph_functions/src/multiply_function.cpp b/inference-engine/tests/ngraph_helpers/lpt_ngraph_functions/src/multiply_function.cpp index 1d36d0f8e35..7d15347dd01 100644 --- a/inference-engine/tests/ngraph_helpers/lpt_ngraph_functions/src/multiply_function.cpp +++ b/inference-engine/tests/ngraph_helpers/lpt_ngraph_functions/src/multiply_function.cpp @@ -7,7 +7,6 @@ #include #include #include "ngraph_functions/subgraph_builders.hpp" -#include "low_precision/common/dequantization_op.hpp" #include "low_precision/network_helper.hpp" #include "lpt_ngraph_functions/common/builders.hpp" @@ -63,13 +62,9 @@ std::shared_ptr MultiplyFunction::get( const BranchNodes branchNodes1 = getBranch(actualValues.branch1); const BranchNodes branchNodes2 = getBranch(actualValues.branch2); - auto multiplyOriginal = actualValues.isDequantization ? - DequantizationMultiply( - ngraph::op::TemporaryReplaceOutputType(branchNodes1.dequantization, element::f32).get(), - ngraph::op::TemporaryReplaceOutputType(branchNodes2.dequantization, element::f32).get()) : - ngraph::opset1::Multiply( - ngraph::op::TemporaryReplaceOutputType(branchNodes1.dequantization, element::f32).get(), - ngraph::op::TemporaryReplaceOutputType(branchNodes2.dequantization, element::f32).get()); + auto multiplyOriginal = opset1::Multiply( + ngraph::op::TemporaryReplaceOutputType(branchNodes1.dequantization, element::f32).get(), + ngraph::op::TemporaryReplaceOutputType(branchNodes2.dequantization, element::f32).get()); const std::shared_ptr multiply = std::make_shared>( multiplyOriginal, diff --git a/inference-engine/tests/ngraph_helpers/lpt_ngraph_functions/src/normalize_l2_function.cpp b/inference-engine/tests/ngraph_helpers/lpt_ngraph_functions/src/normalize_l2_function.cpp index 693a042115d..699e8ccb08e 100644 --- a/inference-engine/tests/ngraph_helpers/lpt_ngraph_functions/src/normalize_l2_function.cpp +++ b/inference-engine/tests/ngraph_helpers/lpt_ngraph_functions/src/normalize_l2_function.cpp @@ -7,7 +7,6 @@ #include #include #include "ngraph_functions/subgraph_builders.hpp" -#include "low_precision/common/dequantization_op.hpp" #include "lpt_ngraph_functions/common/builders.hpp" namespace ngraph { diff --git a/inference-engine/tests/ngraph_helpers/lpt_ngraph_functions/src/precision_propagation_function.cpp b/inference-engine/tests/ngraph_helpers/lpt_ngraph_functions/src/precision_propagation_function.cpp index 212e781127b..1f1f9c66993 100644 --- a/inference-engine/tests/ngraph_helpers/lpt_ngraph_functions/src/precision_propagation_function.cpp +++ b/inference-engine/tests/ngraph_helpers/lpt_ngraph_functions/src/precision_propagation_function.cpp @@ -238,7 +238,7 @@ std::shared_ptr PrecisionPropagationFunction::getReferenceWith shape, std::vector(ngraph::shape_size(shape), 128.f)); - auto subtract = std::make_shared>( + auto subtract = std::make_shared>( std::vector{element::f32, element::f32}, std::vector{ element::f32 }, ngraph::op::TemporaryReplaceOutputType(result2, element::f32).get(), diff --git a/inference-engine/tests/ngraph_helpers/lpt_ngraph_functions/src/reshape_fully_connected_function.cpp b/inference-engine/tests/ngraph_helpers/lpt_ngraph_functions/src/reshape_fully_connected_function.cpp index d06f1d05496..51687b75c09 100644 --- a/inference-engine/tests/ngraph_helpers/lpt_ngraph_functions/src/reshape_fully_connected_function.cpp +++ b/inference-engine/tests/ngraph_helpers/lpt_ngraph_functions/src/reshape_fully_connected_function.cpp @@ -14,7 +14,6 @@ #include "ngraph_functions/subgraph_builders.hpp" #include "lpt_ngraph_functions/common/builders.hpp" #include "low_precision/network_helper.hpp" -#include "low_precision/common/dequantization_op.hpp" namespace ngraph { namespace builder { diff --git a/inference-engine/tests/ngraph_helpers/lpt_ngraph_functions/src/subtract_multiply_to_multiply_add_function.cpp b/inference-engine/tests/ngraph_helpers/lpt_ngraph_functions/src/subtract_multiply_to_multiply_add_function.cpp index d34ed6198fb..03e10be6c83 100644 --- a/inference-engine/tests/ngraph_helpers/lpt_ngraph_functions/src/subtract_multiply_to_multiply_add_function.cpp +++ b/inference-engine/tests/ngraph_helpers/lpt_ngraph_functions/src/subtract_multiply_to_multiply_add_function.cpp @@ -7,7 +7,6 @@ #include #include #include "lpt_ngraph_functions/common/builders.hpp" -#include "low_precision/common/dequantization_op.hpp" using namespace ngraph::pass::low_precision; @@ -66,11 +65,11 @@ std::shared_ptr SubtractMultiplyToMultiplyAddFunction::getRefe std::shared_ptr parent = dequantizationOp; if (!multiply.empty()) { - parent = makeElementwise(parent, multiply); + parent = makeElementwise(parent, multiply); } if (!add.empty()) { - parent = makeElementwise(parent, add); + parent = makeElementwise(parent, add); } parent->set_friendly_name("output"); diff --git a/inference-engine/tests/unit/inference_engine/ie_compilation_context_test.cpp b/inference-engine/tests/unit/inference_engine/ie_compilation_context_test.cpp index a52ce386a7a..ab84e162f14 100644 --- a/inference-engine/tests/unit/inference_engine/ie_compilation_context_test.cpp +++ b/inference-engine/tests/unit/inference_engine/ie_compilation_context_test.cpp @@ -13,7 +13,6 @@ #include "ngraph/ops.hpp" #include "ngraph/variant.hpp" #include "ngraph/opsets/opset6.hpp" -#include "transformations/rt_info/dequantization_attribute.hpp" #include "transformations/rt_info/fused_names_attribute.hpp" #include "transformations/rt_info/primitives_priority_attribute.hpp" #include "cpp/ie_cnn_network.h" @@ -219,18 +218,6 @@ TEST(NetworkContext_CNNNetwork, HashWithPrimitivesPriority) { NetworkCompilationContext::computeHash(net3, {})); } -TEST(NetworkContext_CNNNetwork, HashWithDequantization) { - auto setDeqEmpty = [&](Node::RTMap& rtInfo) { - rtInfo[VariantWrapper::type_info.name] = - std::make_shared>(DequantizationAttr()); - }; - auto setDeq = [&](Node::RTMap& rtInfo, const std::string& name) { - rtInfo[VariantWrapper::type_info.name] = - std::make_shared>(DequantizationAttr(name)); - }; - checkCustomRt(setDeqEmpty, setDeq); -} - TEST(NetworkContext_CNNNetwork, HashWithFusedNames) { auto setFusedEmpty = [&](Node::RTMap& rtInfo) { rtInfo[VariantWrapper::type_info.name] = From 26eea3d9b919dac8618d5fac94f1d10130b44205 Mon Sep 17 00:00:00 2001 From: Ilya Churaev Date: Wed, 1 Sep 2021 10:58:51 +0300 Subject: [PATCH 66/76] Removed template functions from legacy headers (#7280) --- ngraph/core/include/ngraph/enum_names.hpp | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/ngraph/core/include/ngraph/enum_names.hpp b/ngraph/core/include/ngraph/enum_names.hpp index 91b95745cd0..50b8cb05ab6 100644 --- a/ngraph/core/include/ngraph/enum_names.hpp +++ b/ngraph/core/include/ngraph/enum_names.hpp @@ -8,16 +8,7 @@ #include "openvino/core/enum_names.hpp" namespace ngraph { +using ov::as_enum; +using ov::as_string; using ov::EnumNames; -/// Returns the enum value matching the string -template -typename std::enable_if::value, Type>::type as_enum(const Value& value) { - return ov::as_enum(value); -} - -/// Returns the string matching the enum value -template -const std::string& as_string(Value value) { - return ov::as_string(value); -} } // namespace ngraph From bfae017cf21539fbffbd836c77f55c652c691b12 Mon Sep 17 00:00:00 2001 From: Sergey Lyalin Date: Wed, 1 Sep 2021 10:59:42 +0300 Subject: [PATCH 67/76] Dynamic plugin reshape blob (#6969) * Added nGraph as a public dependency * Fixed Windows warning * Fixed CMake * Fixed constant op * Fixed typo * Added reshape to PartialShape to CNNNetwork * Added SetShape to InferRequest * Enable support of DynamicShape in IE Data * Add support of dynamic shapes to template plugin * Fixed build * Enable support dynamic rank * Fixed test for dynamic rank * Fixed some tests * Fix preprocess tests * Fixed SetBlob * Fixed code style * Add more tests * Fixed accuracy tests * Fixed documentation * Added tests for custom operation * Added new tests * WIP: move setShape from infer request to Blob * Returned isApplicable check back * Removed obsolete tests for InferRequest::SetShape and add new test for Blob::setShape (a trivial one) * Fixed artifacts * Break code style * Revert "Break code style" This reverts commit 71ee638cd0244f8f4e9d26f81b5ca206be8c010a. * Added -j8 for fix_all * Applied code style fixes * Adde doxygen items * Fixed style * Applied codestyle patch * Reverted unrelevant commit with template extension * Fixed cmake file for shared func tests (pick from master) * Revert all changes in template_extension * Deleted some old stuff that commented and won't be used * Fixed wrong exception throwing * Code style fix * Fixed preprocessing part * Fixed incorrect blob reshape in GetBlob * Deleted incorrect assert in GAPI that prevents passing some tests in Debug * Fixed issues identified during review * Removed SetShape, replace getLayoutByDims by getLayoutByRank and removed problematic modification from IE preprocessing * Fixed comments * Removed obsolete setShape * [VPU] Fixed allocating dynamic blobs in myriad_infer_request * Fixed comments * Fixed CNNNgraphImpl and comments Co-authored-by: Ilya Churaev Co-authored-by: Polina --- .../src/template_infer_request.cpp | 252 ++++++- .../src/template_infer_request.hpp | 5 +- .../behavior/infer_request_dynamic.cpp | 30 + .../include/ie/cpp/ie_cnn_network.h | 12 + .../src/inference_engine/include/ie/ie_blob.h | 33 + .../src/inference_engine/include/ie/ie_data.h | 39 ++ .../include/ie/ie_icnn_network.hpp | 16 + .../include/ie/ie_input_info.hpp | 11 + .../src/cnn_network_ngraph_impl.cpp | 50 +- .../src/cnn_network_ngraph_impl.hpp | 2 + .../src/cpp/ie_cnn_network.cpp | 8 + .../interface/ie_iinfer_request_internal.cpp | 28 +- .../src/inference_engine/src/ie_data.cpp | 52 +- .../ie_preprocess_gapi_kernels_simd_impl.hpp | 1 - .../myriad_plugin/myriad_infer_request.cpp | 2 +- .../inference_engine/ngraph_reshape_tests.cpp | 118 +++- .../shared/include/behavior/infer_request.hpp | 656 ++++++++++++++++++ .../behavior/infer_request_dynamic.hpp | 320 +++++++++ .../ngraph_functions/subgraph_builders.hpp | 1 + .../unit/inference_engine/ie_blob_test.cpp | 17 + ngraph/core/src/node.cpp | 6 +- .../runtime/interpreter/int_executable.cpp | 44 +- 22 files changed, 1625 insertions(+), 78 deletions(-) create mode 100644 docs/template_plugin/tests/functional/shared_tests_instances/behavior/infer_request_dynamic.cpp create mode 100644 inference-engine/tests/functional/plugin/shared/include/behavior/infer_request.hpp create mode 100644 inference-engine/tests/functional/plugin/shared/include/behavior/infer_request_dynamic.hpp diff --git a/docs/template_plugin/src/template_infer_request.cpp b/docs/template_plugin/src/template_infer_request.cpp index 2f9d0446ca1..94d5620001d 100644 --- a/docs/template_plugin/src/template_infer_request.cpp +++ b/docs/template_plugin/src/template_infer_request.cpp @@ -4,6 +4,9 @@ #include "template_infer_request.hpp" +#include +#include + #include #include #include @@ -45,8 +48,6 @@ TemplateInferRequest::TemplateInferRequest(const InferenceEngine::InputsDataMap& }; _executable = _executableNetwork->_plugin->_backend->compile(_executableNetwork->_function); - _parameters = _executableNetwork->_function->get_parameters(); - _results = _executableNetwork->_function->get_results(); allocateDeviceBuffers(); allocateBlobs(); @@ -65,35 +66,51 @@ void TemplateInferRequest::allocateDeviceBuffers() { _outputTensors.resize(_networkOutputs.size()); } +template +static void AllocateImplSingle(BlobMap& blobMap, + BlobMap& networkBlobMap, + const BlobData& blobData, + GetNetworkPrecisionF&& GetNetworkPrecision, + const SizeVector& dims) { + const auto& precision = blobData.second->getTensorDesc().getPrecision(); + auto layout = blobData.second->getTensorDesc().getLayout(); + if (dims.size() > 0 && layout == InferenceEngine::Layout::SCALAR) { + layout = InferenceEngine::Layout::ANY; + } + const auto deviceLayout = TensorDesc::getLayoutByDims(dims); + Blob::Ptr blob; + blob = make_blob_with_precision({precision, dims, layout}); + blob->allocate(); + blobMap[blobData.first] = blob; + + auto networkPresion = InferenceEngine::details::convertPrecision(GetNetworkPrecision(blobData.first)); + Blob::Ptr networkBlob; + if (precision == networkPresion && layout == deviceLayout) { + networkBlob = blob; + } else { + networkBlob = make_blob_with_precision({networkPresion, dims, deviceLayout}); + networkBlob->allocate(); + } + networkBlobMap[blobData.first] = networkBlob; +} + template static void AllocateImpl(const BlobDataMap& userDataMap, BlobMap& userBlobMap, BlobMap& deviceBlobMap, GetNetworkPrecisionF&& GetNetworkPrecision, bool isInputBlob = true) { - for (auto&& userData : userDataMap) { - const auto& dims = userData.second->getTensorDesc().getDims(); - const auto deviceLayout = TensorDesc::getLayoutByDims(dims); - const auto userPrecision = userData.second->getTensorDesc().getPrecision(); - const auto userLayout = userData.second->getTensorDesc().getLayout(); - - const auto networkPrecision = InferenceEngine::details::convertPrecision(GetNetworkPrecision(userData.first)); - Blob::Ptr userBlob = make_blob_with_precision({userPrecision, dims, userLayout}); - userBlob->allocate(); - userBlobMap[userData.first] = userBlob; - - Blob::Ptr deviceBlob; - if (userPrecision == networkPrecision && userLayout == deviceLayout) { - deviceBlob = userBlob; + for (const auto& userData : userDataMap) { + auto partialShape = userData.second->getPartialShape(); + SizeVector dims; + if (partialShape.is_static()) { + dims = userData.second->getTensorDesc().getDims(); + } else if (partialShape.rank().is_static()) { + dims = SizeVector(partialShape.rank().get_length(), 0); } else { - if (userLayout != deviceLayout && !isInputBlob) { - IE_THROW(NotImplemented) << "Template Plugin: does not support setLayout for outputs"; - } - deviceBlob = make_blob_with_precision({networkPrecision, dims, deviceLayout}); - deviceBlob->allocate(); + dims = SizeVector{0}; } - - deviceBlobMap[userData.first] = deviceBlob; + AllocateImplSingle(userBlobMap, deviceBlobMap, userData, GetNetworkPrecision, dims); } } @@ -239,8 +256,8 @@ void TemplateInferRequest::inferPreprocess() { IInferRequestInternal::execDataPreprocessing(_deviceInputs); for (auto&& networkInput : _deviceInputs) { auto index = _executableNetwork->_inputIndex[networkInput.first]; - const auto& parameter = _parameters[index]; - const auto& parameterShape = parameter->get_shape(); + const auto& parameter = _executableNetwork->_function->get_parameters()[index]; + auto parameterShape = networkInput.second->getTensorDesc().getDims(); const auto& parameterType = parameter->get_element_type(); _inputTensors[index] = _executableNetwork->_plugin->_backend->create_tensor( parameterType, @@ -254,7 +271,11 @@ void TemplateInferRequest::inferPreprocess() { if (outputBlob->getTensorDesc().getPrecision() == networkOutput->getTensorDesc().getPrecision()) { networkOutput = outputBlob; } - const auto& result = _results[index]; + const auto& result = _executableNetwork->_function->get_results()[index]; + if (result->get_output_partial_shape(0).is_dynamic()) { + _outputTensors[index] = _executableNetwork->_plugin->_backend->create_tensor(); + continue; + } const auto& resultShape = result->get_shape(); const auto& resultType = result->get_element_type(); _outputTensors[index] = _executableNetwork->_plugin->_backend->create_tensor( @@ -287,19 +308,190 @@ void TemplateInferRequest::waitPipeline() { void TemplateInferRequest::inferPostprocess() { OV_ITT_SCOPED_TASK(itt::domains::TemplatePlugin, _profilingTask[Postprocess]); auto start = Time::now(); - for (auto&& output : _outputs) { - auto outputBlob = output.second; + for (auto&& output : _networkOutputs) { + auto index = _executableNetwork->_outputIndex[output.first]; + const auto& result = _executableNetwork->_function->get_results()[index]; + if (result->get_output_partial_shape(0).is_dynamic()) { + // Touch blob to allocate it + Blob::Ptr blob; + GetBlob(output.first); + } + auto outputBlob = _outputs.at(output.first); auto networkOutput = _networkOutputBlobs[output.first]; - // perform precision conversion of network output's precision and computational - // graph output's precision are different if (outputBlob->getTensorDesc().getPrecision() != networkOutput->getTensorDesc().getPrecision()) { blobCopy(networkOutput, outputBlob); + } else if (result->get_output_partial_shape(0).is_dynamic()) { + auto tensor = _outputTensors[_executableNetwork->_outputIndex.at(output.first)]; + tensor->read(InferenceEngine::as(outputBlob)->wmap().as(), + tensor->get_size_in_bytes()); } } _durations[Postprocess] = Time::now() - start; } // ! [infer_request:infer_postprocess] +// ! [infer_request:get_blob] +InferenceEngine::Blob::Ptr TemplateInferRequest::GetBlob(const std::string& name) { + OV_ITT_SCOPED_TASK(itt::domains::TemplatePlugin, "GetBlob"); + InputInfo::Ptr foundInput; + DataPtr foundOutput; + Blob::Ptr data; + const SizeVector oneVector = {1}; + if (findInputAndOutputBlobByName(name, foundInput, foundOutput)) { + // ROI blob is returned only if it was set previously. Otherwise default blob is returned. + auto it = _preProcData.find(name); + if (it != _preProcData.end()) { + data = it->second->getRoiBlob(); + } else { + data = _inputs[name]; + SizeVector dims; + if (!data) { + auto&& parameters = _executableNetwork->_function->get_parameters(); + const auto& pshape = parameters.at(_executableNetwork->_inputIndex.at(name))->get_partial_shape(); + dims = pshape.is_dynamic() ? SizeVector({0}) : pshape.get_shape(); + AllocateImplSingle( + _inputs, + _deviceInputs, + *_networkInputs.find(name), + [&](const std::string& blobName) { + return parameters.at(_executableNetwork->_inputIndex.at(blobName))->get_element_type(); + }, + dims); + data = _inputs[name]; + } else { + dims = data->getTensorDesc().getDims(); + } + checkBlob(data, name, true, foundInput->getTensorDesc().getLayout() != SCALAR ? dims : oneVector); + auto& devBlob = _deviceInputs[name]; + if (preProcessingRequired(foundInput, data, devBlob)) { + // if no devBlob, performs inplace + addInputPreProcessingFor(name, data, devBlob ? devBlob : _inputs[name]); + } + } + } else { + data = _outputs[name]; + SizeVector dims; + if (!foundOutput->isDynamic()) { + dims = foundOutput->getTensorDesc().getDims(); + } else if (_outputTensors[_executableNetwork->_outputIndex.at(name)]->get_partial_shape().is_static()) { + dims = _outputTensors[_executableNetwork->_outputIndex.at(name)]->get_shape(); + } else { + IE_THROW() << "Output blob dimensions are not all known for output name " << name + << " with partial shape: " << foundOutput->getPartialShape(); + } + + if (data) { + if (data->getTensorDesc().getDims() != dims) { + // TODO: implement something smart here instead of raw re-allocation + data.reset(); + } + } + + if (!data) { + auto&& results = _executableNetwork->_function->get_results(); + AllocateImplSingle( + _outputs, + _networkOutputBlobs, + *_networkOutputs.find(name), + [&](const std::string& blobName) { + return results.at(_executableNetwork->_outputIndex.at(blobName))->get_element_type(); + }, + dims); + data = _outputs[name]; + } + checkBlob(data, name, false, foundOutput->getTensorDesc().getLayout() != SCALAR ? dims : oneVector); + } + return data; +} +// ! [infer_request:get_blob] + +// ! [infer_request:set_blob] +void TemplateInferRequest::SetBlob(const std::string& name, const InferenceEngine::Blob::Ptr& userBlob) { + OV_ITT_SCOPED_TASK(itt::domains::TemplatePlugin, "SetBlob"); + if (name.empty()) { + IE_THROW(NotFound) << "Failed to set blob with empty name"; + } + if (!userBlob) + IE_THROW(NotAllocated) << "Failed to set empty blob with name: \'" << name << "\'"; + const bool compoundBlobPassed = userBlob->is(); + const bool remoteBlobPassed = userBlob->is(); + if (!compoundBlobPassed && !remoteBlobPassed && userBlob->buffer() == nullptr) + IE_THROW(NotAllocated) << "Input data was not allocated. Input name: \'" << name << "\'"; + if (userBlob->size() == 0) { + IE_THROW() << "Input data is empty. Input name: \'" << name << "\'"; + } + + InputInfo::Ptr foundInput; + DataPtr foundOutput; + size_t dataSize = userBlob->size(); + if (findInputAndOutputBlobByName(name, foundInput, foundOutput)) { + // ilavreno: the condition below is obsolete, but we need an exact list of precisions + // which are supports by G-API preprocessing + if (foundInput->getPrecision() != userBlob->getTensorDesc().getPrecision()) { + IE_THROW(ParameterMismatch) + << "Failed to set Blob with precision not corresponding to user input precision"; + } + + auto& devBlob = _deviceInputs[name]; + auto usrDims = userBlob->getTensorDesc().getDims(); + auto usrLayout = userBlob->getTensorDesc().getLayout(); + auto devDims = devBlob->getTensorDesc().getDims(); + auto devLayout = devBlob->getTensorDesc().getLayout(); + auto devPrecision = devBlob->getTensorDesc().getPrecision(); + if (foundInput->getInputData()->isDynamic() && (devDims != usrDims || devLayout != usrLayout)) { + devBlob = make_blob_with_precision({devPrecision, usrDims, TensorDesc::getLayoutByDims(usrDims)}); + devBlob->allocate(); + _deviceInputs[name] = devBlob; + } + const bool preProcRequired = preProcessingRequired(foundInput, userBlob, devBlob); + if (compoundBlobPassed && !preProcRequired) { + IE_THROW(NotImplemented) << "cannot set compound blob: supported only for input pre-processing"; + } + + if (preProcRequired) { + addInputPreProcessingFor(name, userBlob, devBlob ? devBlob : _inputs[name]); + } else { + size_t inputSize = devBlob->getTensorDesc().getLayout() != InferenceEngine::Layout::SCALAR + ? InferenceEngine::details::product(devBlob->getTensorDesc().getDims()) + : 1; + if (dataSize != inputSize) { + IE_THROW() << "Input blob size is not equal network input size (" << dataSize << "!=" << inputSize + << ")."; + } + _inputs[name] = userBlob; + devBlob = userBlob; + } + } else { + if (compoundBlobPassed) { + IE_THROW(NotImplemented) << "cannot set compound blob: supported only for input pre-processing"; + } + auto& devBlob = _networkOutputBlobs[name]; + auto usrDims = userBlob->getTensorDesc().getDims(); + auto usrLayout = userBlob->getTensorDesc().getLayout(); + auto devDims = devBlob->getTensorDesc().getDims(); + auto devLayout = devBlob->getTensorDesc().getLayout(); + auto devPrecision = devBlob->getTensorDesc().getPrecision(); + if (foundOutput->isDynamic() && (devDims != usrDims || devLayout != usrLayout)) { + devBlob = make_blob_with_precision({devPrecision, usrDims, TensorDesc::getLayoutByDims(usrDims)}); + devBlob->allocate(); + _networkOutputBlobs[name] = devBlob; + } + size_t outputSize = devBlob->getTensorDesc().getLayout() != InferenceEngine::Layout::SCALAR + ? details::product(devBlob->getTensorDesc().getDims()) + : 1; + if (dataSize != outputSize) { + IE_THROW() << "Output blob size is not equal network output size (" << dataSize << "!=" << outputSize + << ")."; + } + if (foundOutput->getPrecision() != userBlob->getTensorDesc().getPrecision()) { + IE_THROW(ParameterMismatch) + << "Failed to set Blob with precision not corresponding to user output precision"; + } + _outputs[name] = userBlob; + } +} +// ! [infer_request:set_blob] + // ! [infer_request:get_performance_counts] std::map TemplateInferRequest::GetPerformanceCounts() const { std::map perfMap; diff --git a/docs/template_plugin/src/template_infer_request.hpp b/docs/template_plugin/src/template_infer_request.hpp index 0e1b904ccdb..f7e9a4f9952 100644 --- a/docs/template_plugin/src/template_infer_request.hpp +++ b/docs/template_plugin/src/template_infer_request.hpp @@ -40,6 +40,9 @@ public: void waitPipeline(); void inferPostprocess(); + InferenceEngine::Blob::Ptr GetBlob(const std::string& name) override; + void SetBlob(const std::string& name, const InferenceEngine::Blob::Ptr& userBlob) override; + private: void allocateDeviceBuffers(); void allocateBlobs(); @@ -52,8 +55,6 @@ private: std::array, numOfStages> _durations; InferenceEngine::BlobMap _networkOutputBlobs; - ngraph::ParameterVector _parameters; - ngraph::ResultVector _results; std::vector> _inputTensors; std::vector> _outputTensors; diff --git a/docs/template_plugin/tests/functional/shared_tests_instances/behavior/infer_request_dynamic.cpp b/docs/template_plugin/tests/functional/shared_tests_instances/behavior/infer_request_dynamic.cpp new file mode 100644 index 00000000000..221fe085158 --- /dev/null +++ b/docs/template_plugin/tests/functional/shared_tests_instances/behavior/infer_request_dynamic.cpp @@ -0,0 +1,30 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include + +#include "behavior/infer_request_dynamic.hpp" + +using namespace BehaviorTestsDefinitions; + +namespace { + +const std::vector netPrecisions = { + InferenceEngine::Precision::FP32, + InferenceEngine::Precision::FP16 +}; + +const std::vector> configs = { + {} +}; + +INSTANTIATE_TEST_CASE_P(smoke_BehaviorTests, InferRequestDynamicTests, + ::testing::Combine( + ::testing::ValuesIn(netPrecisions), + ::testing::Values(CommonTestUtils::DEVICE_TEMPLATE), + ::testing::ValuesIn(configs)), + InferRequestDynamicTests::getTestCaseName); + +} // namespace + diff --git a/inference-engine/src/inference_engine/include/ie/cpp/ie_cnn_network.h b/inference-engine/src/inference_engine/include/ie/cpp/ie_cnn_network.h index 42288ba84ac..25d527b7919 100644 --- a/inference-engine/src/inference_engine/include/ie/cpp/ie_cnn_network.h +++ b/inference-engine/src/inference_engine/include/ie/cpp/ie_cnn_network.h @@ -182,8 +182,20 @@ public: * @param inputShapes A map of pairs: name of corresponding data and its dimension. */ void reshape(const ICNNNetwork::InputShapes& inputShapes); + + /** + * @brief Run shape inference with new input shapes for the network + * @param inputShapes A map of pairs: name of corresponding data and its dimension. + */ + void reshape(const std::initializer_list& inputShapes); IE_SUPPRESS_DEPRECATED_END + /** + * @brief Run shape inference with new input partial shapes for the network + * @param inputShapes A map of pairs: name of corresponding data and its dimension. + */ + void reshape(const std::map& inputShapes); + /** * @brief Serialize network to IR and weights files. * diff --git a/inference-engine/src/inference_engine/include/ie/ie_blob.h b/inference-engine/src/inference_engine/include/ie/ie_blob.h index b25d180747f..21342ae73da 100644 --- a/inference-engine/src/inference_engine/include/ie/ie_blob.h +++ b/inference-engine/src/inference_engine/include/ie/ie_blob.h @@ -187,6 +187,28 @@ public: */ virtual bool deallocate() noexcept = 0; + /** + * @brief Set new shape for blob, deallocate/allocate if new total size is bigger than previous one. + * + * @param dims new shape + */ + void setShape(const SizeVector& dims) { + if (properProduct(dims) > properProduct(getTensorDesc().getDims())) { + // New blob shape requires more memory than old one -- reallocate + if (!deallocate()) + IE_THROW() << "Cannot deallocate blob while an attempt to enlarge blob area in setShape."; + + // Old and new ranks should match as well as layouts + getTensorDesc().setDims(dims); + + allocate(); + // no way to detect if allocation is successful other than map/unmap that we wouldn't like to do here + } else { + // Don't shrink area when new size fit the existing area + getTensorDesc().setDims(dims); + } + } + /** * @deprecated Cast to MemoryBlob and use new wlock/rwlock API instead. * Blob class can represent compound blob, which do not refer to the only solid memory. @@ -239,6 +261,17 @@ protected: return std::accumulate(std::begin(dims), std::end(dims), (size_t)1, std::multiplies()); } + /** + * @deprecated Cast to MemoryBlob and use its API instead. + * @brief Multiplies the dimension vector values. Size of a scalar is 1 instead of 0 as for product. + * + * @param dims Reference to a vector with dimension values of type size_t + * @return Result of multiplication + */ + static size_t properProduct(const SizeVector& dims) noexcept { + return std::accumulate(std::begin(dims), std::end(dims), (size_t)1, std::multiplies()); + } + /** * @brief Gets an allocator for allocator-based blobs * diff --git a/inference-engine/src/inference_engine/include/ie/ie_data.h b/inference-engine/src/inference_engine/include/ie/ie_data.h index 86a3e937adf..95776398a8d 100644 --- a/inference-engine/src/inference_engine/include/ie/ie_data.h +++ b/inference-engine/src/inference_engine/include/ie/ie_data.h @@ -11,6 +11,7 @@ #include #include +#include #include #include @@ -38,6 +39,16 @@ public: */ Data(const std::string& name, Precision _precision, Layout layout = NCHW); + /** + * @brief A constructor with partial shape + * + * @param name Name of the data node + * @param _precision Precision of the data + * @param shape Partial shape of the data + * @param layout Data layout + */ + Data(const std::string& name, Precision _precision, const ngraph::PartialShape& shape, Layout layout = BLOCKED); + /** * @brief A constructor with tensor descriptor * @@ -91,6 +102,20 @@ public: * @param layout new layout */ void reshape(const SizeVector& dims, Layout layout); + /** + * @brief changes dims and layout at same time + * + * @param dims new dimensions + * @param layout new layout + */ + void reshape(const std::initializer_list& dims, Layout layout); + /** + * @brief changes dims and layout at same time + * + * @param dims new dimensions + * @param layout new layout + */ + void reshape(const ngraph::PartialShape& dims, Layout layout); /** * @brief Gets the layout value for this Data instance @@ -142,6 +167,18 @@ public: */ const UserValue& getUserObject() const; + /** + * @brief Checks if current data has dynamic shapes + * @return true if data has dynamic shapes + */ + bool isDynamic() const; + + /** + * @brief Returns partial shapes + * @return shapes which can have dynamic dimensions + */ + const ngraph::PartialShape& getPartialShape() const; + /** * @private * @brief Don't touch this field. An implementation details for Data object. @@ -163,5 +200,7 @@ private: * @brief A tensor descriptor */ mutable TensorDesc tensorDesc; + + ngraph::PartialShape pShape; }; } // namespace InferenceEngine diff --git a/inference-engine/src/inference_engine/include/ie/ie_icnn_network.hpp b/inference-engine/src/inference_engine/include/ie/ie_icnn_network.hpp index acedb48bb2c..30327c14fec 100644 --- a/inference-engine/src/inference_engine/include/ie/ie_icnn_network.hpp +++ b/inference-engine/src/inference_engine/include/ie/ie_icnn_network.hpp @@ -183,6 +183,22 @@ public: return NOT_IMPLEMENTED; }; + /** + * @deprecated Use InferenceEngine::CNNNetwork wrapper instead + * @brief Run shape inference with new input shapes for the network + * + * @param partialShapes - map of pairs: name of corresponding data and its dimension. + * @param resp Pointer to the response message that holds a description of an error if any occurred + * @return Status code of the operation + */ + INFERENCE_ENGINE_DEPRECATED("Use InferenceEngine::CNNNetwork wrapper instead") + virtual StatusCode reshape(const std::map& partialShapes, + ResponseDesc* resp) noexcept { + (void)partialShapes; + (void)resp; + return NOT_IMPLEMENTED; + }; + /** * @deprecated Use InferenceEngine::CNNNetwork wrapper instead * @brief Serialize network to IR and weights files. diff --git a/inference-engine/src/inference_engine/include/ie/ie_input_info.hpp b/inference-engine/src/inference_engine/include/ie/ie_input_info.hpp index e844bf7b844..ef2ee6ced12 100644 --- a/inference-engine/src/inference_engine/include/ie/ie_input_info.hpp +++ b/inference-engine/src/inference_engine/include/ie/ie_input_info.hpp @@ -138,6 +138,17 @@ public: return _inputData->getTensorDesc(); } + /** + * @brief Returns the input shape. May have undefined dimensions. + * @return PartialShape object describing input shape. + */ + ngraph::PartialShape getPartialShape() { + if (!_inputData) { + IE_THROW() << "Data is empty!"; + } + return _inputData->getPartialShape(); + } + /** * @brief Gets pre-process info for the input * @return A reference to the PreProcessInfo instance that contains pre-process info for this input diff --git a/inference-engine/src/inference_engine/src/cnn_network_ngraph_impl.cpp b/inference-engine/src/inference_engine/src/cnn_network_ngraph_impl.cpp index 9e3171d3a10..8ad6e3c4e74 100644 --- a/inference-engine/src/inference_engine/src/cnn_network_ngraph_impl.cpp +++ b/inference-engine/src/inference_engine/src/cnn_network_ngraph_impl.cpp @@ -65,24 +65,21 @@ void CNNNetworkNGraphImpl::createDataForResult(const ::ngraph::Output<::ngraph:: return false; } }; - // query shape from ngraph::Parameter output shape and check there are no zeros in it - SizeVector dims; - if (output.get_partial_shape().is_static()) { - dims = output.get_shape(); - } - for (const auto& dim : dims) { - if (!dim) + auto shape = output.get_partial_shape(); + auto rank = shape.rank().is_static() ? shape.rank().get_length() : 0; + for (const auto& dim : shape) { + if (dim.is_static() && dim.get_length() == 0) IE_THROW() << outName << " has zero dimension which is not allowed"; } if (ptr) { const auto origLayout = ptr->getTensorDesc().getLayout(); - const auto layout = isCompatible(dims.size(), origLayout) ? origLayout : TensorDesc::getLayoutByDims(dims); - ptr->reshape(dims, layout); + const auto layout = isCompatible(rank, origLayout) ? origLayout : TensorDesc::getLayoutByRank(rank); + ptr->reshape(shape, layout); } else { - const auto layout = TensorDesc::getLayoutByDims(dims); + const auto layout = TensorDesc::getLayoutByRank(rank); const auto precision = details::convertPrecision(output.get_element_type()); - ptr.reset(new Data(outName, {precision, dims, layout})); + ptr.reset(new Data(outName, precision, shape, layout)); } } @@ -180,12 +177,15 @@ CNNNetworkNGraphImpl::CNNNetworkNGraphImpl(const CNNNetwork& network) { for (const auto& inputInfo : inputs) { InputInfo::Ptr info = std::make_shared(); const auto& name = inputInfo.second->getInputData()->getName(); - DataPtr input = std::make_shared(name, inputInfo.second->getInputData()->getTensorDesc()); + const auto& inData = inputInfo.second->getInputData(); + DataPtr input = + std::make_shared(name, inData->getPrecision(), inData->getPartialShape(), inData->getLayout()); _data[name] = input; info->setInputData(input); info->getPreProcess() = inputInfo.second->getPreProcess(); info->setPrecision(inputInfo.second->getPrecision()); - info->setLayout(inputInfo.second->getLayout()); + if (!inData->isDynamic()) + info->setLayout(inputInfo.second->getLayout()); _inputData[name] = info; } } @@ -296,9 +296,9 @@ size_t CNNNetworkNGraphImpl::getBatchSize() const noexcept { }); for (const auto& param : params) { - if (param->get_partial_shape().rank().is_dynamic()) + if (param->get_output_partial_shape(0).rank().is_dynamic()) continue; - auto pshape = param->get_partial_shape(); + auto pshape = param->get_output_partial_shape(0); auto rank = pshape.rank().get_length(); // WA: for speech recognition and scalar layouts (copy-past from CNNNetwork) if ((rank == 2 || rank > 3) && pshape[0].is_static()) { @@ -312,7 +312,7 @@ void CNNNetworkNGraphImpl::reshape() { reshape({}); } -StatusCode CNNNetworkNGraphImpl::reshape(const std::map>& inputShapes, +StatusCode CNNNetworkNGraphImpl::reshape(const std::map& inputShapes, ResponseDesc* responseDesc) noexcept { if (inputShapes.empty()) return OK; @@ -326,7 +326,7 @@ StatusCode CNNNetworkNGraphImpl::reshape(const std::mapget_partial_shape().is_dynamic() || param->get_shape() != it->second) { + if (param->get_output_partial_shape(0).is_dynamic() || param->get_output_partial_shape(0) != it->second) { needReshape = true; break; } @@ -338,7 +338,7 @@ StatusCode CNNNetworkNGraphImpl::reshape(const std::map originalInputShapes; for (const auto& param : params) { - originalInputShapes[param->get_friendly_name()] = param->get_partial_shape(); + originalInputShapes[param->get_friendly_name()] = param->get_output_partial_shape(0); } try { @@ -359,6 +359,14 @@ StatusCode CNNNetworkNGraphImpl::reshape(const std::map>& inputShapes, + ResponseDesc* responseDesc) noexcept { + std::map shapes; + for (const auto& shape : inputShapes) + shapes[shape.first] = ngraph::PartialShape(shape.second); + return reshape(shapes, responseDesc); +} + void CNNNetworkNGraphImpl::reshape(const std::map& inputShapes) { OV_ITT_SCOPED_TASK(ov::itt::domains::IE, "CNNNetworkNGraphImpl::reshape"); @@ -565,7 +573,7 @@ StatusCode CNNNetworkNGraphImpl::setBatchSize(size_t size, ResponseDesc* respons if (i) ss << ", "; ss << "\"" << original_parameters[i]->get_friendly_name() - << "\": " << original_parameters[i]->get_partial_shape(); + << "\": " << original_parameters[i]->get_output_partial_shape(0); } // ill-formed logic from the past setBatchSize (we keep it for backward-compatibility) @@ -575,7 +583,7 @@ StatusCode CNNNetworkNGraphImpl::setBatchSize(size_t size, ResponseDesc* respons [](std::shared_ptr lhs, std::shared_ptr rhs) { return lhs->get_friendly_name() < rhs->get_friendly_name(); }); - const auto first_parameter_pshape = first_parameter->get_partial_shape(); + const auto first_parameter_pshape = first_parameter->get_output_partial_shape(0); if (first_parameter_pshape.is_dynamic()) return DescriptionBuffer(PARAMETER_MISMATCH, responseDesc) << "Cannot set batch! Function contains parameter with partially defined shape!" << ss.str(); @@ -587,7 +595,7 @@ StatusCode CNNNetworkNGraphImpl::setBatchSize(size_t size, ResponseDesc* respons std::map> inShapes; for (const auto& parameter : original_parameters) { - const auto& pshape = parameter->get_partial_shape(); + const auto& pshape = parameter->get_output_partial_shape(0); if (pshape.is_dynamic()) return DescriptionBuffer(PARAMETER_MISMATCH, responseDesc) << "Cannot set batch! Function contains parameter with partially defined shape!" << ss.str(); diff --git a/inference-engine/src/inference_engine/src/cnn_network_ngraph_impl.hpp b/inference-engine/src/inference_engine/src/cnn_network_ngraph_impl.hpp index 6a7027327f3..856ab398764 100644 --- a/inference-engine/src/inference_engine/src/cnn_network_ngraph_impl.hpp +++ b/inference-engine/src/inference_engine/src/cnn_network_ngraph_impl.hpp @@ -74,6 +74,8 @@ public: StatusCode reshape(const std::map>& inputShapes, ResponseDesc* resp) noexcept override; + StatusCode reshape(const std::map& inputShapes, + ResponseDesc* resp) noexcept override; StatusCode serialize(const std::string& xmlPath, const std::string& binPath, ResponseDesc* resp) const noexcept override; diff --git a/inference-engine/src/inference_engine/src/cpp/ie_cnn_network.cpp b/inference-engine/src/inference_engine/src/cpp/ie_cnn_network.cpp index 0bc58df4880..0e994bad97a 100644 --- a/inference-engine/src/inference_engine/src/cpp/ie_cnn_network.cpp +++ b/inference-engine/src/inference_engine/src/cpp/ie_cnn_network.cpp @@ -127,6 +127,14 @@ void CNNNetwork::reshape(const ICNNNetwork::InputShapes& inputShapes) { CALL_STATUS_FNC(reshape, inputShapes); } +void CNNNetwork::reshape(const std::initializer_list& inputShapes) { + return reshape(ICNNNetwork::InputShapes(inputShapes)); +} + +void CNNNetwork::reshape(const std::map& inputShapes) { + CALL_STATUS_FNC(reshape, inputShapes); +} + void CNNNetwork::serialize(const std::string& xmlPath, const std::string& binPath) const { CALL_STATUS_FNC(serialize, xmlPath, binPath); } diff --git a/inference-engine/src/inference_engine/src/cpp_interfaces/interface/ie_iinfer_request_internal.cpp b/inference-engine/src/inference_engine/src/cpp_interfaces/interface/ie_iinfer_request_internal.cpp index 9dcde916f1c..c6c1db7c024 100644 --- a/inference-engine/src/inference_engine/src/cpp_interfaces/interface/ie_iinfer_request_internal.cpp +++ b/inference-engine/src/inference_engine/src/cpp_interfaces/interface/ie_iinfer_request_internal.cpp @@ -126,11 +126,8 @@ Blob::Ptr IInferRequestInternal::GetBlob(const std::string& name) { data = it->second->getRoiBlob(); } else { data = _inputs[name]; - checkBlob( - data, - name, - true, - foundInput->getTensorDesc().getLayout() != SCALAR ? foundInput->getTensorDesc().getDims() : oneVector); + const auto& dims = foundInput->getTensorDesc().getDims(); + checkBlob(data, name, true, foundInput->getTensorDesc().getLayout() != SCALAR ? dims : oneVector); auto& devBlob = _deviceInputs[name]; if (preProcessingRequired(foundInput, data, devBlob)) { @@ -140,11 +137,8 @@ Blob::Ptr IInferRequestInternal::GetBlob(const std::string& name) { } } else { data = _outputs[name]; - checkBlob( - data, - name, - false, - foundOutput->getTensorDesc().getLayout() != SCALAR ? foundOutput->getTensorDesc().getDims() : oneVector); + const auto& dims = foundOutput->getTensorDesc().getDims(); + checkBlob(data, name, false, foundOutput->getTensorDesc().getLayout() != SCALAR ? dims : oneVector); } return data; } @@ -252,6 +246,7 @@ void IInferRequestInternal::checkBlob(const Blob::Ptr& blob, IE_THROW(NotAllocated) << strNotAllocated; } size_t refSize; + bool isDynamic = false; if (refDims.empty()) { SizeVector dims; if (isInput) { @@ -263,6 +258,7 @@ void IInferRequestInternal::checkBlob(const Blob::Ptr& blob, if (foundInputPair == std::end(_networkInputs)) { IE_THROW(NotFound) << "Failed to find input with name: \'" << name << "\'"; } + isDynamic = foundInputPair->second->getInputData()->getPartialShape().is_dynamic(); dims = foundInputPair->second->getTensorDesc().getDims(); refSize = foundInputPair->second->getTensorDesc().getLayout() != SCALAR ? details::product(dims) : 1; } else { @@ -274,14 +270,22 @@ void IInferRequestInternal::checkBlob(const Blob::Ptr& blob, if (foundOutputPair == std::end(_networkOutputs)) { IE_THROW(NotFound) << "Failed to find output with name: \'" << name << "\'"; } - dims = foundOutputPair->second->getTensorDesc().getDims(); + isDynamic = foundOutputPair->second->getPartialShape().is_dynamic(); + ngraph::PartialShape blobPartialShape(blob->getTensorDesc().getDims()); + if (foundOutputPair->second->getPartialShape().compatible(blobPartialShape)) { + dims = blob->getTensorDesc().getDims(); + } else { + // TODO: it is strange to request tensor desc from data when the shapes are not compatible, probably we + // need to immediately throw here + dims = foundOutputPair->second->getTensorDesc().getDims(); + } refSize = foundOutputPair->second->getTensorDesc().getLayout() != SCALAR ? details::product(dims) : 1; } } else { refSize = details::product(refDims); } - if (refSize != blob->size()) { + if (!isDynamic && refSize != blob->size()) { IE_THROW() << strNotMatched + ": got " << blob->size() << " expecting " << refSize; } const bool remoteBlobPassed = blob->is(); diff --git a/inference-engine/src/inference_engine/src/ie_data.cpp b/inference-engine/src/inference_engine/src/ie_data.cpp index 24a7b8b020d..aa89b34d9f2 100644 --- a/inference-engine/src/inference_engine/src/ie_data.cpp +++ b/inference-engine/src/inference_engine/src/ie_data.cpp @@ -77,7 +77,22 @@ Data::Data(const std::string& name, Precision _precision, Layout layout) _impl = std::make_shared(); } -Data::Data(const std::string& name, const TensorDesc& desc) : name(name), userObject({0}), tensorDesc(desc) { +Data::Data(const std::string& name, const TensorDesc& desc) + : name(name), + userObject({0}), + tensorDesc(desc), + pShape(desc.getDims()) { + _impl = std::make_shared(); +} + +Data::Data(const std::string& name, Precision _precision, const ngraph::PartialShape& shape, Layout layout) + : name(name), + userObject({0}), + tensorDesc(_precision, layout), + pShape(shape) { + if (pShape.is_static()) { + tensorDesc.reshape(pShape.to_shape(), tensorDesc.getLayout()); + } _impl = std::make_shared(); } @@ -95,6 +110,15 @@ bool Data::isInitialized() const { void Data::setDims(const SizeVector& a_dims) { tensorDesc.setDims(a_dims); + pShape = ngraph::PartialShape(a_dims); +} + +bool Data::isDynamic() const { + return tensorDesc.getDims().empty() && tensorDesc.getLayout() != SCALAR && pShape.is_dynamic(); +} + +const ngraph::PartialShape& Data::getPartialShape() const { + return pShape; } void Data::setLayout(Layout layout) { @@ -103,9 +127,27 @@ void Data::setLayout(Layout layout) { void Data::reshape(const SizeVector& a_dims, Layout a_layout) { tensorDesc.reshape(a_dims, a_layout); + pShape = ngraph::PartialShape(a_dims); } -Data::Data(const Data& data) : name(data.name), userObject(data.userObject), tensorDesc(data.tensorDesc) { +void Data::reshape(const std::initializer_list& dims, Layout layout) { + reshape(SizeVector(dims), layout); +} + +void Data::reshape(const ngraph::PartialShape& dims, Layout layout) { + if (dims.is_static()) { + reshape(SizeVector(dims.to_shape()), layout); + } else { + tensorDesc = TensorDesc(tensorDesc.getPrecision(), layout); + pShape = dims; + } +} + +Data::Data(const Data& data) + : name(data.name), + userObject(data.userObject), + tensorDesc(data.tensorDesc), + pShape(data.pShape) { _impl = std::make_shared(); _impl->creatorLayer = data._impl->creatorLayer; _impl->inputTo = data._impl->inputTo; @@ -116,6 +158,7 @@ Data& Data::operator=(const Data& data) { name = data.name; userObject = data.userObject; tensorDesc = data.tensorDesc; + pShape = data.pShape; _impl->creatorLayer = data._impl->creatorLayer; _impl->inputTo = data._impl->inputTo; @@ -145,6 +188,11 @@ void Data::setPrecision(const Precision& precision) { } const SizeVector& Data::getDims() const { + if (isDynamic()) + IE_THROW() << "Cannot return dims for Data with dynamic shapes!"; + if (tensorDesc.getDims().empty() && tensorDesc.getLayout() != SCALAR) { + tensorDesc.setDims(pShape.to_shape()); + } return tensorDesc.getDims(); } diff --git a/inference-engine/src/preprocessing/ie_preprocess_gapi_kernels_simd_impl.hpp b/inference-engine/src/preprocessing/ie_preprocess_gapi_kernels_simd_impl.hpp index 19b00e41f31..f6ba9d3afbc 100644 --- a/inference-engine/src/preprocessing/ie_preprocess_gapi_kernels_simd_impl.hpp +++ b/inference-engine/src/preprocessing/ie_preprocess_gapi_kernels_simd_impl.hpp @@ -156,7 +156,6 @@ CV_ALWAYS_INLINE void splitRowC3_Impl(const T in[], T out0[], #if MANUAL_SIMD constexpr int nlanes = VecT::nlanes; - GAPI_DbgAssert(length >= nlanes); VecT r0, r1, r2; for (; length >= nlanes;) { diff --git a/inference-engine/src/vpu/myriad_plugin/myriad_infer_request.cpp b/inference-engine/src/vpu/myriad_plugin/myriad_infer_request.cpp index 27ecca826fa..5192f1d2289 100644 --- a/inference-engine/src/vpu/myriad_plugin/myriad_infer_request.cpp +++ b/inference-engine/src/vpu/myriad_plugin/myriad_infer_request.cpp @@ -266,7 +266,7 @@ void MyriadInferRequest::GetResult() { "Can not find tensor descriptor by plugin for {} output", ieBlobName); const auto& dynOutputDesc = descFromPlugin->second; - if (ieBlob->getTensorDesc().getLayout() != dynOutputDesc.getLayout()) { + if (ieBlob->getTensorDesc().getDims() != dynOutputDesc.getDims()) { ieBlob->deallocate(); ieBlob->getTensorDesc().reshape(dynOutputDesc.getDims(), dynOutputDesc.getLayout()); ieBlob->allocate(); diff --git a/inference-engine/tests/functional/inference_engine/ngraph_reshape_tests.cpp b/inference-engine/tests/functional/inference_engine/ngraph_reshape_tests.cpp index 8ddefc82d60..5c8885d7cf7 100644 --- a/inference-engine/tests/functional/inference_engine/ngraph_reshape_tests.cpp +++ b/inference-engine/tests/functional/inference_engine/ngraph_reshape_tests.cpp @@ -70,13 +70,15 @@ TEST_F(NGraphReshapeTests, ReshapedDynamicShapeLayout) { } CNNNetwork cnnNetwork(ngraph); - ASSERT_EQ(Layout::SCALAR, cnnNetwork.getInputsInfo()["A"]->getLayout()); + ASSERT_EQ(Layout::NCHW, cnnNetwork.getInputsInfo()["A"]->getLayout()); + ASSERT_TRUE(cnnNetwork.getInputsInfo()["A"]->getInputData()->isDynamic()); ICNNNetwork::InputShapes new_shape; new_shape["A"] = ngraph::Shape{1, 3, 22, 22}; cnnNetwork.reshape(new_shape); ASSERT_EQ(Layout::NCHW, cnnNetwork.getInputsInfo()["A"]->getLayout()); + ASSERT_FALSE(cnnNetwork.getInputsInfo()["A"]->getInputData()->isDynamic()); } TEST_F(NGraphReshapeTests, ReshapeBatchReLU) { @@ -236,6 +238,120 @@ TEST_F(NGraphReshapeTests, CNNReshapeSpatialReLUWithoutCloneFunction) { ASSERT_EQ(ngraph->get_results()[0]->get_shape(), ngraph::Shape({1, 3, 25, 25})); } +TEST_F(NGraphReshapeTests, CNNReshapeSpatialReLUStaticToDynamic) { + const ngraph::PartialShape refShape{1, 3, ngraph::Dimension::dynamic(), 25}; + std::shared_ptr ngraph; + { + ngraph::PartialShape shape({1, 3, 22, 22}); + ngraph::element::Type type(ngraph::element::Type_t::f32); + auto param = std::make_shared(type, shape); + param->set_friendly_name("data"); + auto relu = std::make_shared(param); + auto result = std::make_shared(relu); + + ngraph::ParameterVector params = {param}; + ngraph::ResultVector results = {result}; + + ngraph = std::make_shared(results, params); + } + + ASSERT_EQ(ngraph->get_parameters()[0]->get_shape(), ngraph::Shape({1, 3, 22, 22})); + ASSERT_EQ(ngraph->get_results()[0]->get_shape(), ngraph::Shape({1, 3, 22, 22})); + + CNNNetwork cnnNetwork(ngraph); + std::map shapes; + shapes["data"] = refShape; + + ASSERT_NO_THROW(cnnNetwork.reshape(shapes)); + + auto changedFunction = cnnNetwork.getFunction(); + ASSERT_NE(nullptr, changedFunction); + ASSERT_TRUE(changedFunction->get_parameters()[0]->get_output_partial_shape(0).is_dynamic()); + ASSERT_TRUE(changedFunction->get_results()[0]->get_output_partial_shape(0).is_dynamic()); + ASSERT_TRUE(ngraph->get_parameters()[0]->get_output_partial_shape(0).is_dynamic()); + ASSERT_TRUE(ngraph->get_results()[0]->get_output_partial_shape(0).is_dynamic()); + ASSERT_EQ(changedFunction->get_parameters()[0]->get_output_partial_shape(0), refShape); + ASSERT_EQ(changedFunction->get_results()[0]->get_output_partial_shape(0), refShape); + ASSERT_EQ(ngraph->get_parameters()[0]->get_output_partial_shape(0), refShape); + ASSERT_EQ(ngraph->get_results()[0]->get_output_partial_shape(0), refShape); +} + +TEST_F(NGraphReshapeTests, CNNReshapeSpatialReLUStaticToFullyDynamic) { + const ngraph::PartialShape refShape = ngraph::PartialShape::dynamic(); + std::shared_ptr ngraph; + { + ngraph::PartialShape shape({1, 3, 22, 22}); + ngraph::element::Type type(ngraph::element::Type_t::f32); + auto param = std::make_shared(type, shape); + param->set_friendly_name("data"); + auto relu = std::make_shared(param); + auto result = std::make_shared(relu); + + ngraph::ParameterVector params = {param}; + ngraph::ResultVector results = {result}; + + ngraph = std::make_shared(results, params); + } + + ASSERT_EQ(ngraph->get_parameters()[0]->get_shape(), ngraph::Shape({1, 3, 22, 22})); + ASSERT_EQ(ngraph->get_results()[0]->get_shape(), ngraph::Shape({1, 3, 22, 22})); + + CNNNetwork cnnNetwork(ngraph); + std::map shapes; + shapes["data"] = refShape; + + ASSERT_NO_THROW(cnnNetwork.reshape(shapes)); + + auto changedFunction = cnnNetwork.getFunction(); + ASSERT_NE(nullptr, changedFunction); + ASSERT_TRUE(changedFunction->get_parameters()[0]->get_output_partial_shape(0).is_dynamic()); + ASSERT_TRUE(changedFunction->get_results()[0]->get_output_partial_shape(0).is_dynamic()); + ASSERT_TRUE(ngraph->get_parameters()[0]->get_output_partial_shape(0).is_dynamic()); + ASSERT_TRUE(ngraph->get_results()[0]->get_output_partial_shape(0).is_dynamic()); + ASSERT_EQ(changedFunction->get_parameters()[0]->get_output_partial_shape(0), refShape); + ASSERT_EQ(changedFunction->get_results()[0]->get_output_partial_shape(0), refShape); + ASSERT_EQ(ngraph->get_parameters()[0]->get_output_partial_shape(0), refShape); + ASSERT_EQ(ngraph->get_results()[0]->get_output_partial_shape(0), refShape); +} + +TEST_F(NGraphReshapeTests, CNNReshapeSpatialReLUDynamicToDynamic) { + const ngraph::PartialShape refShape{1, 3, ngraph::Dimension::dynamic(), 25}; + std::shared_ptr ngraph; + { + ngraph::PartialShape shape({1, 3, 22, ngraph::Dimension::dynamic()}); + ngraph::element::Type type(ngraph::element::Type_t::f32); + auto param = std::make_shared(type, shape); + param->set_friendly_name("data"); + auto relu = std::make_shared(param); + auto result = std::make_shared(relu); + + ngraph::ParameterVector params = {param}; + ngraph::ResultVector results = {result}; + + ngraph = std::make_shared(results, params); + } + + ASSERT_EQ(ngraph->get_parameters()[0]->get_output_partial_shape(0), ngraph::PartialShape({1, 3, 22, ngraph::Dimension::dynamic()})); + ASSERT_EQ(ngraph->get_results()[0]->get_output_partial_shape(0), ngraph::PartialShape({1, 3, 22, ngraph::Dimension::dynamic()})); + + CNNNetwork cnnNetwork(ngraph); + std::map shapes; + shapes["data"] = refShape; + + ASSERT_NO_THROW(cnnNetwork.reshape(shapes)); + + auto changedFunction = cnnNetwork.getFunction(); + ASSERT_NE(nullptr, changedFunction); + ASSERT_TRUE(changedFunction->get_parameters()[0]->get_output_partial_shape(0).is_dynamic()); + ASSERT_TRUE(changedFunction->get_results()[0]->get_output_partial_shape(0).is_dynamic()); + ASSERT_TRUE(ngraph->get_parameters()[0]->get_output_partial_shape(0).is_dynamic()); + ASSERT_TRUE(ngraph->get_results()[0]->get_output_partial_shape(0).is_dynamic()); + ASSERT_EQ(changedFunction->get_parameters()[0]->get_output_partial_shape(0), refShape); + ASSERT_EQ(changedFunction->get_results()[0]->get_output_partial_shape(0), refShape); + ASSERT_EQ(ngraph->get_parameters()[0]->get_output_partial_shape(0), refShape); + ASSERT_EQ(ngraph->get_results()[0]->get_output_partial_shape(0), refShape); +} + class CustomTestOp: public ngraph::op::Op { public: static constexpr ngraph::NodeTypeInfo type_info{"CustomTestLayer", 0}; diff --git a/inference-engine/tests/functional/plugin/shared/include/behavior/infer_request.hpp b/inference-engine/tests/functional/plugin/shared/include/behavior/infer_request.hpp new file mode 100644 index 00000000000..66af6d6397c --- /dev/null +++ b/inference-engine/tests/functional/plugin/shared/include/behavior/infer_request.hpp @@ -0,0 +1,656 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +#include +#include +#include +#include +#include +#include +#include "ie_extension.h" +#include +#include "shared_test_classes/base/layer_test_utils.hpp" +#include "ngraph_functions/utils/ngraph_helpers.hpp" +#include "ngraph_functions/builders.hpp" +#include +#include +#include +#include +#include "common_test_utils/common_utils.hpp" +#include "functional_test_utils/plugin_cache.hpp" +#include "functional_test_utils/blob_utils.hpp" +#include "ngraph_functions/subgraph_builders.hpp" +#include "shared_test_classes/subgraph/basic_lstm.hpp" + +namespace BehaviorTestsDefinitions { +using InferRequestTests = BehaviorTestsUtils::BehaviorTestsBasic; + +// Setting empty config to LoadNetwork doesn't throw +TEST_P(InferRequestTests, SetEmptyConfig) { + // Skip test according to plugin specific disabledTestPatterns() (if any) + SKIP_IF_CURRENT_TEST_IS_DISABLED() + // Create CNNNetwork from ngrpah::Function + InferenceEngine::CNNNetwork cnnNet(function); + // Load CNNNetwork to target plugins + InferenceEngine::ExecutableNetwork execNet; + std::map config {}; + if (targetDevice.find(CommonTestUtils::DEVICE_AUTO) == std::string::npos && + targetDevice.find(CommonTestUtils::DEVICE_MULTI) == std::string::npos && + targetDevice.find(CommonTestUtils::DEVICE_HETERO) == std::string::npos) { + ASSERT_NO_THROW(ie->SetConfig(configuration, targetDevice)); + ASSERT_NO_THROW(execNet = ie->LoadNetwork(cnnNet, targetDevice, config)); + } else { + ASSERT_NO_THROW(ie->SetConfig(configuration, targetDevice)); + ASSERT_NO_THROW(execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration)); + } +} + +// Load correct network to Plugin to get executable network +TEST_P(InferRequestTests, canLoadCorrectNetworkToGetExecutable) { + // Skip test according to plugin specific disabledTestPatterns() (if any) + SKIP_IF_CURRENT_TEST_IS_DISABLED() + // Create CNNNetwork from ngrpah::Function + InferenceEngine::CNNNetwork cnnNet(function); + InferenceEngine::ExecutableNetwork execNet; + ASSERT_NO_THROW(execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration)); +} + +TEST_P(InferRequestTests, CanCreateTwoExeNetworks) { + // Skip test according to plugin specific disabledTestPatterns() (if any) + SKIP_IF_CURRENT_TEST_IS_DISABLED() + // Create CNNNetwork from ngrpah::Function + InferenceEngine::CNNNetwork cnnNet(function); + InferenceEngine::ExecutableNetwork execNet; + for (auto i = 0; i < 2; i++) { + ASSERT_NO_THROW(execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration)); + ASSERT_NE(nullptr, cnnNet.getFunction()); + } +} + +TEST_P(InferRequestTests, CanCreateInferRequest) { + // Skip test according to plugin specific disabledTestPatterns() (if any) + SKIP_IF_CURRENT_TEST_IS_DISABLED() + // Create CNNNetwork from ngrpah::Function + InferenceEngine::CNNNetwork cnnNet(function); + // Load CNNNetwork to target plugins + auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); + // Create InferRequest + InferenceEngine::InferRequest req; + ASSERT_NO_THROW(req = execNet.CreateInferRequest()); +} + +TEST_P(InferRequestTests, failToSetNullptrForInput) { + // Skip test according to plugin specific disabledTestPatterns() (if any) + SKIP_IF_CURRENT_TEST_IS_DISABLED() + // Create CNNNetwork from ngrpah::Function + InferenceEngine::CNNNetwork cnnNet(function); + // Load CNNNetwork to target plugins + auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); + // Create InferRequest + InferenceEngine::InferRequest req; + ASSERT_NO_THROW(req = execNet.CreateInferRequest()); + InferenceEngine::Blob::Ptr inputBlob = nullptr; + ASSERT_THROW(req.SetBlob(cnnNet.getInputsInfo().begin()->first, inputBlob), + InferenceEngine::Exception); +} + +TEST_P(InferRequestTests, failToSetEmptyInputBlob) { + // Skip test according to plugin specific disabledTestPatterns() (if any) + SKIP_IF_CURRENT_TEST_IS_DISABLED() + // Create CNNNetwork from ngrpah::Function + InferenceEngine::CNNNetwork cnnNet(function); + // Load CNNNetwork to target plugins + auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); + // Create InferRequest + InferenceEngine::InferRequest req; + ASSERT_NO_THROW(req = execNet.CreateInferRequest()); + InferenceEngine::Blob::Ptr blob; + ASSERT_THROW(req.SetBlob(cnnNet.getInputsInfo().begin()->first, blob), + InferenceEngine::Exception); +} + +TEST_P(InferRequestTests, failToSetEmptyOutputBlob) { + // Skip test according to plugin specific disabledTestPatterns() (if any) + SKIP_IF_CURRENT_TEST_IS_DISABLED() + // Create CNNNetwork from ngrpah::Function + InferenceEngine::CNNNetwork cnnNet(function); + // Load CNNNetwork to target plugins + auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); + // Create InferRequest + InferenceEngine::InferRequest req; + ASSERT_NO_THROW(req = execNet.CreateInferRequest()); + InferenceEngine::Blob::Ptr blob; + ASSERT_THROW(req.SetBlob(cnnNet.getOutputsInfo().begin()->first, blob), + InferenceEngine::Exception); +} + +TEST_P(InferRequestTests, failToSetNotAllocatedInput) { + // Skip test according to plugin specific disabledTestPatterns() (if any) + SKIP_IF_CURRENT_TEST_IS_DISABLED() + // Create CNNNetwork from ngrpah::Function + InferenceEngine::CNNNetwork cnnNet(function); + // Load CNNNetwork to target plugins + auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); + // Create InferRequest + InferenceEngine::InferRequest req; + ASSERT_NO_THROW(req = execNet.CreateInferRequest()); + InferenceEngine::Blob::Ptr blob = + FuncTestUtils::createAndFillBlob(cnnNet.getInputsInfo().begin()->second->getTensorDesc()); + ASSERT_NO_THROW(req.SetBlob(cnnNet.getInputsInfo().begin()->first, blob)); +} + +TEST_P(InferRequestTests, failToSetNotAllocatedOutput) { + // Skip test according to plugin specific disabledTestPatterns() (if any) + SKIP_IF_CURRENT_TEST_IS_DISABLED() + // Create CNNNetwork from ngrpah::Function + InferenceEngine::CNNNetwork cnnNet(function); + // Load CNNNetwork to target plugins + auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); + // Create InferRequest + InferenceEngine::InferRequest req; + ASSERT_NO_THROW(req = execNet.CreateInferRequest()); + InferenceEngine::Blob::Ptr blob = + FuncTestUtils::createAndFillBlob(cnnNet.getOutputsInfo().begin()->second->getTensorDesc()); + ASSERT_NO_THROW(req.SetBlob(cnnNet.getOutputsInfo().begin()->first, blob)); +} + +TEST_P(InferRequestTests, failToSetBlobWithIncorrectName) { + // Skip test according to plugin specific disabledTestPatterns() (if any) + SKIP_IF_CURRENT_TEST_IS_DISABLED() + // Create CNNNetwork from ngrpah::Function + InferenceEngine::CNNNetwork cnnNet(function); + // Load CNNNetwork to target plugins + auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); + // Create InferRequest + InferenceEngine::InferRequest req; + const char incorrect_input_name[] = "incorrect_input_name"; + ASSERT_NO_THROW(req = execNet.CreateInferRequest()); + InferenceEngine::Blob::Ptr blob = + FuncTestUtils::createAndFillBlob(cnnNet.getInputsInfo().begin()->second->getTensorDesc()); + blob->allocate(); + ASSERT_THROW(req.SetBlob(incorrect_input_name, blob), + InferenceEngine::Exception); +} + +TEST_P(InferRequestTests, failToSetInputWithIncorrectSizes) { + // Skip test according to plugin specific disabledTestPatterns() (if any) + SKIP_IF_CURRENT_TEST_IS_DISABLED() + // Create CNNNetwork from ngrpah::Function + InferenceEngine::CNNNetwork cnnNet(function); + // Load CNNNetwork to target plugins + auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); + // Create InferRequest + InferenceEngine::InferRequest req; + ASSERT_NO_THROW(req = execNet.CreateInferRequest()); + InferenceEngine::Blob::Ptr blob = + FuncTestUtils::createAndFillBlob(cnnNet.getInputsInfo().begin()->second->getTensorDesc()); + blob->allocate(); + blob->getTensorDesc().getDims()[0]*=2; + ASSERT_THROW(req.SetBlob(cnnNet.getInputsInfo().begin()->first, blob), + InferenceEngine::Exception); +} + +TEST_P(InferRequestTests, failToSetOutputWithIncorrectSizes) { + // Skip test according to plugin specific disabledTestPatterns() (if any) + SKIP_IF_CURRENT_TEST_IS_DISABLED() + // Create CNNNetwork from ngrpah::Function + InferenceEngine::CNNNetwork cnnNet(function); + // Load CNNNetwork to target plugins + auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); + // Create InferRequest + InferenceEngine::InferRequest req; + ASSERT_NO_THROW(req = execNet.CreateInferRequest()); + InferenceEngine::Blob::Ptr blob = + FuncTestUtils::createAndFillBlob(cnnNet.getOutputsInfo().begin()->second->getTensorDesc()); + blob->allocate(); + blob->getTensorDesc().getDims()[0]*=2; + ASSERT_THROW(req.SetBlob(cnnNet.getOutputsInfo().begin()->first, blob), + InferenceEngine::Exception); +} + +TEST_P(InferRequestTests, canInferWithoutSetAndGetInOut) { + // Skip test according to plugin specific disabledTestPatterns() (if any) + SKIP_IF_CURRENT_TEST_IS_DISABLED() + // Create CNNNetwork from ngrpah::Function + InferenceEngine::CNNNetwork cnnNet(function); + // Load CNNNetwork to target plugins + auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); + // Create InferRequest + InferenceEngine::InferRequest req; + ASSERT_NO_THROW(req = execNet.CreateInferRequest()); + ASSERT_NO_THROW(req.Infer()); +} + +TEST_P(InferRequestTests, canProcessDeallocatedInputBlobAfterGetBlob) { + // Skip test according to plugin specific disabledTestPatterns() (if any) + SKIP_IF_CURRENT_TEST_IS_DISABLED() + // Create CNNNetwork from ngrpah::Function + InferenceEngine::CNNNetwork cnnNet(function); + // Load CNNNetwork to target plugins + auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); + // Create InferRequest + InferenceEngine::InferRequest req; + InferenceEngine::Blob::Ptr blob; + ASSERT_NO_THROW(req = execNet.CreateInferRequest()); + ASSERT_NO_THROW(blob = req.GetBlob(cnnNet.getInputsInfo().begin()->first)); + ASSERT_NO_THROW(req.Infer()); +} + +TEST_P(InferRequestTests, canProcessDeallocatedInputBlobAfterGetBlobForAsync) { + // Skip test according to plugin specific disabledTestPatterns() (if any) + SKIP_IF_CURRENT_TEST_IS_DISABLED() + // Create CNNNetwork from ngrpah::Function + InferenceEngine::CNNNetwork cnnNet(function); + // Load CNNNetwork to target plugins + auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); + // Create InferRequest + InferenceEngine::InferRequest req; + InferenceEngine::Blob::Ptr blob; + ASSERT_NO_THROW(req = execNet.CreateInferRequest()); + ASSERT_NO_THROW(blob = req.GetBlob(cnnNet.getInputsInfo().begin()->first)); + ASSERT_NO_THROW(req.Infer()); + ASSERT_NO_THROW(req.StartAsync()); +} + +TEST_P(InferRequestTests, canProcessDeallocatedInputBlobAfterGetAndSetBlob) { + // Skip test according to plugin specific disabledTestPatterns() (if any) + SKIP_IF_CURRENT_TEST_IS_DISABLED() + // Create CNNNetwork from ngrpah::Function + InferenceEngine::CNNNetwork cnnNet(function); + // Load CNNNetwork to target plugins + auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); + // Create InferRequest + InferenceEngine::InferRequest req; + InferenceEngine::Blob::Ptr blob; + ASSERT_NO_THROW(req = execNet.CreateInferRequest()); + ASSERT_NO_THROW(blob = req.GetBlob(cnnNet.getInputsInfo().begin()->first)); + ASSERT_NO_THROW(req.SetBlob(cnnNet.getInputsInfo().begin()->first, blob)); + ASSERT_NO_THROW(req.Infer()); + ASSERT_NO_THROW(req.StartAsync()); +} + +TEST_P(InferRequestTests, canProcessDeallocatedInputBlobAfterSetBlob) { + // Skip test according to plugin specific disabledTestPatterns() (if any) + SKIP_IF_CURRENT_TEST_IS_DISABLED() + // Create CNNNetwork from ngrpah::Function + InferenceEngine::CNNNetwork cnnNet(function); + // Load CNNNetwork to target plugins + auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); + // Create InferRequest + InferenceEngine::InferRequest req; + InferenceEngine::Blob::Ptr blob = + FuncTestUtils::createAndFillBlob(cnnNet.getInputsInfo().begin()->second->getTensorDesc()); + ASSERT_NO_THROW(req = execNet.CreateInferRequest()); + blob->allocate(); + ASSERT_NO_THROW(req.SetBlob(cnnNet.getInputsInfo().begin()->first, blob)); + blob->deallocate(); + ASSERT_THROW(req.Infer(), InferenceEngine::Exception); +} + +TEST_P(InferRequestTests, canProcessDeallocatedOutputBlobAfterGetBlob) { + // Skip test according to plugin specific disabledTestPatterns() (if any) + SKIP_IF_CURRENT_TEST_IS_DISABLED() + // Create CNNNetwork from ngrpah::Function + InferenceEngine::CNNNetwork cnnNet(function); + // Load CNNNetwork to target plugins + auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); + // Create InferRequest + InferenceEngine::InferRequest req; + InferenceEngine::Blob::Ptr blob = + FuncTestUtils::createAndFillBlob(cnnNet.getOutputsInfo().begin()->second->getTensorDesc()); + ASSERT_NO_THROW(req = execNet.CreateInferRequest()); + blob->allocate(); + ASSERT_NO_THROW(req.SetBlob(cnnNet.getOutputsInfo().begin()->first, blob)); + blob->deallocate(); + ASSERT_THROW(req.Infer(), InferenceEngine::Exception); +} + +TEST_P(InferRequestTests, canProcessDeallocatedOutputBlobAfterGetBlobForAsync) { + // Skip test according to plugin specific disabledTestPatterns() (if any) + SKIP_IF_CURRENT_TEST_IS_DISABLED() + // Create CNNNetwork from ngrpah::Function + InferenceEngine::CNNNetwork cnnNet(function); + // Load CNNNetwork to target plugins + auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); + // Create InferRequest + InferenceEngine::InferRequest req; + InferenceEngine::Blob::Ptr blob = + FuncTestUtils::createAndFillBlob(cnnNet.getOutputsInfo().begin()->second->getTensorDesc()); + ASSERT_NO_THROW(req = execNet.CreateInferRequest()); + blob->allocate(); + ASSERT_NO_THROW(req.SetBlob(cnnNet.getOutputsInfo().begin()->first, blob)); + blob->deallocate(); + ASSERT_THROW(req.Infer(), InferenceEngine::Exception); + ASSERT_THROW({ req.StartAsync(); req.Wait(); }, InferenceEngine::Exception); +} + +TEST_P(InferRequestTests, canProcessDeallocatedOutputBlobAfterGetAndSetBlob) { + // Skip test according to plugin specific disabledTestPatterns() (if any) + SKIP_IF_CURRENT_TEST_IS_DISABLED() + // Create CNNNetwork from ngrpah::Function + InferenceEngine::CNNNetwork cnnNet(function); + // Load CNNNetwork to target plugins + auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); + // Create InferRequest + InferenceEngine::InferRequest req; + InferenceEngine::Blob::Ptr blob = + FuncTestUtils::createAndFillBlob(cnnNet.getOutputsInfo().begin()->second->getTensorDesc()); + ASSERT_NO_THROW(req = execNet.CreateInferRequest()); + blob->allocate(); + ASSERT_NO_THROW(blob = req.GetBlob(cnnNet.getOutputsInfo().begin()->first)); + ASSERT_NO_THROW(req.SetBlob(cnnNet.getOutputsInfo().begin()->first, blob)); + blob->deallocate(); + ASSERT_THROW(req.Infer(), InferenceEngine::Exception); +} + +TEST_P(InferRequestTests, canProcessDeallocatedOutputBlobAfterSetBlob) { + // Skip test according to plugin specific disabledTestPatterns() (if any) + SKIP_IF_CURRENT_TEST_IS_DISABLED() + // Create CNNNetwork from ngrpah::Function + InferenceEngine::CNNNetwork cnnNet(function); + // Load CNNNetwork to target plugins + auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); + // Create InferRequest + InferenceEngine::InferRequest req; + InferenceEngine::Blob::Ptr blob = + FuncTestUtils::createAndFillBlob(cnnNet.getOutputsInfo().begin()->second->getTensorDesc()); + ASSERT_NO_THROW(req = execNet.CreateInferRequest()); + blob->allocate(); + ASSERT_NO_THROW(req.SetBlob(cnnNet.getOutputsInfo().begin()->first, blob)); + blob->deallocate(); + ASSERT_THROW(req.Infer(), InferenceEngine::Exception); +} + +TEST_P(InferRequestTests, secondCallGetOutputDoNotReAllocateData) { + // Skip test according to plugin specific disabledTestPatterns() (if any) + SKIP_IF_CURRENT_TEST_IS_DISABLED() + // Create CNNNetwork from ngrpah::Function + InferenceEngine::CNNNetwork cnnNet(function); + // Load CNNNetwork to target plugins + auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); + // Create InferRequest + InferenceEngine::InferRequest req; + InferenceEngine::Blob::Ptr blob1; + InferenceEngine::Blob::Ptr blob2; + ASSERT_NO_THROW(req = execNet.CreateInferRequest()); + ASSERT_NO_THROW(blob1 = req.GetBlob(cnnNet.getInputsInfo().begin()->first)); + ASSERT_NO_THROW(blob2 = req.GetBlob(cnnNet.getInputsInfo().begin()->first)); + ASSERT_EQ(blob1.get(), blob2.get()); +} + +TEST_P(InferRequestTests, CorrectOneAsyncInferWithGetInOutWithInfWait) { + // Skip test according to plugin specific disabledTestPatterns() (if any) + SKIP_IF_CURRENT_TEST_IS_DISABLED() + // Create CNNNetwork from ngrpah::Function + InferenceEngine::CNNNetwork cnnNet(function); + // Load CNNNetwork to target plugins + auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); + // Create InferRequest + InferenceEngine::InferRequest req; + InferenceEngine::Blob::Ptr blob; + ASSERT_NO_THROW(req = execNet.CreateInferRequest()); + ASSERT_NO_THROW(blob = req.GetBlob(cnnNet.getInputsInfo().begin()->first)); + req.Infer(); + req.StartAsync(); + InferenceEngine::StatusCode sts; + sts = req.Wait(InferenceEngine::InferRequest::WaitMode::RESULT_READY); + ASSERT_EQ(InferenceEngine::StatusCode::OK, sts); + ASSERT_NO_THROW(blob = req.GetBlob(cnnNet.getOutputsInfo().begin()->first)); +} + +// Plugin correct infer request with allocating input and result BlobMaps inside plugin +TEST_P(InferRequestTests, canStartAsyncInferWithGetInOutWithStatusOnlyWait) { + // Skip test according to plugin specific disabledTestPatterns() (if any) + SKIP_IF_CURRENT_TEST_IS_DISABLED() + // Create CNNNetwork from ngrpah::Function + InferenceEngine::CNNNetwork cnnNet(function); + // Load CNNNetwork to target plugins + auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); + // Create InferRequest + InferenceEngine::InferRequest req; + InferenceEngine::Blob::Ptr blob = + FuncTestUtils::createAndFillBlob(cnnNet.getOutputsInfo().begin()->second->getTensorDesc()); + ASSERT_NO_THROW(req = execNet.CreateInferRequest()); + ASSERT_NO_THROW(blob = req.GetBlob(cnnNet.getInputsInfo().begin()->first)); + req.Infer(); + req.StartAsync(); + InferenceEngine::StatusCode sts; + sts = req.Wait(InferenceEngine::InferRequest::WaitMode::STATUS_ONLY); + ASSERT_TRUE(sts == InferenceEngine::StatusCode::OK || + sts == InferenceEngine::StatusCode::RESULT_NOT_READY); +} + +// Plugin correct infer request with allocating input and result BlobMaps inside plugin +TEST_P(InferRequestTests, FailedAsyncInferWithNegativeTimeForWait) { + // Skip test according to plugin specific disabledTestPatterns() (if any) + SKIP_IF_CURRENT_TEST_IS_DISABLED() + // Create CNNNetwork from ngrpah::Function + InferenceEngine::CNNNetwork cnnNet(function); + // Load CNNNetwork to target plugins + auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); + // Create InferRequest + InferenceEngine::InferRequest req; + InferenceEngine::Blob::Ptr blob = + FuncTestUtils::createAndFillBlob(cnnNet.getOutputsInfo().begin()->second->getTensorDesc()); + ASSERT_NO_THROW(req = execNet.CreateInferRequest()); + ASSERT_NO_THROW(blob = req.GetBlob(cnnNet.getInputsInfo().begin()->first)); + req.Infer(); + req.StartAsync(); + ASSERT_THROW(req.Wait(-2), InferenceEngine::Exception); +} + +TEST_P(InferRequestTests, canRun3SyncRequestsConsistentlyFromThreads) { + // Skip test according to plugin specific disabledTestPatterns() (if any) + SKIP_IF_CURRENT_TEST_IS_DISABLED() + // Create CNNNetwork from ngrpah::Function + InferenceEngine::CNNNetwork cnnNet(function); + // Load CNNNetwork to target plugins + auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); + // Create InferRequest + auto req1 = execNet.CreateInferRequest(); + auto req2 = execNet.CreateInferRequest(); + auto req3 = execNet.CreateInferRequest(); + + + auto f1 = std::async(std::launch::async, [&] { req1.Infer();}); + auto f2 = std::async(std::launch::async, [&] { req2.Infer();}); + auto f3 = std::async(std::launch::async, [&] { req3.Infer();}); + + ASSERT_NO_THROW(f1.get()); + ASSERT_NO_THROW(f2.get()); + ASSERT_NO_THROW(f3.get()); +} + +TEST_P(InferRequestTests, canRun3AsyncRequestsConsistentlyWithWait) { + // Skip test according to plugin specific disabledTestPatterns() (if any) + SKIP_IF_CURRENT_TEST_IS_DISABLED() + // Create CNNNetwork from ngrpah::Function + InferenceEngine::CNNNetwork cnnNet(function); + // Load CNNNetwork to target plugins + auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); + // Create InferRequest + auto req1 = execNet.CreateInferRequest(); + auto req2 = execNet.CreateInferRequest(); + auto req3 = execNet.CreateInferRequest(); + + req1.StartAsync(); + ASSERT_NO_THROW(req1.Wait(InferenceEngine::InferRequest::WaitMode::RESULT_READY)); + + req2.Infer(); + ASSERT_NO_THROW(req2.Wait(InferenceEngine::InferRequest::WaitMode::RESULT_READY)); + + req3.Infer(); + ASSERT_NO_THROW(req3.Wait(InferenceEngine::InferRequest::WaitMode::RESULT_READY)); +} + +TEST_P(InferRequestTests, canRun3AsyncRequestsConsistentlyFromThreadsWithoutWait) { + // Skip test according to plugin specific disabledTestPatterns() (if any) + SKIP_IF_CURRENT_TEST_IS_DISABLED() + // Create CNNNetwork from ngrpah::Function + InferenceEngine::CNNNetwork cnnNet(function); + // Load CNNNetwork to target plugins + auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); + // Create InferRequest + auto req1 = execNet.CreateInferRequest(); + auto req2 = execNet.CreateInferRequest(); + auto req3 = execNet.CreateInferRequest(); + InferenceEngine::ResponseDesc response1, response2, response3; + InferenceEngine::StatusCode sts1, sts2, sts3; + + req1.Infer(); + req2.Infer(); + req3.Infer(); + + std::thread t1([&] { req1.StartAsync(); sts1 = req1.Wait(InferenceEngine::InferRequest::WaitMode::RESULT_READY); }); + std::thread t2([&] { req2.StartAsync(); sts2 = req2.Wait(InferenceEngine::InferRequest::WaitMode::RESULT_READY); }); + std::thread t3([&] { req3.StartAsync(); sts3 = req3.Wait(InferenceEngine::InferRequest::WaitMode::RESULT_READY); }); + + t1.join(); + t2.join(); + t3.join(); + + ASSERT_EQ(static_cast(InferenceEngine::StatusCode::OK), sts1) << response1.msg; + ASSERT_EQ(static_cast(InferenceEngine::StatusCode::OK), sts2) << response2.msg; + ASSERT_EQ(static_cast(InferenceEngine::StatusCode::OK), sts3) << response3.msg; +} + +TEST_P(InferRequestTests, canWaitWithotStartAsync) { + // Skip test according to plugin specific disabledTestPatterns() (if any) + SKIP_IF_CURRENT_TEST_IS_DISABLED() + // Create CNNNetwork from ngrpah::Function + InferenceEngine::CNNNetwork cnnNet(function); + // Load CNNNetwork to target plugins + auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); + // Create InferRequest + auto req = execNet.CreateInferRequest(); + ASSERT_NO_THROW(req.Wait(InferenceEngine::InferRequest::WaitMode::RESULT_READY)); + ASSERT_NO_THROW(req.Wait(InferenceEngine::InferRequest::WaitMode::STATUS_ONLY)); + ASSERT_NO_THROW(req.Wait(1)); +} + +TEST_P(InferRequestTests, returnDeviceBusyOnSetBlobAfterAsyncInfer) { + // Skip test according to plugin specific disabledTestPatterns() (if any) + SKIP_IF_CURRENT_TEST_IS_DISABLED() + auto&& config = configuration; + auto itConfig = config.find(CONFIG_KEY(CPU_THROUGHPUT_STREAMS)); + if (itConfig != config.end()) { + if (itConfig->second != "CPU_THROUGHPUT_AUTO") { + if (std::stoi(itConfig->second) == 0) { + GTEST_SKIP() << "Not applicable with disabled streams"; + } + } + } + // Create CNNNetwork from ngrpah::Function + InferenceEngine::CNNNetwork cnnNet(function); + // Load CNNNetwork to target plugins + auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); + // Create InferRequest + auto req = execNet.CreateInferRequest(); + auto outputBlob = req.GetBlob(cnnNet.getInputsInfo().begin()->first); + InferenceEngine::ResponseDesc response; + + InferenceEngine::StatusCode sts; + sts = req.Wait(InferenceEngine::InferRequest::WaitMode::STATUS_ONLY); + ASSERT_EQ(InferenceEngine::StatusCode::INFER_NOT_STARTED, sts) << response.msg; + req.StartAsync(); + sts = req.Wait(InferenceEngine::InferRequest::WaitMode::RESULT_READY); + ASSERT_EQ(static_cast(InferenceEngine::StatusCode::OK), sts) << response.msg; + try { + req.SetBlob(cnnNet.getInputsInfo().begin()->first, outputBlob); + } + catch (const std::exception &e) { + std::cout << "Exception: " << e.what() << std::endl; + } + sts = req.Wait(InferenceEngine::InferRequest::WaitMode::STATUS_ONLY); + ASSERT_TRUE(sts == InferenceEngine::StatusCode::OK || + sts == InferenceEngine::StatusCode::RESULT_NOT_READY) << response.msg; +} + +TEST_P(InferRequestTests, returnDeviceBusyOnGetBlobAfterAsyncInfer) { + // Skip test according to plugin specific disabledTestPatterns() (if any) + SKIP_IF_CURRENT_TEST_IS_DISABLED() + // Create CNNNetwork from ngrpah::Function + InferenceEngine::CNNNetwork cnnNet(function); + // Load CNNNetwork to target plugins + auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); + // Create InferRequest + auto req = execNet.CreateInferRequest(); + auto outputBlob = req.GetBlob(cnnNet.getInputsInfo().begin()->first); + InferenceEngine::ResponseDesc response; + InferenceEngine::StatusCode sts; + req.StartAsync(); + sts = req.Wait(InferenceEngine::InferRequest::WaitMode::RESULT_READY); + ASSERT_EQ(static_cast(InferenceEngine::StatusCode::OK), sts) << response.msg; + try { + req.SetBlob(cnnNet.getInputsInfo().begin()->first, outputBlob); + } + catch (const std::exception &e) { + std::cout << "Exception" << e.what() << std::endl; + } +} + +TEST_P(InferRequestTests, returnDeviceBusyOnGetPerformanceCountAfterAsyncInfer) { + // Skip test according to plugin specific disabledTestPatterns() (if any) + SKIP_IF_CURRENT_TEST_IS_DISABLED() + // Create CNNNetwork from ngrpah::Function + InferenceEngine::CNNNetwork cnnNet(function); + // Load CNNNetwork to target plugins + auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); + // Create InferRequest + auto req = execNet.CreateInferRequest(); + auto outputBlob = req.GetBlob(cnnNet.getInputsInfo().begin()->first); + InferenceEngine::ResponseDesc response; + InferenceEngine::StatusCode sts; + req.StartAsync(); + sts = req.Wait(InferenceEngine::InferRequest::WaitMode::RESULT_READY); + ASSERT_EQ(static_cast(InferenceEngine::StatusCode::OK), sts) << response.msg; + + std::map perfMap; + + try { + perfMap = req.GetPerformanceCounts(); + } + catch (const std::exception &e) { + std::cout << "Exception" << e.what() << std::endl; + } +} + +class InferRequestTestsResultNotReady : public InferRequestTests { +}; + +TEST_P(InferRequestTestsResultNotReady, ReturnResultNotReadyFromWaitInAsyncModeForTooSmallTimeout) { + // Skip test according to plugin specific disabledTestPatterns() (if any) + SKIP_IF_CURRENT_TEST_IS_DISABLED() + // Create CNNNetwork from ngraph::Function + // return ngrpah::Function + // GetNetwork(3000, 380) make inference around 20ms on GNA SW + // so increases chances for getting RESULT_NOT_READY + function = SubgraphTestsDefinitions::Basic_LSTM_S::GetNetwork(300, 38); + InferenceEngine::CNNNetwork cnnNet(function); + // Load CNNNetwork to target plugins + auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); + // Create InferRequest + InferenceEngine::InferRequest req; + ASSERT_NO_THROW(req = execNet.CreateInferRequest()); + InferenceEngine::StatusCode sts = InferenceEngine::StatusCode::OK; + std::promise callbackTimeStamp; + auto callbackTimeStampFuture = callbackTimeStamp.get_future(); + // add a callback to the request and capture the timestamp + req.SetCompletionCallback([&]() { + callbackTimeStamp.set_value(std::chrono::system_clock::now()); + }); + req.StartAsync(); + ASSERT_NO_THROW(sts = req.Wait(InferenceEngine::InferRequest::WaitMode::STATUS_ONLY)); + // get timestamp taken AFTER return from the Wait(STATUS_ONLY) + const auto afterWaitTimeStamp = std::chrono::system_clock::now(); + // IF the callback timestamp is larger than the afterWaitTimeStamp + // then we should observe RESULT_NOT_READY + if (afterWaitTimeStamp < callbackTimeStampFuture.get()) { + ASSERT_TRUE(sts == InferenceEngine::StatusCode::RESULT_NOT_READY); + } + ASSERT_NO_THROW(req.Wait(InferenceEngine::InferRequest::WaitMode::RESULT_READY)); +} +} // namespace BehaviorTestsDefinitions diff --git a/inference-engine/tests/functional/plugin/shared/include/behavior/infer_request_dynamic.hpp b/inference-engine/tests/functional/plugin/shared/include/behavior/infer_request_dynamic.hpp new file mode 100644 index 00000000000..52116bd19e6 --- /dev/null +++ b/inference-engine/tests/functional/plugin/shared/include/behavior/infer_request_dynamic.hpp @@ -0,0 +1,320 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +#include +#include +#include +#include +#include +#include +#include "ie_extension.h" +#include +#include "shared_test_classes/base/layer_test_utils.hpp" +#include "ngraph_functions/utils/ngraph_helpers.hpp" +#include "ngraph_functions/builders.hpp" +#include +#include +#include +#include +#include +#include "common_test_utils/common_utils.hpp" +#include "functional_test_utils/plugin_cache.hpp" +#include "functional_test_utils/blob_utils.hpp" +#include "ngraph_functions/subgraph_builders.hpp" +#include "shared_test_classes/subgraph/basic_lstm.hpp" + + +namespace BehaviorTestsDefinitions { + +class InferRequestDynamicTests : public BehaviorTestsUtils::BehaviorTestsBasic { +public: + void SetUp() override { + std::tie(netPrecision, targetDevice, configuration) = this->GetParam(); + function = ngraph::builder::subgraph::makeSplitConvConcat(); + } +}; + +TEST_P(InferRequestDynamicTests, InferDynamicNetworkWithoutSetShape) { + const std::string param_name = "Param_1"; + // Skip test according to plugin specific disabledTestPatterns() (if any) + SKIP_IF_CURRENT_TEST_IS_DISABLED() + // Create CNNNetwork from ngrpah::Function + InferenceEngine::CNNNetwork cnnNet(function); + std::map shapes; + shapes[param_name] = {ngraph::Dimension::dynamic(), 4, 20, 20}; + cnnNet.reshape(shapes); + // Load CNNNetwork to target plugins + auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); + // Create InferRequest + InferenceEngine::InferRequest req; + InferenceEngine::Blob::Ptr blob; + ASSERT_NO_THROW(req = execNet.CreateInferRequest()); + ASSERT_NO_THROW(blob = req.GetBlob(cnnNet.getInputsInfo().begin()->first)); +} + +TEST_P(InferRequestDynamicTests, InferDynamicNetworkBoundWithoutSetShape) { + const std::string param_name = "Param_1"; + // Skip test according to plugin specific disabledTestPatterns() (if any) + SKIP_IF_CURRENT_TEST_IS_DISABLED() + // Create CNNNetwork from ngrpah::Function + InferenceEngine::CNNNetwork cnnNet(function); + std::map shapes; + shapes[param_name] = {ngraph::Dimension(0, 5), 4, 20, 20}; + cnnNet.reshape(shapes); + // Load CNNNetwork to target plugins + auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); + // Create InferRequest + InferenceEngine::InferRequest req; + InferenceEngine::Blob::Ptr blob; + ASSERT_NO_THROW(req = execNet.CreateInferRequest()); + ASSERT_NO_THROW(blob = req.GetBlob(cnnNet.getInputsInfo().begin()->first)); +} + + +TEST_P(InferRequestDynamicTests, InferDynamicNetworkWithGetBlob) { + const std::string param_name = "Param_1"; + const InferenceEngine::SizeVector refShape = {1, 4, 20, 20}; + const InferenceEngine::SizeVector refOutShape = {1, 10, 18, 18}; + // Skip test according to plugin specific disabledTestPatterns() (if any) + SKIP_IF_CURRENT_TEST_IS_DISABLED() + // Create CNNNetwork from ngrpah::Function + InferenceEngine::CNNNetwork cnnNet(function); + std::map shapes; + shapes[param_name] = {ngraph::Dimension::dynamic(), 4, 20, 20}; + cnnNet.reshape(shapes); + // Load CNNNetwork to target plugins + auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); + // Create InferRequest + InferenceEngine::InferRequest req; + InferenceEngine::Blob::Ptr blob; + ASSERT_NO_THROW(req = execNet.CreateInferRequest()); + //ASSERT_NO_THROW(req.SetShape(param_name, {1, 4, 20, 20})); + ASSERT_NO_THROW(blob = req.GetBlob(cnnNet.getInputsInfo().begin()->first)); + ASSERT_NO_THROW(blob->setShape({1, 4, 20, 20})); + ASSERT_EQ(blob->getTensorDesc().getDims(), refShape); + req.Infer(); + req.StartAsync(); + InferenceEngine::StatusCode sts; + sts = req.Wait(InferenceEngine::InferRequest::WaitMode::RESULT_READY); + ASSERT_EQ(InferenceEngine::StatusCode::OK, sts); + ASSERT_NO_THROW(blob = req.GetBlob(cnnNet.getOutputsInfo().begin()->first)); + ASSERT_EQ(blob->getTensorDesc().getDims(), refOutShape); +} + +TEST_P(InferRequestDynamicTests, InferUpperBoundNetworkWithGetBlob) { + const std::string param_name = "Param_1"; + const InferenceEngine::SizeVector refShape = {1, 4, 20, 20}; + const InferenceEngine::SizeVector refOutShape = {1, 10, 18, 18}; + // Skip test according to plugin specific disabledTestPatterns() (if any) + SKIP_IF_CURRENT_TEST_IS_DISABLED() + // Create CNNNetwork from ngrpah::Function + InferenceEngine::CNNNetwork cnnNet(function); + std::map shapes; + shapes[param_name] = {ngraph::Dimension(0, 19), 4, 20, 20}; + cnnNet.reshape(shapes); + // Load CNNNetwork to target plugins + auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); + // Create InferRequest + InferenceEngine::InferRequest req; + InferenceEngine::Blob::Ptr blob; + ASSERT_NO_THROW(req = execNet.CreateInferRequest()); + //ASSERT_NO_THROW(req.SetShape(param_name, {1, 4, 20, 20})); + ASSERT_NO_THROW(blob = req.GetBlob(cnnNet.getInputsInfo().begin()->first)); + ASSERT_NO_THROW(blob->setShape({1, 4, 20, 20})); + ASSERT_EQ(blob->getTensorDesc().getDims(), refShape); + req.Infer(); + req.StartAsync(); + InferenceEngine::StatusCode sts; + sts = req.Wait(InferenceEngine::InferRequest::WaitMode::RESULT_READY); + ASSERT_EQ(InferenceEngine::StatusCode::OK, sts); + ASSERT_NO_THROW(blob = req.GetBlob(cnnNet.getOutputsInfo().begin()->first)); + ASSERT_EQ(blob->getTensorDesc().getDims(), refOutShape); +} + +TEST_P(InferRequestDynamicTests, InferOutOfRangeShapeNetworkWithGetBlobLower) { + const std::string param_name = "Param_1"; + const InferenceEngine::SizeVector refShape = {1, 4, 20, 20}; + const InferenceEngine::SizeVector refOutShape = {1, 10, 18, 18}; + // Skip test according to plugin specific disabledTestPatterns() (if any) + SKIP_IF_CURRENT_TEST_IS_DISABLED() + // Create CNNNetwork from ngrpah::Function + InferenceEngine::CNNNetwork cnnNet(function); + std::map shapes; + shapes[param_name] = {ngraph::Dimension(2, 3), 4, 20, 20}; + cnnNet.reshape(shapes); + // Load CNNNetwork to target plugins + auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); + // Create InferRequest + InferenceEngine::InferRequest req; + InferenceEngine::Blob::Ptr blob; + ASSERT_NO_THROW(req = execNet.CreateInferRequest()); + ASSERT_NO_THROW(blob = req.GetBlob(cnnNet.getInputsInfo().begin()->first)); + ASSERT_NO_THROW(blob->setShape({1, 4, 20, 20})); + // Plugin may or may not throw in case if input tensor has dimensions that are out of bounds + //ASSERT_THROW(req.Infer(), InferenceEngine::Exception); +} + +TEST_P(InferRequestDynamicTests, InferOutOfRangeShapeNetworkWithGetBlobUpper) { + const std::string param_name = "Param_1"; + const InferenceEngine::SizeVector refShape = {1, 4, 20, 20}; + const InferenceEngine::SizeVector refOutShape = {1, 10, 18, 18}; + // Skip test according to plugin specific disabledTestPatterns() (if any) + SKIP_IF_CURRENT_TEST_IS_DISABLED() + // Create CNNNetwork from ngrpah::Function + InferenceEngine::CNNNetwork cnnNet(function); + std::map shapes; + shapes[param_name] = {ngraph::Dimension(1, 2), 4, 20, 20}; + cnnNet.reshape(shapes); + // Load CNNNetwork to target plugins + auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); + // Create InferRequest + InferenceEngine::InferRequest req; + InferenceEngine::Blob::Ptr blob; + ASSERT_NO_THROW(req = execNet.CreateInferRequest()); + ASSERT_NO_THROW(blob = req.GetBlob(cnnNet.getInputsInfo().begin()->first)); + ASSERT_NO_THROW(blob->setShape({3, 4, 20, 20})); + // Plugin may or may not throw in case if input tensor has dimensions that are out of bounds + // ASSERT_THROW(req.Infer(), InferenceEngine::Exception); +} + +TEST_P(InferRequestDynamicTests, InferDynamicNetworkWithGetBlob2times) { + const std::string param_name = "Param_1"; + const InferenceEngine::SizeVector refShape = {1, 4, 20, 20}; + const InferenceEngine::SizeVector refShape2 = {2, 4, 20, 20}; + const InferenceEngine::SizeVector refOutShape = {1, 10, 18, 18}; + const InferenceEngine::SizeVector refOutShape2 = {2, 10, 18, 18}; + // Skip test according to plugin specific disabledTestPatterns() (if any) + SKIP_IF_CURRENT_TEST_IS_DISABLED() + // Create CNNNetwork from ngrpah::Function + InferenceEngine::CNNNetwork cnnNet(function); + std::map shapes; + shapes[param_name] = {ngraph::Dimension::dynamic(), 4, 20, 20}; + cnnNet.reshape(shapes); + // Load CNNNetwork to target plugins + auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); + // Create InferRequest + InferenceEngine::InferRequest req; + InferenceEngine::Blob::Ptr blob; + ASSERT_NO_THROW(req = execNet.CreateInferRequest()); + ASSERT_NO_THROW(blob = req.GetBlob(cnnNet.getInputsInfo().begin()->first)); + ASSERT_NO_THROW(blob->setShape(refShape)); + ASSERT_EQ(blob->getTensorDesc().getDims(), refShape); + req.Infer(); + req.StartAsync(); + InferenceEngine::StatusCode sts; + sts = req.Wait(InferenceEngine::InferRequest::WaitMode::RESULT_READY); + ASSERT_EQ(InferenceEngine::StatusCode::OK, sts); + ASSERT_NO_THROW(blob = req.GetBlob(cnnNet.getOutputsInfo().begin()->first)); + ASSERT_EQ(blob->getTensorDesc().getDims(), refOutShape); + + ASSERT_NO_THROW(blob = req.GetBlob(cnnNet.getInputsInfo().begin()->first)); + ASSERT_NO_THROW(blob->setShape(refShape2)); + ASSERT_EQ(blob->getTensorDesc().getDims(), refShape2); + req.Infer(); + req.StartAsync(); + sts = req.Wait(InferenceEngine::InferRequest::WaitMode::RESULT_READY); + ASSERT_EQ(InferenceEngine::StatusCode::OK, sts); + ASSERT_NO_THROW(blob = req.GetBlob(cnnNet.getOutputsInfo().begin()->first)); + ASSERT_EQ(blob->getTensorDesc().getDims(), refOutShape2); +} + + +TEST_P(InferRequestDynamicTests, GetSameBlob2times) { + const std::string param_name = "Param_1"; + const InferenceEngine::SizeVector refShape = {1, 4, 20, 20}; + // Skip test according to plugin specific disabledTestPatterns() (if any) + SKIP_IF_CURRENT_TEST_IS_DISABLED() + // Create CNNNetwork from ngrpah::Function + InferenceEngine::CNNNetwork cnnNet(function); + std::map shapes; + shapes[param_name] = {ngraph::Dimension::dynamic(), 4, 20, 20}; + cnnNet.reshape(shapes); + // Load CNNNetwork to target plugins + auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); + // Create InferRequest + InferenceEngine::InferRequest req; + InferenceEngine::Blob::Ptr blob; + ASSERT_NO_THROW(req = execNet.CreateInferRequest()); + ASSERT_NO_THROW(blob = req.GetBlob(cnnNet.getInputsInfo().begin()->first)); + ASSERT_NO_THROW(blob->setShape(refShape)); + ASSERT_EQ(blob->getTensorDesc().getDims(), refShape); + ASSERT_NO_THROW(blob = req.GetBlob(cnnNet.getInputsInfo().begin()->first)); + ASSERT_EQ(blob->getTensorDesc().getDims(), refShape); +} + +TEST_P(InferRequestDynamicTests, InferDynamicNetworkWithSetBlob) { + const std::string param_name = "Param_1"; + const InferenceEngine::SizeVector refShape = {1, 4, 20, 20}; + const InferenceEngine::SizeVector refOutShape = {1, 10, 18, 18}; + // Skip test according to plugin specific disabledTestPatterns() (if any) + SKIP_IF_CURRENT_TEST_IS_DISABLED() + // Create CNNNetwork from ngrpah::Function + InferenceEngine::CNNNetwork cnnNet(function); + std::map shapes; + shapes[param_name] = {ngraph::Dimension::dynamic(), 4, 20, 20}; + cnnNet.reshape(shapes); + // Load CNNNetwork to target plugins + auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); + // Create InferRequest + InferenceEngine::InferRequest req; + InferenceEngine::Blob::Ptr blob = make_blob_with_precision({InferenceEngine::Precision::FP32, refShape, InferenceEngine::Layout::NCHW}); + blob->allocate(); + ASSERT_NO_THROW(req = execNet.CreateInferRequest()); + ASSERT_NO_THROW(req.SetBlob(cnnNet.getInputsInfo().begin()->first, blob)); + ASSERT_EQ(blob->getTensorDesc().getDims(), refShape); + req.Infer(); + req.StartAsync(); + InferenceEngine::StatusCode sts; + sts = req.Wait(InferenceEngine::InferRequest::WaitMode::RESULT_READY); + ASSERT_EQ(InferenceEngine::StatusCode::OK, sts); + ASSERT_NO_THROW(blob = req.GetBlob(cnnNet.getOutputsInfo().begin()->first)); + ASSERT_EQ(blob->getTensorDesc().getDims(), refOutShape); +} + +TEST_P(InferRequestDynamicTests, InferDynamicNetworkWithSetBlob2times) { + const std::string param_name = "Param_1"; + const InferenceEngine::SizeVector refShape = {1, 4, 20, 20}; + const InferenceEngine::SizeVector refShape2 = {2, 4, 20, 20}; + const InferenceEngine::SizeVector refOutShape = {1, 10, 18, 18}; + const InferenceEngine::SizeVector refOutShape2 = {2, 10, 18, 18}; + // Skip test according to plugin specific disabledTestPatterns() (if any) + SKIP_IF_CURRENT_TEST_IS_DISABLED() + // Create CNNNetwork from ngrpah::Function + InferenceEngine::CNNNetwork cnnNet(function); + std::map shapes; + shapes[param_name] = {ngraph::Dimension::dynamic(), 4, 20, 20}; + cnnNet.reshape(shapes); + // Load CNNNetwork to target plugins + auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); + // Create InferRequest + InferenceEngine::InferRequest req; + InferenceEngine::Blob::Ptr blob = make_blob_with_precision({InferenceEngine::Precision::FP32, refShape, InferenceEngine::Layout::NCHW}); + blob->allocate(); + + ASSERT_NO_THROW(req = execNet.CreateInferRequest()); + ASSERT_NO_THROW(req.SetBlob(cnnNet.getInputsInfo().begin()->first, blob)); + ASSERT_EQ(blob->getTensorDesc().getDims(), refShape); + req.Infer(); + req.StartAsync(); + InferenceEngine::StatusCode sts; + sts = req.Wait(InferenceEngine::InferRequest::WaitMode::RESULT_READY); + ASSERT_EQ(InferenceEngine::StatusCode::OK, sts); + ASSERT_NO_THROW(blob = req.GetBlob(cnnNet.getOutputsInfo().begin()->first)); + ASSERT_EQ(blob->getTensorDesc().getDims(), refOutShape); + + blob = make_blob_with_precision({InferenceEngine::Precision::FP32, refShape2, InferenceEngine::Layout::NCHW}); + blob->allocate(); + ASSERT_NO_THROW(req.SetBlob(cnnNet.getInputsInfo().begin()->first, blob)); + ASSERT_EQ(blob->getTensorDesc().getDims(), refShape2); + req.Infer(); + req.StartAsync(); + sts = req.Wait(InferenceEngine::InferRequest::WaitMode::RESULT_READY); + ASSERT_EQ(InferenceEngine::StatusCode::OK, sts); + ASSERT_NO_THROW(blob = req.GetBlob(cnnNet.getOutputsInfo().begin()->first)); + ASSERT_EQ(blob->getTensorDesc().getDims(), refOutShape2); +} + +} // namespace BehaviorTestsDefinitions diff --git a/inference-engine/tests/ngraph_helpers/ngraph_functions/include/ngraph_functions/subgraph_builders.hpp b/inference-engine/tests/ngraph_helpers/ngraph_functions/include/ngraph_functions/subgraph_builders.hpp index b2c5b1d348a..171bd02fc4b 100644 --- a/inference-engine/tests/ngraph_helpers/ngraph_functions/include/ngraph_functions/subgraph_builders.hpp +++ b/inference-engine/tests/ngraph_helpers/ngraph_functions/include/ngraph_functions/subgraph_builders.hpp @@ -42,6 +42,7 @@ inline std::shared_ptr makeConvPoolRelu(std::vector in inline std::shared_ptr makeSplitConvConcat(std::vector inputShape = {1, 4, 20, 20}, ngraph::element::Type_t ngPrc = ngraph::element::Type_t::f32) { auto params = ngraph::builder::makeParams(ngPrc, {inputShape}); + params.front()->set_friendly_name("Param_1"); auto split = ngraph::builder::makeSplit(params[0], ngPrc, 2, 1); auto conv1 = ngraph::builder::makeConvolution(split->output(0), ngPrc, {3, 3}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, diff --git a/inference-engine/tests/unit/inference_engine/ie_blob_test.cpp b/inference-engine/tests/unit/inference_engine/ie_blob_test.cpp index 0223262a56f..d84f185727b 100644 --- a/inference-engine/tests/unit/inference_engine/ie_blob_test.cpp +++ b/inference-engine/tests/unit/inference_engine/ie_blob_test.cpp @@ -325,6 +325,23 @@ TEST_F(BlobTests, canCreateBlobOnExistedMemory) { } +// SetShape +TEST_F(BlobTests, canSetShape) { + auto b = InferenceEngine::make_shared_blob( + InferenceEngine::TensorDesc(InferenceEngine::Precision::FP32, {1, 2, 3}, InferenceEngine::ANY)); + b->allocate(); + + ASSERT_NO_THROW(b->setShape({4, 5, 6})); + + auto newDims = b->getTensorDesc().getDims(); + ASSERT_EQ(newDims.size(), 3); + ASSERT_EQ(newDims[0], 4); + ASSERT_EQ(newDims[1], 5); + ASSERT_EQ(newDims[2], 6); +} + + + TEST_F(BlobTests, canModifyDataInRangedFor) { InferenceEngine::SizeVector v = {1, 2, 3}; InferenceEngine::TBlob blob({ InferenceEngine::Precision::I32, v, InferenceEngine::CHW }); diff --git a/ngraph/core/src/node.cpp b/ngraph/core/src/node.cpp index 17bfa8723ea..c6f4a9dd352 100644 --- a/ngraph/core/src/node.cpp +++ b/ngraph/core/src/node.cpp @@ -508,11 +508,7 @@ const ov::PartialShape& ov::Node::get_output_partial_shape(size_t i) const { } const ngraph::Shape& ov::Node::get_shape() const { - if (get_output_size() != 1) { - stringstream es; - es << "get_shape() must be called on a node with exactly one output (" << description() << ")"; - throw ngraph::ngraph_error(es); - } + NODE_VALIDATION_CHECK(this, get_output_size() == 1, "get_shape() must be called on a node with exactly one output"); return get_output_shape(0); } diff --git a/ngraph/test/runtime/interpreter/int_executable.cpp b/ngraph/test/runtime/interpreter/int_executable.cpp index 8d24cd6f088..07a86efc5ab 100644 --- a/ngraph/test/runtime/interpreter/int_executable.cpp +++ b/ngraph/test/runtime/interpreter/int_executable.cpp @@ -17,6 +17,34 @@ using namespace ngraph; NGRAPH_SUPPRESS_DEPRECATED_START +class TemporaryOverrideOutputs +{ + std::shared_ptr node; + std::vector orig_shapes; + +public: + TemporaryOverrideOutputs(std::shared_ptr node, + const std::vector>& args) + : node(node) + { + for (size_t i = 0; i < args.size(); ++i) + { + auto output = node->get_input_source_output(i); + orig_shapes.push_back(output.get_partial_shape()); + output.get_tensor().set_partial_shape(args[i]->get_shape()); + } + } + + ~TemporaryOverrideOutputs() + { + for (size_t i = 0; i < orig_shapes.size(); ++i) + { + auto output = node->get_input_source_output(i); + output.get_tensor().set_partial_shape(orig_shapes[i]); + } + } +}; + runtime::interpreter::INTExecutable::INTExecutable(const shared_ptr& function, bool enable_performance_collection) : m_is_compiled{true} @@ -93,6 +121,14 @@ bool runtime::interpreter::INTExecutable::call(const vectorinputs().size(); ++i) + { + outputs.push_back(op->get_input_source_output(i)); + } + auto cloned_node = op->clone_with_new_inputs(outputs); + // get op outputs from map or create vector> op_outputs; for (size_t i = 0; i < op->get_output_size(); ++i) @@ -102,7 +138,8 @@ bool runtime::interpreter::INTExecutable::call(const vector(op->output(i)); + // Use cloned_node to create HostTensor with static dimensions + host_tensor = make_shared(cloned_node->output(i)); tensor_map.insert({tensor, host_tensor}); } else @@ -136,9 +173,10 @@ bool runtime::interpreter::INTExecutable::call(const vectorevaluate(op_outputs, op_inputs)) + // Call evaluate for cloned_node with static shapes + if (!cloned_node->evaluate(op_outputs, op_inputs)) { - evaluate_node(op, op_outputs, op_inputs); + evaluate_node(cloned_node, op_outputs, op_inputs); } if (m_performance_counters_enabled) { From 70e65656197e93fe31584872672c3caac116b6e8 Mon Sep 17 00:00:00 2001 From: Gabriele Galiero Casay Date: Wed, 1 Sep 2021 10:22:46 +0200 Subject: [PATCH 68/76] Refactor backend test suite of Reduction ops into template plugin tests (#6930) * Refactor visitor test of reduce operations to include operation name * Add template plugin tests for reduction operations * Remove backent unit tests of reduction operations * Use Tensor utility to instantiate tests * Use std::for_each instead of raw for loop to produce test case instances * Cover remaining backend tests in manifest by SLTs cases * Fix regex to skip cpu test failing in centos build with precision u64 --- .../functional/op_reference/reduce_l1.cpp | 57 ++ .../functional/op_reference/reduce_l2.cpp | 71 ++ .../functional/op_reference/reduce_max.cpp | 79 ++ .../functional/op_reference/reduce_mean.cpp | 81 ++ .../functional/op_reference/reduce_min.cpp | 78 ++ .../functional/op_reference/reduce_prod.cpp | 102 ++ .../functional/op_reference/reduce_sum.cpp | 130 +++ .../functional/op_reference/reduction.cpp | 15 + .../functional/op_reference/reduction.hpp | 64 ++ .../single_layer_tests/reduce_ops.cpp | 77 +- .../skip_tests_config.cpp | 3 + ngraph/test/CMakeLists.txt | 11 - ngraph/test/backend/reduce_l1.in.cpp | 59 -- ngraph/test/backend/reduce_l2.in.cpp | 57 -- ngraph/test/backend/reduce_max.in.cpp | 456 --------- ngraph/test/backend/reduce_mean.in.cpp | 285 ------ ngraph/test/backend/reduce_min.in.cpp | 489 ---------- ngraph/test/backend/reduce_prod.in.cpp | 525 ----------- ngraph/test/backend/reduce_sum.in.cpp | 875 ------------------ ngraph/test/op_eval/reduce_max.cpp | 284 ------ ngraph/test/op_eval/reduce_min.cpp | 235 ----- ngraph/test/op_eval/reduce_prod.cpp | 223 ----- ngraph/test/op_eval/reduce_sum.cpp | 369 -------- ngraph/test/runtime/ie/unit_test.manifest | 22 - .../runtime/interpreter/unit_test.manifest | 14 - ngraph/test/visitors/op/reduce_l1.cpp | 4 +- ngraph/test/visitors/op/reduce_l2.cpp | 4 +- .../test/visitors/op/reduce_logical_and.cpp | 4 +- ngraph/test/visitors/op/reduce_logical_or.cpp | 4 +- ngraph/test/visitors/op/reduce_max.cpp | 4 +- ngraph/test/visitors/op/reduce_mean.cpp | 4 +- ngraph/test/visitors/op/reduce_min.cpp | 4 +- ngraph/test/visitors/op/reduce_ops.hpp | 73 +- ngraph/test/visitors/op/reduce_prod.cpp | 4 +- ngraph/test/visitors/op/reduce_sum.cpp | 4 +- 35 files changed, 833 insertions(+), 3937 deletions(-) create mode 100644 docs/template_plugin/tests/functional/op_reference/reduce_l1.cpp create mode 100644 docs/template_plugin/tests/functional/op_reference/reduce_l2.cpp create mode 100644 docs/template_plugin/tests/functional/op_reference/reduce_max.cpp create mode 100644 docs/template_plugin/tests/functional/op_reference/reduce_mean.cpp create mode 100644 docs/template_plugin/tests/functional/op_reference/reduce_min.cpp create mode 100644 docs/template_plugin/tests/functional/op_reference/reduce_prod.cpp create mode 100644 docs/template_plugin/tests/functional/op_reference/reduce_sum.cpp create mode 100644 docs/template_plugin/tests/functional/op_reference/reduction.cpp create mode 100644 docs/template_plugin/tests/functional/op_reference/reduction.hpp delete mode 100644 ngraph/test/backend/reduce_l1.in.cpp delete mode 100644 ngraph/test/backend/reduce_l2.in.cpp delete mode 100644 ngraph/test/backend/reduce_max.in.cpp delete mode 100644 ngraph/test/backend/reduce_mean.in.cpp delete mode 100644 ngraph/test/backend/reduce_min.in.cpp delete mode 100644 ngraph/test/backend/reduce_prod.in.cpp delete mode 100644 ngraph/test/backend/reduce_sum.in.cpp delete mode 100644 ngraph/test/op_eval/reduce_max.cpp delete mode 100644 ngraph/test/op_eval/reduce_min.cpp delete mode 100644 ngraph/test/op_eval/reduce_prod.cpp delete mode 100644 ngraph/test/op_eval/reduce_sum.cpp diff --git a/docs/template_plugin/tests/functional/op_reference/reduce_l1.cpp b/docs/template_plugin/tests/functional/op_reference/reduce_l1.cpp new file mode 100644 index 00000000000..b26beac64f8 --- /dev/null +++ b/docs/template_plugin/tests/functional/op_reference/reduce_l1.cpp @@ -0,0 +1,57 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include + +#include +#include +#include +#include + +#include "reduction.hpp" + +using namespace ngraph; +using namespace InferenceEngine; +using ReductionType = ngraph::helpers::ReductionType; + +namespace reference_tests { +namespace ReductionOpsRefTestDefinitions { +namespace { + +template +std::vector generateReductionParams(const bool keep_dims) { + using T = typename element_type_traits::value_type; + std::vector params = { + ReductionParams(ReductionType::L1, keep_dims, std::vector{2}, + Tensor({3, 2, 2}, element::Type(IN_ET), std::vector{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}), + Tensor(reduce(Shape{3, 2, 2}, AxisSet{2}, keep_dims), + element::Type(IN_ET), std::vector{3, 7, 11, 15, 19, 23})) + }; + return params; +} + +std::vector generateReductionCombinedParams() { + const std::vector> reductionTypeParams { + generateReductionParams(true), + generateReductionParams(false), + generateReductionParams(true), + generateReductionParams(false), + generateReductionParams(true), + generateReductionParams(false), + generateReductionParams(true), + generateReductionParams(false), + generateReductionParams(true), + generateReductionParams(false) + }; + std::vector combinedParams; + std::for_each(reductionTypeParams.begin(), reductionTypeParams.end(), [&](std::vector params) { + combinedParams.insert(combinedParams.end(), params.begin(), params.end()); + }); + return combinedParams; +} +} // namespace +INSTANTIATE_TEST_SUITE_P(smoke_Reduction_With_Hardcoded_Refs, ReferenceReductionLayerTest, ::testing::ValuesIn(generateReductionCombinedParams()), + ReferenceReductionLayerTest::getTestCaseName); +} // namespace ReductionOpsRefTestDefinitions +} // namespace reference_tests diff --git a/docs/template_plugin/tests/functional/op_reference/reduce_l2.cpp b/docs/template_plugin/tests/functional/op_reference/reduce_l2.cpp new file mode 100644 index 00000000000..0cc977cf75a --- /dev/null +++ b/docs/template_plugin/tests/functional/op_reference/reduce_l2.cpp @@ -0,0 +1,71 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include + +#include +#include +#include +#include + +#include "reduction.hpp" + +using namespace ngraph; +using namespace InferenceEngine; +using ReductionType = ngraph::helpers::ReductionType; + +namespace reference_tests { +namespace ReductionOpsRefTestDefinitions { +namespace { + +template ::value_type>::value, bool>::type = true> +std::vector generateReductionParams(const bool keep_dims) { + using T = typename element_type_traits::value_type; + std::vector params = { + ReductionParams(ReductionType::L2, keep_dims, std::vector{2}, + Tensor({3, 2, 2}, element::Type(IN_ET), std::vector{1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0}), + Tensor(reduce(Shape{3, 2, 2}, AxisSet{2}, keep_dims), + element::Type(IN_ET), std::vector{2.23606798, 5.0, 7.81024968, 10.63014581, 13.45362405, 16.2788206})) + }; + return params; +} + +template ::value_type>::value, bool>::type = true> +std::vector generateReductionParams(const bool keep_dims) { + using T = typename element_type_traits::value_type; + std::vector params = { + ReductionParams(ReductionType::L2, keep_dims, std::vector{2}, + Tensor({3, 2, 2}, element::Type(IN_ET), std::vector{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}), + Tensor(reduce(Shape{3, 2, 2}, AxisSet{2}, keep_dims), element::Type(IN_ET), std::vector{2, 5, 8, 11, 13, 16})) + }; + return params; +} + +std::vector generateReductionCombinedParams() { + const std::vector> reductionTypeParams { + generateReductionParams(true), + generateReductionParams(false), + generateReductionParams(true), + generateReductionParams(false), + generateReductionParams(true), + generateReductionParams(false), + generateReductionParams(true), + generateReductionParams(false), + generateReductionParams(true), + generateReductionParams(false) + }; + std::vector combinedParams; + std::for_each(reductionTypeParams.begin(), reductionTypeParams.end(), [&](std::vector params) { + combinedParams.insert(combinedParams.end(), params.begin(), params.end()); + }); + return combinedParams; +} + +} // namespace +INSTANTIATE_TEST_SUITE_P(smoke_Reduction_With_Hardcoded_Refs, ReferenceReductionLayerTest, ::testing::ValuesIn(generateReductionCombinedParams()), + ReferenceReductionLayerTest::getTestCaseName); +} // namespace ReductionOpsRefTestDefinitions +} // namespace reference_tests diff --git a/docs/template_plugin/tests/functional/op_reference/reduce_max.cpp b/docs/template_plugin/tests/functional/op_reference/reduce_max.cpp new file mode 100644 index 00000000000..6d3e519efa9 --- /dev/null +++ b/docs/template_plugin/tests/functional/op_reference/reduce_max.cpp @@ -0,0 +1,79 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include + +#include +#include +#include +#include + +#include "reduction.hpp" + +using namespace ngraph; +using namespace InferenceEngine; +using ReductionType = ngraph::helpers::ReductionType; + +namespace reference_tests { +namespace ReductionOpsRefTestDefinitions { +namespace { + +template +std::vector generateReductionParams(const bool keep_dims) { + using T = typename element_type_traits::value_type; + std::vector params = { + ReductionParams(ReductionType::Max, keep_dims, std::vector{0, 1}, + Tensor({2, 2}, element::Type(IN_ET), std::vector{1, 2, 3, 4}), + Tensor(reduce(Shape{2, 2}, AxisSet{0, 1}, keep_dims), element::Type(IN_ET), std::vector{4})), + ReductionParams(ReductionType::Max, keep_dims, std::vector{0}, + Tensor({3, 2}, element::Type(IN_ET), std::vector{1, 2, 3, 4, 5, 6}), + Tensor(reduce(Shape{3, 2}, AxisSet{0}, keep_dims), element::Type(IN_ET), std::vector{5, 6})), + ReductionParams(ReductionType::Max, keep_dims, std::vector{1}, + Tensor({3, 2}, element::Type(IN_ET), std::vector{1, 2, 3, 4, 5, 6}), + Tensor(reduce(Shape{3, 2}, AxisSet{1}, keep_dims), element::Type(IN_ET), std::vector{2, 4, 6})), + ReductionParams(ReductionType::Max, keep_dims, std::vector{0}, + Tensor({3, 3, 3}, element::Type(IN_ET), std::vector{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27}), + Tensor(reduce(Shape{3, 3, 3}, AxisSet{0}, keep_dims), element::Type(IN_ET), std::vector{19, 20, 21, 22, 23, 24, 25, 26, 27})), + ReductionParams(ReductionType::Max, keep_dims, std::vector{2}, + Tensor({3, 3, 3}, element::Type(IN_ET), std::vector{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27}), + Tensor(reduce(Shape{3, 3, 3}, AxisSet{2}, keep_dims), element::Type(IN_ET), std::vector{3, 6, 9, 12, 15, 18, 21, 24, 27})), + ReductionParams(ReductionType::Max, keep_dims, std::vector{0, 1}, + Tensor({3, 3, 3}, element::Type(IN_ET), std::vector{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27}), + Tensor(reduce(Shape{3, 3, 3}, AxisSet{0, 1}, keep_dims), element::Type(IN_ET), std::vector{25, 26, 27})), + ReductionParams(ReductionType::Max, keep_dims, std::vector{0, 1, 2}, + Tensor({3, 3, 3}, element::Type(IN_ET), std::vector{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27}), + Tensor(reduce(Shape{3, 3, 3}, AxisSet{0, 1, 2}, keep_dims), element::Type(IN_ET), std::vector{27})) + }; + return params; +} + +std::vector generateReductionCombinedParams() { + const std::vector> reductionTypeParams { + generateReductionParams(true), + generateReductionParams(false), + generateReductionParams(true), + generateReductionParams(false), + generateReductionParams(true), + generateReductionParams(false), + generateReductionParams(true), + generateReductionParams(false), + generateReductionParams(true), + generateReductionParams(false) + }; + std::vector combinedParams; + std::for_each(reductionTypeParams.begin(), reductionTypeParams.end(), [&](std::vector params) { + combinedParams.insert(combinedParams.end(), params.begin(), params.end()); + }); + return combinedParams; +} + +INSTANTIATE_TEST_SUITE_P(smoke_Reduction_With_Hardcoded_Refs, ReferenceReductionLayerTest, ::testing::ValuesIn(generateReductionCombinedParams()), + ReferenceReductionLayerTest::getTestCaseName); +} // namespace +} // namespace ReductionOpsRefTestDefinitions +} // namespace reference_tests diff --git a/docs/template_plugin/tests/functional/op_reference/reduce_mean.cpp b/docs/template_plugin/tests/functional/op_reference/reduce_mean.cpp new file mode 100644 index 00000000000..b6f05c23c20 --- /dev/null +++ b/docs/template_plugin/tests/functional/op_reference/reduce_mean.cpp @@ -0,0 +1,81 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include + +#include +#include +#include +#include + +#include "reduction.hpp" + +using namespace ngraph; +using namespace InferenceEngine; +using ReductionType = ngraph::helpers::ReductionType; + +namespace reference_tests { +namespace ReductionOpsRefTestDefinitions { +namespace { + +template ::value_type>::value, bool>::type = true> +std::vector generateReductionParams(const bool keep_dims) { + using T = typename element_type_traits::value_type; + std::vector params = { + ReductionParams(ReductionType::Mean, keep_dims, std::vector{0, 1}, + Tensor({2, 2}, element::Type(IN_ET), std::vector{1, 2, 3, 4}), + Tensor(reduce(Shape{2, 2}, AxisSet{0, 1}, keep_dims), element::Type(IN_ET), std::vector{2.5})), + ReductionParams(ReductionType::Mean, keep_dims, std::vector{0}, + Tensor({3, 2}, element::Type(IN_ET), std::vector{1, 2, 3, 4, 5, 6}), + Tensor(reduce(Shape{3, 2}, AxisSet{0}, keep_dims), element::Type(IN_ET), std::vector{3, 4})), + ReductionParams(ReductionType::Mean, keep_dims, std::vector{1}, + Tensor({3, 2}, element::Type(IN_ET), std::vector{1, 2, 3, 4, 5, 6}), + Tensor(reduce(Shape{3, 2}, AxisSet{1}, keep_dims), element::Type(IN_ET), std::vector{1.5, 3.5, 5.5})) + }; + return params; +} + +template ::value_type>::value, bool>::type = true> +std::vector generateReductionParams(const bool keep_dims) { + using T = typename element_type_traits::value_type; + std::vector params = { + ReductionParams(ReductionType::Mean, keep_dims, std::vector{0, 1}, + Tensor({2, 2}, element::Type(IN_ET), std::vector{1, 2, 3, 4}), + Tensor(reduce(Shape{2, 2}, AxisSet{0, 1}, keep_dims), element::Type(IN_ET), std::vector{2})), + ReductionParams(ReductionType::Mean, keep_dims, std::vector{0}, + Tensor({3, 2}, element::Type(IN_ET), std::vector{1, 2, 3, 4, 5, 6}), + Tensor(reduce(Shape{3, 2}, AxisSet{0}, keep_dims), element::Type(IN_ET), std::vector{3, 4})), + ReductionParams(ReductionType::Mean, keep_dims, std::vector{1}, + Tensor({3, 2}, element::Type(IN_ET), std::vector{1, 2, 3, 4, 5, 6}), + Tensor(reduce(Shape{3, 2}, AxisSet{1}, keep_dims), element::Type(IN_ET), std::vector{1, 3, 5})) + }; + return params; +} + +std::vector generateReductionCombinedParams() { + const std::vector> reductionTypeParams { + generateReductionParams(true), + generateReductionParams(false), + generateReductionParams(true), + generateReductionParams(false), + generateReductionParams(true), + generateReductionParams(false), + generateReductionParams(true), + generateReductionParams(false), + generateReductionParams(true), + generateReductionParams(false) + }; + std::vector combinedParams; + std::for_each(reductionTypeParams.begin(), reductionTypeParams.end(), [&](std::vector params) { + combinedParams.insert(combinedParams.end(), params.begin(), params.end()); + }); + return combinedParams; +} +} // namespace +INSTANTIATE_TEST_SUITE_P(smoke_Reduction_With_Hardcoded_Refs, ReferenceReductionLayerTest, ::testing::ValuesIn(generateReductionCombinedParams()), + ReferenceReductionLayerTest::getTestCaseName); +} // namespace ReductionOpsRefTestDefinitions +} // namespace reference_tests diff --git a/docs/template_plugin/tests/functional/op_reference/reduce_min.cpp b/docs/template_plugin/tests/functional/op_reference/reduce_min.cpp new file mode 100644 index 00000000000..ce5c8a2753b --- /dev/null +++ b/docs/template_plugin/tests/functional/op_reference/reduce_min.cpp @@ -0,0 +1,78 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include + +#include +#include +#include +#include + +#include "reduction.hpp" + +using namespace ngraph; +using namespace InferenceEngine; +using ReductionType = ngraph::helpers::ReductionType; + +namespace reference_tests { +namespace ReductionOpsRefTestDefinitions { +namespace { + +template +std::vector generateReductionParams(const bool keep_dims) { + using T = typename element_type_traits::value_type; + std::vector params = { + ReductionParams(ReductionType::Min, keep_dims, std::vector{0, 1}, + Tensor({2, 2}, element::Type(IN_ET), std::vector{1, 2, 3, 4}), + Tensor(reduce(Shape{2, 2}, AxisSet{0, 1}, keep_dims), element::Type(IN_ET), std::vector{1})), + ReductionParams(ReductionType::Min, keep_dims, std::vector{0}, + Tensor({3, 2}, element::Type(IN_ET), std::vector{1, 2, 3, 4, 5, 6}), + Tensor(reduce(Shape{3, 2}, AxisSet{0}, keep_dims), element::Type(IN_ET), std::vector{1, 2})), + ReductionParams(ReductionType::Min, keep_dims, std::vector{1}, + Tensor({3, 2}, element::Type(IN_ET), std::vector{1, 2, 3, 4, 5, 6}), + Tensor(reduce(Shape{3, 2}, AxisSet{1}, keep_dims), element::Type(IN_ET), std::vector{1, 3, 5})), + ReductionParams(ReductionType::Min, keep_dims, std::vector{0}, + Tensor({3, 3, 3}, element::Type(IN_ET), std::vector{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27}), + Tensor(reduce(Shape{3, 3, 3}, AxisSet{0}, keep_dims), element::Type(IN_ET), std::vector{1, 2, 3, 4, 5, 6, 7, 8, 9})), + ReductionParams(ReductionType::Min, keep_dims, std::vector{2}, + Tensor({3, 3, 3}, element::Type(IN_ET), std::vector{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27}), + Tensor(reduce(Shape{3, 3, 3}, AxisSet{2}, keep_dims), element::Type(IN_ET), std::vector{1, 4, 7, 10, 13, 16, 19, 22, 25})), + ReductionParams(ReductionType::Min, keep_dims, std::vector{0, 1}, + Tensor({3, 3, 3}, element::Type(IN_ET), std::vector{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27}), + Tensor(reduce(Shape{3, 3, 3}, AxisSet{0, 1}, keep_dims), element::Type(IN_ET), std::vector{1, 2, 3})), + ReductionParams(ReductionType::Min, keep_dims, std::vector{0, 1, 2}, + Tensor({3, 3, 3}, element::Type(IN_ET), std::vector{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27}), + Tensor(reduce(Shape{3, 3, 3}, AxisSet{0, 1, 2}, keep_dims), element::Type(IN_ET), std::vector{1})) + }; + return params; +} + +std::vector generateReductionCombinedParams() { + const std::vector> reductionTypeParams { + generateReductionParams(true), + generateReductionParams(false), + generateReductionParams(true), + generateReductionParams(false), + generateReductionParams(true), + generateReductionParams(false), + generateReductionParams(true), + generateReductionParams(false), + generateReductionParams(true), + generateReductionParams(false) + }; + std::vector combinedParams; + std::for_each(reductionTypeParams.begin(), reductionTypeParams.end(), [&](std::vector params) { + combinedParams.insert(combinedParams.end(), params.begin(), params.end()); + }); + return combinedParams; +} +} // namespace +INSTANTIATE_TEST_SUITE_P(smoke_Reduction_With_Hardcoded_Refs, ReferenceReductionLayerTest, ::testing::ValuesIn(generateReductionCombinedParams()), + ReferenceReductionLayerTest::getTestCaseName); +} // namespace ReductionOpsRefTestDefinitions +} // namespace reference_tests diff --git a/docs/template_plugin/tests/functional/op_reference/reduce_prod.cpp b/docs/template_plugin/tests/functional/op_reference/reduce_prod.cpp new file mode 100644 index 00000000000..38f316d23dd --- /dev/null +++ b/docs/template_plugin/tests/functional/op_reference/reduce_prod.cpp @@ -0,0 +1,102 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include + +#include +#include +#include +#include + +#include "reduction.hpp" + +using namespace ngraph; +using namespace InferenceEngine; +using ReductionType = ngraph::helpers::ReductionType; + +namespace reference_tests { +namespace ReductionOpsRefTestDefinitions { +namespace { +template +std::vector generateReductionParams(const bool keep_dims) { + using T = typename element_type_traits::value_type; + std::vector params = { + ReductionParams(ReductionType::Prod, keep_dims, std::vector{0, 1}, + Tensor({2, 2}, element::Type(IN_ET), std::vector{1, 2, 3, 4}), + Tensor(reduce(Shape{2, 2}, AxisSet{0, 1}, keep_dims), element::Type(IN_ET), std::vector{24})), + ReductionParams(ReductionType::Prod, keep_dims, std::vector{0}, + Tensor({3, 2}, element::Type(IN_ET), std::vector{1, 2, 3, 4, 5, 6}), + Tensor(reduce(Shape{3, 2}, AxisSet{0}, keep_dims), element::Type(IN_ET), std::vector{15, 48})), + ReductionParams(ReductionType::Prod, keep_dims, std::vector{1}, + Tensor({3, 2}, element::Type(IN_ET), std::vector{1, 2, 3, 4, 5, 6}), + Tensor(reduce(Shape{3, 2}, AxisSet{1}, keep_dims), element::Type(IN_ET), std::vector{2, 12, 30})), + ReductionParams(ReductionType::Prod, keep_dims, std::vector{0}, + Tensor({3, 3, 3}, element::Type(IN_ET), std::vector{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27}), + Tensor(reduce(Shape{3, 3, 3}, AxisSet{0}, keep_dims), element::Type(IN_ET), std::vector{1 * 10 * 19, + 2 * 11 * 20, + 3 * 12 * 21, + 4 * 13 * 22, + 5 * 14 * 23, + 6 * 15 * 24, + 7 * 16 * 25, + 8 * 17 * 26, + 9 * 18 * 27})), + ReductionParams(ReductionType::Prod, keep_dims, std::vector{2}, + Tensor({3, 3, 3}, element::Type(IN_ET), std::vector{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27}), + Tensor(reduce(Shape{3, 3, 3}, AxisSet{2}, keep_dims), element::Type(IN_ET), std::vector{1 * 2 * 3, + 4 * 5 * 6, + 7 * 8 * 9, + 10 * 11 * 12, + 13 * 14 * 15, + 16 * 17 * 18, + 19 * 20 * 21, + 22 * 23 * 24, + 25 * 26 * 27})) + }; + return params; +} + +std::vector generateReductionCombinedParams() { + const std::vector> reductionTypeParams { + generateReductionParams(true), + generateReductionParams(false), + generateReductionParams(true), + generateReductionParams(false), + generateReductionParams(true), + generateReductionParams(false), + generateReductionParams(true), + generateReductionParams(false), + generateReductionParams(true), + generateReductionParams(false) + }; + std::vector combinedParams; + std::for_each(reductionTypeParams.begin(), reductionTypeParams.end(), [&](std::vector params) { + combinedParams.insert(combinedParams.end(), params.begin(), params.end()); + }); + + combinedParams.push_back( + ReductionParams(ReductionType::Prod, true, std::vector{0, 1}, + Tensor({3, 3, 3}, element::Type_t::f32, std::vector{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27}), + Tensor({1, 1, 3}, element::Type_t::f32, std::vector{1.0f * 10.0f * 19.0f * 4.0f * 13.0f * 22.0f * 7.0f * 16.0f * 25.0f, + 2.0f * 11.0f * 20.0f * 5.0f * 14.0f * 23.0f * 8.0f * 17.0f * 26.0f, + 3.0f * 12.0f * 21.0f * 6.0f * 15.0f * 24.0f * 9.0f * 18.0f * 27.0f}))); + combinedParams.push_back( + ReductionParams(ReductionType::Prod, true, std::vector{0, 1, 2}, + Tensor({3, 3, 3}, element::Type_t::f32, std::vector{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1}), + Tensor({1, 1, 1}, element::Type_t::f32, std::vector{1.0f * 10.0f * 9.0f * 4.0f * 13.0f * 6.0f * 7.0f * + 12.0f * 3.0f * 2.0f * 11.0f * 8.0f * 5.0f * 14.0f * + 5.0f * 8.0f * 11.0f * 2.0f * 3.0f * 12.0f * 7.0f * + 6.0f * 13.0f * 4.0f * 9.0f * 10.0f * 1.0f}))); + + return combinedParams; +} +} // namespace +INSTANTIATE_TEST_SUITE_P(smoke_Reduction_With_Hardcoded_Refs, ReferenceReductionLayerTest, ::testing::ValuesIn(generateReductionCombinedParams()), + ReferenceReductionLayerTest::getTestCaseName); +} // namespace ReductionOpsRefTestDefinitions +} // namespace reference_tests diff --git a/docs/template_plugin/tests/functional/op_reference/reduce_sum.cpp b/docs/template_plugin/tests/functional/op_reference/reduce_sum.cpp new file mode 100644 index 00000000000..8498280ca07 --- /dev/null +++ b/docs/template_plugin/tests/functional/op_reference/reduce_sum.cpp @@ -0,0 +1,130 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include + +#include +#include +#include +#include + +#include "reduction.hpp" + +using namespace ngraph; +using namespace InferenceEngine; +using ReductionType = ngraph::helpers::ReductionType; + +static std::mt19937_64 random_generator; + +namespace reference_tests { +namespace ReductionOpsRefTestDefinitions { +namespace { + +std::vector generateRandomVector(const size_t count) { + std::vector result(count, 0); + random_generator.seed(2); + for (int i = 0; i < 1000000; i++) { + result[i] = static_cast(random_generator() % 255); + } + return result; +} + +template +std::vector generateReductionParams(const bool keep_dims) { + using T = typename element_type_traits::value_type; + std::vector params = { + ReductionParams(ReductionType::Sum, keep_dims, std::vector{0, 1}, + Tensor({2, 2}, element::Type(IN_ET), std::vector{1, 2, 3, 4}), + Tensor(reduce(Shape{2, 2}, AxisSet{0, 1}, keep_dims), element::Type(IN_ET), std::vector{10})), + ReductionParams(ReductionType::Sum, keep_dims, std::vector{0}, + Tensor({3, 2}, element::Type(IN_ET), std::vector{1, 2, 3, 4, 5, 6}), + Tensor(reduce(Shape{3, 2}, AxisSet{0}, keep_dims), element::Type(IN_ET), std::vector{9, 12})), + ReductionParams(ReductionType::Sum, keep_dims, std::vector{1}, + Tensor({3, 2}, element::Type(IN_ET), std::vector{1, 2, 3, 4, 5, 6}), + Tensor(reduce(Shape{3, 2}, AxisSet{1}, keep_dims), element::Type(IN_ET), std::vector{3, 7, 11})), + ReductionParams(ReductionType::Sum, keep_dims, std::vector{0}, + Tensor({3, 3, 3}, element::Type(IN_ET), std::vector{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27}), + Tensor(reduce(Shape{3, 3, 3}, AxisSet{0}, keep_dims), element::Type(IN_ET), std::vector{1 + 10 + 19, + 2 + 11 + 20, + 3 + 12 + 21, + 4 + 13 + 22, + 5 + 14 + 23, + 6 + 15 + 24, + 7 + 16 + 25, + 8 + 17 + 26, + 9 + 18 + 27})), + ReductionParams(ReductionType::Sum, keep_dims, std::vector{2}, + Tensor({3, 3, 3}, element::Type(IN_ET), std::vector{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27}), + Tensor(reduce(Shape{3, 3, 3}, AxisSet{2}, keep_dims), element::Type(IN_ET), std::vector{1 + 2 + 3, + 4 + 5 + 6, + 7 + 8 + 9, + 10 + 11 + 12, + 13 + 14 + 15, + 16 + 17 + 18, + 19 + 20 + 21, + 22 + 23 + 24, + 25 + 26 + 27})), + ReductionParams(ReductionType::Sum, keep_dims, std::vector{0, 1}, + Tensor({3, 3, 3}, element::Type(IN_ET), std::vector{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27}), + Tensor(reduce(Shape{3, 3, 3}, AxisSet{0, 1}, keep_dims), element::Type(IN_ET), std::vector{1 + 10 + 19 + 4 + 13 + 22 + 7 + 16 + 25, + 2 + 11 + 20 + 5 + 14 + 23 + 8 + 17 + 26, + 3 + 12 + 21 + 6 + 15 + 24 + 9 + 18 + 27})), + ReductionParams(ReductionType::Sum, keep_dims, std::vector{0, 1, 2}, + Tensor({3, 3, 3}, element::Type(IN_ET), std::vector{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27}), + Tensor(reduce(Shape{3, 3, 3}, AxisSet{0, 1, 2}, keep_dims), element::Type(IN_ET), + std::vector{1 + 10 + 19 + 4 + 13 + 22 + 7 + 16 + 25 + 2 + 11 + 20 + 5 + 14 + 23 + 8 + + 17 + 26 + 3 + 12 + 21 + 6 + 15 + 24 + 9 + 18 + 27})), + ReductionParams(ReductionType::Sum, keep_dims, std::vector{0, 1, 2, 3, 4}, + Tensor({3, 3, 3, 3, 3}, element::Type(IN_ET), std::vector(std::pow(3, 5), 1)), + Tensor(reduce(Shape{3, 3, 3, 3, 3}, AxisSet{0, 1, 2, 3, 4}, keep_dims), element::Type(IN_ET), std::vector{243})) + }; + return params; +} + +std::vector generateReductionParamsFloat(const bool keep_dims) { + std::vector in = generateRandomVector(1000000); + float res = std::accumulate(std::begin(in), std::end(in), 0); + std::vector params = { + ReductionParams(ReductionType::Sum, keep_dims, std::vector{0}, + Tensor({1000000}, element::f32, in), + Tensor(reduce(Shape{1000000}, AxisSet{0}, keep_dims), element::f32, std::vector{res})), + ReductionParams(ReductionType::Sum, keep_dims, std::vector{0}, + Tensor({20}, element::f32, std::vector{10000000.0f, 0.9f, 0.3f, 0.4f, 0.5f, 0.6f, 0.7f, + 0.8f, 0.1f, 0.9f, 0.5f, 0.2f, 0.3f, 0.4f, + 0.5f, 0.6f, 0.7f, 0.8f, 0.9f, 0.1f}), + Tensor(reduce(Shape{20}, AxisSet{0}, keep_dims), element::f32, std::vector{10000010.2f})) + }; + return params; +} + +std::vector generateReductionCombinedParams() { + const std::vector> reductionTypeParams { + generateReductionParams(true), + generateReductionParams(false), + generateReductionParams(true), + generateReductionParams(false), + generateReductionParams(true), + generateReductionParams(false), + generateReductionParams(true), + generateReductionParams(false), + generateReductionParams(true), + generateReductionParams(false), + generateReductionParamsFloat(true), + generateReductionParamsFloat(false) + }; + std::vector combinedParams; + std::for_each(reductionTypeParams.begin(), reductionTypeParams.end(), [&](std::vector params) { + combinedParams.insert(combinedParams.end(), params.begin(), params.end()); + }); + return combinedParams; +} +} // namespace +INSTANTIATE_TEST_SUITE_P(smoke_Reduction_With_Hardcoded_Refs, ReferenceReductionLayerTest, ::testing::ValuesIn(generateReductionCombinedParams()), + ReferenceReductionLayerTest::getTestCaseName); +} // namespace ReductionOpsRefTestDefinitions +} // namespace reference_tests diff --git a/docs/template_plugin/tests/functional/op_reference/reduction.cpp b/docs/template_plugin/tests/functional/op_reference/reduction.cpp new file mode 100644 index 00000000000..436b1047646 --- /dev/null +++ b/docs/template_plugin/tests/functional/op_reference/reduction.cpp @@ -0,0 +1,15 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "reduction.hpp" + +namespace reference_tests { +namespace ReductionOpsRefTestDefinitions { +namespace { +TEST_P(ReferenceReductionLayerTest, CompareWithHardcodedRefs) { + Exec(); +} +} // namespace +} // namespace ReductionOpsRefTestDefinitions +} // namespace reference_tests diff --git a/docs/template_plugin/tests/functional/op_reference/reduction.hpp b/docs/template_plugin/tests/functional/op_reference/reduction.hpp new file mode 100644 index 00000000000..951711511b8 --- /dev/null +++ b/docs/template_plugin/tests/functional/op_reference/reduction.hpp @@ -0,0 +1,64 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include + +#include +#include +#include +#include +#include + +#include "base_reference_test.hpp" +#include "ngraph_functions/builders.hpp" + +namespace reference_tests { +namespace ReductionOpsRefTestDefinitions { + +struct ReductionParams { + ReductionParams(const ngraph::helpers::ReductionType& reductType, const bool keepDims, const std::vector& axes, + const Tensor& dataTensor, const Tensor& outputTensor) : reductionType(reductType), keepDimensions(keepDims), reductionAxes(axes), + data(dataTensor), output(outputTensor) {} + + ngraph::helpers::ReductionType reductionType; + bool keepDimensions; + std::vector reductionAxes; + Tensor data; + Tensor output; +}; + +class ReferenceReductionLayerTest : public testing::TestWithParam, public CommonReferenceTest { +public: + void SetUp() override { + auto params = GetParam(); + function = CreateFunction(params); + inputData = {params.data.data}; + refOutData = {params.output.data}; + } + + static std::string getTestCaseName(const testing::TestParamInfo& obj) { + auto param = obj.param; + std::ostringstream result; + result << "reductionType=" << param.reductionType << "_"; + result << "dataType=" << param.data.type << "_"; + result << "dataShape=" << param.data.shape << "_"; + result << "axes=" << CommonTestUtils::vec2str(param.reductionAxes); + if (param.keepDimensions) { + result << "_keepDims"; + } + return result.str(); + } + +private: + static std::shared_ptr CreateFunction(const ReductionParams& params) { + const auto data = std::make_shared(params.data.type, params.data.shape); + const auto axes = std::make_shared(ngraph::element::i64, + ngraph::Shape{params.reductionAxes.size()}, + params.reductionAxes); + const auto reduction = ngraph::builder::makeReduce(data, axes, params.keepDimensions, params.reductionType); + return std::make_shared(reduction, ngraph::ParameterVector{data}); + } +}; +} // namespace ReductionOpsRefTestDefinitions +} // namespace reference_tests diff --git a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/single_layer_tests/reduce_ops.cpp b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/single_layer_tests/reduce_ops.cpp index 2608c1bb458..d52ec25a285 100644 --- a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/single_layer_tests/reduce_ops.cpp +++ b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/single_layer_tests/reduce_ops.cpp @@ -12,7 +12,10 @@ using namespace LayerTestsDefinitions; namespace { const std::vector netPrecisions = { InferenceEngine::Precision::FP32, - InferenceEngine::Precision::I32 + InferenceEngine::Precision::FP16, + InferenceEngine::Precision::I64, + InferenceEngine::Precision::I32, + InferenceEngine::Precision::U64 }; const std::vector keepDims = { @@ -92,7 +95,7 @@ const auto paramsOneAxisLogical = testing::Combine( testing::Values(InferenceEngine::Precision::UNSPECIFIED), testing::Values(InferenceEngine::Precision::UNSPECIFIED), testing::Values(InferenceEngine::Layout::ANY), - testing::ValuesIn(inputShapes), + testing::ValuesIn(inputShapesOneAxis), testing::Values(CommonTestUtils::DEVICE_CPU) ); @@ -100,7 +103,11 @@ const auto params_Precisions = testing::Combine( testing::Values(std::vector{1, 3}), testing::Values(opTypes[1]), testing::ValuesIn(keepDims), - testing::Values(ngraph::helpers::ReductionType::Sum), + testing::Values(ngraph::helpers::ReductionType::Max, + ngraph::helpers::ReductionType::Mean, + ngraph::helpers::ReductionType::Min, + ngraph::helpers::ReductionType::Sum, + ngraph::helpers::ReductionType::Prod), testing::ValuesIn(netPrecisions), testing::Values(InferenceEngine::Precision::UNSPECIFIED), testing::Values(InferenceEngine::Precision::UNSPECIFIED), @@ -109,6 +116,36 @@ const auto params_Precisions = testing::Combine( testing::Values(CommonTestUtils::DEVICE_CPU) ); +const auto params_Precisions_ReduceL1 = testing::Combine( + testing::Values(std::vector{1, 3}), + testing::Values(opTypes[1]), + testing::ValuesIn(keepDims), + testing::Values(ngraph::helpers::ReductionType::L1), + testing::Values(InferenceEngine::Precision::FP32, + InferenceEngine::Precision::FP16, + InferenceEngine::Precision::I64, + InferenceEngine::Precision::I32), + testing::Values(InferenceEngine::Precision::UNSPECIFIED), + testing::Values(InferenceEngine::Precision::UNSPECIFIED), + testing::Values(InferenceEngine::Layout::ANY), + testing::Values(std::vector{2, 2, 2, 2}), + testing::Values(CommonTestUtils::DEVICE_CPU) +); + +const auto params_Precisions_ReduceL2 = testing::Combine( + testing::Values(std::vector{1, 3}), + testing::Values(opTypes[1]), + testing::ValuesIn(keepDims), + testing::Values(ngraph::helpers::ReductionType::L2), + testing::Values(InferenceEngine::Precision::FP32, + InferenceEngine::Precision::FP16), + testing::Values(InferenceEngine::Precision::UNSPECIFIED), + testing::Values(InferenceEngine::Precision::UNSPECIFIED), + testing::Values(InferenceEngine::Layout::ANY), + testing::Values(std::vector{2, 2, 2, 2}), + testing::Values(CommonTestUtils::DEVICE_CPU) +); + const auto params_InputShapes = testing::Combine( testing::Values(std::vector{0}), testing::Values(opTypes[1]), @@ -166,6 +203,26 @@ const auto params_ReductionTypesLogical = testing::Combine( testing::Values(CommonTestUtils::DEVICE_CPU) ); +const auto params_ReduceSum_accuracy = testing::Combine( + testing::Values(std::vector{0}), + testing::Values(opTypes[1]), + testing::Values(true), + testing::Values(ngraph::helpers::ReductionType::Sum), + testing::Values(InferenceEngine::Precision::FP32), + testing::Values(InferenceEngine::Precision::UNSPECIFIED), + testing::Values(InferenceEngine::Precision::UNSPECIFIED), + testing::Values(InferenceEngine::Layout::ANY), + testing::Values(std::vector{1000000}), + testing::Values(CommonTestUtils::DEVICE_CPU) +); + +INSTANTIATE_TEST_SUITE_P( + smoke_ReduceSum_Accuracy, + ReduceOpsLayerTest, + params_ReduceSum_accuracy, + ReduceOpsLayerTest::getTestCaseName +); + INSTANTIATE_TEST_SUITE_P( smoke_ReduceOneAxis, ReduceOpsLayerTest, @@ -187,6 +244,20 @@ INSTANTIATE_TEST_SUITE_P( ReduceOpsLayerTest::getTestCaseName ); +INSTANTIATE_TEST_SUITE_P( + smoke_Reduce_Precisions_L1, + ReduceOpsLayerTest, + params_Precisions_ReduceL1, + ReduceOpsLayerTest::getTestCaseName +); + +INSTANTIATE_TEST_SUITE_P( + smoke_Reduce_Precisions_L2, + ReduceOpsLayerTest, + params_Precisions_ReduceL2, + ReduceOpsLayerTest::getTestCaseName +); + INSTANTIATE_TEST_SUITE_P( smoke_Reduce_InputShapes, ReduceOpsLayerTest, diff --git a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/skip_tests_config.cpp b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/skip_tests_config.cpp index 1bb848fcdca..e3b6c8e1a15 100644 --- a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/skip_tests_config.cpp +++ b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/skip_tests_config.cpp @@ -87,6 +87,9 @@ std::vector disabledTestPatterns() { R"(.*Auto_Behavior.*InferRequestIOBBlobTest.*canProcessDeallocatedOutputBlobAfterGetAndSetBlob.*)", // azure is failing after #6199 R"(.*/NmsLayerTest.*)", + // TODO: 56520 Accuracy mismatch + R"(.*ReduceOpsLayerTest.*type=Mean_.*netPRC=(I64|I32).*)", + R"(.*ReduceOpsLayerTest.*type=Mean_.*netPRC=U64.*)" }; #if ((IE_THREAD == IE_THREAD_TBB) || (IE_THREAD == IE_THREAD_TBB_AUTO)) diff --git a/ngraph/test/CMakeLists.txt b/ngraph/test/CMakeLists.txt index ec621a10509..1ac9ee9fcba 100644 --- a/ngraph/test/CMakeLists.txt +++ b/ngraph/test/CMakeLists.txt @@ -62,10 +62,6 @@ set(SRC op_eval/memory.cpp op_eval/mish.cpp op_eval/non_zero.cpp - op_eval/reduce_max.cpp - op_eval/reduce_min.cpp - op_eval/reduce_prod.cpp - op_eval/reduce_sum.cpp op_eval/roi_align.cpp op_eval/roi_pooling.cpp op_eval/round.cpp @@ -490,13 +486,6 @@ set(MULTI_TEST_SRC backend/psroi_pooling.in.cpp backend/range.in.cpp backend/recurrent_cells.in.cpp - backend/reduce_l1.in.cpp - backend/reduce_l2.in.cpp - backend/reduce_max.in.cpp - backend/reduce_mean.in.cpp - backend/reduce_min.in.cpp - backend/reduce_prod.in.cpp - backend/reduce_sum.in.cpp backend/region_yolo.in.cpp backend/relu.in.cpp backend/reorg_yolo.in.cpp diff --git a/ngraph/test/backend/reduce_l1.in.cpp b/ngraph/test/backend/reduce_l1.in.cpp deleted file mode 100644 index a57712f2cfb..00000000000 --- a/ngraph/test/backend/reduce_l1.in.cpp +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright (C) 2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#include "gtest/gtest.h" -#include "ngraph/ngraph.hpp" -#include "util/all_close.hpp" -#include "util/all_close_f.hpp" -#include "util/test_control.hpp" -#include "util/test_tools.hpp" - -using namespace std; -using namespace ngraph; - -static string s_manifest = "${MANIFEST}"; - -NGRAPH_TEST(${BACKEND_NAME}, reduce_l1_one_axis_keep_dims) { - auto data = make_shared(element::f32, Shape{3, 2, 2}); - auto axes = op::Constant::create(element::i32, Shape{1}, {2}); - auto reduce_l1 = make_shared(data, axes, true); - auto f = make_shared(OutputVector{reduce_l1}, ParameterVector{data}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}"); - - // Create tensors for input/output - std::vector input{1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0}; - std::vector expected_result{3.0, 7.0, 11.0, 15.0, 19.0, 23.0}; - - auto data_tensor = backend->create_tensor(element::f32, Shape{3, 2, 2}); - copy_data(data_tensor, input); - - auto result_tensor = backend->create_tensor(element::f32, Shape{3, 2, 1}); - - auto handle = backend->compile(f); - handle->call_with_validate({result_tensor}, {data_tensor}); - EXPECT_TRUE(test::all_close_f((expected_result), read_vector(result_tensor))); -} - -NGRAPH_TEST(${BACKEND_NAME}, reduce_l1_one_axis_do_not_keep_dims) { - auto data = make_shared(element::f32, Shape{3, 2, 2}); - auto axes = op::Constant::create(element::i32, Shape{1}, {2}); - auto reduce_l1 = make_shared(data, axes, false); - auto f = make_shared(OutputVector{reduce_l1}, ParameterVector{data}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}"); - - // Create tensors for input/output - std::vector input{1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0}; - std::vector expected_result{3.0, 7.0, 11.0, 15.0, 19.0, 23.0}; - - auto data_tensor = backend->create_tensor(element::f32, Shape{3, 2, 2}); - copy_data(data_tensor, input); - - auto result_tensor = backend->create_tensor(element::f32, Shape{3, 2}); - - auto handle = backend->compile(f); - handle->call_with_validate({result_tensor}, {data_tensor}); - EXPECT_TRUE(test::all_close_f((expected_result), read_vector(result_tensor))); -} diff --git a/ngraph/test/backend/reduce_l2.in.cpp b/ngraph/test/backend/reduce_l2.in.cpp deleted file mode 100644 index a7647052787..00000000000 --- a/ngraph/test/backend/reduce_l2.in.cpp +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright (C) 2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#include "gtest/gtest.h" -#include "ngraph/ngraph.hpp" -#include "util/all_close.hpp" -#include "util/all_close_f.hpp" -#include "util/test_control.hpp" -#include "util/test_tools.hpp" - -using namespace std; -using namespace ngraph; - -static string s_manifest = "${MANIFEST}"; - -NGRAPH_TEST(${BACKEND_NAME}, reduce_l2_one_axis_keep_dims) { - auto data = make_shared(element::f32, Shape{3, 2, 2}); - auto axes = op::Constant::create(element::i32, Shape{1}, {2}); - auto reduce_l2 = make_shared(data, axes, true); - auto f = make_shared(OutputVector{reduce_l2}, ParameterVector{data}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}"); - - std::vector input{1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0}; - std::vector expected_result{2.23606798, 5.0, 7.81024968, 10.63014581, 13.45362405, 16.2788206}; - - auto data_tensor = backend->create_tensor(element::f32, Shape{3, 2, 2}); - copy_data(data_tensor, input); - - auto result_tensor = backend->create_tensor(element::f32, Shape{3, 2, 1}); - - auto handle = backend->compile(f); - handle->call_with_validate({result_tensor}, {data_tensor}); - EXPECT_TRUE(test::all_close_f((expected_result), read_vector(result_tensor))); -} - -NGRAPH_TEST(${BACKEND_NAME}, reduce_l2_one_axis_do_not_keep_dims) { - auto data = make_shared(element::f32, Shape{3, 2, 2}); - auto axes = op::Constant::create(element::i32, Shape{1}, {2}); - auto reduce_l2 = make_shared(data, axes, false); - auto f = make_shared(OutputVector{reduce_l2}, ParameterVector{data}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}"); - - std::vector input{1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0}; - std::vector expected_result{2.23606798, 5.0, 7.81024968, 10.63014581, 13.45362405, 16.2788206}; - - auto data_tensor = backend->create_tensor(element::f32, Shape{3, 2, 2}); - copy_data(data_tensor, input); - - auto result_tensor = backend->create_tensor(element::f32, Shape{3, 2}); - - auto handle = backend->compile(f); - handle->call_with_validate({result_tensor}, {data_tensor}); - EXPECT_TRUE(test::all_close_f((expected_result), read_vector(result_tensor))); -} diff --git a/ngraph/test/backend/reduce_max.in.cpp b/ngraph/test/backend/reduce_max.in.cpp deleted file mode 100644 index b144b944014..00000000000 --- a/ngraph/test/backend/reduce_max.in.cpp +++ /dev/null @@ -1,456 +0,0 @@ -// Copyright (C) 2018-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#include "gtest/gtest.h" -#include "ngraph/ngraph.hpp" -#include "util/engine/test_engines.hpp" -#include "util/test_case.hpp" -#include "util/test_control.hpp" - -using namespace std; -using namespace ngraph; - -static string s_manifest = "${MANIFEST}"; -using TestEngine = test::ENGINE_CLASS_NAME(${BACKEND_NAME}); - -// ----------------------- keep dims = false ----------------------- // - -NGRAPH_TEST(${BACKEND_NAME}, reduce_max_to_scalar) { - Shape shape{2, 2}; - auto A = make_shared(element::f32, shape); - auto axes = make_shared(element::i32, Shape{2}, vector{0, 1}); - auto f = make_shared(make_shared(A, axes, false), ParameterVector{A}); - - // Create some tensors for input/output - std::vector a{1, 2, 3, 4}; - - auto test_case = test::TestCase(f); - test_case.add_input({a}); - test_case.add_expected_output({4}); - test_case.run(); -} - -NGRAPH_TEST(${BACKEND_NAME}, reduce_max_to_scalar_int8) { - Shape shape{2, 2}; - auto A = make_shared(element::i8, shape); - auto axes = make_shared(element::i32, Shape{2}, vector{0, 1}); - auto f = make_shared(make_shared(A, axes, false), ParameterVector{A}); - - // Create some tensors for input/output - std::vector a{1, 2, 3, 4}; - - auto test_case = test::TestCase(f); - test_case.add_input({a}); - test_case.add_expected_output({4}); - test_case.run(); -} - -NGRAPH_TEST(${BACKEND_NAME}, reduce_max_matrix_columns) { - Shape shape_a{3, 2}; - auto A = make_shared(element::f32, shape_a); - Shape shape_rt{2}; - auto axes = make_shared(element::i32, Shape{}, 0); - auto f = make_shared(make_shared(A, axes, false), ParameterVector{A}); - - // Create some tensors for input/output - std::vector a{1, 2, 3, 4, 5, 6}; - - auto test_case = test::TestCase(f); - test_case.add_input({a}); - test_case.add_expected_output(shape_rt, {5, 6}); - test_case.run(); -} - -NGRAPH_TEST(${BACKEND_NAME}, reduce_max_matrix_rows) { - Shape shape_a{3, 2}; - auto A = make_shared(element::f32, shape_a); - Shape shape_rt{3}; - auto axes = make_shared(element::i32, Shape{}, 1); - auto f = make_shared(make_shared(A, axes, false), ParameterVector{A}); - - // Create some tensors for input/output - std::vector a{1, 2, 3, 4, 5, 6}; - - auto test_case = test::TestCase(f); - test_case.add_input({a}); - test_case.add_expected_output(shape_rt, {2, 4, 6}); - test_case.run(); -} - -NGRAPH_TEST(${BACKEND_NAME}, reduce_max_matrix_rows_int32) { - Shape shape_a{3, 2}; - auto A = make_shared(element::i32, shape_a); - Shape shape_rt{3}; - auto axes = make_shared(element::i32, Shape{}, 1); - auto f = make_shared(make_shared(A, axes, false), ParameterVector{A}); - - // Create some tensors for input/output - std::vector a{1, 2, 3, 4, 5, 6}; - - auto test_case = test::TestCase(f); - test_case.add_input({a}); - test_case.add_expected_output(shape_rt, {2, 4, 6}); - test_case.run(); -} - -NGRAPH_TEST(${BACKEND_NAME}, reduce_max_3d_to_matrix_most_sig) { - Shape shape_a{3, 3, 3}; - auto A = make_shared(element::f32, shape_a); - Shape shape_rt{3, 3}; - auto axes = make_shared(element::i32, Shape{}, 0); - auto f = make_shared(make_shared(A, axes, false), ParameterVector{A}); - - // Create some tensors for input/output - std::vector a{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27}; - - auto test_case = test::TestCase(f); - test_case.add_input({a}); - test_case.add_expected_output(shape_rt, {19, 20, 21, 22, 23, 24, 25, 26, 27}); - test_case.run(MIN_FLOAT_TOLERANCE_BITS); -} - -NGRAPH_TEST(${BACKEND_NAME}, reduce_max_3d_to_matrix_least_sig) { - Shape shape_a{3, 3, 3}; - auto A = make_shared(element::f32, shape_a); - Shape shape_rt{3, 3}; - auto axes = make_shared(element::i32, Shape{}, 2); - auto f = make_shared(make_shared(A, axes, false), ParameterVector{A}); - - // Create some tensors for input/output - std::vector a{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27}; - - auto test_case = test::TestCase(f); - test_case.add_input({a}); - test_case.add_expected_output(shape_rt, {3, 6, 9, 12, 15, 18, 21, 24, 27}); - test_case.run(MIN_FLOAT_TOLERANCE_BITS); -} - -NGRAPH_TEST(${BACKEND_NAME}, reduce_max_3d_to_vector) { - Shape shape_a{3, 3, 3}; - auto A = make_shared(element::f32, shape_a); - Shape shape_rt{3}; - auto axes = make_shared(element::i32, Shape{2}, vector{0, 1}); - auto f = make_shared(make_shared(A, axes, false), ParameterVector{A}); - - // Create some tensors for input/output - std::vector a{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27}; - - auto test_case = test::TestCase(f); - test_case.add_input({a}); - test_case.add_expected_output(shape_rt, {25.0f, 26.0f, 27.0f}); - test_case.run(MIN_FLOAT_TOLERANCE_BITS); -} - -NGRAPH_TEST(${BACKEND_NAME}, reduce_max_3d_to_scalar) { - Shape shape_a{3, 3, 3}; - auto A = make_shared(element::f32, shape_a); - Shape shape_rt{}; - auto axes = make_shared(element::i32, Shape{3}, vector{0, 1, 2}); - auto f = make_shared(make_shared(A, axes, false), ParameterVector{A}); - - // Create some tensors for input/output - std::vector a{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1}; - - auto test_case = test::TestCase(f); - test_case.add_input({a}); - test_case.add_expected_output(shape_rt, {14.0f}); - test_case.run(MIN_FLOAT_TOLERANCE_BITS); -} - -NGRAPH_TEST(${BACKEND_NAME}, reduce_max_3d_to_scalar_int32) { - Shape shape_a{3, 3, 3}; - auto A = make_shared(element::i32, shape_a); - Shape shape_rt{}; - auto axes = make_shared(element::i32, Shape{3}, vector{0, 1, 2}); - auto f = make_shared(make_shared(A, axes, false), ParameterVector{A}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::i32, shape_a); - copy_data(a, vector{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1}); - auto result = backend->create_tensor(element::i32, shape_rt); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_EQ((vector{14}), read_vector(result)); -} - -// ----------------------- keep dims = true ----------------------- // - -NGRAPH_TEST(${BACKEND_NAME}, reduce_max_keep_to_scalar) { - Shape shape{2, 2}; - auto A = make_shared(element::f32, shape); - auto axes = make_shared(element::i32, Shape{2}, vector{0, 1}); - auto f = make_shared(make_shared(A, axes, true), ParameterVector{A}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::f32, shape); - copy_data(a, vector{1, 2, 3, 4}); - auto result = backend->create_tensor(element::f32, Shape{1, 1}); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_TRUE(test::all_close_f((vector{4}), read_vector(result))); -} - -NGRAPH_TEST(${BACKEND_NAME}, reduce_max_keep_to_scalar_int8) { - Shape shape{2, 2}; - auto A = make_shared(element::i8, shape); - auto axes = make_shared(element::i32, Shape{2}, vector{0, 1}); - auto f = make_shared(make_shared(A, axes, true), ParameterVector{A}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::i8, shape); - copy_data(a, vector{1, 2, 3, 4}); - auto result = backend->create_tensor(element::i8, Shape{1, 1}); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_EQ((vector{4}), read_vector(result)); -} - -NGRAPH_TEST(${BACKEND_NAME}, reduce_max_keep_matrix_columns) { - Shape shape_a{3, 2}; - auto A = make_shared(element::f32, shape_a); - Shape shape_rt{1, 2}; - auto axes = make_shared(element::i32, Shape{}, 0); - auto f = make_shared(make_shared(A, axes, true), ParameterVector{A}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::f32, shape_a); - copy_data(a, vector{1, 2, 3, 4, 5, 6}); - auto result = backend->create_tensor(element::f32, shape_rt); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_TRUE(test::all_close_f((vector{5, 6}), read_vector(result))); -} - -NGRAPH_TEST(${BACKEND_NAME}, reduce_max_keep_matrix_rows) { - Shape shape_a{3, 2}; - auto A = make_shared(element::f32, shape_a); - Shape shape_rt{3, 1}; - auto axes = make_shared(element::i32, Shape{}, 1); - auto f = make_shared(make_shared(A, axes, true), ParameterVector{A}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::f32, shape_a); - copy_data(a, vector{1, 2, 3, 4, 5, 6}); - auto result = backend->create_tensor(element::f32, shape_rt); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_TRUE(test::all_close_f((vector{2, 4, 6}), read_vector(result))); -} - -NGRAPH_TEST(${BACKEND_NAME}, reduce_max_keep_matrix_rows_int32) { - Shape shape_a{3, 2}; - auto A = make_shared(element::i32, shape_a); - Shape shape_rt{3, 1}; - auto axes = make_shared(element::i32, Shape{}, 1); - auto f = make_shared(make_shared(A, axes, true), ParameterVector{A}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::i32, shape_a); - copy_data(a, vector{1, 2, 3, 4, 5, 6}); - auto result = backend->create_tensor(element::i32, shape_rt); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_EQ((vector{2, 4, 6}), read_vector(result)); -} - -NGRAPH_TEST(${BACKEND_NAME}, reduce_max_keep_3d_to_matrix_most_sig) { - Shape shape_a{3, 3, 3}; - auto A = make_shared(element::f32, shape_a); - Shape shape_rt{1, 3, 3}; - auto axes = make_shared(element::i32, Shape{}, 0); - auto f = make_shared(make_shared(A, axes, true), ParameterVector{A}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::f32, shape_a); - copy_data(a, vector{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27}); - auto result = backend->create_tensor(element::f32, shape_rt); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_TRUE(test::all_close_f((vector{19, 20, 21, 22, 23, 24, 25, 26, 27}), - read_vector(result), - MIN_FLOAT_TOLERANCE_BITS)); -} - -NGRAPH_TEST(${BACKEND_NAME}, reduce_max_keep_3d_to_matrix_least_sig) { - Shape shape_a{3, 3, 3}; - auto A = make_shared(element::f32, shape_a); - Shape shape_rt{3, 3, 1}; - auto axes = make_shared(element::i32, Shape{}, 2); - auto f = make_shared(make_shared(A, axes, true), ParameterVector{A}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::f32, shape_a); - copy_data(a, vector{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27}); - auto result = backend->create_tensor(element::f32, shape_rt); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_TRUE(test::all_close_f((vector{3, 6, 9, 12, 15, 18, 21, 24, 27}), - read_vector(result), - MIN_FLOAT_TOLERANCE_BITS)); -} - -NGRAPH_TEST(${BACKEND_NAME}, reduce_max_keep_3d_to_vector) { - Shape shape_a{3, 3, 3}; - auto A = make_shared(element::f32, shape_a); - Shape shape_rt{1, 1, 3}; - auto axes = make_shared(element::i32, Shape{2}, vector{0, 1}); - auto f = make_shared(make_shared(A, axes, true), ParameterVector{A}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::f32, shape_a); - copy_data(a, vector{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27}); - auto result = backend->create_tensor(element::f32, shape_rt); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_TRUE( - test::all_close_f((vector{25.0f, 26.0f, 27.0f}), read_vector(result), MIN_FLOAT_TOLERANCE_BITS)); -} - -NGRAPH_TEST(${BACKEND_NAME}, reduce_max_keep_3d_to_scalar) { - Shape shape_a{3, 3, 3}; - auto A = make_shared(element::f32, shape_a); - Shape shape_rt{1, 1, 1}; - auto axes = make_shared(element::i32, Shape{3}, vector{0, 1, 2}); - auto f = make_shared(make_shared(A, axes, true), ParameterVector{A}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::f32, shape_a); - copy_data(a, - vector{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1}); - auto result = backend->create_tensor(element::f32, shape_rt); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_TRUE(test::all_close_f((vector{14.0f}), read_vector(result), MIN_FLOAT_TOLERANCE_BITS)); -} - -NGRAPH_TEST(${BACKEND_NAME}, reduce_max_keep_3d_to_scalar_int32) { - Shape shape_a{3, 3, 3}; - auto A = make_shared(element::i32, shape_a); - Shape shape_rt{1, 1, 1}; - auto axes = make_shared(element::i32, Shape{3}, vector{0, 1, 2}); - auto f = make_shared(make_shared(A, axes, true), ParameterVector{A}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::i32, shape_a); - copy_data(a, vector{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1}); - auto result = backend->create_tensor(element::i32, shape_rt); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_EQ((vector{14}), read_vector(result)); -} - -// Dynamic - -NGRAPH_TEST(${BACKEND_NAME}, reduce_max_matrix_columns_dynamic) { - auto A = make_shared(element::f32, PartialShape::dynamic()); - auto axes = make_shared(element::i32, Shape{}, 0); - auto f = make_shared(make_shared(A, axes, false), ParameterVector{A}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}", true); - - // Create some tensors for input/output - Shape shape_a{3, 2}; - auto a = backend->create_tensor(element::f32, shape_a); - copy_data(a, vector{1, 2, 3, 4, 5, 6}); - auto result = backend->create_dynamic_tensor(element::f32, PartialShape::dynamic()); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_TRUE(test::all_close_f((vector{5, 6}), read_vector(result))); -} - -NGRAPH_TEST(${BACKEND_NAME}, reduce_max_matrix_rows_dynamic) { - auto A = make_shared(element::f32, PartialShape::dynamic()); - auto axes = make_shared(element::i32, Shape{}, 1); - auto f = make_shared(make_shared(A, axes, false), ParameterVector{A}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}", true); - - // Create some tensors for input/output - Shape shape_a{3, 2}; - auto a = backend->create_tensor(element::f32, shape_a); - copy_data(a, vector{1, 2, 3, 4, 5, 6}); - auto result = backend->create_dynamic_tensor(element::f32, PartialShape::dynamic()); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_TRUE(test::all_close_f((vector{2, 4, 6}), read_vector(result))); -} - -NGRAPH_TEST(${BACKEND_NAME}, reduce_max_keep_matrix_columns_dynamic) { - auto A = make_shared(element::f32, PartialShape::dynamic()); - auto axes = make_shared(element::i32, Shape{}, 0); - auto f = make_shared(make_shared(A, axes, true), ParameterVector{A}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}", true); - - // Create some tensors for input/output - Shape shape_a{3, 2}; - auto a = backend->create_tensor(element::f32, shape_a); - copy_data(a, vector{1, 2, 3, 4, 5, 6}); - auto result = backend->create_dynamic_tensor(element::f32, PartialShape::dynamic()); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_TRUE(test::all_close_f((vector{5, 6}), read_vector(result))); -} - -NGRAPH_TEST(${BACKEND_NAME}, reduce_max_keep_matrix_rows_dynamic) { - auto A = make_shared(element::f32, PartialShape::dynamic()); - auto axes = make_shared(element::i32, Shape{}, 1); - auto f = make_shared(make_shared(A, axes, true), ParameterVector{A}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}", true); - - // Create some tensors for input/output - Shape shape_a{3, 2}; - auto a = backend->create_tensor(element::f32, shape_a); - copy_data(a, vector{1, 2, 3, 4, 5, 6}); - auto result = backend->create_dynamic_tensor(element::f32, PartialShape::dynamic()); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_TRUE(test::all_close_f((vector{2, 4, 6}), read_vector(result))); -} diff --git a/ngraph/test/backend/reduce_mean.in.cpp b/ngraph/test/backend/reduce_mean.in.cpp deleted file mode 100644 index ff3c15840f4..00000000000 --- a/ngraph/test/backend/reduce_mean.in.cpp +++ /dev/null @@ -1,285 +0,0 @@ -// Copyright (C) 2018-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#include "gtest/gtest.h" -#include "ngraph/ngraph.hpp" -#include "util/all_close.hpp" -#include "util/all_close_f.hpp" -#include "util/known_element_types.hpp" -#include "util/ndarray.hpp" -#include "util/test_control.hpp" -#include "util/test_tools.hpp" - -using namespace std; -using namespace ngraph; - -static string s_manifest = "${MANIFEST}"; - -// ----------------------- keep dims = false ----------------------- // - -NGRAPH_TEST(${BACKEND_NAME}, reduce_mean_to_scalar) { - Shape shape{2, 2}; - auto A = make_shared(element::f32, shape); - auto axes = make_shared(element::i32, Shape{2}, vector{0, 1}); - auto f = make_shared(make_shared(A, axes, false), ParameterVector{A}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::f32, shape); - copy_data(a, vector{1, 2, 3, 4}); - auto result = backend->create_tensor(element::f32, Shape{}); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_TRUE(test::all_close_f((vector{2.5}), read_vector(result), MIN_FLOAT_TOLERANCE_BITS)); -} - -NGRAPH_TEST(${BACKEND_NAME}, reduce_mean_to_scalar_int8) { - Shape shape{2, 2}; - auto A = make_shared(element::i8, shape); - auto axes = make_shared(element::i32, Shape{2}, vector{0, 1}); - auto f = make_shared(make_shared(A, axes, false), ParameterVector{A}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::i8, shape); - copy_data(a, vector{1, 2, 3, 4}); - auto result = backend->create_tensor(element::i8, Shape{}); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_EQ((vector{2}), read_vector(result)); -} - -NGRAPH_TEST(${BACKEND_NAME}, reduce_mean_matrix_columns) { - Shape shape_a{3, 2}; - auto A = make_shared(element::f32, shape_a); - Shape shape_rt{2}; - auto axes = make_shared(element::i32, Shape{}, 0); - auto f = make_shared(make_shared(A, axes, false), ParameterVector{A}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::f32, shape_a); - copy_data(a, vector{1, 2, 3, 4, 5, 6}); - auto result = backend->create_tensor(element::f32, shape_rt); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_TRUE(test::all_close_f((vector{3, 4}), read_vector(result), MIN_FLOAT_TOLERANCE_BITS)); -} - -NGRAPH_TEST(${BACKEND_NAME}, reduce_mean_matrix_rows) { - Shape shape_a{3, 2}; - auto A = make_shared(element::f32, shape_a); - Shape shape_rt{3}; - auto axes = make_shared(element::i32, Shape{}, 1); - auto f = make_shared(make_shared(A, axes, false), ParameterVector{A}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::f32, shape_a); - copy_data(a, vector{1, 2, 3, 4, 5, 6}); - auto result = backend->create_tensor(element::f32, shape_rt); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_TRUE( - test::all_close_f((vector{1.5, 3.5, 5.5}), read_vector(result), MIN_FLOAT_TOLERANCE_BITS)); -} - -NGRAPH_TEST(${BACKEND_NAME}, reduce_mean_matrix_rows_int32) { - Shape shape_a{3, 2}; - auto A = make_shared(element::i32, shape_a); - Shape shape_rt{3}; - auto axes = make_shared(element::i32, Shape{}, 1); - auto f = make_shared(make_shared(A, axes, false), ParameterVector{A}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::i32, shape_a); - copy_data(a, vector{1, 2, 3, 4, 5, 6}); - auto result = backend->create_tensor(element::i32, shape_rt); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_EQ((vector{1, 3, 5}), read_vector(result)); -} - -// ----------------------- keep dims = true ----------------------- // - -NGRAPH_TEST(${BACKEND_NAME}, reduce_mean_keep_to_scalar) { - Shape shape{2, 2}; - auto A = make_shared(element::f32, shape); - auto axes = make_shared(element::i32, Shape{2}, vector{0, 1}); - auto f = make_shared(make_shared(A, axes, true), ParameterVector{A}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::f32, shape); - copy_data(a, vector{1, 2, 3, 4}); - auto result = backend->create_tensor(element::f32, Shape{1, 1}); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_TRUE(test::all_close_f((vector{2.5}), read_vector(result), MIN_FLOAT_TOLERANCE_BITS)); -} - -NGRAPH_TEST(${BACKEND_NAME}, reduce_mean_keep_to_scalar_int8) { - Shape shape{2, 2}; - auto A = make_shared(element::i8, shape); - auto axes = make_shared(element::i32, Shape{2}, vector{0, 1}); - auto f = make_shared(make_shared(A, axes, true), ParameterVector{A}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::i8, shape); - copy_data(a, vector{1, 2, 3, 4}); - auto result = backend->create_tensor(element::i8, Shape{1, 1}); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_EQ((vector{2}), read_vector(result)); -} - -NGRAPH_TEST(${BACKEND_NAME}, reduce_mean_keep_matrix_columns) { - Shape shape_a{3, 2}; - auto A = make_shared(element::f32, shape_a); - Shape shape_rt{1, 2}; - auto axes = make_shared(element::i32, Shape{}, 0); - auto f = make_shared(make_shared(A, axes, true), ParameterVector{A}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::f32, shape_a); - copy_data(a, vector{1, 2, 3, 4, 5, 6}); - auto result = backend->create_tensor(element::f32, shape_rt); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_TRUE(test::all_close_f((vector{3, 4}), read_vector(result), MIN_FLOAT_TOLERANCE_BITS)); -} - -NGRAPH_TEST(${BACKEND_NAME}, reduce_mean_keep_matrix_rows) { - Shape shape_a{3, 2}; - auto A = make_shared(element::f32, shape_a); - Shape shape_rt{3, 1}; - auto axes = make_shared(element::i32, Shape{}, 1); - auto f = make_shared(make_shared(A, axes, true), ParameterVector{A}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::f32, shape_a); - copy_data(a, vector{1, 2, 3, 4, 5, 6}); - auto result = backend->create_tensor(element::f32, shape_rt); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_TRUE( - test::all_close_f((vector{1.5, 3.5, 5.5}), read_vector(result), MIN_FLOAT_TOLERANCE_BITS)); -} - -NGRAPH_TEST(${BACKEND_NAME}, reduce_mean_keep_matrix_rows_int32) { - Shape shape_a{3, 2}; - auto A = make_shared(element::i32, shape_a); - Shape shape_rt{3, 1}; - auto axes = make_shared(element::i32, Shape{}, 1); - auto f = make_shared(make_shared(A, axes, true), ParameterVector{A}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::i32, shape_a); - copy_data(a, vector{1, 2, 3, 4, 5, 6}); - auto result = backend->create_tensor(element::i32, shape_rt); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_EQ((vector{1, 3, 5}), read_vector(result)); -} - -// Dynamic - -NGRAPH_TEST(${BACKEND_NAME}, reduce_mean_matrix_columns_dynamic) { - auto A = make_shared(element::f32, PartialShape::dynamic()); - auto axes = make_shared(element::i32, Shape{}, 0); - auto f = make_shared(make_shared(A, axes, false), ParameterVector{A}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}", true); - - // Create some tensors for input/output - Shape shape_a{3, 2}; - auto a = backend->create_tensor(element::f32, shape_a); - copy_data(a, vector{1, 2, 3, 4, 5, 6}); - auto result = backend->create_dynamic_tensor(element::f32, PartialShape::dynamic()); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_TRUE(test::all_close_f((vector{3, 4}), read_vector(result), MIN_FLOAT_TOLERANCE_BITS)); -} - -NGRAPH_TEST(${BACKEND_NAME}, reduce_mean_matrix_rows_dynamic) { - auto A = make_shared(element::f32, PartialShape::dynamic()); - auto axes = make_shared(element::i32, Shape{}, 1); - auto f = make_shared(make_shared(A, axes, false), ParameterVector{A}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}", true); - - // Create some tensors for input/output - Shape shape_a{3, 2}; - auto a = backend->create_tensor(element::f32, shape_a); - copy_data(a, vector{1, 2, 3, 4, 5, 6}); - auto result = backend->create_dynamic_tensor(element::f32, PartialShape::dynamic()); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_TRUE( - test::all_close_f((vector{1.5, 3.5, 5.5}), read_vector(result), MIN_FLOAT_TOLERANCE_BITS)); -} - -NGRAPH_TEST(${BACKEND_NAME}, reduce_mean_keep_matrix_columns_dynamic) { - auto A = make_shared(element::f32, PartialShape::dynamic()); - auto axes = make_shared(element::i32, Shape{}, 0); - auto f = make_shared(make_shared(A, axes, true), ParameterVector{A}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}", true); - - // Create some tensors for input/output - Shape shape_a{3, 2}; - auto a = backend->create_tensor(element::f32, shape_a); - copy_data(a, vector{1, 2, 3, 4, 5, 6}); - auto result = backend->create_dynamic_tensor(element::f32, PartialShape::dynamic()); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_TRUE(test::all_close_f((vector{3, 4}), read_vector(result), MIN_FLOAT_TOLERANCE_BITS)); -} - -NGRAPH_TEST(${BACKEND_NAME}, reduce_mean_keep_matrix_rows_dynamic) { - auto A = make_shared(element::f32, PartialShape::dynamic()); - auto axes = make_shared(element::i32, Shape{}, 1); - auto f = make_shared(make_shared(A, axes, true), ParameterVector{A}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}", true); - - // Create some tensors for input/output - Shape shape_a{3, 2}; - auto a = backend->create_tensor(element::f32, shape_a); - copy_data(a, vector{1, 2, 3, 4, 5, 6}); - auto result = backend->create_dynamic_tensor(element::f32, PartialShape::dynamic()); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_TRUE( - test::all_close_f((vector{1.5, 3.5, 5.5}), read_vector(result), MIN_FLOAT_TOLERANCE_BITS)); -} diff --git a/ngraph/test/backend/reduce_min.in.cpp b/ngraph/test/backend/reduce_min.in.cpp deleted file mode 100644 index d422fb18a23..00000000000 --- a/ngraph/test/backend/reduce_min.in.cpp +++ /dev/null @@ -1,489 +0,0 @@ -// Copyright (C) 2018-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#include "gtest/gtest.h" -#include "ngraph/ngraph.hpp" -#include "util/all_close.hpp" -#include "util/all_close_f.hpp" -#include "util/known_element_types.hpp" -#include "util/ndarray.hpp" -#include "util/test_control.hpp" -#include "util/test_tools.hpp" - -using namespace std; -using namespace ngraph; - -static string s_manifest = "${MANIFEST}"; - -// ----------------------- keep dims = false ----------------------- // - -NGRAPH_TEST(${BACKEND_NAME}, reduce_min_to_scalar) { - Shape shape{2, 2}; - auto A = make_shared(element::f32, shape); - auto axes = make_shared(element::i32, Shape{2}, vector{0, 1}); - auto f = make_shared(make_shared(A, axes, false), ParameterVector{A}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::f32, shape); - copy_data(a, vector{1, 2, 3, 4}); - auto result = backend->create_tensor(element::f32, Shape{}); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_TRUE(test::all_close_f((vector{1}), read_vector(result), MIN_FLOAT_TOLERANCE_BITS)); -} - -NGRAPH_TEST(${BACKEND_NAME}, reduce_min_to_scalar_int8) { - Shape shape{2, 2}; - auto A = make_shared(element::i8, shape); - auto axes = make_shared(element::i32, Shape{2}, vector{0, 1}); - auto f = make_shared(make_shared(A, axes, false), ParameterVector{A}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::i8, shape); - copy_data(a, vector{1, 2, 3, 4}); - auto result = backend->create_tensor(element::i8, Shape{}); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_EQ((vector{1}), read_vector(result)); -} - -NGRAPH_TEST(${BACKEND_NAME}, reduce_min_matrix_columns) { - Shape shape_a{3, 2}; - auto A = make_shared(element::f32, shape_a); - Shape shape_rt{2}; - auto axes = make_shared(element::i32, Shape{}, 0); - auto f = make_shared(make_shared(A, axes, false), ParameterVector{A}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::f32, shape_a); - copy_data(a, vector{1, 2, 3, 4, 5, 6}); - auto result = backend->create_tensor(element::f32, shape_rt); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_TRUE(test::all_close_f((vector{1, 2}), read_vector(result), MIN_FLOAT_TOLERANCE_BITS)); -} - -NGRAPH_TEST(${BACKEND_NAME}, reduce_min_matrix_rows) { - Shape shape_a{3, 2}; - auto A = make_shared(element::f32, shape_a); - Shape shape_rt{3}; - auto axes = make_shared(element::i32, Shape{}, 1); - auto f = make_shared(make_shared(A, axes, false), ParameterVector{A}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::f32, shape_a); - copy_data(a, vector{1, 2, 3, 4, 5, 6}); - auto result = backend->create_tensor(element::f32, shape_rt); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_TRUE(test::all_close_f((vector{1, 3, 5}), read_vector(result), MIN_FLOAT_TOLERANCE_BITS)); -} - -NGRAPH_TEST(${BACKEND_NAME}, reduce_min_matrix_rows_int32) { - Shape shape_a{3, 2}; - auto A = make_shared(element::i32, shape_a); - Shape shape_rt{3}; - auto axes = make_shared(element::i32, Shape{}, 1); - auto f = make_shared(make_shared(A, axes, false), ParameterVector{A}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::i32, shape_a); - copy_data(a, vector{1, 2, 3, 4, 5, 6}); - auto result = backend->create_tensor(element::i32, shape_rt); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_EQ((vector{1, 3, 5}), read_vector(result)); -} - -NGRAPH_TEST(${BACKEND_NAME}, reduce_min_3d_to_matrix_most_sig) { - Shape shape_a{3, 3, 3}; - auto A = make_shared(element::f32, shape_a); - Shape shape_rt{3, 3}; - auto axes = make_shared(element::i32, Shape{}, 0); - auto f = make_shared(make_shared(A, axes, false), ParameterVector{A}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::f32, shape_a); - copy_data(a, vector{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27}); - auto result = backend->create_tensor(element::f32, shape_rt); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_TRUE(test::all_close_f((vector{1, 2, 3, 4, 5, 6, 7, 8, 9}), - read_vector(result), - MIN_FLOAT_TOLERANCE_BITS)); -} - -NGRAPH_TEST(${BACKEND_NAME}, reduce_min_3d_to_matrix_least_sig) { - Shape shape_a{3, 3, 3}; - auto A = make_shared(element::f32, shape_a); - Shape shape_rt{3, 3}; - auto axes = make_shared(element::i32, Shape{}, 2); - auto f = make_shared(make_shared(A, axes, false), ParameterVector{A}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::f32, shape_a); - copy_data(a, vector{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27}); - auto result = backend->create_tensor(element::f32, shape_rt); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_TRUE(test::all_close_f((vector{1, 4, 7, 10, 13, 16, 19, 22, 25}), - read_vector(result), - MIN_FLOAT_TOLERANCE_BITS)); -} - -NGRAPH_TEST(${BACKEND_NAME}, reduce_min_3d_to_vector) { - Shape shape_a{3, 3, 3}; - auto A = make_shared(element::f32, shape_a); - Shape shape_rt{3}; - auto axes = make_shared(element::i32, Shape{2}, vector{0, 1}); - auto f = make_shared(make_shared(A, axes, false), ParameterVector{A}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::f32, shape_a); - copy_data(a, vector{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27}); - auto result = backend->create_tensor(element::f32, shape_rt); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_TRUE(test::all_close_f((vector{1, 2, 3}), read_vector(result), MIN_FLOAT_TOLERANCE_BITS)); -} - -NGRAPH_TEST(${BACKEND_NAME}, reduce_min_3d_to_scalar) { - Shape shape_a{3, 3, 3}; - auto A = make_shared(element::f32, shape_a); - Shape shape_rt{}; - auto axes = make_shared(element::i32, Shape{3}, vector{0, 1, 2}); - auto f = make_shared(make_shared(A, axes, false), ParameterVector{A}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::f32, shape_a); - copy_data(a, - vector{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1}); - auto result = backend->create_tensor(element::f32, shape_rt); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_TRUE(test::all_close_f((vector{1}), read_vector(result), MIN_FLOAT_TOLERANCE_BITS)); -} - -NGRAPH_TEST(${BACKEND_NAME}, reduce_min_3d_to_scalar_int32) { - Shape shape_a{3, 3, 3}; - auto A = make_shared(element::i32, shape_a); - Shape shape_rt{}; - auto axes = make_shared(element::i32, Shape{3}, vector{0, 1, 2}); - auto f = make_shared(make_shared(A, axes, false), ParameterVector{A}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::i32, shape_a); - copy_data(a, vector{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1}); - auto result = backend->create_tensor(element::i32, shape_rt); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_EQ((vector{1}), read_vector(result)); -} - -// ----------------------- keep dims = true ----------------------- // - -NGRAPH_TEST(${BACKEND_NAME}, reduce_min_keep_to_scalar) { - Shape shape{2, 2}; - auto A = make_shared(element::f32, shape); - auto axes = make_shared(element::i32, Shape{2}, vector{0, 1}); - auto f = make_shared(make_shared(A, axes, true), ParameterVector{A}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::f32, shape); - copy_data(a, vector{1, 2, 3, 4}); - auto result = backend->create_tensor(element::f32, Shape{1, 1}); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_TRUE(test::all_close_f((vector{1}), read_vector(result), MIN_FLOAT_TOLERANCE_BITS)); -} - -NGRAPH_TEST(${BACKEND_NAME}, reduce_min_keep_to_scalar_int8) { - Shape shape{2, 2}; - auto A = make_shared(element::i8, shape); - auto axes = make_shared(element::i32, Shape{2}, vector{0, 1}); - auto f = make_shared(make_shared(A, axes, true), ParameterVector{A}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::i8, shape); - copy_data(a, vector{1, 2, 3, 4}); - auto result = backend->create_tensor(element::i8, Shape{1, 1}); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_EQ((vector{1}), read_vector(result)); -} - -NGRAPH_TEST(${BACKEND_NAME}, reduce_min_keep_matrix_columns) { - Shape shape_a{3, 2}; - auto A = make_shared(element::f32, shape_a); - Shape shape_rt{1, 2}; - auto axes = make_shared(element::i32, Shape{}, 0); - auto f = make_shared(make_shared(A, axes, true), ParameterVector{A}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::f32, shape_a); - copy_data(a, vector{1, 2, 3, 4, 5, 6}); - auto result = backend->create_tensor(element::f32, shape_rt); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_TRUE(test::all_close_f((vector{1, 2}), read_vector(result), MIN_FLOAT_TOLERANCE_BITS)); -} - -NGRAPH_TEST(${BACKEND_NAME}, reduce_min_keep_matrix_rows) { - Shape shape_a{3, 2}; - auto A = make_shared(element::f32, shape_a); - Shape shape_rt{3, 1}; - auto axes = make_shared(element::i32, Shape{}, 1); - auto f = make_shared(make_shared(A, axes, true), ParameterVector{A}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::f32, shape_a); - copy_data(a, vector{1, 2, 3, 4, 5, 6}); - auto result = backend->create_tensor(element::f32, shape_rt); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_TRUE(test::all_close_f((vector{1, 3, 5}), read_vector(result), MIN_FLOAT_TOLERANCE_BITS)); -} - -NGRAPH_TEST(${BACKEND_NAME}, reduce_min_keep_matrix_rows_int32) { - Shape shape_a{3, 2}; - auto A = make_shared(element::i32, shape_a); - Shape shape_rt{3, 1}; - auto axes = make_shared(element::i32, Shape{}, 1); - auto f = make_shared(make_shared(A, axes, true), ParameterVector{A}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::i32, shape_a); - copy_data(a, vector{1, 2, 3, 4, 5, 6}); - auto result = backend->create_tensor(element::i32, shape_rt); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_EQ((vector{1, 3, 5}), read_vector(result)); -} - -NGRAPH_TEST(${BACKEND_NAME}, reduce_min_keep_3d_to_matrix_most_sig) { - Shape shape_a{3, 3, 3}; - auto A = make_shared(element::f32, shape_a); - Shape shape_rt{1, 3, 3}; - auto axes = make_shared(element::i32, Shape{}, 0); - auto f = make_shared(make_shared(A, axes, true), ParameterVector{A}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::f32, shape_a); - copy_data(a, vector{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27}); - auto result = backend->create_tensor(element::f32, shape_rt); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_TRUE(test::all_close_f((vector{1, 2, 3, 4, 5, 6, 7, 8, 9}), - read_vector(result), - MIN_FLOAT_TOLERANCE_BITS)); -} - -NGRAPH_TEST(${BACKEND_NAME}, reduce_min_keep_3d_to_matrix_least_sig) { - Shape shape_a{3, 3, 3}; - auto A = make_shared(element::f32, shape_a); - Shape shape_rt{3, 3, 1}; - auto axes = make_shared(element::i32, Shape{}, 2); - auto f = make_shared(make_shared(A, axes, true), ParameterVector{A}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::f32, shape_a); - copy_data(a, vector{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27}); - auto result = backend->create_tensor(element::f32, shape_rt); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_TRUE(test::all_close_f((vector{1, 4, 7, 10, 13, 16, 19, 22, 25}), - read_vector(result), - MIN_FLOAT_TOLERANCE_BITS)); -} - -NGRAPH_TEST(${BACKEND_NAME}, reduce_min_keep_3d_to_vector) { - Shape shape_a{3, 3, 3}; - auto A = make_shared(element::f32, shape_a); - Shape shape_rt{1, 1, 3}; - auto axes = make_shared(element::i32, Shape{2}, vector{0, 1}); - auto f = make_shared(make_shared(A, axes, true), ParameterVector{A}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::f32, shape_a); - copy_data(a, vector{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27}); - auto result = backend->create_tensor(element::f32, shape_rt); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_TRUE(test::all_close_f((vector{1, 2, 3}), read_vector(result), MIN_FLOAT_TOLERANCE_BITS)); -} - -NGRAPH_TEST(${BACKEND_NAME}, reduce_min_keep_3d_to_scalar) { - Shape shape_a{3, 3, 3}; - auto A = make_shared(element::f32, shape_a); - Shape shape_rt{1, 1, 1}; - auto axes = make_shared(element::i32, Shape{3}, vector{0, 1, 2}); - auto f = make_shared(make_shared(A, axes, true), ParameterVector{A}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::f32, shape_a); - copy_data(a, - vector{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1}); - auto result = backend->create_tensor(element::f32, shape_rt); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_TRUE(test::all_close_f((vector{1}), read_vector(result), MIN_FLOAT_TOLERANCE_BITS)); -} - -NGRAPH_TEST(${BACKEND_NAME}, reduce_min_keep_3d_to_scalar_int32) { - Shape shape_a{3, 3, 3}; - auto A = make_shared(element::i32, shape_a); - Shape shape_rt{1, 1, 1}; - auto axes = make_shared(element::i32, Shape{3}, vector{0, 1, 2}); - auto f = make_shared(make_shared(A, axes, true), ParameterVector{A}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::i32, shape_a); - copy_data(a, vector{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1}); - auto result = backend->create_tensor(element::i32, shape_rt); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_EQ((vector{1}), read_vector(result)); -} - -// Dynamic - -NGRAPH_TEST(${BACKEND_NAME}, reduce_min_matrix_columns_dynamic) { - auto A = make_shared(element::f32, PartialShape::dynamic()); - auto axes = make_shared(element::i32, Shape{}, 0); - auto f = make_shared(make_shared(A, axes, false), ParameterVector{A}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}", true); - - // Create some tensors for input/output - Shape shape_a{3, 2}; - auto a = backend->create_tensor(element::f32, shape_a); - copy_data(a, vector{1, 2, 3, 4, 5, 6}); - auto result = backend->create_dynamic_tensor(element::f32, PartialShape::dynamic()); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_TRUE(test::all_close_f((vector{1, 2}), read_vector(result), MIN_FLOAT_TOLERANCE_BITS)); -} - -NGRAPH_TEST(${BACKEND_NAME}, reduce_min_matrix_rows_dynamic) { - auto A = make_shared(element::f32, PartialShape::dynamic()); - auto axes = make_shared(element::i32, Shape{}, 1); - auto f = make_shared(make_shared(A, axes, false), ParameterVector{A}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}", true); - - // Create some tensors for input/output - Shape shape_a{3, 2}; - auto a = backend->create_tensor(element::f32, shape_a); - copy_data(a, vector{1, 2, 3, 4, 5, 6}); - auto result = backend->create_dynamic_tensor(element::f32, PartialShape::dynamic()); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_TRUE(test::all_close_f((vector{1, 3, 5}), read_vector(result), MIN_FLOAT_TOLERANCE_BITS)); -} - -NGRAPH_TEST(${BACKEND_NAME}, reduce_min_keep_matrix_columns_dynamic) { - auto A = make_shared(element::f32, PartialShape::dynamic()); - auto axes = make_shared(element::i32, Shape{}, 0); - auto f = make_shared(make_shared(A, axes, true), ParameterVector{A}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}", true); - - // Create some tensors for input/output - Shape shape_a{3, 2}; - auto a = backend->create_tensor(element::f32, shape_a); - copy_data(a, vector{1, 2, 3, 4, 5, 6}); - auto result = backend->create_dynamic_tensor(element::f32, PartialShape::dynamic()); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_TRUE(test::all_close_f((vector{1, 2}), read_vector(result), MIN_FLOAT_TOLERANCE_BITS)); -} - -NGRAPH_TEST(${BACKEND_NAME}, reduce_min_keep_matrix_rows_dynamic) { - auto A = make_shared(element::f32, PartialShape::dynamic()); - auto axes = make_shared(element::i32, Shape{}, 1); - auto f = make_shared(make_shared(A, axes, true), ParameterVector{A}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}", true); - - // Create some tensors for input/output - Shape shape_a{3, 2}; - auto a = backend->create_tensor(element::f32, shape_a); - copy_data(a, vector{1, 2, 3, 4, 5, 6}); - auto result = backend->create_dynamic_tensor(element::f32, PartialShape::dynamic()); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_TRUE(test::all_close_f((vector{1, 3, 5}), read_vector(result), MIN_FLOAT_TOLERANCE_BITS)); -} diff --git a/ngraph/test/backend/reduce_prod.in.cpp b/ngraph/test/backend/reduce_prod.in.cpp deleted file mode 100644 index 5d50b794f04..00000000000 --- a/ngraph/test/backend/reduce_prod.in.cpp +++ /dev/null @@ -1,525 +0,0 @@ -// Copyright (C) 2018-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#include "gtest/gtest.h" -#include "ngraph/ngraph.hpp" -#include "util/all_close.hpp" -#include "util/all_close_f.hpp" -#include "util/known_element_types.hpp" -#include "util/ndarray.hpp" -#include "util/test_control.hpp" -#include "util/test_tools.hpp" - -using namespace std; -using namespace ngraph; - -static string s_manifest = "${MANIFEST}"; - -// ----------------------- keep dims = false ----------------------- // - -NGRAPH_TEST(${BACKEND_NAME}, reduce_product_to_scalar) { - Shape shape{2, 2}; - auto A = make_shared(element::f32, shape); - auto axes = make_shared(element::i32, Shape{2}, vector{0, 1}); - auto f = make_shared(make_shared(A, axes, false), ParameterVector{A}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::f32, shape); - copy_data(a, vector{1, 2, 3, 4}); - auto result = backend->create_tensor(element::f32, Shape{}); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_TRUE(test::all_close_f((vector{24}), read_vector(result))); -} - -NGRAPH_TEST(${BACKEND_NAME}, reduce_product_matrix_columns) { - Shape shape_a{3, 2}; - auto A = make_shared(element::f32, shape_a); - Shape shape_rt{2}; - auto axes = make_shared(element::i32, Shape{}, 0); - auto f = make_shared(make_shared(A, axes, false), ParameterVector{A}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::f32, shape_a); - copy_data(a, vector{1, 2, 3, 4, 5, 6}); - auto result = backend->create_tensor(element::f32, shape_rt); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_TRUE(test::all_close_f((vector{15, 48}), read_vector(result))); -} - -NGRAPH_TEST(${BACKEND_NAME}, reduce_product_matrix_rows) { - Shape shape_a{3, 2}; - auto A = make_shared(element::f32, shape_a); - Shape shape_rt{3}; - auto axes = make_shared(element::i32, Shape{}, 1); - auto f = make_shared(make_shared(A, axes, false), ParameterVector{A}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::f32, shape_a); - copy_data(a, vector{1, 2, 3, 4, 5, 6}); - auto result = backend->create_tensor(element::f32, shape_rt); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_TRUE(test::all_close_f((vector{2, 12, 30}), read_vector(result))); -} - -NGRAPH_TEST(${BACKEND_NAME}, reduce_product_3d_to_matrix_most_sig) { - Shape shape_a{3, 3, 3}; - auto A = make_shared(element::f32, shape_a); - Shape shape_rt{3, 3}; - auto axes = make_shared(element::i32, Shape{}, 0); - auto f = make_shared(make_shared(A, axes, false), ParameterVector{A}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::f32, shape_a); - copy_data(a, vector{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27}); - auto result = backend->create_tensor(element::f32, shape_rt); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_TRUE(test::all_close_f((vector{1 * 10 * 19, - 2 * 11 * 20, - 3 * 12 * 21, - 4 * 13 * 22, - 5 * 14 * 23, - 6 * 15 * 24, - 7 * 16 * 25, - 8 * 17 * 26, - 9 * 18 * 27}), - read_vector(result))); -} - -NGRAPH_TEST(${BACKEND_NAME}, reduce_product_3d_to_matrix_least_sig) { - Shape shape_a{3, 3, 3}; - auto A = make_shared(element::f32, shape_a); - Shape shape_rt{3, 3}; - auto axes = make_shared(element::i32, Shape{}, 2); - auto f = make_shared(make_shared(A, axes, false), ParameterVector{A}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::f32, shape_a); - copy_data(a, vector{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27}); - auto result = backend->create_tensor(element::f32, shape_rt); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_TRUE(test::all_close_f((vector{1 * 2 * 3, - 4 * 5 * 6, - 7 * 8 * 9, - 10 * 11 * 12, - 13 * 14 * 15, - 16 * 17 * 18, - 19 * 20 * 21, - 22 * 23 * 24, - 25 * 26 * 27}), - read_vector(result))); -} - -NGRAPH_TEST(${BACKEND_NAME}, reduce_product_3d_to_vector) { - Shape shape_a{3, 3, 3}; - auto A = make_shared(element::f32, shape_a); - Shape shape_rt{3}; - auto axes = make_shared(element::i32, Shape{2}, vector{0, 1}); - auto f = make_shared(make_shared(A, axes, false), ParameterVector{A}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::f32, shape_a); - copy_data(a, vector{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27}); - auto result = backend->create_tensor(element::f32, shape_rt); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_TRUE(test::all_close_f((vector{1.0f * 10.0f * 19.0f * 4.0f * 13.0f * 22.0f * 7.0f * 16.0f * 25.0f, - 2.0f * 11.0f * 20.0f * 5.0f * 14.0f * 23.0f * 8.0f * 17.0f * 26.0f, - 3.0f * 12.0f * 21.0f * 6.0f * 15.0f * 24.0f * 9.0f * 18.0f * 27.0f}), - read_vector(result))); -} - -NGRAPH_TEST(${BACKEND_NAME}, reduce_product_3d_to_scalar) { - Shape shape_a{3, 3, 3}; - auto A = make_shared(element::f32, shape_a); - Shape shape_rt{}; - auto axes = make_shared(element::i32, Shape{3}, vector{0, 1, 2}); - auto f = make_shared(make_shared(A, axes, false), ParameterVector{A}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::f32, shape_a); - copy_data(a, - vector{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1}); - auto result = backend->create_tensor(element::f32, shape_rt); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_TRUE(test::all_close_f(vector{1.0f * 10.0f * 9.0f * 4.0f * 13.0f * 6.0f * 7.0f * 12.0f * 3.0f * 2.0f * - 11.0f * 8.0f * 5.0f * 14.0f * 5.0f * 8.0f * 11.0f * 2.0f * 3.0f * - 12.0f * 7.0f * 6.0f * 13.0f * 4.0f * 9.0f * 10.0f * 1.0f}, - read_vector(result))); -} - -NGRAPH_TEST(${BACKEND_NAME}, reduce_product_2d_to_scalar_int32) { - Shape shape_a{3, 3}; - auto A = make_shared(element::i32, shape_a); - Shape shape_rt{}; - auto axes = make_shared(element::i32, Shape{2}, vector{0, 1}); - auto f = make_shared(make_shared(A, axes, false), ParameterVector{A}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::i32, shape_a); - copy_data(a, vector{1, 2, 3, 4, 5, 6, 7, 8, 9}); - auto result = backend->create_tensor(element::i32, shape_rt); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_EQ(vector{1 * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9}, read_vector(result)); -} - -NGRAPH_TEST(${BACKEND_NAME}, reduce_product_to_scalar_int32) { - Shape shape{2, 2}; - auto A = make_shared(element::i32, shape); - auto axes = make_shared(element::i32, Shape{2}, vector{0, 1}); - auto f = make_shared(make_shared(A, axes, false), ParameterVector{A}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::i32, shape); - copy_data(a, vector{1, 2, 3, 4}); - auto result = backend->create_tensor(element::i32, Shape{}); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_EQ((vector{24}), read_vector(result)); -} - -NGRAPH_TEST(${BACKEND_NAME}, reduce_product_to_scalar_int8) { - Shape shape{2, 2}; - auto A = make_shared(element::i8, shape); - auto axes = make_shared(element::i32, Shape{2}, vector{0, 1}); - auto f = make_shared(make_shared(A, axes, false), ParameterVector{A}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::i8, shape); - copy_data(a, vector{1, 2, 3, 4}); - auto result = backend->create_tensor(element::i8, Shape{}); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_EQ((vector{24}), read_vector(result)); -} - -// ----------------------- keep dims = true ----------------------- // - -NGRAPH_TEST(${BACKEND_NAME}, reduce_product_keep_to_scalar) { - Shape shape{2, 2}; - auto A = make_shared(element::f32, shape); - auto axes = make_shared(element::i32, Shape{2}, vector{0, 1}); - auto f = make_shared(make_shared(A, axes, true), ParameterVector{A}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::f32, shape); - copy_data(a, vector{1, 2, 3, 4}); - auto result = backend->create_tensor(element::f32, Shape{1, 1}); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_TRUE(test::all_close_f((vector{24}), read_vector(result))); -} - -NGRAPH_TEST(${BACKEND_NAME}, reduce_product_keep_matrix_columns) { - Shape shape_a{3, 2}; - auto A = make_shared(element::f32, shape_a); - Shape shape_rt{1, 2}; - auto axes = make_shared(element::i32, Shape{}, 0); - auto f = make_shared(make_shared(A, axes, true), ParameterVector{A}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::f32, shape_a); - copy_data(a, vector{1, 2, 3, 4, 5, 6}); - auto result = backend->create_tensor(element::f32, shape_rt); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_TRUE(test::all_close_f((vector{15, 48}), read_vector(result))); -} - -NGRAPH_TEST(${BACKEND_NAME}, reduce_product_keep_matrix_rows) { - Shape shape_a{3, 2}; - auto A = make_shared(element::f32, shape_a); - Shape shape_rt{3, 1}; - auto axes = make_shared(element::i32, Shape{}, 1); - auto f = make_shared(make_shared(A, axes, true), ParameterVector{A}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::f32, shape_a); - copy_data(a, vector{1, 2, 3, 4, 5, 6}); - auto result = backend->create_tensor(element::f32, shape_rt); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_TRUE(test::all_close_f((vector{2, 12, 30}), read_vector(result))); -} - -NGRAPH_TEST(${BACKEND_NAME}, reduce_product_keep_3d_to_matrix_most_sig) { - Shape shape_a{3, 3, 3}; - auto A = make_shared(element::f32, shape_a); - Shape shape_rt{1, 3, 3}; - auto axes = make_shared(element::i32, Shape{}, 0); - auto f = make_shared(make_shared(A, axes, true), ParameterVector{A}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::f32, shape_a); - copy_data(a, vector{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27}); - auto result = backend->create_tensor(element::f32, shape_rt); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_TRUE(test::all_close_f((vector{1 * 10 * 19, - 2 * 11 * 20, - 3 * 12 * 21, - 4 * 13 * 22, - 5 * 14 * 23, - 6 * 15 * 24, - 7 * 16 * 25, - 8 * 17 * 26, - 9 * 18 * 27}), - read_vector(result))); -} - -NGRAPH_TEST(${BACKEND_NAME}, reduce_product_keep_3d_to_matrix_least_sig) { - Shape shape_a{3, 3, 3}; - auto A = make_shared(element::f32, shape_a); - Shape shape_rt{3, 3, 1}; - auto axes = make_shared(element::i32, Shape{}, 2); - auto f = make_shared(make_shared(A, axes, true), ParameterVector{A}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::f32, shape_a); - copy_data(a, vector{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27}); - auto result = backend->create_tensor(element::f32, shape_rt); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_TRUE(test::all_close_f((vector{1 * 2 * 3, - 4 * 5 * 6, - 7 * 8 * 9, - 10 * 11 * 12, - 13 * 14 * 15, - 16 * 17 * 18, - 19 * 20 * 21, - 22 * 23 * 24, - 25 * 26 * 27}), - read_vector(result))); -} - -NGRAPH_TEST(${BACKEND_NAME}, reduce_product_keep_3d_to_vector) { - Shape shape_a{3, 3, 3}; - auto A = make_shared(element::f32, shape_a); - Shape shape_rt{1, 1, 3}; - auto axes = make_shared(element::i32, Shape{2}, vector{0, 1}); - auto f = make_shared(make_shared(A, axes, true), ParameterVector{A}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::f32, shape_a); - copy_data(a, vector{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27}); - auto result = backend->create_tensor(element::f32, shape_rt); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_TRUE(test::all_close_f((vector{1.0f * 10.0f * 19.0f * 4.0f * 13.0f * 22.0f * 7.0f * 16.0f * 25.0f, - 2.0f * 11.0f * 20.0f * 5.0f * 14.0f * 23.0f * 8.0f * 17.0f * 26.0f, - 3.0f * 12.0f * 21.0f * 6.0f * 15.0f * 24.0f * 9.0f * 18.0f * 27.0f}), - read_vector(result))); -} - -NGRAPH_TEST(${BACKEND_NAME}, reduce_product_keep_3d_to_scalar) { - Shape shape_a{3, 3, 3}; - auto A = make_shared(element::f32, shape_a); - Shape shape_rt{1, 1, 1}; - auto axes = make_shared(element::i32, Shape{3}, vector{0, 1, 2}); - auto f = make_shared(make_shared(A, axes, true), ParameterVector{A}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::f32, shape_a); - copy_data(a, - vector{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1}); - auto result = backend->create_tensor(element::f32, shape_rt); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_TRUE(test::all_close_f(vector{1.0f * 10.0f * 9.0f * 4.0f * 13.0f * 6.0f * 7.0f * 12.0f * 3.0f * 2.0f * - 11.0f * 8.0f * 5.0f * 14.0f * 5.0f * 8.0f * 11.0f * 2.0f * 3.0f * - 12.0f * 7.0f * 6.0f * 13.0f * 4.0f * 9.0f * 10.0f * 1.0f}, - read_vector(result))); -} - -NGRAPH_TEST(${BACKEND_NAME}, reduce_product_keep_2d_to_scalar_int32) { - Shape shape_a{3, 3}; - auto A = make_shared(element::i32, shape_a); - Shape shape_rt{1, 1}; - auto axes = make_shared(element::i32, Shape{2}, vector{0, 1}); - auto f = make_shared(make_shared(A, axes, true), ParameterVector{A}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::i32, shape_a); - copy_data(a, vector{1, 2, 3, 4, 5, 6, 7, 8, 9}); - auto result = backend->create_tensor(element::i32, shape_rt); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_EQ(vector{1 * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9}, read_vector(result)); -} - -NGRAPH_TEST(${BACKEND_NAME}, reduce_product_keep_to_scalar_int32) { - Shape shape{2, 2}; - auto A = make_shared(element::i32, shape); - auto axes = make_shared(element::i32, Shape{2}, vector{0, 1}); - auto f = make_shared(make_shared(A, axes, true), ParameterVector{A}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::i32, shape); - copy_data(a, vector{1, 2, 3, 4}); - auto result = backend->create_tensor(element::i32, Shape{1, 1}); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_EQ((vector{24}), read_vector(result)); -} - -NGRAPH_TEST(${BACKEND_NAME}, reduce_product_keep_to_scalar_int8) { - Shape shape{2, 2}; - auto A = make_shared(element::i8, shape); - auto axes = make_shared(element::i32, Shape{2}, vector{0, 1}); - auto f = make_shared(make_shared(A, axes, true), ParameterVector{A}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::i8, shape); - copy_data(a, vector{1, 2, 3, 4}); - auto result = backend->create_tensor(element::i8, Shape{1, 1}); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_EQ((vector{24}), read_vector(result)); -} - -// Dynamic - -NGRAPH_TEST(${BACKEND_NAME}, reduce_product_matrix_columns_dynamic) { - auto A = make_shared(element::f32, PartialShape::dynamic()); - auto axes = make_shared(element::i32, Shape{}, 0); - auto f = make_shared(make_shared(A, axes, false), ParameterVector{A}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}", true); - - // Create some tensors for input/output - Shape shape_a{3, 2}; - auto a = backend->create_tensor(element::f32, shape_a); - copy_data(a, vector{1, 2, 3, 4, 5, 6}); - auto result = backend->create_dynamic_tensor(element::f32, PartialShape::dynamic()); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_TRUE(test::all_close_f((vector{15, 48}), read_vector(result))); -} - -NGRAPH_TEST(${BACKEND_NAME}, reduce_product_matrix_rows_dynamic) { - auto A = make_shared(element::f32, PartialShape::dynamic()); - auto axes = make_shared(element::i32, Shape{}, 1); - auto f = make_shared(make_shared(A, axes, false), ParameterVector{A}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}", true); - - // Create some tensors for input/output - Shape shape_a{3, 2}; - auto a = backend->create_tensor(element::f32, shape_a); - copy_data(a, vector{1, 2, 3, 4, 5, 6}); - auto result = backend->create_dynamic_tensor(element::f32, PartialShape::dynamic()); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_TRUE(test::all_close_f((vector{2, 12, 30}), read_vector(result))); -} - -NGRAPH_TEST(${BACKEND_NAME}, reduce_product_keep_matrix_columns_dynamic) { - auto A = make_shared(element::f32, PartialShape::dynamic()); - auto axes = make_shared(element::i32, Shape{}, 0); - auto f = make_shared(make_shared(A, axes, true), ParameterVector{A}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}", true); - - // Create some tensors for input/output - Shape shape_a{3, 2}; - auto a = backend->create_tensor(element::f32, shape_a); - copy_data(a, vector{1, 2, 3, 4, 5, 6}); - auto result = backend->create_dynamic_tensor(element::f32, PartialShape::dynamic()); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_TRUE(test::all_close_f((vector{15, 48}), read_vector(result))); -} - -NGRAPH_TEST(${BACKEND_NAME}, reduce_product_keep_matrix_rows_dynamic) { - auto A = make_shared(element::f32, PartialShape::dynamic()); - auto axes = make_shared(element::i32, Shape{}, 1); - auto f = make_shared(make_shared(A, axes, true), ParameterVector{A}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}", true); - - // Create some tensors for input/output - Shape shape_a{3, 2}; - auto a = backend->create_tensor(element::f32, shape_a); - copy_data(a, vector{1, 2, 3, 4, 5, 6}); - auto result = backend->create_dynamic_tensor(element::f32, PartialShape::dynamic()); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_TRUE(test::all_close_f((vector{2, 12, 30}), read_vector(result))); -} diff --git a/ngraph/test/backend/reduce_sum.in.cpp b/ngraph/test/backend/reduce_sum.in.cpp deleted file mode 100644 index 44f0c107311..00000000000 --- a/ngraph/test/backend/reduce_sum.in.cpp +++ /dev/null @@ -1,875 +0,0 @@ -// Copyright (C) 2018-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#include -#include -#include -#include -#include -#include -#include - -#include "gtest/gtest.h" -#include "ngraph/ngraph.hpp" -#include "util/all_close.hpp" -#include "util/all_close_f.hpp" -#include "util/ndarray.hpp" -#include "util/random.hpp" -#include "util/test_control.hpp" -#include "util/test_tools.hpp" - -static std::mt19937_64 random_generator; - -using namespace std; -using namespace ngraph; - -static string s_manifest = "${MANIFEST}"; - -// ----------------------- keep dims = false ----------------------- // - -NGRAPH_TEST(${BACKEND_NAME}, reduce_sum_to_scalar) { - Shape shape{2, 2}; - auto A = make_shared(element::f32, shape); - auto axes = make_shared(element::i32, Shape{2}, vector{0, 1}); - auto f = make_shared(make_shared(A, axes, false), ParameterVector{A}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::f32, shape); - copy_data(a, vector{1, 2, 3, 4}); - auto result = backend->create_tensor(element::f32, Shape{}); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_TRUE(test::all_close_f((vector{10}), read_vector(result))); -} - -NGRAPH_TEST(${BACKEND_NAME}, reduce_sum_large_1d_to_scalar) { - Shape shape{1000000}; - auto A = make_shared(element::f32, shape); - auto axes = make_shared(element::i32, Shape{}, 0); - auto f = make_shared(make_shared(A, axes, false), ParameterVector{A}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}"); - - // Create some tensors for input/output - random_generator.seed(2); - vector v_a(1000000, 0); - double r = 0; - for (int i = 0; i < 1000000; i++) { - v_a[i] = static_cast(random_generator() % 255); - r += static_cast(v_a[i]); - } - auto a = backend->create_tensor(element::f32, shape); - copy_data(a, v_a); - auto result = backend->create_tensor(element::f32, Shape{}); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - - EXPECT_TRUE(test::all_close_f(vector{static_cast(r)}, read_vector(result))); -} - -NGRAPH_TEST(${BACKEND_NAME}, reduce_sum_matrix_columns) { - Shape shape_a{3, 2}; - auto A = make_shared(element::f32, shape_a); - Shape shape_rt{2}; - auto axes = make_shared(element::i32, Shape{}, 0); - auto f = make_shared(make_shared(A, axes, false), ParameterVector{A}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::f32, shape_a); - copy_data(a, vector{1, 2, 3, 4, 5, 6}); - auto result = backend->create_tensor(element::f32, shape_rt); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_TRUE(test::all_close_f((vector{9, 12}), read_vector(result))); -} - -NGRAPH_TEST(${BACKEND_NAME}, reduce_sum_matrix_6d) { - Shape shape_a{2, 6, 4, 5, 7, 3}; - auto A = make_shared(element::f32, shape_a); - Shape shape_rt{2, 4, 5, 3}; - auto axes = make_shared(element::i32, Shape{2}, vector{1, 4}); - auto f = make_shared(make_shared(A, axes, false), ParameterVector{A}); - - auto backend_wrk = runtime::Backend::create("${BACKEND_NAME}"); - auto backend_ref = runtime::Backend::create("INTERPRETER"); - - // Create some tensors for input/output - auto a_wrk = backend_wrk->create_tensor(element::f32, shape_a); - auto a_ref = backend_ref->create_tensor(element::f32, shape_a); - auto result_wrk = backend_wrk->create_tensor(element::f32, shape_rt); - auto result_ref = backend_ref->create_tensor(element::f32, shape_rt); - - vector inp_data(shape_size(shape_a)); - iota(inp_data.begin(), inp_data.end(), 1.f); - copy_data(a_wrk, inp_data); - copy_data(a_ref, inp_data); - - auto handle_wrk = backend_wrk->compile(f); - auto handle_ref = backend_ref->compile(f); - handle_wrk->call_with_validate({result_wrk}, {a_wrk}); - handle_ref->call_with_validate({result_ref}, {a_ref}); - - EXPECT_TRUE(test::all_close_f(read_vector(result_ref), read_vector(result_wrk))); -} - -NGRAPH_TEST(${BACKEND_NAME}, reduce_sum_matrix_rows) { - Shape shape_a{3, 2}; - auto A = make_shared(element::f32, shape_a); - Shape shape_rt{3}; - auto axes = make_shared(element::i32, Shape{}, 1); - auto f = make_shared(make_shared(A, axes, false), ParameterVector{A}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::f32, shape_a); - copy_data(a, vector{1, 2, 3, 4, 5, 6}); - auto result = backend->create_tensor(element::f32, shape_rt); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_TRUE(test::all_close_f((vector{3, 7, 11}), read_vector(result))); -} - -NGRAPH_TEST(${BACKEND_NAME}, reduce_sum_3d_to_matrix_most_sig) { - Shape shape_a{3, 3, 3}; - auto A = make_shared(element::f32, shape_a); - Shape shape_rt{3, 3}; - auto axes = make_shared(element::i32, Shape{}, 0); - auto f = make_shared(make_shared(A, axes, false), ParameterVector{A}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::f32, shape_a); - copy_data(a, vector{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27}); - auto result = backend->create_tensor(element::f32, shape_rt); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_TRUE(test::all_close_f((vector{1 + 10 + 19, - 2 + 11 + 20, - 3 + 12 + 21, - 4 + 13 + 22, - 5 + 14 + 23, - 6 + 15 + 24, - 7 + 16 + 25, - 8 + 17 + 26, - 9 + 18 + 27}), - read_vector(result))); -} - -NGRAPH_TEST(${BACKEND_NAME}, reduce_sum_3d_to_matrix_least_sig) { - Shape shape_a{3, 3, 3}; - auto A = make_shared(element::f32, shape_a); - Shape shape_rt{3, 3}; - auto axes = make_shared(element::i32, Shape{}, 2); - auto f = make_shared(make_shared(A, axes, false), ParameterVector{A}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::f32, shape_a); - copy_data(a, vector{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27}); - auto result = backend->create_tensor(element::f32, shape_rt); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_TRUE(test::all_close_f((vector{1 + 2 + 3, - 4 + 5 + 6, - 7 + 8 + 9, - 10 + 11 + 12, - 13 + 14 + 15, - 16 + 17 + 18, - 19 + 20 + 21, - 22 + 23 + 24, - 25 + 26 + 27}), - read_vector(result))); -} - -NGRAPH_TEST(${BACKEND_NAME}, reduce_sum_3d_to_vector) { - Shape shape_a{3, 3, 3}; - auto A = make_shared(element::f32, shape_a); - Shape shape_rt{3}; - auto axes = make_shared(element::i32, Shape{2}, vector{0, 1}); - auto f = make_shared(make_shared(A, axes, false), ParameterVector{A}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::f32, shape_a); - copy_data(a, vector{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27}); - auto result = backend->create_tensor(element::f32, shape_rt); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_TRUE(test::all_close_f((vector{1 + 10 + 19 + 4 + 13 + 22 + 7 + 16 + 25, - 2 + 11 + 20 + 5 + 14 + 23 + 8 + 17 + 26, - 3 + 12 + 21 + 6 + 15 + 24 + 9 + 18 + 27}), - read_vector(result))); -} - -NGRAPH_TEST(${BACKEND_NAME}, reduce_sum_3d_to_scalar) { - Shape shape_a{3, 3, 3}; - auto A = make_shared(element::f32, shape_a); - Shape shape_rt{}; - auto axes = make_shared(element::i32, Shape{3}, vector{0, 1, 2}); - auto f = make_shared(make_shared(A, axes, false), ParameterVector{A}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::f32, shape_a); - copy_data(a, vector{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27}); - auto result = backend->create_tensor(element::f32, shape_rt); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_TRUE(test::all_close_f((vector{1 + 10 + 19 + 4 + 13 + 22 + 7 + 16 + 25 + 2 + 11 + 20 + 5 + 14 + 23 + - 8 + 17 + 26 + 3 + 12 + 21 + 6 + 15 + 24 + 9 + 18 + 27}), - read_vector(result))); -} - -NGRAPH_TEST(${BACKEND_NAME}, reduce_sum_3d_to_scalar_int32) { - Shape shape_a{3, 3, 3}; - auto A = make_shared(element::i32, shape_a); - Shape shape_rt{}; - auto axes = make_shared(element::i32, Shape{3}, vector{0, 1, 2}); - auto f = make_shared(make_shared(A, axes, false), ParameterVector{A}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::i32, shape_a); - copy_data(a, vector{0x40000001, 10, 19, 4, 13, 22, 7, 16, 25, 2, 11, 20, 5, 14, - 23, 8, 17, 26, 3, 12, 21, 6, 15, 24, 9, 18, 27}); - auto result = backend->create_tensor(element::i32, shape_rt); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_EQ((vector{0x40000001 + 10 + 19 + 4 + 13 + 22 + 7 + 16 + 25 + 2 + 11 + 20 + 5 + 14 + 23 + 8 + 17 + - 26 + 3 + 12 + 21 + 6 + 15 + 24 + 9 + 18 + 27}), - read_vector(result)); -} - -NGRAPH_TEST(${BACKEND_NAME}, reduce_sum_5d_to_scalar) { - Shape shape_a{3, 3, 3, 3, 3}; - auto A = make_shared(element::f32, shape_a); - Shape shape_rt{}; - auto axes = make_shared(element::i32, Shape{5}, vector{0, 1, 2, 3, 4}); - auto f = make_shared(make_shared(A, axes, false), ParameterVector{A}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::f32, shape_a); - copy_data(a, std::vector(std::pow(3, 5), 1)); - auto result = backend->create_tensor(element::f32, shape_rt); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_TRUE(test::all_close_f(std::vector{243.}, read_vector(result))); -} - -NGRAPH_TEST(${BACKEND_NAME}, reduce_sum_5d_to_scalar_int32) { - Shape shape_a{3, 3, 3, 3, 3}; - auto A = make_shared(element::i32, shape_a); - Shape shape_rt{}; - auto axes = make_shared(element::i32, Shape{5}, vector{0, 1, 2, 3, 4}); - auto f = make_shared(make_shared(A, axes, false), ParameterVector{A}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::i32, shape_a); - copy_data(a, std::vector(std::pow(3, 5), 1)); - auto result = backend->create_tensor(element::i32, shape_rt); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_EQ(std::vector{243}, read_vector(result)); -} - -NGRAPH_TEST(${BACKEND_NAME}, reduce_sum_2d_to_scalar_int8) { - Shape shape_a{3, 3}; - auto A = make_shared(element::i8, shape_a); - Shape shape_rt{}; - auto axes = make_shared(element::i32, Shape{2}, vector{0, 1}); - auto f = make_shared(make_shared(A, axes, false), ParameterVector{A}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::i8, shape_a); - copy_data(a, std::vector{1, 2, 3, 4, 5, 6, 7, 8, 9}); - auto result = backend->create_tensor(element::i8, shape_rt); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_EQ(std::vector{45}, read_vector(result)); -} - -#ifndef _WIN32 -NGRAPH_TEST(${BACKEND_NAME}, reduce_sum_stable_acc) { - std::string backend_name = "${BACKEND_NAME}"; - if (backend_name == "INTERPRETER") { - return; - } - Shape shape_a{10, 10, 10, 30}; - auto A = make_shared(element::f32, shape_a); - - Shape shape_rt{10}; - auto axes = make_shared(element::i32, Shape{3}, vector{1, 2, 3}); - auto f = make_shared(make_shared(A, axes, false), ParameterVector{A}); - - test::Uniform rng(1000.0f, 1000.1f, 2112); - vector> args; - for (shared_ptr param : f->get_parameters()) { - vector tensor_val(shape_size(param->get_shape())); - rng.initialize(tensor_val); - args.push_back(tensor_val); - } - - auto ref_func = clone_function(*f); - auto bk_func = clone_function(*f); - - auto ref_results = execute(ref_func, args, "INTERPRETER"); - auto bk_results = execute(bk_func, args, "${BACKEND_NAME}"); - - EXPECT_TRUE(test::all_close_f(ref_results.at(0), bk_results.at(0), DEFAULT_FLOAT_TOLERANCE_BITS + 1)); -} -#endif - -NGRAPH_TEST(${BACKEND_NAME}, reduce_sum_stable_simple_float) { - std::string backend_name = "${BACKEND_NAME}"; - if (backend_name == "INTERPRETER") { - return; - } - Shape shape_a{20}; - auto A = make_shared(element::f32, shape_a); - - Shape shape_rt{}; - auto axes = make_shared(element::i32, Shape{}, 0); - auto f = make_shared(make_shared(A, axes, false), ParameterVector{A}); - - vector> args; - args.push_back(vector{10000000.0f, 0.9f, 0.3f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f, 0.1f, 0.9f, - 0.5f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f, 0.9f, 0.1f}); - - auto ref_func = clone_function(*f); - auto bk_func = clone_function(*f); - - auto ref_results = execute(ref_func, args, "INTERPRETER"); - auto bk_results = execute(bk_func, args, "${BACKEND_NAME}"); - - EXPECT_TRUE(test::all_close_f(ref_results.at(0), bk_results.at(0), DEFAULT_FLOAT_TOLERANCE_BITS - 1)); -} - -NGRAPH_TEST(${BACKEND_NAME}, reduce_sum_inf) { - Shape shape{7, 4}; - auto A = make_shared(element::f32, shape); - auto axes = make_shared(element::i32, Shape{}, 1); - auto f = make_shared(make_shared(A, axes, false), ParameterVector{A}); - - auto infi = std::numeric_limits::infinity(); - - auto backend = runtime::Backend::create("${BACKEND_NAME}"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::f32, shape); - copy_data(a, - test::NDArray({{-infi, 0, 0, infi}, - {infi, 100, -100, -infi}, - {infi, 0, 100, infi}, - {-infi, -100, 0, -infi}, - {infi, infi, infi, infi}, - {infi, infi, infi, -infi}, - {infi, std::nanf(""), 42, infi}}) - .get_vector()); - auto result = backend->create_tensor(element::f32, Shape{7}); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - auto r = read_vector(result); - ASSERT_EQ(r.size(), 7); - EXPECT_TRUE(isnan(r[0])); - EXPECT_TRUE(isnan(r[1])); - EXPECT_TRUE(r[2] > 0 && isinf(r[2])); - EXPECT_TRUE(r[3] < 0 && isinf(r[3])); - EXPECT_TRUE(r[4] > 0 && isinf(r[4])); - EXPECT_TRUE(isnan(r[5])); - EXPECT_TRUE(isnan(r[6])); -} - -// ----------------------- keep dims = true ----------------------- // - -NGRAPH_TEST(${BACKEND_NAME}, reduce_sum_keep_to_scalar) { - Shape shape{2, 2}; - auto A = make_shared(element::f32, shape); - auto axes = make_shared(element::i32, Shape{2}, vector{0, 1}); - auto f = make_shared(make_shared(A, axes, true), ParameterVector{A}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::f32, shape); - copy_data(a, vector{1, 2, 3, 4}); - auto result = backend->create_tensor(element::f32, Shape{1, 1}); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_TRUE(test::all_close_f((vector{10}), read_vector(result))); -} - -NGRAPH_TEST(${BACKEND_NAME}, reduce_sum_keep_large_1d_to_scalar) { - Shape shape{1000000}; - auto A = make_shared(element::f32, shape); - auto axes = make_shared(element::i32, Shape{}, 0); - auto f = make_shared(make_shared(A, axes, true), ParameterVector{A}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}"); - - // Create some tensors for input/output - random_generator.seed(2); - vector v_a(1000000, 0); - double r = 0; - for (int i = 0; i < 1000000; i++) { - v_a[i] = static_cast(random_generator() % 255); - r += static_cast(v_a[i]); - } - auto a = backend->create_tensor(element::f32, shape); - copy_data(a, v_a); - auto result = backend->create_tensor(element::f32, Shape{1}); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - - EXPECT_TRUE(test::all_close_f(vector{static_cast(r)}, read_vector(result))); -} - -NGRAPH_TEST(${BACKEND_NAME}, reduce_sum_keep_matrix_columns) { - Shape shape_a{3, 2}; - auto A = make_shared(element::f32, shape_a); - Shape shape_rt{1, 2}; - auto axes = make_shared(element::i32, Shape{}, 0); - auto f = make_shared(make_shared(A, axes, true), ParameterVector{A}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::f32, shape_a); - copy_data(a, vector{1, 2, 3, 4, 5, 6}); - auto result = backend->create_tensor(element::f32, shape_rt); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_TRUE(test::all_close_f((vector{9, 12}), read_vector(result))); -} - -NGRAPH_TEST(${BACKEND_NAME}, reduce_sum_keep_matrix_6d) { - Shape shape_a{2, 6, 4, 5, 7, 3}; - auto A = make_shared(element::f32, shape_a); - Shape shape_rt{2, 1, 4, 5, 1, 3}; - auto axes = make_shared(element::i32, Shape{2}, vector{1, 4}); - auto f = make_shared(make_shared(A, axes, true), ParameterVector{A}); - - auto backend_wrk = runtime::Backend::create("${BACKEND_NAME}"); - auto backend_ref = runtime::Backend::create("INTERPRETER"); - - // Create some tensors for input/output - auto a_wrk = backend_wrk->create_tensor(element::f32, shape_a); - auto a_ref = backend_ref->create_tensor(element::f32, shape_a); - auto result_wrk = backend_wrk->create_tensor(element::f32, shape_rt); - auto result_ref = backend_ref->create_tensor(element::f32, shape_rt); - - vector inp_data(shape_size(shape_a)); - iota(inp_data.begin(), inp_data.end(), 1.f); - copy_data(a_wrk, inp_data); - copy_data(a_ref, inp_data); - - auto handle_wrk = backend_wrk->compile(f); - auto handle_ref = backend_ref->compile(f); - handle_wrk->call_with_validate({result_wrk}, {a_wrk}); - handle_ref->call_with_validate({result_ref}, {a_ref}); - - EXPECT_TRUE(test::all_close_f(read_vector(result_ref), read_vector(result_wrk))); -} - -NGRAPH_TEST(${BACKEND_NAME}, reduce_sum_keep_matrix_rows) { - Shape shape_a{3, 2}; - auto A = make_shared(element::f32, shape_a); - Shape shape_rt{3, 1}; - auto axes = make_shared(element::i32, Shape{}, 1); - auto f = make_shared(make_shared(A, axes, true), ParameterVector{A}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::f32, shape_a); - copy_data(a, vector{1, 2, 3, 4, 5, 6}); - auto result = backend->create_tensor(element::f32, shape_rt); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_TRUE(test::all_close_f((vector{3, 7, 11}), read_vector(result))); -} - -NGRAPH_TEST(${BACKEND_NAME}, reduce_sum_keep_3d_to_matrix_most_sig) { - Shape shape_a{3, 3, 3}; - auto A = make_shared(element::f32, shape_a); - Shape shape_rt{1, 3, 3}; - auto axes = make_shared(element::i32, Shape{}, 0); - auto f = make_shared(make_shared(A, axes, true), ParameterVector{A}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::f32, shape_a); - copy_data(a, vector{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27}); - auto result = backend->create_tensor(element::f32, shape_rt); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_TRUE(test::all_close_f((vector{1 + 10 + 19, - 2 + 11 + 20, - 3 + 12 + 21, - 4 + 13 + 22, - 5 + 14 + 23, - 6 + 15 + 24, - 7 + 16 + 25, - 8 + 17 + 26, - 9 + 18 + 27}), - read_vector(result))); -} - -NGRAPH_TEST(${BACKEND_NAME}, reduce_sum_keep_3d_to_matrix_least_sig) { - Shape shape_a{3, 3, 3}; - auto A = make_shared(element::f32, shape_a); - Shape shape_rt{3, 3, 1}; - auto axes = make_shared(element::i32, Shape{}, 2); - auto f = make_shared(make_shared(A, axes, true), ParameterVector{A}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::f32, shape_a); - copy_data(a, vector{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27}); - auto result = backend->create_tensor(element::f32, shape_rt); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_TRUE(test::all_close_f((vector{1 + 2 + 3, - 4 + 5 + 6, - 7 + 8 + 9, - 10 + 11 + 12, - 13 + 14 + 15, - 16 + 17 + 18, - 19 + 20 + 21, - 22 + 23 + 24, - 25 + 26 + 27}), - read_vector(result))); -} - -NGRAPH_TEST(${BACKEND_NAME}, reduce_sum_keep_3d_to_vector) { - Shape shape_a{3, 3, 3}; - auto A = make_shared(element::f32, shape_a); - Shape shape_rt{1, 1, 3}; - auto axes = make_shared(element::i32, Shape{2}, vector{0, 1}); - auto f = make_shared(make_shared(A, axes, true), ParameterVector{A}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::f32, shape_a); - copy_data(a, vector{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27}); - auto result = backend->create_tensor(element::f32, shape_rt); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_TRUE(test::all_close_f((vector{1 + 10 + 19 + 4 + 13 + 22 + 7 + 16 + 25, - 2 + 11 + 20 + 5 + 14 + 23 + 8 + 17 + 26, - 3 + 12 + 21 + 6 + 15 + 24 + 9 + 18 + 27}), - read_vector(result))); -} - -NGRAPH_TEST(${BACKEND_NAME}, reduce_sum_keep_3d_to_scalar) { - Shape shape_a{3, 3, 3}; - auto A = make_shared(element::f32, shape_a); - Shape shape_rt{1, 1, 1}; - auto axes = make_shared(element::i32, Shape{3}, vector{0, 1, 2}); - auto f = make_shared(make_shared(A, axes, true), ParameterVector{A}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::f32, shape_a); - copy_data(a, vector{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27}); - auto result = backend->create_tensor(element::f32, shape_rt); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_TRUE(test::all_close_f((vector{1 + 10 + 19 + 4 + 13 + 22 + 7 + 16 + 25 + 2 + 11 + 20 + 5 + 14 + 23 + - 8 + 17 + 26 + 3 + 12 + 21 + 6 + 15 + 24 + 9 + 18 + 27}), - read_vector(result))); -} - -NGRAPH_TEST(${BACKEND_NAME}, reduce_sum_keep_3d_to_scalar_int32) { - Shape shape_a{3, 3, 3}; - auto A = make_shared(element::i32, shape_a); - Shape shape_rt{1, 1, 1}; - auto axes = make_shared(element::i32, Shape{3}, vector{0, 1, 2}); - auto f = make_shared(make_shared(A, axes, true), ParameterVector{A}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::i32, shape_a); - copy_data(a, vector{0x40000001, 10, 19, 4, 13, 22, 7, 16, 25, 2, 11, 20, 5, 14, - 23, 8, 17, 26, 3, 12, 21, 6, 15, 24, 9, 18, 27}); - auto result = backend->create_tensor(element::i32, shape_rt); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_EQ((vector{0x40000001 + 10 + 19 + 4 + 13 + 22 + 7 + 16 + 25 + 2 + 11 + 20 + 5 + 14 + 23 + 8 + 17 + - 26 + 3 + 12 + 21 + 6 + 15 + 24 + 9 + 18 + 27}), - read_vector(result)); -} - -NGRAPH_TEST(${BACKEND_NAME}, reduce_sum_keep_5d_to_scalar) { - Shape shape_a{3, 3, 3, 3, 3}; - auto A = make_shared(element::f32, shape_a); - Shape shape_rt{1, 1, 1, 1, 1}; - auto axes = make_shared(element::i32, Shape{5}, vector{0, 1, 2, 3, 4}); - auto f = make_shared(make_shared(A, axes, true), ParameterVector{A}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::f32, shape_a); - copy_data(a, std::vector(std::pow(3, 5), 1)); - auto result = backend->create_tensor(element::f32, shape_rt); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_TRUE(test::all_close_f(std::vector{243.}, read_vector(result))); -} - -NGRAPH_TEST(${BACKEND_NAME}, reduce_sum_keep_5d_to_scalar_int32) { - Shape shape_a{3, 3, 3, 3, 3}; - auto A = make_shared(element::i32, shape_a); - Shape shape_rt{1, 1, 1, 1, 1}; - auto axes = make_shared(element::i32, Shape{5}, vector{0, 1, 2, 3, 4}); - auto f = make_shared(make_shared(A, axes, true), ParameterVector{A}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::i32, shape_a); - copy_data(a, std::vector(std::pow(3, 5), 1)); - auto result = backend->create_tensor(element::i32, shape_rt); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_EQ(std::vector{243}, read_vector(result)); -} - -NGRAPH_TEST(${BACKEND_NAME}, reduce_sum_keep_2d_to_scalar_int8) { - Shape shape_a{3, 3}; - auto A = make_shared(element::i8, shape_a); - Shape shape_rt{1, 1}; - auto axes = make_shared(element::i32, Shape{2}, vector{0, 1}); - auto f = make_shared(make_shared(A, axes, true), ParameterVector{A}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::i8, shape_a); - copy_data(a, std::vector{1, 2, 3, 4, 5, 6, 7, 8, 9}); - auto result = backend->create_tensor(element::i8, shape_rt); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_EQ(std::vector{45}, read_vector(result)); -} - -#ifndef _WIN32 -NGRAPH_TEST(${BACKEND_NAME}, reduce_sum_keep_stable_acc) { - std::string backend_name = "${BACKEND_NAME}"; - if (backend_name == "INTERPRETER") { - return; - } - Shape shape_a{10, 10, 10, 30}; - auto A = make_shared(element::f32, shape_a); - - Shape shape_rt{10, 1, 1, 1}; - auto axes = make_shared(element::i32, Shape{3}, vector{1, 2, 3}); - auto f = make_shared(make_shared(A, axes, true), ParameterVector{A}); - - test::Uniform rng(1000.0f, 1000.1f, 2112); - vector> args; - for (shared_ptr param : f->get_parameters()) { - vector tensor_val(shape_size(param->get_shape())); - rng.initialize(tensor_val); - args.push_back(tensor_val); - } - - auto ref_func = clone_function(*f); - auto bk_func = clone_function(*f); - - auto ref_results = execute(ref_func, args, "INTERPRETER"); - auto bk_results = execute(bk_func, args, "${BACKEND_NAME}"); - - EXPECT_TRUE(test::all_close_f(ref_results.at(0), bk_results.at(0), DEFAULT_FLOAT_TOLERANCE_BITS + 1)); -} -#endif - -NGRAPH_TEST(${BACKEND_NAME}, reduce_sum_keep_stable_simple_float) { - std::string backend_name = "${BACKEND_NAME}"; - if (backend_name == "INTERPRETER") { - return; - } - Shape shape_a{20}; - auto A = make_shared(element::f32, shape_a); - - Shape shape_rt{1}; - auto axes = make_shared(element::i32, Shape{}, 0); - auto f = make_shared(make_shared(A, axes, true), ParameterVector{A}); - - vector> args; - args.push_back(vector{10000000.0f, 0.9f, 0.3f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f, 0.1f, 0.9f, - 0.5f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f, 0.9f, 0.1f}); - - auto ref_func = clone_function(*f); - auto bk_func = clone_function(*f); - - auto ref_results = execute(ref_func, args, "INTERPRETER"); - auto bk_results = execute(bk_func, args, "${BACKEND_NAME}"); - - EXPECT_TRUE(test::all_close_f(ref_results.at(0), bk_results.at(0), DEFAULT_FLOAT_TOLERANCE_BITS - 1)); -} - -NGRAPH_TEST(${BACKEND_NAME}, reduce_sum_keep_inf) { - Shape shape{7, 4}; - auto A = make_shared(element::f32, shape); - auto axes = make_shared(element::i32, Shape{}, 1); - auto f = make_shared(make_shared(A, axes, true), ParameterVector{A}); - - auto infi = std::numeric_limits::infinity(); - - auto backend = runtime::Backend::create("${BACKEND_NAME}"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::f32, shape); - copy_data(a, - test::NDArray({{-infi, 0, 0, infi}, - {infi, 100, -100, -infi}, - {infi, 0, 100, infi}, - {-infi, -100, 0, -infi}, - {infi, infi, infi, infi}, - {infi, infi, infi, -infi}, - {infi, std::nanf(""), 42, infi}}) - .get_vector()); - auto result = backend->create_tensor(element::f32, Shape{7, 1}); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - auto r = read_vector(result); - ASSERT_EQ(r.size(), 7); - EXPECT_TRUE(isnan(r[0])); - EXPECT_TRUE(isnan(r[1])); - EXPECT_TRUE(r[2] > 0 && isinf(r[2])); - EXPECT_TRUE(r[3] < 0 && isinf(r[3])); - EXPECT_TRUE(r[4] > 0 && isinf(r[4])); - EXPECT_TRUE(isnan(r[5])); - EXPECT_TRUE(isnan(r[6])); -} - -// Dynamic - -NGRAPH_TEST(${BACKEND_NAME}, reduce_sum_matrix_columns_dynamic) { - auto A = make_shared(element::f32, PartialShape::dynamic()); - auto axes = make_shared(element::i32, Shape{}, 0); - auto f = make_shared(make_shared(A, axes, false), ParameterVector{A}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}", true); - - // Create some tensors for input/output - Shape shape_a{3, 2}; - auto a = backend->create_tensor(element::f32, shape_a); - copy_data(a, vector{1, 2, 3, 4, 5, 6}); - auto result = backend->create_dynamic_tensor(element::f32, PartialShape::dynamic()); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_TRUE(test::all_close_f((vector{9, 12}), read_vector(result))); -} - -NGRAPH_TEST(${BACKEND_NAME}, reduce_sum_matrix_rows_dynamic) { - auto A = make_shared(element::f32, PartialShape::dynamic()); - auto axes = make_shared(element::i32, Shape{}, 1); - auto f = make_shared(make_shared(A, axes, false), ParameterVector{A}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}", true); - - // Create some tensors for input/output - Shape shape_a{3, 2}; - auto a = backend->create_tensor(element::f32, shape_a); - copy_data(a, vector{1, 2, 3, 4, 5, 6}); - auto result = backend->create_dynamic_tensor(element::f32, PartialShape::dynamic()); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_TRUE(test::all_close_f((vector{3, 7, 11}), read_vector(result))); -} - -NGRAPH_TEST(${BACKEND_NAME}, reduce_sum_keep_matrix_columns_dynamic) { - auto A = make_shared(element::f32, PartialShape::dynamic()); - auto axes = make_shared(element::i32, Shape{}, 0); - auto f = make_shared(make_shared(A, axes, true), ParameterVector{A}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}", true); - - // Create some tensors for input/output - Shape shape_a{3, 2}; - auto a = backend->create_tensor(element::f32, shape_a); - copy_data(a, vector{1, 2, 3, 4, 5, 6}); - auto result = backend->create_dynamic_tensor(element::f32, PartialShape::dynamic()); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_TRUE(test::all_close_f((vector{9, 12}), read_vector(result))); -} - -NGRAPH_TEST(${BACKEND_NAME}, reduce_sum_keep_matrix_rows_dynamic) { - auto A = make_shared(element::f32, PartialShape::dynamic()); - auto axes = make_shared(element::i32, Shape{}, 1); - auto f = make_shared(make_shared(A, axes, true), ParameterVector{A}); - - auto backend = runtime::Backend::create("${BACKEND_NAME}", true); - - // Create some tensors for input/output - Shape shape_a{3, 2}; - auto a = backend->create_tensor(element::f32, shape_a); - copy_data(a, vector{1, 2, 3, 4, 5, 6}); - auto result = backend->create_dynamic_tensor(element::f32, PartialShape::dynamic()); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_TRUE(test::all_close_f((vector{3, 7, 11}), read_vector(result))); -} diff --git a/ngraph/test/op_eval/reduce_max.cpp b/ngraph/test/op_eval/reduce_max.cpp deleted file mode 100644 index dd8c0daa082..00000000000 --- a/ngraph/test/op_eval/reduce_max.cpp +++ /dev/null @@ -1,284 +0,0 @@ -// Copyright (C) 2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#include "gtest/gtest.h" -#include "ngraph/ngraph.hpp" -#include "util/all_close.hpp" -#include "util/all_close_f.hpp" -#include "util/ndarray.hpp" -#include "util/test_control.hpp" - -using namespace std; -using namespace ngraph; - -static string s_manifest = "${MANIFEST}"; - -TEST(op_eval, reduce_max_matrix_rows_zero) { - Shape shape_a{3, 0}; - auto A = make_shared(element::f32, shape_a); - Shape shape_rt{3}; - auto axes = make_shared(element::i32, Shape{}, 1); - auto f = make_shared(make_shared(A, axes, false), ParameterVector{A}); - - auto backend = runtime::Backend::create("INTERPRETER"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::f32, shape_a); - copy_data(a, vector{}); - auto result = backend->create_tensor(element::f32, shape_rt); - copy_data(result, vector({3, 3, 3})); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - - EXPECT_EQ((vector{-std::numeric_limits::infinity(), - -std::numeric_limits::infinity(), - -std::numeric_limits::infinity()}), - read_vector(result)); -} - -TEST(op_eval, reduce_max_matrix_rows_zero_int32) { - Shape shape_a{3, 0}; - auto A = make_shared(element::i32, shape_a); - Shape shape_rt{3}; - auto axes = make_shared(element::i32, Shape{}, 1); - auto f = make_shared(make_shared(A, axes, false), ParameterVector{A}); - - auto backend = runtime::Backend::create("INTERPRETER"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::i32, shape_a); - copy_data(a, vector{}); - auto result = backend->create_tensor(element::i32, shape_rt); - copy_data(result, vector({3, 3, 3})); - - int32_t minval = std::numeric_limits::has_infinity ? -std::numeric_limits::infinity() - : std::numeric_limits::min(); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_EQ((vector{minval, minval, minval}), read_vector(result)); - EXPECT_EQ((vector{}), read_vector(a)); -} - -TEST(op_eval, reduce_max_matrix_cols_zero) { - // Now the reduction (g(x:float32[2,2],y:float32[]) = reduce(x,y,f,axes={})). - Shape shape_a{0, 2}; - auto A = make_shared(element::f32, shape_a); - Shape shape_rt{2}; - auto axes = make_shared(element::i32, Shape{}, 0); - auto f = make_shared(make_shared(A, axes, false), ParameterVector{A}); - - auto backend = runtime::Backend::create("INTERPRETER"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::f32, shape_a); - copy_data(a, vector{}); - auto result = backend->create_tensor(element::f32, shape_rt); - copy_data(result, vector({3, 3})); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_EQ((vector{-std::numeric_limits::infinity(), -std::numeric_limits::infinity()}), - read_vector(result)); -} - -TEST(op_eval, reduce_max_vector_zero) { - Shape shape_a{0}; - auto A = make_shared(element::f32, shape_a); - Shape shape_rt{}; - auto axes = make_shared(element::i32, Shape{}, 0); - auto f = make_shared(make_shared(A, axes, false), ParameterVector{A}); - - auto backend = runtime::Backend::create("INTERPRETER"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::f32, shape_a); - copy_data(a, vector{}); - auto result = backend->create_tensor(element::f32, shape_rt); - copy_data(result, vector({3})); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_EQ((vector{-std::numeric_limits::infinity()}), read_vector(result)); -} - -TEST(op_eval, reduce_max_matrix_to_scalar_zero_by_zero) { - Shape shape_a{0, 0}; - auto A = make_shared(element::f32, shape_a); - Shape shape_rt{}; - auto axes = make_shared(element::i32, Shape{2}, vector{0, 1}); - auto f = make_shared(make_shared(A, axes, false), ParameterVector{A}); - - auto backend = runtime::Backend::create("INTERPRETER"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::f32, shape_a); - copy_data(a, vector{}); - auto result = backend->create_tensor(element::f32, shape_rt); - copy_data(result, vector({3})); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_EQ((vector{-std::numeric_limits::infinity()}), read_vector(result)); -} - -TEST(op_eval, reduce_max_3d_eliminate_zero_dim) { - Shape shape_a{3, 0, 2}; - auto A = make_shared(element::f32, shape_a); - Shape shape_rt{3, 2}; - auto axes = make_shared(element::i32, Shape{}, 1); - auto f = make_shared(make_shared(A, axes, false), ParameterVector{A}); - - auto backend = runtime::Backend::create("INTERPRETER"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::f32, shape_a); - copy_data(a, vector{}); - auto result = backend->create_tensor(element::f32, shape_rt); - - // Overwrite the initial result vector to make sure we're not just coincidentally getting the - // right value. - copy_data(result, vector{2112, 2112, 2112, 2112, 2112, 2112}); - - float mi = -std::numeric_limits::infinity(); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_EQ((vector{mi, mi, mi, mi, mi, mi}), read_vector(result)); -} - -TEST(op_eval, reduce_max_keep_matrix_rows_zero) { - Shape shape_a{3, 0}; - auto A = make_shared(element::f32, shape_a); - Shape shape_rt{3, 1}; - auto axes = make_shared(element::i32, Shape{}, 1); - auto f = make_shared(make_shared(A, axes, true), ParameterVector{A}); - - auto backend = runtime::Backend::create("INTERPRETER"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::f32, shape_a); - copy_data(a, vector{}); - auto result = backend->create_tensor(element::f32, shape_rt); - copy_data(result, vector({3, 3, 3})); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_EQ((vector{-std::numeric_limits::infinity(), - -std::numeric_limits::infinity(), - -std::numeric_limits::infinity()}), - read_vector(result)); -} - -TEST(op_eval, reduce_max_keep_matrix_rows_zero_int32) { - Shape shape_a{3, 0}; - auto A = make_shared(element::i32, shape_a); - Shape shape_rt{3, 1}; - auto axes = make_shared(element::i32, Shape{}, 1); - auto f = make_shared(make_shared(A, axes, true), ParameterVector{A}); - - auto backend = runtime::Backend::create("INTERPRETER"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::i32, shape_a); - copy_data(a, vector{}); - auto result = backend->create_tensor(element::i32, shape_rt); - copy_data(result, vector({3, 3, 3})); - - int32_t minval = std::numeric_limits::has_infinity ? -std::numeric_limits::infinity() - : std::numeric_limits::min(); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_EQ((vector{minval, minval, minval}), read_vector(result)); - EXPECT_EQ((vector{}), read_vector(a)); -} - -TEST(op_eval, reduce_max_keep_matrix_cols_zero) { - // Now the reduction (g(x:float32[2,2],y:float32[]) = reduce(x,y,f,axes={})). - Shape shape_a{0, 2}; - auto A = make_shared(element::f32, shape_a); - Shape shape_rt{1, 2}; - auto axes = make_shared(element::i32, Shape{}, 0); - auto f = make_shared(make_shared(A, axes, true), ParameterVector{A}); - - auto backend = runtime::Backend::create("INTERPRETER"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::f32, shape_a); - copy_data(a, vector{}); - auto result = backend->create_tensor(element::f32, shape_rt); - copy_data(result, vector({3, 3})); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_EQ((vector{-std::numeric_limits::infinity(), -std::numeric_limits::infinity()}), - read_vector(result)); -} - -TEST(op_eval, reduce_max_keep_vector_zero) { - Shape shape_a{0}; - auto A = make_shared(element::f32, shape_a); - Shape shape_rt{1}; - auto axes = make_shared(element::i32, Shape{}, 0); - auto f = make_shared(make_shared(A, axes, true), ParameterVector{A}); - - auto backend = runtime::Backend::create("INTERPRETER"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::f32, shape_a); - copy_data(a, vector{}); - auto result = backend->create_tensor(element::f32, shape_rt); - copy_data(result, vector({3})); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_EQ((vector{-std::numeric_limits::infinity()}), read_vector(result)); -} - -TEST(op_eval, reduce_max_keep_matrix_to_scalar_zero_by_zero) { - Shape shape_a{0, 0}; - auto A = make_shared(element::f32, shape_a); - Shape shape_rt{1, 1}; - auto axes = make_shared(element::i32, Shape{2}, vector{0, 1}); - auto f = make_shared(make_shared(A, axes, true), ParameterVector{A}); - - auto backend = runtime::Backend::create("INTERPRETER"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::f32, shape_a); - copy_data(a, vector{}); - auto result = backend->create_tensor(element::f32, shape_rt); - copy_data(result, vector({3})); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_EQ((vector{-std::numeric_limits::infinity()}), read_vector(result)); -} - -TEST(op_eval, reduce_max_keep_3d_eliminate_zero_dim) { - Shape shape_a{3, 0, 2}; - auto A = make_shared(element::f32, shape_a); - Shape shape_rt{3, 1, 2}; - auto axes = make_shared(element::i32, Shape{}, 1); - auto f = make_shared(make_shared(A, axes, true), ParameterVector{A}); - - auto backend = runtime::Backend::create("INTERPRETER"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::f32, shape_a); - copy_data(a, vector{}); - auto result = backend->create_tensor(element::f32, shape_rt); - - // Overwrite the initial result vector to make sure we're not just coincidentally getting the - // right value. - copy_data(result, vector{2112, 2112, 2112, 2112, 2112, 2112}); - - float mi = -std::numeric_limits::infinity(); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_EQ((vector{mi, mi, mi, mi, mi, mi}), read_vector(result)); -} \ No newline at end of file diff --git a/ngraph/test/op_eval/reduce_min.cpp b/ngraph/test/op_eval/reduce_min.cpp deleted file mode 100644 index b12fe6d64fa..00000000000 --- a/ngraph/test/op_eval/reduce_min.cpp +++ /dev/null @@ -1,235 +0,0 @@ -// Copyright (C) 2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#include "gtest/gtest.h" -#include "ngraph/ngraph.hpp" -#include "util/all_close.hpp" -#include "util/all_close_f.hpp" -#include "util/ndarray.hpp" -#include "util/test_control.hpp" - -using namespace std; -using namespace ngraph; - -static string s_manifest = "${MANIFEST}"; - -TEST(op_eval, reduce_min_matrix_rows_zero) { - Shape shape_a{3, 0}; - auto A = make_shared(element::f32, shape_a); - Shape shape_rt{3}; - auto axes = make_shared(element::i32, Shape{}, 1); - auto f = make_shared(make_shared(A, axes, false), ParameterVector{A}); - - auto backend = runtime::Backend::create("INTERPRETER"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::f32, shape_a); - copy_data(a, vector{}); - auto result = backend->create_tensor(element::f32, shape_rt); - copy_data(result, vector({3, 3, 3})); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_EQ((vector{std::numeric_limits::infinity(), - std::numeric_limits::infinity(), - std::numeric_limits::infinity()}), - read_vector(result)); -} - -TEST(op_eval, reduce_min_matrix_cols_zero) { - // Now the reduction (g(x:float32[2,2],y:float32[]) = reduce(x,y,f,axes={})). - Shape shape_a{0, 2}; - auto A = make_shared(element::f32, shape_a); - Shape shape_rt{2}; - auto axes = make_shared(element::i32, Shape{}, 0); - auto f = make_shared(make_shared(A, axes, false), ParameterVector{A}); - - auto backend = runtime::Backend::create("INTERPRETER"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::f32, shape_a); - copy_data(a, vector{}); - auto result = backend->create_tensor(element::f32, shape_rt); - copy_data(result, vector({3, 3})); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_EQ((vector{std::numeric_limits::infinity(), std::numeric_limits::infinity()}), - read_vector(result)); -} - -TEST(op_eval, reduce_min_vector_zero) { - Shape shape_a{0}; - auto A = make_shared(element::f32, shape_a); - Shape shape_rt{}; - auto axes = make_shared(element::i32, Shape{}, 0); - auto f = make_shared(make_shared(A, axes, false), ParameterVector{A}); - - auto backend = runtime::Backend::create("INTERPRETER"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::f32, shape_a); - copy_data(a, vector{}); - auto result = backend->create_tensor(element::f32, shape_rt); - copy_data(result, vector({3})); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_EQ((vector{std::numeric_limits::infinity()}), read_vector(result)); -} - -TEST(op_eval, reduce_min_matrix_to_scalar_zero_by_zero) { - Shape shape_a{0, 0}; - auto A = make_shared(element::f32, shape_a); - Shape shape_rt{}; - auto axes = make_shared(element::i32, Shape{2}, vector{0, 1}); - auto f = make_shared(make_shared(A, axes, false), ParameterVector{A}); - - auto backend = runtime::Backend::create("INTERPRETER"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::f32, shape_a); - copy_data(a, vector{}); - auto result = backend->create_tensor(element::f32, shape_rt); - copy_data(result, vector({3})); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_EQ((vector{std::numeric_limits::infinity()}), read_vector(result)); -} - -TEST(op_eval, reduce_min_3d_eliminate_zero_dim) { - Shape shape_a{3, 0, 2}; - auto A = make_shared(element::f32, shape_a); - Shape shape_rt{3, 2}; - auto axes = make_shared(element::i32, Shape{}, 1); - auto f = make_shared(make_shared(A, axes, false), ParameterVector{A}); - - auto backend = runtime::Backend::create("INTERPRETER"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::f32, shape_a); - copy_data(a, vector{}); - auto result = backend->create_tensor(element::f32, shape_rt); - - // Overwrite the initial result vector to make sure we're not just coincidentally getting the - // right value. - copy_data(result, vector{2112, 2112, 2112, 2112, 2112, 2112}); - - float inf = std::numeric_limits::infinity(); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_EQ((vector{inf, inf, inf, inf, inf, inf}), read_vector(result)); -} - -TEST(op_eval, reduce_min_keep_matrix_rows_zero) { - Shape shape_a{3, 0}; - auto A = make_shared(element::f32, shape_a); - Shape shape_rt{3, 1}; - auto axes = make_shared(element::i32, Shape{}, 1); - auto f = make_shared(make_shared(A, axes, true), ParameterVector{A}); - - auto backend = runtime::Backend::create("INTERPRETER"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::f32, shape_a); - copy_data(a, vector{}); - auto result = backend->create_tensor(element::f32, shape_rt); - copy_data(result, vector({3, 3, 3})); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_EQ((vector{std::numeric_limits::infinity(), - std::numeric_limits::infinity(), - std::numeric_limits::infinity()}), - read_vector(result)); -} - -TEST(op_eval, reduce_min_keep_matrix_cols_zero) { - // Now the reduction (g(x:float32[2,2],y:float32[]) = reduce(x,y,f,axes={})). - Shape shape_a{0, 2}; - auto A = make_shared(element::f32, shape_a); - Shape shape_rt{1, 2}; - auto axes = make_shared(element::i32, Shape{}, 0); - auto f = make_shared(make_shared(A, axes, true), ParameterVector{A}); - - auto backend = runtime::Backend::create("INTERPRETER"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::f32, shape_a); - copy_data(a, vector{}); - auto result = backend->create_tensor(element::f32, shape_rt); - copy_data(result, vector({3, 3})); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_EQ((vector{std::numeric_limits::infinity(), std::numeric_limits::infinity()}), - read_vector(result)); -} - -TEST(op_eval, reduce_min_keep_vector_zero) { - Shape shape_a{0}; - auto A = make_shared(element::f32, shape_a); - Shape shape_rt{1}; - auto axes = make_shared(element::i32, Shape{}, 0); - auto f = make_shared(make_shared(A, axes, true), ParameterVector{A}); - - auto backend = runtime::Backend::create("INTERPRETER"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::f32, shape_a); - copy_data(a, vector{}); - auto result = backend->create_tensor(element::f32, shape_rt); - copy_data(result, vector({3})); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_EQ((vector{std::numeric_limits::infinity()}), read_vector(result)); -} - -TEST(op_eval, reduce_min_keep_matrix_to_scalar_zero_by_zero) { - Shape shape_a{0, 0}; - auto A = make_shared(element::f32, shape_a); - Shape shape_rt{1, 1}; - auto axes = make_shared(element::i32, Shape{2}, vector{0, 1}); - auto f = make_shared(make_shared(A, axes, true), ParameterVector{A}); - - auto backend = runtime::Backend::create("INTERPRETER"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::f32, shape_a); - copy_data(a, vector{}); - auto result = backend->create_tensor(element::f32, shape_rt); - copy_data(result, vector({3})); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_EQ((vector{std::numeric_limits::infinity()}), read_vector(result)); -} - -TEST(op_eval, reduce_min_keep_3d_eliminate_zero_dim) { - Shape shape_a{3, 0, 2}; - auto A = make_shared(element::f32, shape_a); - Shape shape_rt{3, 1, 2}; - auto axes = make_shared(element::i32, Shape{}, 1); - auto f = make_shared(make_shared(A, axes, true), ParameterVector{A}); - - auto backend = runtime::Backend::create("INTERPRETER"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::f32, shape_a); - copy_data(a, vector{}); - auto result = backend->create_tensor(element::f32, shape_rt); - - // Overwrite the initial result vector to make sure we're not just coincidentally getting the - // right value. - copy_data(result, vector{2112, 2112, 2112, 2112, 2112, 2112}); - - float inf = std::numeric_limits::infinity(); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_EQ((vector{inf, inf, inf, inf, inf, inf}), read_vector(result)); -} diff --git a/ngraph/test/op_eval/reduce_prod.cpp b/ngraph/test/op_eval/reduce_prod.cpp deleted file mode 100644 index 0b74886f89a..00000000000 --- a/ngraph/test/op_eval/reduce_prod.cpp +++ /dev/null @@ -1,223 +0,0 @@ -// Copyright (C) 2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#include "gtest/gtest.h" -#include "ngraph/ngraph.hpp" -#include "util/all_close.hpp" -#include "util/all_close_f.hpp" -#include "util/ndarray.hpp" -#include "util/test_control.hpp" - -using namespace std; -using namespace ngraph; - -static string s_manifest = "${MANIFEST}"; - -TEST(op_eval, reduce_product_matrix_rows_zero) { - Shape shape_a{3, 0}; - auto A = make_shared(element::f32, shape_a); - Shape shape_rt{3}; - auto axes = make_shared(element::i32, Shape{}, 1); - auto f = make_shared(make_shared(A, axes, false), ParameterVector{A}); - - auto backend = runtime::Backend::create("INTERPRETER"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::f32, shape_a); - copy_data(a, vector{}); - auto result = backend->create_tensor(element::f32, shape_rt); - copy_data(result, vector({3, 3, 3})); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_TRUE(test::all_close_f((vector{1, 1, 1}), read_vector(result))); -} - -TEST(op_eval, reduce_product_matrix_cols_zero) { - // Now the reduction (g(x:float32[2,2],y:float32[]) = reduce(x,y,f,axes={})). - Shape shape_a{0, 2}; - auto A = make_shared(element::f32, shape_a); - Shape shape_rt{2}; - auto axes = make_shared(element::i32, Shape{}, 0); - auto f = make_shared(make_shared(A, axes, false), ParameterVector{A}); - - auto backend = runtime::Backend::create("INTERPRETER"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::f32, shape_a); - copy_data(a, vector{}); - auto result = backend->create_tensor(element::f32, shape_rt); - copy_data(result, vector({3, 3})); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_TRUE(test::all_close_f((vector{1, 1}), read_vector(result))); -} - -TEST(op_eval, reduce_product_vector_zero) { - Shape shape_a{0}; - auto A = make_shared(element::f32, shape_a); - Shape shape_rt{}; - auto axes = make_shared(element::i32, Shape{}, 0); - auto f = make_shared(make_shared(A, axes, false), ParameterVector{A}); - - auto backend = runtime::Backend::create("INTERPRETER"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::f32, shape_a); - copy_data(a, vector{}); - auto result = backend->create_tensor(element::f32, shape_rt); - copy_data(result, vector({3})); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_TRUE(test::all_close_f((vector{1}), read_vector(result))); -} - -TEST(op_eval, reduce_product_matrix_to_scalar_zero_by_zero) { - Shape shape_a{0, 0}; - auto A = make_shared(element::f32, shape_a); - Shape shape_rt{}; - auto axes = make_shared(element::i32, Shape{2}, vector{0, 1}); - auto f = make_shared(make_shared(A, axes, false), ParameterVector{A}); - - auto backend = runtime::Backend::create("INTERPRETER"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::f32, shape_a); - copy_data(a, vector{}); - auto result = backend->create_tensor(element::f32, shape_rt); - copy_data(result, vector({3})); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_TRUE(test::all_close_f((vector{1}), read_vector(result))); -} - -TEST(op_eval, reduce_product_3d_eliminate_zero_dim) { - Shape shape_a{3, 0, 2}; - auto A = make_shared(element::f32, shape_a); - Shape shape_rt{3, 2}; - auto axes = make_shared(element::i32, Shape{}, 1); - auto f = make_shared(make_shared(A, axes, false), ParameterVector{A}); - - auto backend = runtime::Backend::create("INTERPRETER"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::f32, shape_a); - copy_data(a, vector{}); - auto result = backend->create_tensor(element::f32, shape_rt); - - // Overwrite the initial result vector to make sure we're not just coincidentally getting the - // right value. - copy_data(result, vector{2112, 2112, 2112, 2112, 2112, 2112}); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_TRUE(test::all_close_f((vector{1, 1, 1, 1, 1, 1}), read_vector(result))); -} - -TEST(op_eval, reduce_product_keep_matrix_rows_zero) { - Shape shape_a{3, 0}; - auto A = make_shared(element::f32, shape_a); - Shape shape_rt{3, 1}; - auto axes = make_shared(element::i32, Shape{}, 1); - auto f = make_shared(make_shared(A, axes, true), ParameterVector{A}); - - auto backend = runtime::Backend::create("INTERPRETER"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::f32, shape_a); - copy_data(a, vector{}); - auto result = backend->create_tensor(element::f32, shape_rt); - copy_data(result, vector({3, 3, 3})); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_TRUE(test::all_close_f((vector{1, 1, 1}), read_vector(result))); -} - -TEST(op_eval, reduce_product_keep_matrix_cols_zero) { - // Now the reduction (g(x:float32[2,2],y:float32[]) = reduce(x,y,f,axes={})). - Shape shape_a{0, 2}; - auto A = make_shared(element::f32, shape_a); - Shape shape_rt{1, 2}; - auto axes = make_shared(element::i32, Shape{}, 0); - auto f = make_shared(make_shared(A, axes, true), ParameterVector{A}); - - auto backend = runtime::Backend::create("INTERPRETER"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::f32, shape_a); - copy_data(a, vector{}); - auto result = backend->create_tensor(element::f32, shape_rt); - copy_data(result, vector({3, 3})); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_TRUE(test::all_close_f((vector{1, 1}), read_vector(result))); -} - -TEST(op_eval, reduce_product_keep_vector_zero) { - Shape shape_a{0}; - auto A = make_shared(element::f32, shape_a); - Shape shape_rt{1}; - auto axes = make_shared(element::i32, Shape{}, 0); - auto f = make_shared(make_shared(A, axes, true), ParameterVector{A}); - - auto backend = runtime::Backend::create("INTERPRETER"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::f32, shape_a); - copy_data(a, vector{}); - auto result = backend->create_tensor(element::f32, shape_rt); - copy_data(result, vector({3})); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_TRUE(test::all_close_f((vector{1}), read_vector(result))); -} - -TEST(op_eval, reduce_product_keep_matrix_to_scalar_zero_by_zero) { - Shape shape_a{0, 0}; - auto A = make_shared(element::f32, shape_a); - Shape shape_rt{1, 1}; - auto axes = make_shared(element::i32, Shape{2}, vector{0, 1}); - auto f = make_shared(make_shared(A, axes, true), ParameterVector{A}); - - auto backend = runtime::Backend::create("INTERPRETER"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::f32, shape_a); - copy_data(a, vector{}); - auto result = backend->create_tensor(element::f32, shape_rt); - copy_data(result, vector({3})); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_TRUE(test::all_close_f((vector{1}), read_vector(result))); -} - -TEST(op_eval, reduce_product_keep_3d_eliminate_zero_dim) { - Shape shape_a{3, 0, 2}; - auto A = make_shared(element::f32, shape_a); - Shape shape_rt{3, 1, 2}; - auto axes = make_shared(element::i32, Shape{}, 1); - auto f = make_shared(make_shared(A, axes, true), ParameterVector{A}); - - auto backend = runtime::Backend::create("INTERPRETER"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::f32, shape_a); - copy_data(a, vector{}); - auto result = backend->create_tensor(element::f32, shape_rt); - - // Overwrite the initial result vector to make sure we're not just coincidentally getting the - // right value. - copy_data(result, vector{2112, 2112, 2112, 2112, 2112, 2112}); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_TRUE(test::all_close_f((vector{1, 1, 1, 1, 1, 1}), read_vector(result))); -} diff --git a/ngraph/test/op_eval/reduce_sum.cpp b/ngraph/test/op_eval/reduce_sum.cpp deleted file mode 100644 index fc1ecee1719..00000000000 --- a/ngraph/test/op_eval/reduce_sum.cpp +++ /dev/null @@ -1,369 +0,0 @@ -// Copyright (C) 2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#include "gtest/gtest.h" -#include "ngraph/ngraph.hpp" -#include "util/all_close.hpp" -#include "util/all_close_f.hpp" -#include "util/ndarray.hpp" -#include "util/test_control.hpp" - -using namespace std; -using namespace ngraph; - -static string s_manifest = "${MANIFEST}"; - -TEST(op_eval, reduce_sum_matrix_rows_zero) { - Shape shape_a{3, 0}; - auto A = make_shared(element::f32, shape_a); - Shape shape_rt{3}; - auto axes = make_shared(element::i32, Shape{}, 1); - auto f = make_shared(make_shared(A, axes, false), ParameterVector{A}); - - auto backend = runtime::Backend::create("INTERPRETER"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::f32, shape_a); - copy_data(a, vector{}); - auto result = backend->create_tensor(element::f32, shape_rt); - copy_data(result, vector({3, 3, 3})); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_TRUE(test::all_close_f((vector{0, 0, 0}), read_vector(result))); -} - -TEST(op_eval, reduce_sum_vector_zero) { - Shape shape_a{0}; - auto A = make_shared(element::f32, shape_a); - Shape shape_rt{}; - auto axes = make_shared(element::i32, Shape{}, 0); - auto f = make_shared(make_shared(A, axes, false), ParameterVector{A}); - - auto backend = runtime::Backend::create("INTERPRETER"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::f32, shape_a); - copy_data(a, vector{}); - auto result = backend->create_tensor(element::f32, shape_rt); - copy_data(result, vector({3})); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_TRUE(test::all_close_f((vector{0}), read_vector(result))); -} - -TEST(op_eval, reduce_sum_matrix_cols_zero) { - // Now the reduction (g(x:float32[2,2],y:float32[]) = reduce(x,y,f,axes={})). - Shape shape_a{0, 2}; - auto A = make_shared(element::f32, shape_a); - Shape shape_rt{2}; - auto axes = make_shared(element::i32, Shape{}, 0); - auto f = make_shared(make_shared(A, axes, false), ParameterVector{A}); - - auto backend = runtime::Backend::create("INTERPRETER"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::f32, shape_a); - copy_data(a, vector{}); - auto result = backend->create_tensor(element::f32, shape_rt); - copy_data(result, vector({3, 3})); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_TRUE(test::all_close_f((vector{0, 0}), read_vector(result))); -} - -TEST(op_eval, reduce_sum_matrix_to_scalar_zero_by_zero) { - Shape shape_a{0, 0}; - auto A = make_shared(element::f32, shape_a); - Shape shape_rt{}; - auto axes = make_shared(element::i32, Shape{2}, vector{0, 1}); - auto f = make_shared(make_shared(A, axes, false), ParameterVector{A}); - - auto backend = runtime::Backend::create("INTERPRETER"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::f32, shape_a); - copy_data(a, vector{}); - auto result = backend->create_tensor(element::f32, shape_rt); - copy_data(result, vector({3})); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_TRUE(test::all_close_f((vector{0}), read_vector(result))); -} - -TEST(op_eval, reduce_sum_3d_eliminate_zero_dim) { - Shape shape_a{3, 0, 2}; - auto A = make_shared(element::f32, shape_a); - Shape shape_rt{3, 2}; - auto axes = make_shared(element::i32, Shape{}, 1); - auto f = make_shared(make_shared(A, axes, false), ParameterVector{A}); - - auto backend = runtime::Backend::create("INTERPRETER"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::f32, shape_a); - copy_data(a, vector{}); - auto result = backend->create_tensor(element::f32, shape_rt); - - // Overwrite the initial result vector to make sure we're not just coincidentally getting the - // right value. - copy_data(result, vector{2112, 2112, 2112, 2112, 2112, 2112}); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_TRUE(test::all_close_f((vector{0, 0, 0, 0, 0, 0}), read_vector(result))); -} - -TEST(op_eval, reduce_sum_3d_eliminate_zero_dim_int32) { - Shape shape_a{3, 0, 2}; - auto A = make_shared(element::i32, shape_a); - Shape shape_rt{3, 2}; - auto axes = make_shared(element::i32, Shape{}, 1); - auto f = make_shared(make_shared(A, axes, false), ParameterVector{A}); - - auto backend = runtime::Backend::create("INTERPRETER"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::i32, shape_a); - copy_data(a, vector{}); - auto result = backend->create_tensor(element::i32, shape_rt); - - // Overwrite the initial result vector to make sure we're not just coincidentally getting the - // right value. - copy_data(result, vector{2112, 2112, 2112, 2112, 2112, 2112}); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_EQ((vector{0, 0, 0, 0, 0, 0}), read_vector(result)); -} - -TEST(op_eval, reduce_sum_dynamic) { - // Create a graph for f(x,axes:int32) = Sum(x,Convert(axes)). - auto x = make_shared(element::f32, PartialShape::dynamic()); - auto axes = make_shared(element::i32, PartialShape{Dimension::dynamic()}); - auto axes_i64 = make_shared(axes, element::i64); - - auto sum = make_shared(x, axes_i64, false); - ASSERT_TRUE(sum->get_output_partial_shape(0).rank().is_dynamic()); - - auto f = make_shared(NodeVector{sum}, ParameterVector{x, axes}); - - auto backend = runtime::Backend::create("INTERPRETER", true); - - auto ex = backend->compile(f); - - auto t_r = backend->create_dynamic_tensor(element::f32, PartialShape::dynamic()); - - std::vector x_shapes{Shape{2, 3}, Shape{2, 3}, Shape{2, 3}, Shape{2, 3}, Shape{5}, Shape{5}}; - std::vector> axeses{{}, {0}, {1}, {0, 1}, {}, {0}}; - std::vector> inputs{{1, 2, 3, 4, 5, 6}, - {1, 2, 3, 4, 5, 6}, - {1, 2, 3, 4, 5, 6}, - {1, 2, 3, 4, 5, 6}, - {1, 2, 3, 4, 5}, - {1, 2, 3, 4, 5}}; - std::vector expected_result_shapes{Shape{2, 3}, Shape{3}, Shape{2}, Shape{}, Shape{5}, Shape{}}; - std::vector> expected_results{{1, 2, 3, 4, 5, 6}, - {5, 7, 9}, - {6, 15}, - {21}, - {1, 2, 3, 4, 5}, - {15}}; - - for (size_t i = 0; i < x_shapes.size(); i++) { - auto t_x = backend->create_tensor(element::f32, x_shapes[i]); - auto t_axes = backend->create_tensor(element::i32, Shape{axeses[i].size()}); - - copy_data(t_x, inputs[i]); - copy_data(t_axes, axeses[i]); - - ex->call_with_validate({t_r}, {t_x, t_axes}); - - ASSERT_EQ(t_r->get_shape(), expected_result_shapes[i]); - - auto results = read_vector(t_r); - - ASSERT_TRUE(test::all_close_f(results, expected_results[i], MIN_FLOAT_TOLERANCE_BITS)); - } -} - -TEST(op_eval, reduce_sum_keep_matrix_rows_zero) { - Shape shape_a{3, 0}; - auto A = make_shared(element::f32, shape_a); - Shape shape_rt{3, 1}; - auto axes = make_shared(element::i32, Shape{}, 1); - auto f = make_shared(make_shared(A, axes, true), ParameterVector{A}); - - auto backend = runtime::Backend::create("INTERPRETER"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::f32, shape_a); - copy_data(a, vector{}); - auto result = backend->create_tensor(element::f32, shape_rt); - copy_data(result, vector({3, 3, 3})); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_TRUE(test::all_close_f((vector{0, 0, 0}), read_vector(result))); -} - -TEST(op_eval, reduce_sum_keep_matrix_cols_zero) { - // Now the reduction (g(x:float32[2,2],y:float32[]) = reduce(x,y,f,axes={})). - Shape shape_a{0, 2}; - auto A = make_shared(element::f32, shape_a); - Shape shape_rt{1, 2}; - auto axes = make_shared(element::i32, Shape{}, 0); - auto f = make_shared(make_shared(A, axes, true), ParameterVector{A}); - - auto backend = runtime::Backend::create("INTERPRETER"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::f32, shape_a); - copy_data(a, vector{}); - auto result = backend->create_tensor(element::f32, shape_rt); - copy_data(result, vector({3, 3})); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_TRUE(test::all_close_f((vector{0, 0}), read_vector(result))); -} - -TEST(op_eval, reduce_sum_keep_vector_zero) { - Shape shape_a{0}; - auto A = make_shared(element::f32, shape_a); - Shape shape_rt{1}; - auto axes = make_shared(element::i32, Shape{}, 0); - auto f = make_shared(make_shared(A, axes, true), ParameterVector{A}); - - auto backend = runtime::Backend::create("INTERPRETER"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::f32, shape_a); - copy_data(a, vector{}); - auto result = backend->create_tensor(element::f32, shape_rt); - copy_data(result, vector({3})); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_TRUE(test::all_close_f((vector{0}), read_vector(result))); -} - -TEST(op_eval, reduce_sum_keep_matrix_to_scalar_zero_by_zero) { - Shape shape_a{0, 0}; - auto A = make_shared(element::f32, shape_a); - Shape shape_rt{1, 1}; - auto axes = make_shared(element::i32, Shape{2}, vector{0, 1}); - auto f = make_shared(make_shared(A, axes, true), ParameterVector{A}); - - auto backend = runtime::Backend::create("INTERPRETER"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::f32, shape_a); - copy_data(a, vector{}); - auto result = backend->create_tensor(element::f32, shape_rt); - copy_data(result, vector({3})); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_TRUE(test::all_close_f((vector{0}), read_vector(result))); -} - -TEST(op_eval, reduce_sum_keep_3d_eliminate_zero_dim) { - Shape shape_a{3, 0, 2}; - auto A = make_shared(element::f32, shape_a); - Shape shape_rt{3, 1, 2}; - auto axes = make_shared(element::i32, Shape{}, 1); - auto f = make_shared(make_shared(A, axes, true), ParameterVector{A}); - - auto backend = runtime::Backend::create("INTERPRETER"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::f32, shape_a); - copy_data(a, vector{}); - auto result = backend->create_tensor(element::f32, shape_rt); - - // Overwrite the initial result vector to make sure we're not just coincidentally getting the - // right value. - copy_data(result, vector{2112, 2112, 2112, 2112, 2112, 2112}); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_TRUE(test::all_close_f((vector{0, 0, 0, 0, 0, 0}), read_vector(result))); -} - -TEST(op_eval, reduce_sum_keep_3d_eliminate_zero_dim_int32) { - Shape shape_a{3, 0, 2}; - auto A = make_shared(element::i32, shape_a); - Shape shape_rt{3, 1, 2}; - auto axes = make_shared(element::i32, Shape{}, 1); - auto f = make_shared(make_shared(A, axes, true), ParameterVector{A}); - - auto backend = runtime::Backend::create("INTERPRETER"); - - // Create some tensors for input/output - auto a = backend->create_tensor(element::i32, shape_a); - copy_data(a, vector{}); - auto result = backend->create_tensor(element::i32, shape_rt); - - // Overwrite the initial result vector to make sure we're not just coincidentally getting the - // right value. - copy_data(result, vector{2112, 2112, 2112, 2112, 2112, 2112}); - - auto handle = backend->compile(f); - handle->call_with_validate({result}, {a}); - EXPECT_EQ((vector{0, 0, 0, 0, 0, 0}), read_vector(result)); -} - -TEST(op_eval, reduce_sum_keep_dynamic) { - // Create a graph for f(x,axes:int32) = Sum(x,Convert(axes)). - auto x = make_shared(element::f32, PartialShape::dynamic()); - auto axes = make_shared(element::i32, PartialShape{Dimension::dynamic()}); - auto axes_i64 = make_shared(axes, element::i64); - - auto sum = make_shared(x, axes_i64, true); - ASSERT_TRUE(sum->get_output_partial_shape(0).rank().is_dynamic()); - - auto f = make_shared(NodeVector{sum}, ParameterVector{x, axes}); - - auto backend = runtime::Backend::create("INTERPRETER", true); - - auto ex = backend->compile(f); - - auto t_r = backend->create_dynamic_tensor(element::f32, PartialShape::dynamic()); - - std::vector x_shapes{Shape{2, 3}, Shape{2, 3}, Shape{2, 3}, Shape{2, 3}, Shape{5}, Shape{5}}; - std::vector> axeses{{}, {0}, {1}, {0, 1}, {}, {0}}; - std::vector> inputs{{1, 2, 3, 4, 5, 6}, - {1, 2, 3, 4, 5, 6}, - {1, 2, 3, 4, 5, 6}, - {1, 2, 3, 4, 5, 6}, - {1, 2, 3, 4, 5}, - {1, 2, 3, 4, 5}}; - std::vector expected_result_shapes{Shape{2, 3}, Shape{1, 3}, Shape{2, 1}, Shape{1, 1}, Shape{5}, Shape{1}}; - std::vector> expected_results{{1, 2, 3, 4, 5, 6}, - {5, 7, 9}, - {6, 15}, - {21}, - {1, 2, 3, 4, 5}, - {15}}; - - for (size_t i = 0; i < x_shapes.size(); i++) { - auto t_x = backend->create_tensor(element::f32, x_shapes[i]); - auto t_axes = backend->create_tensor(element::i32, Shape{axeses[i].size()}); - - copy_data(t_x, inputs[i]); - copy_data(t_axes, axeses[i]); - - ex->call_with_validate({t_r}, {t_x, t_axes}); - - ASSERT_EQ(t_r->get_shape(), expected_result_shapes[i]); - - auto results = read_vector(t_r); - - ASSERT_TRUE(test::all_close_f(results, expected_results[i], MIN_FLOAT_TOLERANCE_BITS)); - } -} diff --git a/ngraph/test/runtime/ie/unit_test.manifest b/ngraph/test/runtime/ie/unit_test.manifest index 04c2983ada5..c32732c3c26 100644 --- a/ngraph/test/runtime/ie/unit_test.manifest +++ b/ngraph/test/runtime/ie/unit_test.manifest @@ -361,28 +361,6 @@ all_trivial all_2x0_to_scalar all_dynamic -# Reduce ops disabled/accuracy: 56520 -# disabled reference implementation -reduce_max_to_scalar_int8 -reduce_max_keep_to_scalar_int8 -reduce_mean_to_scalar_int8 -reduce_mean_keep_to_scalar_int8 -reduce_sum_keep_2d_to_scalar_int8 -reduce_sum_2d_to_scalar_int8 -reduce_product_to_scalar_int8 -reduce_product_keep_to_scalar_int8 -reduce_min_to_scalar_int8 -reduce_min_keep_to_scalar_int8 -# accuracy -reduce_mean_matrix_rows_int32 -reduce_mean_keep_matrix_rows_int32 -reduce_sum_keep_stable_acc -reduce_sum_keep_3d_to_scalar_int32 -reduce_sum_keep_large_1d_to_scalar -reduce_sum_stable_acc -reduce_sum_3d_to_scalar_int32 -reduce_sum_large_1d_to_scalar - # Doesn't throw expected exception type. unhandled_op diff --git a/ngraph/test/runtime/interpreter/unit_test.manifest b/ngraph/test/runtime/interpreter/unit_test.manifest index 8ce07a2dcea..ec77901f320 100644 --- a/ngraph/test/runtime/interpreter/unit_test.manifest +++ b/ngraph/test/runtime/interpreter/unit_test.manifest @@ -1,10 +1,6 @@ INTERPRETER.onnx_model_quant_conv_linear INTERPRETER.onnx_top_k_opset_10 -# Failed in ubuntu18 i386 -reduce_sum_large_1d_to_scalar -reduce_sum_keep_large_1d_to_scalar - # Temporarily disabled: INTERPRETER.onnx_resize11_scales_nearest_asymmetric_floor_dynamic_sizes INTERPRETER.onnx_resize11_up_sizes_cubic_half_pixel_dynamic_sizes @@ -30,16 +26,6 @@ INTERPRETER.onnx_model_matmul_integer_4d_no_zero_point # Disabled tests for disabled reference implementations INTERPRETER.onnx_dyn_shapes_expand_uint16_dyn_shape INTERPRETER.sum_2d_to_scalar_int8 -INTERPRETER.reduce_sum_2d_to_scalar_int8 -INTERPRETER.reduce_sum_keep_2d_to_scalar_int8 -INTERPRETER.reduce_product_to_scalar_int8 -INTERPRETER.reduce_product_keep_to_scalar_int8 -INTERPRETER.reduce_min_to_scalar_int8 -INTERPRETER.reduce_min_keep_to_scalar_int8 -INTERPRETER.reduce_mean_to_scalar_int8 -INTERPRETER.reduce_mean_keep_to_scalar_int8 -INTERPRETER.reduce_max_to_scalar_int8 -INTERPRETER.reduce_max_keep_to_scalar_int8 INTERPRETER.product_to_scalar_int8 INTERPRETER.max_pool_uint8 INTERPRETER.max_pool_int8 diff --git a/ngraph/test/visitors/op/reduce_l1.cpp b/ngraph/test/visitors/op/reduce_l1.cpp index 03ef0f0f77b..7b471606922 100644 --- a/ngraph/test/visitors/op/reduce_l1.cpp +++ b/ngraph/test/visitors/op/reduce_l1.cpp @@ -4,5 +4,5 @@ #include "reduce_ops.hpp" -using Type = ::testing::Types; -INSTANTIATE_TYPED_TEST_SUITE_P(attributes_reduce_l1, ReduceOpsAttrTest, Type); +using Type = ::testing::Types>; +INSTANTIATE_TYPED_TEST_SUITE_P(attributes_reduce_op, ReduceOperatorVisitor, Type, ReduceOperatorTypeName); diff --git a/ngraph/test/visitors/op/reduce_l2.cpp b/ngraph/test/visitors/op/reduce_l2.cpp index 4ace59a9514..72760f603ea 100644 --- a/ngraph/test/visitors/op/reduce_l2.cpp +++ b/ngraph/test/visitors/op/reduce_l2.cpp @@ -4,5 +4,5 @@ #include "reduce_ops.hpp" -using Type = ::testing::Types; -INSTANTIATE_TYPED_TEST_SUITE_P(attributes_reduce_l2, ReduceOpsAttrTest, Type); +using Type = ::testing::Types>; +INSTANTIATE_TYPED_TEST_SUITE_P(attributes_reduce_op, ReduceOperatorVisitor, Type, ReduceOperatorTypeName); diff --git a/ngraph/test/visitors/op/reduce_logical_and.cpp b/ngraph/test/visitors/op/reduce_logical_and.cpp index af149103baa..ca45207b286 100644 --- a/ngraph/test/visitors/op/reduce_logical_and.cpp +++ b/ngraph/test/visitors/op/reduce_logical_and.cpp @@ -4,5 +4,5 @@ #include "reduce_ops.hpp" -using Type = ::testing::Types; -INSTANTIATE_TYPED_TEST_SUITE_P(attributes_reduce_logical_and, ReduceOpsAttrTest, Type); +using Type = ::testing::Types>; +INSTANTIATE_TYPED_TEST_SUITE_P(attributes_reduce_op, ReduceOperatorVisitor, Type, ReduceOperatorTypeName); diff --git a/ngraph/test/visitors/op/reduce_logical_or.cpp b/ngraph/test/visitors/op/reduce_logical_or.cpp index 216a3a73ba6..19e50e51adf 100644 --- a/ngraph/test/visitors/op/reduce_logical_or.cpp +++ b/ngraph/test/visitors/op/reduce_logical_or.cpp @@ -4,5 +4,5 @@ #include "reduce_ops.hpp" -using Type = ::testing::Types; -INSTANTIATE_TYPED_TEST_SUITE_P(attributes_reduce_logical_or, ReduceOpsAttrTest, Type); +using Type = ::testing::Types>; +INSTANTIATE_TYPED_TEST_SUITE_P(attributes_reduce_op, ReduceOperatorVisitor, Type, ReduceOperatorTypeName); diff --git a/ngraph/test/visitors/op/reduce_max.cpp b/ngraph/test/visitors/op/reduce_max.cpp index 713114717f9..0c1e2cabff9 100644 --- a/ngraph/test/visitors/op/reduce_max.cpp +++ b/ngraph/test/visitors/op/reduce_max.cpp @@ -4,5 +4,5 @@ #include "reduce_ops.hpp" -using Type = ::testing::Types; -INSTANTIATE_TYPED_TEST_SUITE_P(attributes_reduce_max, ReduceOpsAttrTest, Type); +using Type = ::testing::Types>; +INSTANTIATE_TYPED_TEST_SUITE_P(attributes_reduce_op, ReduceOperatorVisitor, Type, ReduceOperatorTypeName); diff --git a/ngraph/test/visitors/op/reduce_mean.cpp b/ngraph/test/visitors/op/reduce_mean.cpp index 382fc2d704f..06626e8757e 100644 --- a/ngraph/test/visitors/op/reduce_mean.cpp +++ b/ngraph/test/visitors/op/reduce_mean.cpp @@ -4,5 +4,5 @@ #include "reduce_ops.hpp" -using Type = ::testing::Types; -INSTANTIATE_TYPED_TEST_SUITE_P(attributes_reduce_mean, ReduceOpsAttrTest, Type); +using Type = ::testing::Types>; +INSTANTIATE_TYPED_TEST_SUITE_P(attributes_reduce_op, ReduceOperatorVisitor, Type, ReduceOperatorTypeName); diff --git a/ngraph/test/visitors/op/reduce_min.cpp b/ngraph/test/visitors/op/reduce_min.cpp index 9d212d8cf6b..e91f2337cda 100644 --- a/ngraph/test/visitors/op/reduce_min.cpp +++ b/ngraph/test/visitors/op/reduce_min.cpp @@ -4,5 +4,5 @@ #include "reduce_ops.hpp" -using Type = ::testing::Types; -INSTANTIATE_TYPED_TEST_SUITE_P(attributes_reduce_min, ReduceOpsAttrTest, Type); +using Type = ::testing::Types>; +INSTANTIATE_TYPED_TEST_SUITE_P(attributes_reduce_op, ReduceOperatorVisitor, Type, ReduceOperatorTypeName); diff --git a/ngraph/test/visitors/op/reduce_ops.hpp b/ngraph/test/visitors/op/reduce_ops.hpp index 7fc3c2e914b..743f8e3d239 100644 --- a/ngraph/test/visitors/op/reduce_ops.hpp +++ b/ngraph/test/visitors/op/reduce_ops.hpp @@ -14,33 +14,82 @@ using namespace ngraph; using ngraph::test::NodeBuilder; using ngraph::test::ValueMap; -template -class ReduceOpsAttrTest : public ::testing::Test +template +class ReduceOperatorType +{ +public: + using op_type = T; + static constexpr ngraph::element::Type_t element_type = ELEMENT_TYPE; +}; + +template +class ReduceOperatorVisitor : public ::testing::Test { }; -TYPED_TEST_SUITE_P(ReduceOpsAttrTest); - -TYPED_TEST_P(ReduceOpsAttrTest, reduce_ops) +class ReduceOperatorTypeName { +public: + template + static std::string GetName(int) + { + using OP_Type = typename T::op_type; + constexpr ngraph::element::Type precision(T::element_type); + const ngraph::Node::type_info_t typeinfo = OP_Type::get_type_info_static(); + return std::string{typeinfo.name} + "_" + precision.get_type_name(); + } +}; + +TYPED_TEST_SUITE_P(ReduceOperatorVisitor); + +TYPED_TEST_P(ReduceOperatorVisitor, keep_dims_3D) +{ + using OP_Type = typename TypeParam::op_type; + Shape in_shape{3, 4, 5}; - element::Type in_et = element::dynamic; + const ngraph::element::Type_t in_et = TypeParam::element_type; Shape axes_shape{2}; element::Type axes_et = element::i64; bool keep_dims = true; - NodeBuilder::get_ops().register_factory(); - auto data = make_shared(in_et, in_shape); - auto reduction_axes = make_shared(axes_et, axes_shape); - auto reduce_op = make_shared(data, reduction_axes, keep_dims); + ngraph::test::NodeBuilder::get_ops().register_factory(); + const auto data = make_shared(in_et, in_shape); + const auto reduction_axes = make_shared(axes_et, axes_shape); + const auto reduce_op = make_shared(data, reduction_axes, keep_dims); NodeBuilder builder(reduce_op); const auto expected_attr_count = 1; EXPECT_EQ(builder.get_value_map_size(), expected_attr_count); - auto g_reduce_op = ov::as_type_ptr(builder.create()); + auto g_reduce_op = as_type_ptr(builder.create()); EXPECT_EQ(g_reduce_op->get_keep_dims(), reduce_op->get_keep_dims()); } -REGISTER_TYPED_TEST_SUITE_P(ReduceOpsAttrTest, reduce_ops); +TYPED_TEST_P(ReduceOperatorVisitor, do_not_keep_dims_3D) +{ + using OP_Type = typename TypeParam::op_type; + + Shape in_shape{3, 4, 5}; + const ngraph::element::Type_t in_et = TypeParam::element_type; + + Shape axes_shape{2}; + element::Type axes_et = element::i64; + + bool keep_dims = false; + + ngraph::test::NodeBuilder::get_ops().register_factory(); + const auto data = make_shared(in_et, in_shape); + const auto reduction_axes = make_shared(axes_et, axes_shape); + const auto reduce_op = make_shared(data, reduction_axes, keep_dims); + + NodeBuilder builder(reduce_op); + const auto expected_attr_count = 1; + EXPECT_EQ(builder.get_value_map_size(), expected_attr_count); + auto g_reduce_op = ov::as_type_ptr(builder.create()); + EXPECT_EQ(g_reduce_op->get_keep_dims(), reduce_op->get_keep_dims()); +} + +REGISTER_TYPED_TEST_SUITE_P(ReduceOperatorVisitor, + keep_dims_3D, + do_not_keep_dims_3D); diff --git a/ngraph/test/visitors/op/reduce_prod.cpp b/ngraph/test/visitors/op/reduce_prod.cpp index 2343d69ed74..7132279ee1f 100644 --- a/ngraph/test/visitors/op/reduce_prod.cpp +++ b/ngraph/test/visitors/op/reduce_prod.cpp @@ -4,5 +4,5 @@ #include "reduce_ops.hpp" -using Type = ::testing::Types; -INSTANTIATE_TYPED_TEST_SUITE_P(attributes_reduce_prod, ReduceOpsAttrTest, Type); +using Type = ::testing::Types>; +INSTANTIATE_TYPED_TEST_SUITE_P(attributes_reduce_op, ReduceOperatorVisitor, Type, ReduceOperatorTypeName); diff --git a/ngraph/test/visitors/op/reduce_sum.cpp b/ngraph/test/visitors/op/reduce_sum.cpp index 4caf85b012b..7e411b9b718 100644 --- a/ngraph/test/visitors/op/reduce_sum.cpp +++ b/ngraph/test/visitors/op/reduce_sum.cpp @@ -4,5 +4,5 @@ #include "reduce_ops.hpp" -using Type = ::testing::Types; -INSTANTIATE_TYPED_TEST_SUITE_P(attributes_reduce_sum, ReduceOpsAttrTest, Type); +using Type = ::testing::Types>; +INSTANTIATE_TYPED_TEST_SUITE_P(attributes_reduce_op, ReduceOperatorVisitor, Type, ReduceOperatorTypeName); From 8550579b60e404e04339188aa1923e413604853c Mon Sep 17 00:00:00 2001 From: Evgenya Stepyreva Date: Wed, 1 Sep 2021 12:50:18 +0300 Subject: [PATCH 69/76] Signature dumping while reshaping (#7316) --- .../src/cnn_network_ngraph_impl.cpp | 63 +++++++++++-------- 1 file changed, 36 insertions(+), 27 deletions(-) diff --git a/inference-engine/src/inference_engine/src/cnn_network_ngraph_impl.cpp b/inference-engine/src/inference_engine/src/cnn_network_ngraph_impl.cpp index 8ad6e3c4e74..e4438d781ff 100644 --- a/inference-engine/src/inference_engine/src/cnn_network_ngraph_impl.cpp +++ b/inference-engine/src/inference_engine/src/cnn_network_ngraph_impl.cpp @@ -412,42 +412,51 @@ void CNNNetworkNGraphImpl::reshape(const std::mapget_ordered_ops()) { - cout << "[ " << op->description() << " ] " << op->get_friendly_name() << endl; - cout << " Inputs: "; - for (const auto &in : op->inputs()) { - cout << "[" << in.get_element_type().get_type_name() << "]"; - if (in.get_partial_shape().is_dynamic()) { - cout << "dyn_shape"; - } else { - cout << "{"; - bool first = true; - for (auto i : in.get_shape()) { - if (!first) cout << ","; - cout << i; + bool obfuscate = true; // set to false to get exact dimensions + std::map> signatures; + for (const auto& op : _ngraph_function->get_ordered_ops()) { + const auto& type_name = string(op->get_type_info().name) + "_" + to_string(op->get_type_info().version); + + std::stringstream shape_representation; + for (const auto& input : op->input_values()) { + bool first = true; + for (const auto& dimension : input.get_partial_shape()) { + if (!first) { + shape_representation << ","; + } else { + shape_representation << "{"; first = false; } - cout << "} "; + if (obfuscate) + shape_representation << (dimension.is_dynamic() ? "D" : "S"); + else + shape_representation << dimension; } + shape_representation << "} "; } - cout << endl << " Outputs: "; - for (const auto &in : op->outputs()) { - cout << "[" << in.get_element_type().get_type_name() << "]"; - if (in.get_partial_shape().is_dynamic()) { - cout << "dyn_shape"; - } else { - cout << "{"; - bool first = true; - for (auto i : in.get_shape()) { - if (!first) cout << ","; - cout << i; + shape_representation << "-> "; + for (const auto& output: op->outputs()) { + bool first = true; + for (const auto& dimension : output.get_partial_shape()) { + if (!first) { + shape_representation << ","; + } else { + shape_representation << "{"; first = false; } - cout << "} "; + if (obfuscate) + shape_representation << (dimension.is_dynamic() ? "D" : "S"); + else + shape_representation << dimension; } + shape_representation << "} "; } - cout << endl; + signatures[type_name][shape_representation.str()]++; } + + for (const auto& item : signatures) + for (const auto& shape_to_count : item.second) + std::cout << item.first << " " << shape_to_count.second << "x " << shape_to_count.first << std::endl; #endif std::unordered_set opName; for (const auto& result : specialized_ngraph_function->get_results()) { From 3081fac7581933568b496a3c4e744d1cee481619 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dawid=20Ko=C5=BCykowski?= Date: Wed, 1 Sep 2021 13:19:38 +0200 Subject: [PATCH 70/76] Unify SLTs classes of Convert and ConvertLike operations (#7129) * update comparisiofiles to use const ref param * introduce conversion layer test definitions * adapt old tests to the new format * remove old duplicated conversion tests * fix "convertion" typo to "conversion" * fix style issues and abandon unnecessary changes * fix include order * update remaining conversion tests to use introduced class * fix gpu class test naming * bring back convert.hpp and convert_like.hpp files * bring back convert.hppcppd convert_like.cpp files * bring back single_layer_tests/convert.hpp file * add missing copyright info * fix issue with braces initiator for conversion types * add missing convert_like tests * add deprecated code macros * update deprecated code macro message * add missing space in deprecated code macro message * update skip ConvertLike tests ticket * update deprecated code to use IE macros * update remaining ngraph_deprecated macros to use IE macros --- .../functional/op_reference/conversion.hpp | 2 +- .../{convert.cpp => conversion.cpp} | 18 ++++--- .../single_layer_tests/conversion.cpp | 50 +++++++++++++++++++ .../single_layer_tests/convert.cpp | 47 ----------------- .../single_layer_tests/convert_like.cpp | 33 ------------ .../skip_tests_config.cpp | 4 +- .../{convert.cpp => conversion.cpp} | 27 ++++++---- .../{convert.cpp => conversion.cpp} | 12 +++-- .../single_layer_tests/convert_like.cpp | 33 ------------ .../{convert_like.hpp => conversion.hpp} | 8 ++- .../include/single_layer_tests/convert.hpp | 7 ++- .../single_layer/comparison.hpp | 2 +- .../single_layer/conversion.hpp | 39 +++++++++++++++ .../single_layer/convert.hpp | 8 +-- .../single_layer/convert_like.hpp | 8 +-- .../src/single_layer/comparison.cpp | 2 +- .../src/single_layer/conversion.cpp | 45 +++++++++++++++++ .../src/single_layer/convert.cpp | 7 ++- .../src/single_layer/convert_like.cpp | 7 ++- 19 files changed, 208 insertions(+), 151 deletions(-) rename inference-engine/tests/functional/inference_engine/serialization/single_layer/{convert.cpp => conversion.cpp} (70%) create mode 100644 inference-engine/tests/functional/plugin/cpu/shared_tests_instances/single_layer_tests/conversion.cpp delete mode 100644 inference-engine/tests/functional/plugin/cpu/shared_tests_instances/single_layer_tests/convert.cpp delete mode 100644 inference-engine/tests/functional/plugin/cpu/shared_tests_instances/single_layer_tests/convert_like.cpp rename inference-engine/tests/functional/plugin/cpu/single_layer_tests/{convert.cpp => conversion.cpp} (63%) rename inference-engine/tests/functional/plugin/gpu/shared_tests_instances/single_layer_tests/{convert.cpp => conversion.cpp} (70%) delete mode 100644 inference-engine/tests/functional/plugin/gpu/shared_tests_instances/single_layer_tests/convert_like.cpp rename inference-engine/tests/functional/plugin/shared/include/single_layer_tests/{convert_like.hpp => conversion.hpp} (50%) create mode 100644 inference-engine/tests/functional/shared_test_classes/include/shared_test_classes/single_layer/conversion.hpp create mode 100644 inference-engine/tests/functional/shared_test_classes/src/single_layer/conversion.cpp diff --git a/docs/template_plugin/tests/functional/op_reference/conversion.hpp b/docs/template_plugin/tests/functional/op_reference/conversion.hpp index f3846c7eab6..666060ddb82 100644 --- a/docs/template_plugin/tests/functional/op_reference/conversion.hpp +++ b/docs/template_plugin/tests/functional/op_reference/conversion.hpp @@ -47,7 +47,7 @@ public: static std::string getTestCaseName(const testing::TestParamInfo& obj) { const auto& param = obj.param; std::ostringstream result; - result << "convertionType=" << conversionNames[param.conversionType] << "_"; + result << "conversionType=" << conversionNames[param.conversionType] << "_"; result << "shape=" << param.pshape << "_"; result << "iType=" << param.inType << "_"; result << "oType=" << param.outType; diff --git a/inference-engine/tests/functional/inference_engine/serialization/single_layer/convert.cpp b/inference-engine/tests/functional/inference_engine/serialization/single_layer/conversion.cpp similarity index 70% rename from inference-engine/tests/functional/inference_engine/serialization/single_layer/convert.cpp rename to inference-engine/tests/functional/inference_engine/serialization/single_layer/conversion.cpp index 7cc308c41e2..e62e5ca4ccc 100644 --- a/inference-engine/tests/functional/inference_engine/serialization/single_layer/convert.cpp +++ b/inference-engine/tests/functional/inference_engine/serialization/single_layer/conversion.cpp @@ -2,13 +2,18 @@ // SPDX-License-Identifier: Apache-2.0 // -#include "shared_test_classes/single_layer/convert.hpp" +#include "shared_test_classes/single_layer/conversion.hpp" #include using namespace LayerTestsDefinitions; namespace { +const std::vector conversionOpTypes = { + ngraph::helpers::ConversionTypes::CONVERT, + ngraph::helpers::ConversionTypes::CONVERT_LIKE, +}; + const std::vector> inShape = {{1, 2, 3, 4}}; const std::vector precisions = { @@ -21,18 +26,19 @@ const std::vector precisions = { InferenceEngine::Precision::BF16, InferenceEngine::Precision::FP16, InferenceEngine::Precision::FP32, InferenceEngine::Precision::FP64}; -TEST_P(ConvertLayerTest, Serialize) { +TEST_P(ConversionLayerTest, Serialize) { Serialize(); } INSTANTIATE_TEST_SUITE_P( - smoke_Serialization_ConvertLayerTest, ConvertLayerTest, - ::testing::Combine(::testing::Values(inShape), + smoke_Serialization_ConversionLayerTest, ConversionLayerTest, + ::testing::Combine(::testing::ValuesIn(conversionOpTypes), + ::testing::Values(inShape), ::testing::ValuesIn(precisions), ::testing::ValuesIn(precisions), ::testing::Values(InferenceEngine::Layout::ANY), ::testing::Values(InferenceEngine::Layout::ANY), ::testing::Values(CommonTestUtils::DEVICE_CPU)), - ConvertLayerTest::getTestCaseName); + ConversionLayerTest::getTestCaseName); -} // namespace \ No newline at end of file +} // namespace diff --git a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/single_layer_tests/conversion.cpp b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/single_layer_tests/conversion.cpp new file mode 100644 index 00000000000..03be6f86285 --- /dev/null +++ b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/single_layer_tests/conversion.cpp @@ -0,0 +1,50 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include + +#include "common_test_utils/test_constants.hpp" +#include "single_layer_tests/conversion.hpp" + +using namespace LayerTestsDefinitions; + +namespace { +const std::vector conversionOpTypes = { + ngraph::helpers::ConversionTypes::CONVERT, + ngraph::helpers::ConversionTypes::CONVERT_LIKE, +}; + +const std::vector> inShape = {{1, 2, 3, 4}}; + +const std::vector netPrecisions = { + // Ticket: 59594 + // InferenceEngine::Precision::I4, + InferenceEngine::Precision::I8, + InferenceEngine::Precision::I16, + InferenceEngine::Precision::I32, + InferenceEngine::Precision::I64, + // Ticket: 59594 + // InferenceEngine::Precision::BIN, + // InferenceEngine::Precision::BOOL, + // InferenceEngine::Precision::U4, + InferenceEngine::Precision::U8, + InferenceEngine::Precision::U16, + // Ticket: 59594 + // InferenceEngine::Precision::U32, + InferenceEngine::Precision::U64, + InferenceEngine::Precision::BF16, + InferenceEngine::Precision::FP16, + InferenceEngine::Precision::FP32}; + +INSTANTIATE_TEST_SUITE_P(smoke_ConversionLayerTest, + ConversionLayerTest, + ::testing::Combine(::testing::ValuesIn(conversionOpTypes), + ::testing::Values(inShape), + ::testing::ValuesIn(netPrecisions), + ::testing::ValuesIn(netPrecisions), + ::testing::Values(InferenceEngine::Layout::ANY), + ::testing::Values(InferenceEngine::Layout::ANY), + ::testing::Values(CommonTestUtils::DEVICE_CPU)), + ConversionLayerTest::getTestCaseName); +} // namespace diff --git a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/single_layer_tests/convert.cpp b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/single_layer_tests/convert.cpp deleted file mode 100644 index e7ac96b6540..00000000000 --- a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/single_layer_tests/convert.cpp +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright (C) 2018-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#include - -#include "single_layer_tests/convert.hpp" -#include "common_test_utils/test_constants.hpp" - -using namespace LayerTestsDefinitions; -using namespace InferenceEngine; - -namespace { -const std::vector> inShape = {{1, 2, 3, 4}}; - -const std::vector precisions = { - // Ticket: 59594 - // Precision::I4, - Precision::I8, - Precision::I16, - Precision::I32, - Precision::I64, - // Ticket: 59594 - // Precision::BIN, - // Precision::BOOL, - // Precision::U4, - Precision::U8, - Precision::U16, - // Ticket: 59594 - // Precision::U32, - Precision::U64, - Precision::BF16, - Precision::FP16, - Precision::FP32 -}; - -INSTANTIATE_TEST_SUITE_P(smoke_ConvertLayerTest, ConvertLayerTest, - ::testing::Combine( - ::testing::Values(inShape), - ::testing::ValuesIn(precisions), - ::testing::ValuesIn(precisions), - ::testing::Values(Layout::ANY), - ::testing::Values(Layout::ANY), - ::testing::Values(CommonTestUtils::DEVICE_CPU)), - ConvertLayerTest::getTestCaseName); - -} // namespace diff --git a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/single_layer_tests/convert_like.cpp b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/single_layer_tests/convert_like.cpp deleted file mode 100644 index f9e20dcf0de..00000000000 --- a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/single_layer_tests/convert_like.cpp +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (C) 2018-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#include - -#include "single_layer_tests/convert_like.hpp" -#include "common_test_utils/test_constants.hpp" - -using namespace LayerTestsDefinitions; - -namespace { -const std::vector> inShape = {{1, 2, 3, 4}}; - -const std::vector netPrecisions = { - InferenceEngine::Precision::FP32, - InferenceEngine::Precision::FP16, - InferenceEngine::Precision::U8, - InferenceEngine::Precision::I8, -}; - -INSTANTIATE_TEST_SUITE_P(smoke_NoReshape, ConvertLikeLayerTest, - ::testing::Combine( - ::testing::Values(inShape), - ::testing::ValuesIn(netPrecisions), - ::testing::Values(inShape), - ::testing::ValuesIn(netPrecisions), - ::testing::Values(InferenceEngine::Layout::ANY), - ::testing::Values(InferenceEngine::Layout::ANY), - ::testing::Values(CommonTestUtils::DEVICE_CPU)), - ConvertLikeLayerTest::getTestCaseName); - -} // namespace \ No newline at end of file diff --git a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/skip_tests_config.cpp b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/skip_tests_config.cpp index e3b6c8e1a15..be837c29702 100644 --- a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/skip_tests_config.cpp +++ b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/skip_tests_config.cpp @@ -29,8 +29,8 @@ std::vector disabledTestPatterns() { R"(.*InferRequestPreprocessDynamicallyInSetBlobTest.*oPRC=0.*_oLT=1.*)", // TODO: Issue: 34348 R"(.*IEClassGetAvailableDevices.*)", - // TODO: Issue: 25533 - R"(.*ConvertLikeLayerTest.*)", + // TODO: Issue: 63469 + R"(.*ConversionLayerTest.*ConvertLike.*)", // TODO: Issue: 34055 R"(.*ShapeOfLayerTest.*)", R"(.*ReluShapeOfSubgraphTest.*)", diff --git a/inference-engine/tests/functional/plugin/cpu/single_layer_tests/convert.cpp b/inference-engine/tests/functional/plugin/cpu/single_layer_tests/conversion.cpp similarity index 63% rename from inference-engine/tests/functional/plugin/cpu/single_layer_tests/convert.cpp rename to inference-engine/tests/functional/plugin/cpu/single_layer_tests/conversion.cpp index 3a8d3a920e2..b41ea5a889c 100644 --- a/inference-engine/tests/functional/plugin/cpu/single_layer_tests/convert.cpp +++ b/inference-engine/tests/functional/plugin/cpu/single_layer_tests/conversion.cpp @@ -2,26 +2,31 @@ // SPDX-License-Identifier: Apache-2.0 // -#include +#include using namespace LayerTestsDefinitions; using namespace InferenceEngine; namespace CPULayerTestsDefinitions { -class ConvertCPULayerTest : public ConvertLayerTest {}; +class ConvertCPULayerTest : public ConversionLayerTest {}; TEST_P(ConvertCPULayerTest, CompareWithRefs) { SKIP_IF_CURRENT_TEST_IS_DISABLED() - ConvertParamsTuple params = GetParam(); - inPrc = std::get<1>(params); - outPrc = std::get<2>(params); + ConversionParamsTuple params = GetParam(); + inPrc = std::get<2>(params); + outPrc = std::get<3>(params); Run(); } namespace { +const std::vector conversionOpTypes = { + ngraph::helpers::ConversionTypes::CONVERT, + ngraph::helpers::ConversionTypes::CONVERT_LIKE, +}; + const std::vector> inShape = {{1, 2, 3, 4}}; // List of precisions natively supported by mkldnn. @@ -33,24 +38,26 @@ const std::vector precisions = { Precision::BF16 }; -INSTANTIATE_TEST_SUITE_P(smoke_ConvertLayerTest_From_BF16, ConvertCPULayerTest, +INSTANTIATE_TEST_SUITE_P(smoke_ConversionLayerTest_From_BF16, ConvertCPULayerTest, ::testing::Combine( + ::testing::ValuesIn(conversionOpTypes), ::testing::Values(inShape), ::testing::Values(Precision::BF16), ::testing::ValuesIn(precisions), ::testing::Values(Layout::ANY), ::testing::Values(Layout::ANY), ::testing::Values(CommonTestUtils::DEVICE_CPU)), - ConvertLayerTest::getTestCaseName); + ConversionLayerTest::getTestCaseName); -INSTANTIATE_TEST_SUITE_P(smoke_ConvertLayerTest_To_BF16, ConvertCPULayerTest, +INSTANTIATE_TEST_SUITE_P(smoke_ConversionLayerTest_To_BF16, ConvertCPULayerTest, ::testing::Combine( + ::testing::ValuesIn(conversionOpTypes), ::testing::Values(inShape), ::testing::ValuesIn(precisions), ::testing::Values(Precision::BF16), ::testing::Values(Layout::ANY), ::testing::Values(Layout::ANY), ::testing::Values(CommonTestUtils::DEVICE_CPU)), - ConvertLayerTest::getTestCaseName); + ConversionLayerTest::getTestCaseName); } // namespace -} // namespace CPULayerTestsDefinitions \ No newline at end of file +} // namespace CPULayerTestsDefinitions diff --git a/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/single_layer_tests/convert.cpp b/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/single_layer_tests/conversion.cpp similarity index 70% rename from inference-engine/tests/functional/plugin/gpu/shared_tests_instances/single_layer_tests/convert.cpp rename to inference-engine/tests/functional/plugin/gpu/shared_tests_instances/single_layer_tests/conversion.cpp index e404be39af6..41df370e47b 100644 --- a/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/single_layer_tests/convert.cpp +++ b/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/single_layer_tests/conversion.cpp @@ -4,12 +4,17 @@ #include -#include "single_layer_tests/convert.hpp" +#include "single_layer_tests/conversion.hpp" #include "common_test_utils/test_constants.hpp" using namespace LayerTestsDefinitions; namespace { +const std::vector conversionOpTypes = { + ngraph::helpers::ConversionTypes::CONVERT, + ngraph::helpers::ConversionTypes::CONVERT_LIKE, +}; + const std::vector> inShape = {{1, 2, 3, 4}}; const std::vector netPrecisions = { @@ -19,14 +24,15 @@ const std::vector netPrecisions = { InferenceEngine::Precision::I8, }; -INSTANTIATE_TEST_SUITE_P(smoke_NoReshape, ConvertLayerTest, +INSTANTIATE_TEST_SUITE_P(smoke_NoReshape, ConversionLayerTest, ::testing::Combine( + ::testing::ValuesIn(conversionOpTypes), ::testing::Values(inShape), ::testing::ValuesIn(netPrecisions), ::testing::ValuesIn(netPrecisions), ::testing::Values(InferenceEngine::Layout::ANY), ::testing::Values(InferenceEngine::Layout::ANY), ::testing::Values(CommonTestUtils::DEVICE_GPU)), - ConvertLayerTest::getTestCaseName); + ConversionLayerTest::getTestCaseName); } // namespace diff --git a/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/single_layer_tests/convert_like.cpp b/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/single_layer_tests/convert_like.cpp deleted file mode 100644 index c55dc9d85bd..00000000000 --- a/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/single_layer_tests/convert_like.cpp +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (C) 2018-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#include - -#include "single_layer_tests/convert_like.hpp" -#include "common_test_utils/test_constants.hpp" - -using namespace LayerTestsDefinitions; - -namespace { -const std::vector> inShape = {{1, 2, 3, 4}}; - -const std::vector netPrecisions = { - InferenceEngine::Precision::FP32, - InferenceEngine::Precision::FP16, - InferenceEngine::Precision::U8, - InferenceEngine::Precision::I8, -}; - -INSTANTIATE_TEST_SUITE_P(smoke_NoReshape, ConvertLikeLayerTest, - ::testing::Combine( - ::testing::Values(inShape), - ::testing::ValuesIn(netPrecisions), - ::testing::Values(inShape), - ::testing::ValuesIn(netPrecisions), - ::testing::Values(InferenceEngine::Layout::ANY), - ::testing::Values(InferenceEngine::Layout::ANY), - ::testing::Values(CommonTestUtils::DEVICE_GPU)), - ConvertLikeLayerTest::getTestCaseName); - -} // namespace diff --git a/inference-engine/tests/functional/plugin/shared/include/single_layer_tests/convert_like.hpp b/inference-engine/tests/functional/plugin/shared/include/single_layer_tests/conversion.hpp similarity index 50% rename from inference-engine/tests/functional/plugin/shared/include/single_layer_tests/convert_like.hpp rename to inference-engine/tests/functional/plugin/shared/include/single_layer_tests/conversion.hpp index e4baa2315b9..18396e4ed99 100644 --- a/inference-engine/tests/functional/plugin/shared/include/single_layer_tests/convert_like.hpp +++ b/inference-engine/tests/functional/plugin/shared/include/single_layer_tests/conversion.hpp @@ -4,12 +4,10 @@ #pragma once -#include "shared_test_classes/single_layer/convert_like.hpp" +#include "shared_test_classes/single_layer/conversion.hpp" namespace LayerTestsDefinitions { - -TEST_P(ConvertLikeLayerTest, CompareWithRefs) { +TEST_P(ConversionLayerTest, CompareWithRefs) { Run(); }; - -} // namespace LayerTestsDefinitions \ No newline at end of file +} // namespace LayerTestsDefinitions diff --git a/inference-engine/tests/functional/plugin/shared/include/single_layer_tests/convert.hpp b/inference-engine/tests/functional/plugin/shared/include/single_layer_tests/convert.hpp index 81e61f78234..02bd6dd05fc 100644 --- a/inference-engine/tests/functional/plugin/shared/include/single_layer_tests/convert.hpp +++ b/inference-engine/tests/functional/plugin/shared/include/single_layer_tests/convert.hpp @@ -4,6 +4,9 @@ #pragma once +#include +IE_SUPPRESS_DEPRECATED_START + #include "shared_test_classes/single_layer/convert.hpp" namespace LayerTestsDefinitions { @@ -12,4 +15,6 @@ TEST_P(ConvertLayerTest, CompareWithRefs) { Run(); }; -} // namespace LayerTestsDefinitions \ No newline at end of file +} // namespace LayerTestsDefinitions + +IE_SUPPRESS_DEPRECATED_END diff --git a/inference-engine/tests/functional/shared_test_classes/include/shared_test_classes/single_layer/comparison.hpp b/inference-engine/tests/functional/shared_test_classes/include/shared_test_classes/single_layer/comparison.hpp index 1335d721eff..cfa0ae928d9 100644 --- a/inference-engine/tests/functional/shared_test_classes/include/shared_test_classes/single_layer/comparison.hpp +++ b/inference-engine/tests/functional/shared_test_classes/include/shared_test_classes/single_layer/comparison.hpp @@ -36,6 +36,6 @@ protected: void SetUp() override; public: - static std::string getTestCaseName(testing::TestParamInfo obj); + static std::string getTestCaseName(const testing::TestParamInfo &obj); }; } // namespace LayerTestsDefinitions diff --git a/inference-engine/tests/functional/shared_test_classes/include/shared_test_classes/single_layer/conversion.hpp b/inference-engine/tests/functional/shared_test_classes/include/shared_test_classes/single_layer/conversion.hpp new file mode 100644 index 00000000000..093ad7fa07e --- /dev/null +++ b/inference-engine/tests/functional/shared_test_classes/include/shared_test_classes/single_layer/conversion.hpp @@ -0,0 +1,39 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +#include + +#include +#include + +#include "common_test_utils/common_utils.hpp" +#include "common_test_utils/test_common.hpp" +#include "common_test_utils/test_constants.hpp" +#include "ie_core.hpp" + +namespace LayerTestsDefinitions { + +static std::map conversionNames = { + {ngraph::helpers::ConversionTypes::CONVERT, "Convert"}, + {ngraph::helpers::ConversionTypes::CONVERT_LIKE, "ConvertLike"}}; + +using ConversionParamsTuple = typename std::tuple>, // Input1 shapes + InferenceEngine::Precision, // Input1 precision + InferenceEngine::Precision, // Input2 precision + InferenceEngine::Layout, // Input layout + InferenceEngine::Layout, // Output layout + std::string>; // Device name + +class ConversionLayerTest : public testing::WithParamInterface, + virtual public LayerTestsUtils::LayerTestsCommon { +public: + static std::string getTestCaseName(const testing::TestParamInfo& obj); + +protected: + void SetUp() override; +}; +} // namespace LayerTestsDefinitions diff --git a/inference-engine/tests/functional/shared_test_classes/include/shared_test_classes/single_layer/convert.hpp b/inference-engine/tests/functional/shared_test_classes/include/shared_test_classes/single_layer/convert.hpp index a50b1d2d6a9..545d85e7752 100644 --- a/inference-engine/tests/functional/shared_test_classes/include/shared_test_classes/single_layer/convert.hpp +++ b/inference-engine/tests/functional/shared_test_classes/include/shared_test_classes/single_layer/convert.hpp @@ -23,8 +23,10 @@ using ConvertParamsTuple = typename std::tuple< InferenceEngine::Layout, // Output layout std::string>; // Device name -class ConvertLayerTest : public testing::WithParamInterface, - virtual public LayerTestsUtils::LayerTestsCommon { +class INFERENCE_ENGINE_DEPRECATED("This class is deprecated and will be removed soon. " + "Please use new ConversionLayerTest class.") ConvertLayerTest : + public testing::WithParamInterface, + virtual public LayerTestsUtils::LayerTestsCommon { public: static std::string getTestCaseName(const testing::TestParamInfo &obj); @@ -32,4 +34,4 @@ protected: void SetUp() override; }; -} // namespace LayerTestsDefinitions \ No newline at end of file +} // namespace LayerTestsDefinitions diff --git a/inference-engine/tests/functional/shared_test_classes/include/shared_test_classes/single_layer/convert_like.hpp b/inference-engine/tests/functional/shared_test_classes/include/shared_test_classes/single_layer/convert_like.hpp index d7872ac1d93..12d72d8a770 100644 --- a/inference-engine/tests/functional/shared_test_classes/include/shared_test_classes/single_layer/convert_like.hpp +++ b/inference-engine/tests/functional/shared_test_classes/include/shared_test_classes/single_layer/convert_like.hpp @@ -24,8 +24,10 @@ using ConvertLikeParamsTuple = typename std::tuple< InferenceEngine::Layout, // Output layout std::string>; // Device name -class ConvertLikeLayerTest : public testing::WithParamInterface, - virtual public LayerTestsUtils::LayerTestsCommon { +class INFERENCE_ENGINE_DEPRECATED("This class is deprecated and will be removed soon. " + "Please use new ConversionLayerTest class.") ConvertLikeLayerTest : + public testing::WithParamInterface, + virtual public LayerTestsUtils::LayerTestsCommon { public: static std::string getTestCaseName(const testing::TestParamInfo &obj); @@ -33,4 +35,4 @@ protected: void SetUp() override; }; -} // namespace LayerTestsDefinitions \ No newline at end of file +} // namespace LayerTestsDefinitions diff --git a/inference-engine/tests/functional/shared_test_classes/src/single_layer/comparison.cpp b/inference-engine/tests/functional/shared_test_classes/src/single_layer/comparison.cpp index 1f2981b35ac..8092f41f6e5 100644 --- a/inference-engine/tests/functional/shared_test_classes/src/single_layer/comparison.cpp +++ b/inference-engine/tests/functional/shared_test_classes/src/single_layer/comparison.cpp @@ -8,7 +8,7 @@ using namespace LayerTestsDefinitions::ComparisonParams; namespace LayerTestsDefinitions { -std::string ComparisonLayerTest::getTestCaseName(testing::TestParamInfo obj) { +std::string ComparisonLayerTest::getTestCaseName(const testing::TestParamInfo &obj) { InputShapesTuple inputShapes; InferenceEngine::Precision ngInputsPrecision; ngraph::helpers::ComparisonTypes comparisonOpType; diff --git a/inference-engine/tests/functional/shared_test_classes/src/single_layer/conversion.cpp b/inference-engine/tests/functional/shared_test_classes/src/single_layer/conversion.cpp new file mode 100644 index 00000000000..0c5e7a387a7 --- /dev/null +++ b/inference-engine/tests/functional/shared_test_classes/src/single_layer/conversion.cpp @@ -0,0 +1,45 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "shared_test_classes/single_layer/conversion.hpp" + +#include "ngraph_functions/builders.hpp" + +namespace LayerTestsDefinitions { + +std::string ConversionLayerTest::getTestCaseName(const testing::TestParamInfo& obj) { + ngraph::helpers::ConversionTypes conversionOpType; + InferenceEngine::Precision inputPrecision, targetPrecision; + InferenceEngine::Layout inLayout, outLayout; + std::string targetName; + std::vector> inputShape; + std::tie(conversionOpType, inputShape, inputPrecision, targetPrecision, inLayout, outLayout, targetName) = + obj.param; + std::ostringstream result; + result << "conversionOpType=" << conversionNames[conversionOpType] << "_"; + result << "IS=" << CommonTestUtils::vec2str(inputShape) << "_"; + result << "inputPRC=" << inputPrecision.name() << "_"; + result << "targetPRC=" << targetPrecision.name() << "_"; + result << "inL=" << inLayout << "_"; + result << "outL=" << outLayout << "_"; + result << "trgDev=" << targetName; + return result.str(); +} + +void ConversionLayerTest::SetUp() { + ngraph::helpers::ConversionTypes conversionOpType; + InferenceEngine::Precision inputPrecision, targetPrecision; + std::vector> inputShape; + std::tie(conversionOpType, inputShape, inputPrecision, targetPrecision, inLayout, outLayout, targetDevice) = + GetParam(); + + auto ngPrc = FuncTestUtils::PrecisionUtils::convertIE2nGraphPrc(inputPrecision); + auto targetPrc = FuncTestUtils::PrecisionUtils::convertIE2nGraphPrc(targetPrecision); + auto params = ngraph::builder::makeParams(ngPrc, inputShape); + auto conversion = ngraph::builder::makeConversion(params.front(), targetPrc, conversionOpType); + + ngraph::ResultVector results{std::make_shared(conversion)}; + function = std::make_shared(results, params, "Conversion"); +} +} // namespace LayerTestsDefinitions diff --git a/inference-engine/tests/functional/shared_test_classes/src/single_layer/convert.cpp b/inference-engine/tests/functional/shared_test_classes/src/single_layer/convert.cpp index 17c23818fe9..01def7670cc 100644 --- a/inference-engine/tests/functional/shared_test_classes/src/single_layer/convert.cpp +++ b/inference-engine/tests/functional/shared_test_classes/src/single_layer/convert.cpp @@ -2,6 +2,9 @@ // SPDX-License-Identifier: Apache-2.0 // +#include +IE_SUPPRESS_DEPRECATED_START + #include "shared_test_classes/single_layer/convert.hpp" namespace LayerTestsDefinitions { @@ -33,4 +36,6 @@ void ConvertLayerTest::SetUp() { ngraph::ResultVector results{std::make_shared(convert)}; function = std::make_shared(results, params, "Convert"); } -} // namespace LayerTestsDefinitions \ No newline at end of file +} // namespace LayerTestsDefinitions + +IE_SUPPRESS_DEPRECATED_END diff --git a/inference-engine/tests/functional/shared_test_classes/src/single_layer/convert_like.cpp b/inference-engine/tests/functional/shared_test_classes/src/single_layer/convert_like.cpp index d08d402c81e..8f2a92b78af 100644 --- a/inference-engine/tests/functional/shared_test_classes/src/single_layer/convert_like.cpp +++ b/inference-engine/tests/functional/shared_test_classes/src/single_layer/convert_like.cpp @@ -2,6 +2,9 @@ // SPDX-License-Identifier: Apache-2.0 // +#include +IE_SUPPRESS_DEPRECATED_START + #include "shared_test_classes/single_layer/convert_like.hpp" namespace LayerTestsDefinitions { @@ -35,4 +38,6 @@ void ConvertLikeLayerTest::SetUp() { ngraph::ResultVector results{std::make_shared(convertLike)}; function = std::make_shared(results, params, "ConvertLike"); } -} // namespace LayerTestsDefinitions \ No newline at end of file +} // namespace LayerTestsDefinitions + +IE_SUPPRESS_DEPRECATED_END From 3775dad345606b3db22d6cbe226ddb992f92ca16 Mon Sep 17 00:00:00 2001 From: Evgeny Lazarev Date: Wed, 1 Sep 2021 14:35:06 +0300 Subject: [PATCH 71/76] MO dynamic shapes support (#5918) * Allow MO to generate IR with -1 in dimensions * Some fixes to support -1 for StridedSlice operation * Updated TensorArrayGatherV3 shape infer to support dynamic output shape * Several fixes to support undefined dimensions in the Broadcast,Reshape,Slice and Tile * Fixed bug in the normalization transformation of TF NMS to opset NMS * Updated shape infer functions related to StridedSlice and NMS * Updated Select shape inference function to use common shape broadcasting function supporting dynamism * Fixed operation TFResize shape infer function to work correctly for case when model is converted with --disable_nhwc_to_nchw * Dynamic Range and update asserts in NMS * Changed the way how dynamic dimensions are specified. Refactored shape inference functions and common places to use new approach * More fixes to support dynamic shapes * More fixes for support of dynamic shapes * Fixed generation of IR with dynamic dimensions * Allow reading IRs with undefined dimensions * More changes in the IE to support dynamic dimensions * Fixes for Switch, Merge, Concat shape and value infer related to dynamism * Fixed TensorArray related ops to properly handle dynamic dimensions. Fixed StridedSlice infer for case with new_axis * Fixed shape_for_layout function to generate masked array * Fixed shape inference for Convolution and Poolings to support dynamic spatial dimensions * Updated shape infer functions for CTCGreedyDecotder, CTCLoss and Enter * Fixed shape inference with dynamic dimensions for MatMul, Split, Upsample, SpaceToBatch, some fixes for the TI * Fixes for undefined dimensions support for Proposal and DetectionOutput * Fixed ExtractImagePatches, DepthToSpace and RegionYolo shape infer functions to work with partially dynamic dimensions * Changes in tf_window_op_pad_infer to better work with dynamic dimensions * Fixed output shape calculation for StridedSlice operation * More StridedSlice fixes * Fixed resolve_convolution_with_group * Fixed unit tests * Fixed unit tests * Fixed Switch op unit tests * Fixed shape inference for Upsample operation * Updated unit tests for the Concat operation * Fixed eltwise shape infer unit tests * Fixed shape infer tests for Convolution and DetectionOutput ops * Fixed Crop shape infer function tests * Fixed Slice op unit test and minor fix in the shape inference. Fixed emitter * Updated unit test for telemetry and match_shape function for dynamism * Fixed unit test for the DetectionOutput * Added support for the TF ClipByValue operation * Fixed GatherND shape inference for dynamic shapes support * Dynamic shapes support for the MO IR Reader * Fixed BlockLSTM operation to not work as an extractor * Allow to serialize IRs with partially defined shapes * Updated SelectBroadcast transformation to not check shape values * Fixed MO IR comparator * Fixed SS value propagation when slices are dynamic * Do not re-run graph clean-up for ProposalMutation * Fixed InterpolateSequenceToInterpolate transformation to support dynamic dimensions * Fixed Loop iteration count calculation and reading IteratorGetNext shapes * Fixed unit test for serialization * Fixed serialization test * Fixed RandomUniform shape infer * Fixed several transformations related to RNN to respect dynamic output shapes * Fixed Deconvolutin shape calculation for dynamic batch. Eltwise shape infer improvements * Fixed shape infer functions for ExperimentalDetectron ops, reverted changes for NonZero and removed debug prints * Fixed check for dynamism of a list, fixed value propagation for Concat op and remove redundant shape infer for reshape * Update Eltwise value propagation to use np.ma * Fixed ExpandDims shape infer function * Shape infer functions fixes and improvements * Remove Accum op from the MO * Updated activation functions shape infer * Removed unsupported operation Correlation * Fixed shape infers for several functions * Removed unsupported DataAugmentation operation * Fixed shape infer functions for several ops in extensions directory * Removed not-support operation PowerFile * Removed unsupported SpatialTransformer,SimplerNMS and PredictionHeatmap operations * More shape infer functions updates * Merge shape infer fix * Fixed typo * Fixed TensorArraySize shape infer function * Fixed VariadicSplit and Squeeze shape infer * Fixed ONNX models Parameter extractor * Updated Select value propagation for the dynamic case * Fixed ReorgYolo shape infer and test * Removed unnecessary tests * Fixed Tile shape infer * Fixed SparseFillEmptryRows unit tests * Fixed package bom * Added extractor for the TF operation Mod * Fixed value propagation for MatMul operation * Updated Parameter extender to generate shape_array when shape is partially defined only * Fixed BOM file * Fixed issue with the TF OD API models and DetectionOutput op. Now the shape infer function for the DO do not re-infer "num_classes" attribute value if it is already known * Fixed unit test for the DO infer * Fixed num classes calculation for the DO generation for Faster/Mask-RCNN models * Changed NMS op to produce static output shape * Restore dynamic output shape calculation for the NMS for NMS-5 * Fixed CellNormalizer transformation. It should work for static shapes only * RNNCell Op class fixes * Revert some changes * Updated documentation with a list of supported operations * Revert changes * Fixes for the ConstantFill op * Removed redundant SequenceLengthToMask transformation * TensorArray* ops shape infer code style and refactoring * Reverse some unnecessary changes in the ConvolutionNormalizer * Fixes and unit tests for shape_array, compare_shapes, is_fully_defined functions * Implemented shape_insert, shape_delete functions and tests for them * Modified code to use shape_delete function * Added usage of shape_insert function where necessary * Use shape_insert function in many places * Some fixes in shape inference for various ops * Updated shape_delete function to support negative indices * Changes and unit tests for the MatMul infer function * Removed strange code from the TF Merge infer function * Merge op shape infer fixes * Fixed value propagation in the transformation EltwiseInputReshape.py for the dynamic dimension case * Code cleanup * Updated GatherND to support dynamic dimensions * Minor fixes * Fixed shape_insert and shape_delete to support np.int64 and np.int32 types * Updated Upsample operation unit tests with dynamic input shapes * Minor change in the extensions/back/ConvolutionNormalizer.py to make sure that input dimensions are static * Fixed ConvertGroupedStridedSlice transformation and added unit tests * Revert debug changes * Fixed value propagation for Unsqueeze to work with partially defined input values * Typo fix * Added unit tests for the Unsqueeze op shape infer * broadcasting functions changes and unit tests * Fixed Tile value inference for partially defined input tensor * Unit tests for Split and VariadicSplit ops * Fixes for the Concat infer + unit tests * Removed redundant tf_pack shape infer * Fixed Concat value infer and added unit tests * Fixed StridedSlice shape inference for case with dynamic slices * Fixes related to StridedSlice shape infer, changes in tests * Unit tests for the eltwise shape and value infer * Fixed Pad op value propagation to allow dynamic input values to be propagated * Unit test for Pooling dynamic input shape infer * Squeeze op unit tests for dynamic input shape * Added assert to the Squeeze op shape infer for case when squeeze dimension is dynamic value * Added message to the MO when input shapes are dynamic * Convolution dynamic unit test * Removed redundant transformation GroupedConvWeightsNormalize * Removed non-ascii character from the message * Fixed typo in the BOM file * Code style and comment fixes * Fixed copy-paste issue in the DO shape infer function * Fixed setting dynamic shape in the MO command line * Added function to compare tensor with dynamic values. Fixes in the unit tests and shape infer functions * Improved Reshape shape infer + added unit tests * Fixed value propagation for Select op * Renamed several internal functions, minor code fixes. * Code style fixes * Modified condition in the _set_shape method of the Port class to not check shape if the "override_output_shape" attribute is specified * Fixed constant value propagation for ReduceOps when inputs have dynamic values. Added unit test * Fixed shape infer for the Loop for dynamic dimensions case * Fix in the NMS shape infer to avoid ragged numpy array generation. Fixed Scatter shape infer validation * Improved shapes infer for eltwise ops with respect to dynamic dimensions * Changed code comments * Renamed tensor names in the ClipByValueTFTransformation * Changed np.ma.allequal to strict_compare_tensors in the Merge op infer * Chanded np.ma.allequal with strict_compare_tensor. * Fixed Merge op value infer * Fixed debug code * Removed commented line * Updated condition to check for dynamic shapes in the Partial infer to not fail for MxNet models * Improvements to the get_shape_from_slice and is_dynamic_slice functions * Reverted change in the `normalize_slices_attr` for ellipsis mask case * Updated shape conditions in the ScatterNDBase op to support dynamic dimensions * Crop op file refactoring * Set "type" attribute to None for SparseFillEmptyRows op which is not from any opset * Removed unnecessary extractor test * Restored Crop operation type * Removed "type" attribute from the Crop operation and updated the MO code to find Crop by "op" attribute * Fixed If shape infer function to produce dynamic dimensions * Updated If shape and value infer to properly work when condition is static * Fixed fusing transformation check to work with dynamic dimensions. Change comparison in the shape_inference function to not use strict shapes comparison * Optimize imports in the LayerNorm * ConvertGroupedStridedSlice minor fixes related to dynamism support * Fixed ConvertGroupedStridedSlice to properly check if the dimension is sliced --- .../Supported_Frameworks_Layers.md | 2 + .../ir_serialization/cleanup.cpp | 2 +- model-optimizer/automation/package_BOM.txt | 20 +- .../extensions/back/CellNormalizer.py | 4 +- .../extensions/back/ConvolutionNormalizer.py | 24 +-- .../extensions/back/CropToStridedSlice.py | 2 +- .../extensions/back/FakeOutputResolver.py | 2 +- .../back/GroupedConvWeightsNormalize.py | 38 ---- .../extensions/back/ProposalMutation.py | 2 +- .../extensions/back/ReverseInputChannels.py | 4 - .../extensions/back/SelectBroadcast.py | 5 - .../back/disable_unsupported_ND_operations.py | 35 --- .../extensions/back/op_versioning.py | 2 - model-optimizer/extensions/front/LayerNorm.py | 2 +- .../extensions/front/caffe/accum_ext.py | 21 -- .../extensions/front/caffe/correlation_ext.py | 40 ---- .../extensions/front/caffe/crop_ext.py | 1 - .../front/caffe/data_augmentation_ext.py | 45 ---- .../extensions/front/caffe/power_file_ext.py | 22 -- .../extensions/front/caffe/simplernms_ext.py | 32 --- .../front/caffe/spatial_transformer_ext.py | 36 ---- .../extensions/front/onnx/fused_bn_ext.py | 3 - .../extensions/front/onnx/parameter_ext.py | 5 +- .../front/tf/ClipByValueTFTransformation.py | 27 +++ .../extensions/front/tf/ClipByValue_ext.py | 15 ++ .../front/tf/IteratorGetNext_ext.py | 6 +- .../extensions/front/tf/ObjectDetectionAPI.py | 3 +- .../front/tf/TFResizeToInterpolate.py | 11 +- .../front/tf/TensorArrayGatherV3.py | 2 +- .../extensions/front/tf/elementwise_ext.py | 12 +- .../front/tf/extract_image_patches_ext.py | 3 +- .../front/tf/non_max_suppression_normalize.py | 2 +- .../extensions/middle/AddMeanScaleValues.py | 3 +- .../extensions/middle/ApplyPermutations.py | 7 +- .../middle/ConvertGroupedStridedSlice.py | 25 ++- .../extensions/middle/CustomSubgraphCall.py | 17 +- .../DecomposeBidirectionalRNNSequence.py | 3 +- .../extensions/middle/DilatedConvolution.py | 3 +- .../extensions/middle/EltwiseChecker.py | 3 +- .../extensions/middle/EltwiseInputReshape.py | 6 +- .../middle/GRURNNSequenceToTensorIterator.py | 3 +- .../InterpolateSequenceToInterpolate.py | 6 +- .../middle/LSTMRNNSequenceToTensorIterator.py | 5 +- .../middle/MXNetRNNSequenceNormalize.py | 10 +- .../middle/MXNetSplitMultiLayers.py | 5 +- .../middle/ONNXRNNSequenceNormalize.py | 3 +- .../extensions/middle/PartialInfer.py | 19 ++ .../middle/RNNSequenceNormalizeToIE.py | 4 +- .../extensions/middle/SequenceLengthToMask.py | 50 ----- .../middle/StridedSliceNormalizer.py | 14 +- .../middle/TensorIteratorConditionChecker.py | 3 +- .../extensions/middle/TensorIteratorMerge.py | 6 +- model-optimizer/extensions/ops/BlockLSTM.py | 13 +- .../extensions/ops/ClipByValueTF.py | 21 ++ model-optimizer/extensions/ops/Enter.py | 13 +- .../extensions/ops/ExtractImagePatches.py | 7 +- model-optimizer/extensions/ops/GRUCell.py | 6 +- model-optimizer/extensions/ops/GatherTree.py | 14 +- model-optimizer/extensions/ops/If.py | 40 +++- model-optimizer/extensions/ops/LSTM.py | 4 +- .../extensions/ops/LookupTableInsert.py | 7 +- model-optimizer/extensions/ops/MatMul.py | 51 +++-- .../extensions/ops/ONNXResize11.py | 8 +- model-optimizer/extensions/ops/RNN.py | 18 +- model-optimizer/extensions/ops/RNNCell.py | 7 +- model-optimizer/extensions/ops/ReduceOps.py | 24 ++- model-optimizer/extensions/ops/Reverse.py | 19 +- model-optimizer/extensions/ops/TFResize.py | 9 +- model-optimizer/extensions/ops/TensorArray.py | 9 +- .../extensions/ops/TensorArrayGather.py | 15 +- .../extensions/ops/TensorArrayRead.py | 16 +- .../extensions/ops/TensorArrayScatter.py | 8 +- .../extensions/ops/TensorArraySize.py | 9 +- .../extensions/ops/TensorArrayWrite.py | 11 +- model-optimizer/extensions/ops/accum.py | 78 ------- .../extensions/ops/activation_ops.py | 48 ++--- model-optimizer/extensions/ops/argmax.py | 3 +- model-optimizer/extensions/ops/assert_op.py | 2 +- model-optimizer/extensions/ops/box_nms.py | 9 +- model-optimizer/extensions/ops/bucketize.py | 12 +- .../extensions/ops/constant_fill.py | 14 +- model-optimizer/extensions/ops/correlation.py | 66 ------ .../extensions/ops/ctc_greedy_decoder.py | 24 +-- .../ops/ctc_greedy_decoder_seq_len.py | 8 +- model-optimizer/extensions/ops/ctc_loss.py | 11 +- .../extensions/ops/data_augmentation.py | 53 ----- .../extensions/ops/depth_to_space.py | 18 +- .../extensions/ops/detectionoutput_onnx.py | 11 +- model-optimizer/extensions/ops/dft.py | 2 +- model-optimizer/extensions/ops/einsum.py | 8 +- model-optimizer/extensions/ops/elementwise.py | 38 ++-- .../extensions/ops/embedding_bag.py | 6 +- model-optimizer/extensions/ops/gather.py | 13 +- model-optimizer/extensions/ops/gathernd.py | 19 +- model-optimizer/extensions/ops/interpolate.py | 7 +- model-optimizer/extensions/ops/loop.py | 27 ++- model-optimizer/extensions/ops/lstm_cell.py | 12 +- .../extensions/ops/lstm_sequence.py | 16 +- model-optimizer/extensions/ops/merge.py | 23 +- model-optimizer/extensions/ops/mvn.py | 6 +- model-optimizer/extensions/ops/mxfft.py | 3 +- .../extensions/ops/non_max_suppression.py | 20 +- model-optimizer/extensions/ops/non_zero.py | 12 +- model-optimizer/extensions/ops/one_hot.py | 3 +- model-optimizer/extensions/ops/parameter.py | 3 +- model-optimizer/extensions/ops/pnorm.py | 6 +- model-optimizer/extensions/ops/power_file.py | 24 --- .../extensions/ops/prediction_heatmap.py | 32 --- model-optimizer/extensions/ops/priorbox.py | 4 +- .../extensions/ops/priorbox_clustered.py | 4 +- .../extensions/ops/priorgridgenerator_onnx.py | 20 +- model-optimizer/extensions/ops/proposal.py | 9 +- .../extensions/ops/proposal_onnx.py | 12 +- model-optimizer/extensions/ops/range.py | 14 +- model-optimizer/extensions/ops/regionyolo.py | 30 +-- model-optimizer/extensions/ops/reorgyolo.py | 13 +- model-optimizer/extensions/ops/resize.py | 10 +- .../extensions/ops/reverse_sequence.py | 10 +- model-optimizer/extensions/ops/roialign.py | 7 +- .../ops/roifeatureextractor_onnx.py | 16 +- model-optimizer/extensions/ops/scatter.py | 8 +- model-optimizer/extensions/ops/scatternd.py | 21 +- model-optimizer/extensions/ops/select.py | 38 ++-- model-optimizer/extensions/ops/simplernms.py | 71 ------ model-optimizer/extensions/ops/size.py | 6 +- model-optimizer/extensions/ops/slice_like.py | 5 +- .../extensions/ops/space_to_depth.py | 13 +- .../extensions/ops/sparse_fill_empty_rows.py | 60 +++--- .../extensions/ops/spatial_transformer.py | 47 ---- model-optimizer/extensions/ops/splice.py | 11 +- model-optimizer/extensions/ops/split.py | 15 +- .../extensions/ops/stop_gradient.py | 8 +- model-optimizer/extensions/ops/swapaxis.py | 4 +- model-optimizer/extensions/ops/switch.py | 33 ++- .../extensions/ops/tensor_iterator.py | 3 +- model-optimizer/extensions/ops/topk.py | 4 +- .../extensions/ops/topkrois_onnx.py | 10 +- model-optimizer/extensions/ops/transpose.py | 4 +- model-optimizer/extensions/ops/upsample.py | 42 ++-- .../mo/back/ie_ir_ver_2/emitter.py | 13 +- model-optimizer/mo/front/common/layout.py | 5 +- .../mo/front/common/partial_infer/concat.py | 55 +++-- .../mo/front/common/partial_infer/eltwise.py | 54 +++-- .../partial_infer/multi_box_detection.py | 43 ++-- .../common/partial_infer/random_uniform.py | 8 +- .../mo/front/common/partial_infer/reshape.py | 58 ----- .../front/common/partial_infer/roipooling.py | 10 +- .../mo/front/common/partial_infer/utils.py | 204 +++++++++++++++--- model-optimizer/mo/front/extractor.py | 29 ++- .../mo/front/mxnet/extractors/slice_axis.py | 2 +- .../mo/front/tf/extractors/fused_bn.py | 3 +- .../mo/front/tf/extractors/pack.py | 4 +- .../mo/front/tf/extractors/utils.py | 3 +- model-optimizer/mo/graph/graph.py | 2 - model-optimizer/mo/graph/port.py | 12 +- model-optimizer/mo/middle/passes/eliminate.py | 7 +- .../middle/passes/fusing/fuse_linear_seq.py | 14 +- model-optimizer/mo/middle/passes/infer.py | 21 +- model-optimizer/mo/ops/broadcast.py | 12 +- model-optimizer/mo/ops/concat.py | 4 +- model-optimizer/mo/ops/convolution.py | 50 ++--- model-optimizer/mo/ops/crop.py | 67 +++--- model-optimizer/mo/ops/deconvolution.py | 21 +- model-optimizer/mo/ops/eltwise.py | 22 +- model-optimizer/mo/ops/expand_dims.py | 36 ++-- model-optimizer/mo/ops/memory.py | 4 +- model-optimizer/mo/ops/op.py | 8 +- model-optimizer/mo/ops/pad.py | 13 +- model-optimizer/mo/ops/pooling.py | 10 +- model-optimizer/mo/ops/reshape.py | 46 +++- model-optimizer/mo/ops/result.py | 4 +- model-optimizer/mo/ops/shape.py | 3 +- model-optimizer/mo/ops/slice.py | 24 +-- model-optimizer/mo/ops/space_to_batch.py | 36 ++-- model-optimizer/mo/ops/squeeze.py | 28 +-- model-optimizer/mo/ops/strided_slice.py | 74 +++---- model-optimizer/mo/ops/tile.py | 12 +- model-optimizer/mo/ops/unsqueeze.py | 10 +- model-optimizer/mo/utils/broadcasting.py | 51 +++-- model-optimizer/mo/utils/cli_parser.py | 18 +- .../mo/utils/ir_engine/compare_graphs.py | 82 ++++--- .../mo/utils/ir_engine/ir_engine.py | 3 + .../ir_reader/extenders/parameter_extender.py | 4 +- model-optimizer/mo/utils/telemetry_utils.py | 9 +- model-optimizer/mo/utils/utils.py | 11 +- .../back/GatherTreeNormalizer_test.py | 49 +++++ .../back/compress_quantized_weights_test.py | 8 +- .../extensions/front/caffe/accum_ext_test.py | 55 ----- .../front/caffe/correlation_ext_test.py | 64 ------ .../extensions/front/caffe/crop_ext_test.py | 2 +- .../front/caffe/data_augmentation_ext_test.py | 81 ------- .../front/caffe/power_file_ext_test.py | 51 ----- .../front/caffe/simplernms_ext_test.py | 61 ------ .../caffe/spatial_transformer_ext_test.py | 68 ------ .../extensions/front/mxnet/crop_ext_test.py | 30 --- .../middle/ConvertGroupedStridedSlice_test.py | 43 +++- .../middle/SequenceLenthToMask_test.py | 54 ----- .../extensions/middle/quantize_fuses_test.py | 10 +- .../unit_tests/extensions/ops/If_test.py | 45 ++-- .../unit_tests/extensions/ops/MatMul_test.py | 14 +- .../extensions/ops/ReduceOps_test.py | 35 ++- .../unit_tests/extensions/ops/accum_test.py | 119 ---------- .../extensions/ops/correlation_test.py | 48 ----- .../extensions/ops/data_augmentation_test.py | 52 ----- .../extensions/ops/gathernd_test.py | 22 +- .../unit_tests/extensions/ops/merge_test.py | 2 +- .../extensions/ops/normalize_test.py | 2 +- .../extensions/ops/regionyolo_test.py | 30 ++- .../extensions/ops/reorgyolo_test.py | 4 +- .../unit_tests/extensions/ops/select_test.py | 72 ++----- .../extensions/ops/simplernms_test.py | 49 ----- .../extensions/ops/space_to_depth_test.py | 14 ++ .../ops/sparse_fill_empty_rows_test.py | 15 +- .../ops/spatial_transformer_test.py | 63 ------ .../unit_tests/extensions/ops/split_test.py | 58 ++++- .../unit_tests/extensions/ops/switch_test.py | 113 +++++----- .../extensions/ops/upsample_test.py | 31 +-- .../front/common/partial_infer/concat_test.py | 61 +++--- .../front/common/partial_infer/crop_test.py | 2 +- .../common/partial_infer/eltwise_test.py | 100 +++------ .../partial_infer/multi_box_detection_test.py | 77 +++++-- .../front/common/partial_infer/utils_test.py | 131 +++++++++++ .../unit_tests/mo/front/extractor_test.py | 5 +- .../front/mxnet/extractors/slice_axis_test.py | 2 +- .../passes/fusing/resnet_optimization_test.py | 6 - .../unit_tests/mo/ops/convolution_test.py | 78 ++++++- .../unit_tests/mo/ops/crop_test.py | 39 ++-- .../unit_tests/mo/ops/expand_dims_test.py | 22 ++ model-optimizer/unit_tests/mo/ops/pad_test.py | 28 ++- .../unit_tests/mo/ops/pooling_test.py | 29 ++- .../unit_tests/mo/ops/reshape_test.py | 93 ++++++++ .../unit_tests/mo/ops/slice_test.py | 91 +++++--- .../unit_tests/mo/ops/squeeze_test.py | 50 +++-- .../unit_tests/mo/ops/strided_slice_test.py | 47 +++- .../unit_tests/mo/ops/unsqueeze_test.py | 59 ++--- .../unit_tests/mo/utils/broadcasting_test.py | 62 +++++- .../mo/utils/ir_engine/ir_engine_test.py | 13 +- .../mo/utils/telemetry_utils_test.py | 10 +- .../unit_tests/mo/utils/utils_test.py | 28 +-- model-optimizer/unit_tests/utils/graph.py | 13 +- 240 files changed, 2669 insertions(+), 3093 deletions(-) delete mode 100644 model-optimizer/extensions/back/GroupedConvWeightsNormalize.py delete mode 100644 model-optimizer/extensions/back/disable_unsupported_ND_operations.py delete mode 100644 model-optimizer/extensions/front/caffe/accum_ext.py delete mode 100644 model-optimizer/extensions/front/caffe/correlation_ext.py delete mode 100644 model-optimizer/extensions/front/caffe/data_augmentation_ext.py delete mode 100644 model-optimizer/extensions/front/caffe/power_file_ext.py delete mode 100644 model-optimizer/extensions/front/caffe/simplernms_ext.py delete mode 100644 model-optimizer/extensions/front/caffe/spatial_transformer_ext.py create mode 100644 model-optimizer/extensions/front/tf/ClipByValueTFTransformation.py create mode 100644 model-optimizer/extensions/front/tf/ClipByValue_ext.py delete mode 100644 model-optimizer/extensions/middle/SequenceLengthToMask.py create mode 100644 model-optimizer/extensions/ops/ClipByValueTF.py delete mode 100644 model-optimizer/extensions/ops/accum.py delete mode 100644 model-optimizer/extensions/ops/correlation.py delete mode 100644 model-optimizer/extensions/ops/data_augmentation.py delete mode 100644 model-optimizer/extensions/ops/power_file.py delete mode 100644 model-optimizer/extensions/ops/prediction_heatmap.py delete mode 100644 model-optimizer/extensions/ops/simplernms.py delete mode 100644 model-optimizer/extensions/ops/spatial_transformer.py delete mode 100644 model-optimizer/mo/front/common/partial_infer/reshape.py create mode 100644 model-optimizer/unit_tests/extensions/back/GatherTreeNormalizer_test.py delete mode 100644 model-optimizer/unit_tests/extensions/front/caffe/accum_ext_test.py delete mode 100644 model-optimizer/unit_tests/extensions/front/caffe/correlation_ext_test.py delete mode 100644 model-optimizer/unit_tests/extensions/front/caffe/data_augmentation_ext_test.py delete mode 100644 model-optimizer/unit_tests/extensions/front/caffe/power_file_ext_test.py delete mode 100644 model-optimizer/unit_tests/extensions/front/caffe/simplernms_ext_test.py delete mode 100644 model-optimizer/unit_tests/extensions/front/caffe/spatial_transformer_ext_test.py delete mode 100644 model-optimizer/unit_tests/extensions/front/mxnet/crop_ext_test.py delete mode 100644 model-optimizer/unit_tests/extensions/middle/SequenceLenthToMask_test.py delete mode 100644 model-optimizer/unit_tests/extensions/ops/accum_test.py delete mode 100644 model-optimizer/unit_tests/extensions/ops/correlation_test.py delete mode 100644 model-optimizer/unit_tests/extensions/ops/data_augmentation_test.py delete mode 100644 model-optimizer/unit_tests/extensions/ops/simplernms_test.py delete mode 100644 model-optimizer/unit_tests/extensions/ops/spatial_transformer_test.py create mode 100644 model-optimizer/unit_tests/mo/front/common/partial_infer/utils_test.py create mode 100644 model-optimizer/unit_tests/mo/ops/reshape_test.py diff --git a/docs/MO_DG/prepare_model/Supported_Frameworks_Layers.md b/docs/MO_DG/prepare_model/Supported_Frameworks_Layers.md index fdda8f40a0b..a09df51a56a 100644 --- a/docs/MO_DG/prepare_model/Supported_Frameworks_Layers.md +++ b/docs/MO_DG/prepare_model/Supported_Frameworks_Layers.md @@ -179,6 +179,7 @@ Standard TensorFlow\* operations: | BroadcastTo | No | | Cast | No | | Ceil | No | +| ClipByValue | No | | Concat | No | | ConcatV2 | No | | Const | No | @@ -253,6 +254,7 @@ Standard TensorFlow\* operations: | Min | No | | Minimum | No | | MirrorPad | No | +| Mod | No | | Mul | No | | Neg | No | | NextIteration | Supported only when it is fused to the TensorIterator layer | diff --git a/inference-engine/tests/functional/inference_engine/ir_serialization/cleanup.cpp b/inference-engine/tests/functional/inference_engine/ir_serialization/cleanup.cpp index 734c96089cf..6cf426ba60b 100644 --- a/inference-engine/tests/functional/inference_engine/ir_serialization/cleanup.cpp +++ b/inference-engine/tests/functional/inference_engine/ir_serialization/cleanup.cpp @@ -56,4 +56,4 @@ TEST_F(SerializationCleanupTest, SerializationShouldWorkWithDynamicFunction) { // .xml & .bin files should be present ASSERT_TRUE(std::ifstream(m_out_xml_path, std::ios::in).good()); ASSERT_TRUE(std::ifstream(m_out_bin_path, std::ios::in).good()); -} \ No newline at end of file +} diff --git a/model-optimizer/automation/package_BOM.txt b/model-optimizer/automation/package_BOM.txt index 87976b57117..618f988a4c8 100644 --- a/model-optimizer/automation/package_BOM.txt +++ b/model-optimizer/automation/package_BOM.txt @@ -18,14 +18,12 @@ extensions/back/ConvolutionNormalizer.py extensions/back/CorrectName.py extensions/back/CropToStridedSlice.py extensions/back/CutMemory.py -extensions/back/disable_unsupported_ND_operations.py extensions/back/EnableConstantStridedSlice.py extensions/back/FakeOutputResolver.py extensions/back/ForceStrictPrecision.py extensions/back/fuse_sub_div_min.py extensions/back/FuseTransposesSequence.py extensions/back/GatherNormalizer.py -extensions/back/GroupedConvWeightsNormalize.py extensions/back/insert_compatibility_l2normalization.py extensions/back/InterpolateReshape.py extensions/back/kaldi_remove_memory_output.py @@ -75,7 +73,6 @@ extensions/front/AttributedRollToRoll.py extensions/front/binary_quantize_normalization.py extensions/front/broadcast_with_range.py extensions/front/caffe/__init__.py -extensions/front/caffe/accum_ext.py extensions/front/caffe/argmax_ext.py extensions/front/caffe/ArgMaxFlatten.py extensions/front/caffe/axpy.py @@ -86,11 +83,9 @@ extensions/front/caffe/bn.py extensions/front/caffe/bn_ext.py extensions/front/caffe/concat_ext.py extensions/front/caffe/conv_ext.py -extensions/front/caffe/correlation_ext.py extensions/front/caffe/crop_ext.py extensions/front/caffe/ctcgreedydecoder_ext.py extensions/front/caffe/CustomLayersMapping.xml.example -extensions/front/caffe/data_augmentation_ext.py extensions/front/caffe/detection_output.py extensions/front/caffe/dropout_ext.py extensions/front/caffe/elementwise_ext.py @@ -107,7 +102,6 @@ extensions/front/caffe/MVNCaffeToMVN.py extensions/front/caffe/normalize_ext.py extensions/front/caffe/permute_ext.py extensions/front/caffe/pooling_ext.py -extensions/front/caffe/power_file_ext.py extensions/front/caffe/prelu_ext.py extensions/front/caffe/priorbox_clustered_ext.py extensions/front/caffe/priorbox_ext.py @@ -124,11 +118,9 @@ extensions/front/caffe/roipooling_ext.py extensions/front/caffe/scale_ext.py extensions/front/caffe/shufflechannel_ext.py extensions/front/caffe/sigmoid.py -extensions/front/caffe/simplernms_ext.py extensions/front/caffe/slice_ext.py extensions/front/caffe/slice_to_split.py extensions/front/caffe/softmax_ext.py -extensions/front/caffe/spatial_transformer_ext.py extensions/front/caffe/split_to_identity.py extensions/front/caffe/tanh.py extensions/front/ChangePlaceholderTypes.py @@ -388,6 +380,8 @@ extensions/front/tf/broadcast_ext.py extensions/front/tf/bucketize.py extensions/front/tf/bucketize_ext.py extensions/front/tf/Cast_ext.py +extensions/front/tf/ClipByValue_ext.py +extensions/front/tf/ClipByValueTFTransformation.py extensions/front/tf/ComplexAbs.py extensions/front/tf/ComplexAbsAfterComplex.py extensions/front/tf/concat.py @@ -632,7 +626,6 @@ extensions/middle/ReverseTransposeNormalization.py extensions/middle/ReverseV2ToReverseSequence.py extensions/middle/RNNSequenceNormalizeToIE.py extensions/middle/ScaleInput.py -extensions/middle/SequenceLengthToMask.py extensions/middle/SharedWeightsDuplication.py extensions/middle/SliceConverter.py extensions/middle/SliceLikeToStridedSlice.py @@ -656,7 +649,6 @@ extensions/middle/UpsampleToResample.py extensions/middle/UselessMerge.py extensions/middle/UselessSplitEraser.py extensions/ops/__init__.py -extensions/ops/accum.py extensions/ops/activation_ops.py extensions/ops/adaptive_avg_pooling.py extensions/ops/argmax.py @@ -671,15 +663,14 @@ extensions/ops/BN.py extensions/ops/box_nms.py extensions/ops/bucketize.py extensions/ops/Cast.py +extensions/ops/ClipByValueTF.py extensions/ops/constant_fill.py extensions/ops/ConvertLike.py extensions/ops/copyop.py -extensions/ops/correlation.py extensions/ops/ctc_greedy_decoder.py extensions/ops/ctc_greedy_decoder_seq_len.py extensions/ops/ctc_loss.py extensions/ops/cumsum.py -extensions/ops/data_augmentation.py extensions/ops/depth_to_space.py extensions/ops/dequantize_linear.py extensions/ops/DetectionOutput.py @@ -729,8 +720,6 @@ extensions/ops/ONNXResize11.py extensions/ops/pack.py extensions/ops/parameter.py extensions/ops/pnorm.py -extensions/ops/power_file.py -extensions/ops/prediction_heatmap.py extensions/ops/prelu.py extensions/ops/priorbox.py extensions/ops/priorbox_clustered.py @@ -758,7 +747,6 @@ extensions/ops/scatter.py extensions/ops/scatternd.py extensions/ops/select.py extensions/ops/shufflechannel.py -extensions/ops/simplernms.py extensions/ops/size.py extensions/ops/slice_like.py extensions/ops/space_to_depth.py @@ -767,7 +755,6 @@ extensions/ops/sparse_reshape.py extensions/ops/sparse_segment_mean.py extensions/ops/sparse_segment_sqrtn.py extensions/ops/sparse_segment_sum.py -extensions/ops/spatial_transformer.py extensions/ops/splice.py extensions/ops/split.py extensions/ops/stop_gradient.py @@ -845,7 +832,6 @@ mo/front/common/partial_infer/eltwise.py mo/front/common/partial_infer/multi_box_detection.py mo/front/common/partial_infer/multi_box_prior.py mo/front/common/partial_infer/random_uniform.py -mo/front/common/partial_infer/reshape.py mo/front/common/partial_infer/roipooling.py mo/front/common/partial_infer/utils.py mo/front/common/register_custom_ops.py diff --git a/model-optimizer/extensions/back/CellNormalizer.py b/model-optimizer/extensions/back/CellNormalizer.py index b4b4ad2769f..2204219e408 100644 --- a/model-optimizer/extensions/back/CellNormalizer.py +++ b/model-optimizer/extensions/back/CellNormalizer.py @@ -5,10 +5,9 @@ import numpy as np from extensions.ops.split import VariadicSplit from mo.back.replacement import BackReplacementPattern -from mo.front.common.partial_infer.utils import int64_array +from mo.front.common.partial_infer.utils import int64_array, is_fully_defined from mo.front.tf.graph_utils import create_op_node_with_second_input, create_op_with_const_inputs from mo.graph.graph import Graph -from mo.ops.const import Const from mo.ops.reshape import Reshape @@ -41,6 +40,7 @@ class CellNormalizer(BackReplacementPattern): WR_shape = node.in_port(WR_input_id).data.get_shape() assert WR_shape is not None, "Undefined 'WR' input shape for Cell node '{}'".format(cell_name) + assert is_fully_defined(WR_shape), 'Not fully defined shape for WR for Cell node "{}"'.format(cell_name) num_elements_in_WR = np.prod(WR_shape) input_size = (num_elements_in_WR / (hidden_size_coef * hidden_size)) - hidden_size diff --git a/model-optimizer/extensions/back/ConvolutionNormalizer.py b/model-optimizer/extensions/back/ConvolutionNormalizer.py index 0abfbec0e20..77aa35a34e0 100644 --- a/model-optimizer/extensions/back/ConvolutionNormalizer.py +++ b/model-optimizer/extensions/back/ConvolutionNormalizer.py @@ -6,7 +6,7 @@ import numpy as np from extensions.back.ReshapeMutation import ReshapeMutation from extensions.back.ReverseInputChannels import ApplyReverseChannels from mo.back.replacement import BackReplacementPattern -from mo.front.common.partial_infer.utils import int64_array +from mo.front.common.partial_infer.utils import shape_array, is_fully_defined, int64_array from mo.front.tf.graph_utils import create_op_node_with_second_input, create_op_with_const_inputs from mo.graph.graph import Graph, Node from mo.ops.const import Const @@ -24,18 +24,18 @@ def resolve_convolution_with_group(node: Node, group: int, ir_version: str): assert len(weights_shape) in [3, 4, 5] assert weights_shape[0] % group == 0 - assert int64_array(node.output).ndim == 0 if ir_version == 'V7': if weights_shape[0] == node.output: # weights are already is in [G*O I X Y] format return - new_shape = int64_array([node.output, -1, *weights_shape[2:]]) - + new_shape = shape_array([node.output, -1, *weights_shape[2:]]) elif ir_version == 'V10': + # TODO rewrite this transformation to generate a shape-computing sub-graph. Ticket 62076 I = input_shape[1] - new_shape = int64_array([group, node.output / group, I / group, *weights_shape[2:]]) - assert np.prod(weights_shape) == np.prod(new_shape), \ - 'Initial weights shape {}, grouped weights shape {}'.format(weights_shape, new_shape) + new_shape = shape_array([group, node.output // group, I // group, *weights_shape[2:]]) + assert is_fully_defined(weights_shape[2:]) and is_fully_defined(I) and \ + np.prod(weights_shape) == np.prod(new_shape), 'Initial weights shape {}, grouped weights shape {}' \ + ''.format(weights_shape, new_shape) del node['group'] node['type'] = 'GroupConvolution' else: @@ -244,12 +244,12 @@ class DeconvolutionNormalizer(BackReplacementPattern): assert I % group == 0 assert node.output % group == 0 - new_shape = int64_array([group, I / group, node.output / group, *weights_shape[2:]]) + new_shape = shape_array([group, I // group, node.output // group, *weights_shape[2:]]) - assert np.prod(weights_shape) == np.prod(new_shape), \ - 'Initial weights shape {}, grouped weights shape {}'.format(weights_shape, new_shape) - reshape = create_op_node_with_second_input(graph, Reshape, int64_array(new_shape), - {'override_output_shape': True}, + assert not is_fully_defined(new_shape) or not is_fully_defined(weights_shape) or \ + np.prod(weights_shape) == np.prod(new_shape), 'Initial weights shape {}, grouped weights shape {}' \ + ''.format(weights_shape, new_shape) + reshape = create_op_node_with_second_input(graph, Reshape, new_shape, {'override_output_shape': True}, node.in_port(1).get_source().node) node.in_port(1).get_connection().set_source(reshape.out_port(0)) diff --git a/model-optimizer/extensions/back/CropToStridedSlice.py b/model-optimizer/extensions/back/CropToStridedSlice.py index 26c0bb11f44..bae197b158d 100644 --- a/model-optimizer/extensions/back/CropToStridedSlice.py +++ b/model-optimizer/extensions/back/CropToStridedSlice.py @@ -24,7 +24,7 @@ class CropToStridedSlice(BackReplacementPattern): def pattern(): return dict( nodes=[ - ('crop', dict(type='Crop')) + ('crop', dict(op='Crop')) ], edges=[] ) diff --git a/model-optimizer/extensions/back/FakeOutputResolver.py b/model-optimizer/extensions/back/FakeOutputResolver.py index e007a66ee01..99e80448e0d 100644 --- a/model-optimizer/extensions/back/FakeOutputResolver.py +++ b/model-optimizer/extensions/back/FakeOutputResolver.py @@ -5,7 +5,7 @@ from extensions.ops.elementwise import Add from mo.back.replacement import BackReplacementPattern from mo.front.common.partial_infer.utils import int64_array from mo.front.tf.graph_utils import create_op_with_const_inputs -from mo.graph.graph import Graph, rename_nodes, rename_node +from mo.graph.graph import Graph, rename_nodes class FakeOutputResolver(BackReplacementPattern): diff --git a/model-optimizer/extensions/back/GroupedConvWeightsNormalize.py b/model-optimizer/extensions/back/GroupedConvWeightsNormalize.py deleted file mode 100644 index fbcbb4c5ef0..00000000000 --- a/model-optimizer/extensions/back/GroupedConvWeightsNormalize.py +++ /dev/null @@ -1,38 +0,0 @@ -# Copyright (C) 2018-2021 Intel Corporation -# SPDX-License-Identifier: Apache-2.0 - -import numpy as np - -from mo.back.replacement import BackReplacementPattern -from mo.front.common.partial_infer.utils import int64_array -from mo.graph.graph import Graph -from mo.ops.const import Const - - -class GroupedConvWeightsNormalize(BackReplacementPattern): - """ - This pass is a workaround for nGraph GroupedConvolution operation - It requires that weights layout will be next: G*O*I,1,H,W - """ - enabled = True - force_clean_up = True - - def pattern(self): - return dict( - nodes=[ - ('conv', {'type': 'Convolution', 'group': lambda x: x != 1}), - ('weights', {'type': 'Const', 'kind': 'op'}), - ('weights_data', {'kind': 'data'}), - ], - edges=[('weights', 'weights_data'), ('weights_data', 'conv')] - ) - - def replace_pattern(self, graph: Graph, match: dict): - conv = match['conv'] - weights = match['weights'] - input_shape = conv.in_port(0).data.get_shape() - new_weights_shape = int64_array([(weights.value.shape[0] * weights.value.shape[1]) / (input_shape[1] / conv.group), input_shape[1] / conv.group, *weights.value.shape[2:]]) - new_weights = Const(graph, {'value': np.reshape(weights.value, new_weights_shape), - 'name': weights.soft_get('name', weights.id) + '_new'}).create_node() - weights.out_port(0).get_connection().set_source(new_weights.out_port(0)) - new_weights.infer(new_weights) diff --git a/model-optimizer/extensions/back/ProposalMutation.py b/model-optimizer/extensions/back/ProposalMutation.py index 7ac6f7e06c3..49b8357f0e2 100644 --- a/model-optimizer/extensions/back/ProposalMutation.py +++ b/model-optimizer/extensions/back/ProposalMutation.py @@ -17,7 +17,7 @@ from mo.ops.strided_slice import StridedSlice class ProposalMutation(BackReplacementPattern): enabled = True - force_clean_up = True + force_shape_inference = True def run_before(self): return [ReshapeMutation, StridedSliceMasksNormalizer] diff --git a/model-optimizer/extensions/back/ReverseInputChannels.py b/model-optimizer/extensions/back/ReverseInputChannels.py index 987347ef6c1..088130e0bf2 100644 --- a/model-optimizer/extensions/back/ReverseInputChannels.py +++ b/model-optimizer/extensions/back/ReverseInputChannels.py @@ -460,10 +460,6 @@ class ApplyReverseChannels(BackReplacementPattern): run_not_recursively = True force_clean_up = True - def run_before(self): - from extensions.back.GroupedConvWeightsNormalize import GroupedConvWeightsNormalize - return [GroupedConvWeightsNormalize] - def find_and_replace_pattern(self, graph: Graph): """ Following transformations should run in strict order, that is why we disabled them all and run here diff --git a/model-optimizer/extensions/back/SelectBroadcast.py b/model-optimizer/extensions/back/SelectBroadcast.py index 5770887d9a8..bb0ce11c751 100644 --- a/model-optimizer/extensions/back/SelectBroadcast.py +++ b/model-optimizer/extensions/back/SelectBroadcast.py @@ -1,8 +1,6 @@ # Copyright (C) 2018-2021 Intel Corporation # SPDX-License-Identifier: Apache-2.0 -import numpy as np - from extensions.back.ReshapeMutation import ReshapeMutation from mo.back.replacement import BackReplacementPattern from mo.front.common.partial_infer.utils import int64_array @@ -40,9 +38,6 @@ class SelectBroadcast(BackReplacementPattern): if select.has_valid('format') and select['format'] == 'tf': condition = select.in_node(0) input_1 = select.in_node(1) - input_2 = select.in_node(2) - - assert np.array_equal(input_1.shape, input_2.shape) if len(condition.shape) == 1 and len(input_1.shape) > 1: unsqueeze_op = create_op_node_with_second_input( diff --git a/model-optimizer/extensions/back/disable_unsupported_ND_operations.py b/model-optimizer/extensions/back/disable_unsupported_ND_operations.py deleted file mode 100644 index b673966779f..00000000000 --- a/model-optimizer/extensions/back/disable_unsupported_ND_operations.py +++ /dev/null @@ -1,35 +0,0 @@ -# Copyright (C) 2018-2021 Intel Corporation -# SPDX-License-Identifier: Apache-2.0 - -from mo.back.replacement import BackReplacementPattern -from mo.graph.graph import Node, Graph -from mo.utils.error import Error - - -class DisableUnsupportedNDOperations(BackReplacementPattern): - """ - This pass disables ND Convolutions/Deconvolutions/Poolings - """ - enabled = False - - unsupported_operations = ['Convolution', 'Deconvolution', 'Pooling'] - - def find_and_replace_pattern(self, graph: Graph): - unsupported_nodes = [] - for node in graph.nodes(): - node = Node(graph, node) - if node.kind == 'op' and node.soft_get('type') in self.unsupported_operations: - input_shape = node.in_node(0).shape - if len(input_shape) > 4: - unsupported_nodes.append((node.id, node.type)) - - if len(unsupported_nodes) == 0: - return - - error_message = "\nOperations below were marked as unsupported due to they expect more than two spatial dims" \ - " (input shape length more than 4)\n" - error_message += "List of unsupported operations ({})\n".format(len(unsupported_nodes)) - for node, type in unsupported_nodes: - error_message += " {} {}\n".format(type, node) - - raise Error(error_message) diff --git a/model-optimizer/extensions/back/op_versioning.py b/model-optimizer/extensions/back/op_versioning.py index 5afd10a5d12..81f0146e306 100644 --- a/model-optimizer/extensions/back/op_versioning.py +++ b/model-optimizer/extensions/back/op_versioning.py @@ -124,8 +124,6 @@ class OpVersioning(BackReplacementPattern): ])) opset_1_experimental_ops = set(map(lambda s: s.lower(), [ - "SimplerNMS", - "SpatialTransformer", "ExperimentalDetectronGenerateProposalsSingleImage", "ExperimentalDetectronTopKROIs", "ExperimentalDetectronROIFeatureExtractor", diff --git a/model-optimizer/extensions/front/LayerNorm.py b/model-optimizer/extensions/front/LayerNorm.py index 11293e39924..41b5918199b 100644 --- a/model-optimizer/extensions/front/LayerNorm.py +++ b/model-optimizer/extensions/front/LayerNorm.py @@ -3,10 +3,10 @@ import logging as log +from extensions.ops.mvn import MVN from mo.front.common.replacement import FrontReplacementPattern from mo.front.tf.graph_utils import create_op_with_const_inputs from mo.graph.graph import Graph, rename_nodes -from extensions.ops.mvn import MVN from mo.middle.pattern_match import apply_pattern diff --git a/model-optimizer/extensions/front/caffe/accum_ext.py b/model-optimizer/extensions/front/caffe/accum_ext.py deleted file mode 100644 index dda896921d9..00000000000 --- a/model-optimizer/extensions/front/caffe/accum_ext.py +++ /dev/null @@ -1,21 +0,0 @@ -# Copyright (C) 2018-2021 Intel Corporation -# SPDX-License-Identifier: Apache-2.0 - -from extensions.ops.accum import AccumOp -from mo.front.caffe.collect_attributes import collect_attributes -from mo.front.extractor import FrontExtractorOp - - -class AccumFrontExtractor(FrontExtractorOp): - op = 'Accum' - enabled = True - - @classmethod - def extract(cls, node): - proto_layer = node.pb - param = proto_layer.accum_param - - attrs = collect_attributes(param) - # update the attributes of the node - AccumOp.update_node_stat(node, attrs) - return cls.enabled diff --git a/model-optimizer/extensions/front/caffe/correlation_ext.py b/model-optimizer/extensions/front/caffe/correlation_ext.py deleted file mode 100644 index f63a49be5e7..00000000000 --- a/model-optimizer/extensions/front/caffe/correlation_ext.py +++ /dev/null @@ -1,40 +0,0 @@ -# Copyright (C) 2018-2021 Intel Corporation -# SPDX-License-Identifier: Apache-2.0 - -from extensions.ops.correlation import CorrelationOp -from mo.front.caffe.collect_attributes import merge_attrs -from mo.front.common.extractors.utils import layout_attrs -from mo.front.extractor import FrontExtractorOp - - -class CorrelationFrontExtractor(FrontExtractorOp): - op = 'Correlation' - enabled = True - - @classmethod - def extract(cls, node): - proto_layer = node.pb - param = proto_layer.correlation_param - - corr_type = 'caffe.CorrelationParameter.MULTIPLY' - if param.correlation_type == 1: - corr_type = 'caffe.CorrelationParameter.SUBTRACT' - - update_attrs = { - 'pad': param.pad, - 'kernel_size': param.kernel_size, - 'max_displacement': param.max_displacement, - 'stride_1': param.stride_1, - 'stride_2': param.stride_2, - 'single_direction': param.single_direction, - 'do_abs': int(param.do_abs), - 'correlation_type': corr_type, - } - - mapping_rule = merge_attrs(param, update_attrs) - - mapping_rule.update(layout_attrs()) - - # update the attributes of the node - CorrelationOp.update_node_stat(node, mapping_rule) - return cls.enabled diff --git a/model-optimizer/extensions/front/caffe/crop_ext.py b/model-optimizer/extensions/front/caffe/crop_ext.py index 4cb52303a71..e17a3807d7d 100644 --- a/model-optimizer/extensions/front/caffe/crop_ext.py +++ b/model-optimizer/extensions/front/caffe/crop_ext.py @@ -15,7 +15,6 @@ class CropFrontExtractor(FrontExtractorOp): proto_layer = node.pb param = proto_layer.crop_param mapping_rule = { - 'type': 'Crop', 'axis': param.axis, 'offset': param.offset, 'dim': None, # set in infer diff --git a/model-optimizer/extensions/front/caffe/data_augmentation_ext.py b/model-optimizer/extensions/front/caffe/data_augmentation_ext.py deleted file mode 100644 index 19e84bd068a..00000000000 --- a/model-optimizer/extensions/front/caffe/data_augmentation_ext.py +++ /dev/null @@ -1,45 +0,0 @@ -# Copyright (C) 2018-2021 Intel Corporation -# SPDX-License-Identifier: Apache-2.0 - -from extensions.ops.data_augmentation import DataAugmentationOp -from mo.front.caffe.collect_attributes import merge_attrs -from mo.front.caffe.extractors.utils import embed_input -from mo.front.extractor import FrontExtractorOp - - -class DataAugmentationFrontExtractor(FrontExtractorOp): - op = 'DataAugmentation' - enabled = True - - @classmethod - def extract(cls, node): - proto_layer = node.pb - param = proto_layer.augmentation_param - # slice_dim is deprecated parameter and is used as alias for axis - # however if slice_dim is defined and axis is default, we use slice_dim - update_attrs = { - 'crop_width': param.crop_width, - 'crop_height': param.crop_height, - 'write_augmented': param.write_augmented, - 'max_multiplier': param.max_multiplier, - 'augment_during_test': int(param.augment_during_test), - 'recompute_mean': param.recompute_mean, - 'write_mean': param.write_mean, - 'mean_per_pixel': int(param.mean_per_pixel), - 'mean': param.mean, - 'mode': param.mode, - 'bottomwidth': param.bottomwidth, - 'bottomheight': param.bottomheight, - 'num': param.num, - 'chromatic_eigvec': param.chromatic_eigvec - } - - mapping_rule = merge_attrs(param, update_attrs) - - if node.model_pb: - for index in range(0, len(node.model_pb.blobs)): - embed_input(mapping_rule, index + 1, 'custom_{}'.format(index), node.model_pb.blobs[index].data) - - # update the attributes of the node - DataAugmentationOp.update_node_stat(node, mapping_rule) - return cls.enabled diff --git a/model-optimizer/extensions/front/caffe/power_file_ext.py b/model-optimizer/extensions/front/caffe/power_file_ext.py deleted file mode 100644 index 5c2a6a42ea4..00000000000 --- a/model-optimizer/extensions/front/caffe/power_file_ext.py +++ /dev/null @@ -1,22 +0,0 @@ -# Copyright (C) 2018-2021 Intel Corporation -# SPDX-License-Identifier: Apache-2.0 - -from extensions.ops.power_file import PowerFileOp -from mo.front.caffe.collect_attributes import collect_attributes -from mo.front.extractor import FrontExtractorOp - - -class PowerFileFrontExtractor(FrontExtractorOp): - op = 'PowerFile' - enabled = True - - @classmethod - def extract(cls, node): - proto_layer = node.pb - param = proto_layer.power_file_param - - attrs = collect_attributes(param) - - # update the attributes of the node - PowerFileOp.update_node_stat(node, attrs) - return cls.enabled diff --git a/model-optimizer/extensions/front/caffe/simplernms_ext.py b/model-optimizer/extensions/front/caffe/simplernms_ext.py deleted file mode 100644 index 09b6fcab092..00000000000 --- a/model-optimizer/extensions/front/caffe/simplernms_ext.py +++ /dev/null @@ -1,32 +0,0 @@ -# Copyright (C) 2018-2021 Intel Corporation -# SPDX-License-Identifier: Apache-2.0 - -from extensions.ops.simplernms import SimplerNMSOp -from mo.front.caffe.collect_attributes import merge_attrs -from mo.front.extractor import FrontExtractorOp - - -class SimplerNMSFrontExtractor(FrontExtractorOp): - op = 'SimplerNMS' - enabled = True - - @classmethod - def extract(cls, node): - proto_layer = node.pb - param = proto_layer.simpler_nms_param - update_attrs = { - 'cls_threshold': param.cls_threshold, - 'max_num_proposals': param.max_num_proposals, - 'iou_threshold': param.iou_threshold, - 'min_bbox_size': param.min_bbox_size, - 'feat_stride': param.feat_stride, - 'pre_nms_topn': param.pre_nms_topn, - 'post_nms_topn': param.post_nms_topn, - 'scale': param.scale, - } - - mapping_rule = merge_attrs(param, update_attrs) - - # update the attributes of the node - SimplerNMSOp.update_node_stat(node, mapping_rule) - return cls.enabled diff --git a/model-optimizer/extensions/front/caffe/spatial_transformer_ext.py b/model-optimizer/extensions/front/caffe/spatial_transformer_ext.py deleted file mode 100644 index 7227196d532..00000000000 --- a/model-optimizer/extensions/front/caffe/spatial_transformer_ext.py +++ /dev/null @@ -1,36 +0,0 @@ -# Copyright (C) 2018-2021 Intel Corporation -# SPDX-License-Identifier: Apache-2.0 - -from extensions.ops.spatial_transformer import SpatialTransformOp -from mo.front.caffe.collect_attributes import merge_attrs -from mo.front.extractor import FrontExtractorOp - - -class SpatialTransformFrontExtractor(FrontExtractorOp): - op = 'SpatialTransformer' - enabled = True - - @classmethod - def extract(cls, node): - proto_layer = node.pb - param = proto_layer.st_param - - update_attrs = { - 'transform_type': param.transform_type, - 'sampler_type': param.sampler_type, - 'output_H': param.output_H, - 'output_W': param.output_W, - 'to_compute_dU': int(param.to_compute_dU), - 'theta_1_1': param.theta_1_1, - 'theta_1_2': param.theta_1_2, - 'theta_1_3': param.theta_1_3, - 'theta_2_1': param.theta_2_1, - 'theta_2_2': param.theta_2_2, - 'theta_2_3': param.theta_2_3 - } - - mapping_rule = merge_attrs(param, update_attrs) - - # update the attributes of the node - SpatialTransformOp.update_node_stat(node, mapping_rule) - return cls.enabled diff --git a/model-optimizer/extensions/front/onnx/fused_bn_ext.py b/model-optimizer/extensions/front/onnx/fused_bn_ext.py index 64b89b3119d..584d03733e9 100644 --- a/model-optimizer/extensions/front/onnx/fused_bn_ext.py +++ b/model-optimizer/extensions/front/onnx/fused_bn_ext.py @@ -1,14 +1,11 @@ # Copyright (C) 2018-2021 Intel Corporation # SPDX-License-Identifier: Apache-2.0 -import logging as log - from extensions.ops.BatchNormInference import BatchNormInference from mo.front.extractor import FrontExtractorOp from mo.front.onnx.extractors.utils import onnx_attr - class BatchNormalizationExtractor(FrontExtractorOp): op = 'BatchNormalization' enabled = True diff --git a/model-optimizer/extensions/front/onnx/parameter_ext.py b/model-optimizer/extensions/front/onnx/parameter_ext.py index 4ce1a98f4f8..22e86c8ce75 100644 --- a/model-optimizer/extensions/front/onnx/parameter_ext.py +++ b/model-optimizer/extensions/front/onnx/parameter_ext.py @@ -1,10 +1,10 @@ # Copyright (C) 2018-2021 Intel Corporation # SPDX-License-Identifier: Apache-2.0 -import numpy as np from onnx.mapping import TENSOR_TYPE_TO_NP_TYPE from extensions.ops.parameter import Parameter +from mo.front.common.partial_infer.utils import shape_array, dynamic_dimension_value from mo.front.extractor import FrontExtractorOp @@ -16,7 +16,8 @@ class PlaceholderFrontExtractor(FrontExtractorOp): def extract(cls, node): t_type = node.pb.type.tensor_type attrs = { - 'shape': np.array([d.dim_value for d in t_type.shape.dim], dtype=np.int64), + 'shape': shape_array([d.dim_value if (not hasattr(d, 'dim_param') or d.dim_param == '') and d.dim_value != 0 + else dynamic_dimension_value for d in t_type.shape.dim]), 'data_type': TENSOR_TYPE_TO_NP_TYPE[t_type.elem_type] } Parameter.update_node_stat(node, attrs) diff --git a/model-optimizer/extensions/front/tf/ClipByValueTFTransformation.py b/model-optimizer/extensions/front/tf/ClipByValueTFTransformation.py new file mode 100644 index 00000000000..ef3c71f95be --- /dev/null +++ b/model-optimizer/extensions/front/tf/ClipByValueTFTransformation.py @@ -0,0 +1,27 @@ +# Copyright (C) 2018-2021 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 +from extensions.ops.elementwise import Minimum, Maximum +from mo.front.common.replacement import FrontReplacementSubgraph +from mo.graph.graph import Graph, rename_nodes + + +class ClipByValueTFTransformation(FrontReplacementSubgraph): + """ + The transformation replaces the ClipByValueTF operation which works as Clamp but supports broadcasting of inputs + with Minimum and Maximum. + """ + enabled = True + + def find_and_replace_pattern(self, graph: Graph): + for cbv in graph.get_op_nodes(op='ClipByValueTF'): + cbv_name = cbv.soft_get('name', cbv.id) + minimum = Minimum(graph, {'name': cbv_name + '/CLipMinimum'}).create_node() + maximum = Maximum(graph, {'name': cbv_name + '/CLipMaximum'}).create_node() + minimum.in_port(0).connect(cbv.in_port(0).get_source()) + minimum.in_port(1).connect(cbv.in_port(2).get_source()) + maximum.in_port(0).connect(minimum.out_port(0)) + maximum.in_port(1).connect(cbv.in_port(1).get_source()) + cbv.out_port(0).get_connection().set_source(maximum.out_port(0)) + + rename_nodes([(cbv, cbv_name + '/TBR'), (maximum, cbv_name)]) + graph.remove_node(cbv.id) diff --git a/model-optimizer/extensions/front/tf/ClipByValue_ext.py b/model-optimizer/extensions/front/tf/ClipByValue_ext.py new file mode 100644 index 00000000000..c15667746d6 --- /dev/null +++ b/model-optimizer/extensions/front/tf/ClipByValue_ext.py @@ -0,0 +1,15 @@ +# Copyright (C) 2018-2021 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 + +from mo.front.extractor import FrontExtractorOp +from extensions.ops.ClipByValueTF import ClibByValueTF + + +class ClipByValueExtractor(FrontExtractorOp): + op = 'ClipByValue' + enabled = True + + @classmethod + def extract(cls, node): + ClibByValueTF.update_node_stat(node, {}) + return cls.enabled diff --git a/model-optimizer/extensions/front/tf/IteratorGetNext_ext.py b/model-optimizer/extensions/front/tf/IteratorGetNext_ext.py index d3ceb2b4627..e7999164714 100644 --- a/model-optimizer/extensions/front/tf/IteratorGetNext_ext.py +++ b/model-optimizer/extensions/front/tf/IteratorGetNext_ext.py @@ -1,9 +1,8 @@ # Copyright (C) 2018-2021 Intel Corporation # SPDX-License-Identifier: Apache-2.0 -from mo.front.common.partial_infer.utils import int64_array from mo.front.extractor import FrontExtractorOp -from mo.front.tf.extractors.utils import tf_dtype_extractor +from mo.front.tf.extractors.utils import tf_dtype_extractor, tf_tensor_shape from mo.ops.op import Op @@ -20,7 +19,6 @@ class IteratorGetNextExtractor(FrontExtractorOp): extracted_types.append(tf_dtype_extractor(t)) result_shapes = [] for shape_pb in shapes: - shape = shape_pb.dim - result_shapes.append(int64_array([dim.size for dim in shape])) + result_shapes.append(tf_tensor_shape(shape_pb)) Op.update_node_stat(node, {'shapes': result_shapes, 'types': extracted_types}) return cls.enabled diff --git a/model-optimizer/extensions/front/tf/ObjectDetectionAPI.py b/model-optimizer/extensions/front/tf/ObjectDetectionAPI.py index 9f1228aec58..ec3a357fa90 100644 --- a/model-optimizer/extensions/front/tf/ObjectDetectionAPI.py +++ b/model-optimizer/extensions/front/tf/ObjectDetectionAPI.py @@ -948,7 +948,7 @@ class ObjectDetectionAPIDetectionOutputReplacement(FrontReplacementFromConfigFil background_label_id=background_label_id, code_type='caffe.PriorBoxParameter.CENTER_SIZE', pad_mode='caffe.ResizeParameter.CONSTANT', resize_mode='caffe.ResizeParameter.WARP', - num_classes=num_classes, + num_classes=num_classes + 1, confidence_threshold=_value_or_raise(match, pipeline_config, 'postprocessing_score_threshold'), top_k=_value_or_raise(match, pipeline_config, 'postprocessing_max_detections_per_class'), keep_top_k=_value_or_raise(match, pipeline_config, 'postprocessing_max_total_detections'), @@ -1475,6 +1475,7 @@ class ObjectDetectionAPISSDPostprocessorReplacement(FrontReplacementFromConfigFi detection_output_node = detection_output_op.create_node( [reshape_loc_node, reshape_conf_node, priors_node], dict(name=detection_output_op.attrs['type'], + num_classes=num_classes, confidence_threshold=_value_or_raise(match, pipeline_config, 'postprocessing_score_threshold'), top_k=_value_or_raise(match, pipeline_config, 'postprocessing_max_detections_per_class'), keep_top_k=_value_or_raise(match, pipeline_config, 'postprocessing_max_total_detections'), diff --git a/model-optimizer/extensions/front/tf/TFResizeToInterpolate.py b/model-optimizer/extensions/front/tf/TFResizeToInterpolate.py index e9660a8b290..a72d7a21573 100644 --- a/model-optimizer/extensions/front/tf/TFResizeToInterpolate.py +++ b/model-optimizer/extensions/front/tf/TFResizeToInterpolate.py @@ -8,7 +8,6 @@ import numpy as np from extensions.ops.Cast import Cast from extensions.ops.elementwise import Div from extensions.ops.interpolate import Interpolate -from mo.front.common.layout import get_height_dim, get_width_dim from mo.front.common.partial_infer.utils import int64_array from mo.front.common.replacement import FrontReplacementOp from mo.front.tf.graph_utils import create_op_with_const_inputs @@ -32,13 +31,9 @@ def replace_tf_resize(graph: Graph, resize: Node, interpolation_mode: str): shape = Shape(graph, {'name': resize_name + '/shapeof'}).create_node() - layout = graph.graph['layout'] - height_dim = get_height_dim(layout, 4) - width_dim = get_width_dim(layout, 4) - ss = create_op_with_const_inputs(graph, StridedSlice, - {1: int64_array([height_dim]), - 2: int64_array([width_dim + 1]), + {1: int64_array([1]), + 2: int64_array([3]), 3: int64_array([1]) }, {'name': resize_name + '/StridedSlice', @@ -74,7 +69,7 @@ def replace_tf_resize(graph: Graph, resize: Node, interpolation_mode: str): interpolate4 = create_op_with_const_inputs(graph, Interpolate, { - 3: int64_array([height_dim, width_dim]) + 3: int64_array([1, 2]) }, { 'name': resize_name + '/interpolate_4', diff --git a/model-optimizer/extensions/front/tf/TensorArrayGatherV3.py b/model-optimizer/extensions/front/tf/TensorArrayGatherV3.py index 158a681f208..e5c89be2e6d 100644 --- a/model-optimizer/extensions/front/tf/TensorArrayGatherV3.py +++ b/model-optimizer/extensions/front/tf/TensorArrayGatherV3.py @@ -7,7 +7,7 @@ from mo.front.tf.extractors.utils import tf_tensor_shape from mo.graph.graph import Node -class TensorArrayGatherV3Exteractor(FrontExtractorOp): +class TensorArrayGatherV3Extractor(FrontExtractorOp): op = "TensorArrayGatherV3" enabled = True diff --git a/model-optimizer/extensions/front/tf/elementwise_ext.py b/model-optimizer/extensions/front/tf/elementwise_ext.py index bbdddc1b657..22b232d637a 100644 --- a/model-optimizer/extensions/front/tf/elementwise_ext.py +++ b/model-optimizer/extensions/front/tf/elementwise_ext.py @@ -2,7 +2,7 @@ # SPDX-License-Identifier: Apache-2.0 from extensions.ops.elementwise import Add, Mul, Sub, Div, Maximum, Minimum, Pow, LogicalAnd, LogicalOr, Equal, \ - GreaterEqual, Greater, Less, LessEqual, NotEqual, FloorMod, BiasAdd, SquaredDifference, Round + GreaterEqual, Greater, Less, LessEqual, NotEqual, FloorMod, BiasAdd, SquaredDifference, Round, Mod from mo.front.extractor import FrontExtractorOp from mo.front.tf.extractors.utils import tf_dtype_extractor from mo.ops.eltwise_n import EltwiseNAdd @@ -70,6 +70,16 @@ class SubExtractor(FrontExtractorOp): return cls.enabled +class ModExtractor(FrontExtractorOp): + op = 'Mod' + enabled = True + + @classmethod + def extract(cls, node): + Mod.update_node_stat(node, {'data_type': tf_dtype_extractor(node.pb.attr["T"].type)}) + return cls.enabled + + class DivExtractor(FrontExtractorOp): op = 'RealDiv' enabled = True diff --git a/model-optimizer/extensions/front/tf/extract_image_patches_ext.py b/model-optimizer/extensions/front/tf/extract_image_patches_ext.py index 7ebcc118fb7..da6c721b2f3 100644 --- a/model-optimizer/extensions/front/tf/extract_image_patches_ext.py +++ b/model-optimizer/extensions/front/tf/extract_image_patches_ext.py @@ -7,13 +7,13 @@ from mo.front.common.partial_infer.utils import int64_array from mo.front.extractor import FrontExtractorOp from mo.front.tf.extractors.utils import tf_int_list + class ExtractImagePatchesExtractor(FrontExtractorOp): op = 'ExtractImagePatches' enabled = True @classmethod def extract(cls, node): - attrs = { 'spatial_dims': int64_array([1, 2]), 'sizes': tf_int_list(node.pb.attr['ksizes'].list), @@ -23,3 +23,4 @@ class ExtractImagePatchesExtractor(FrontExtractorOp): } ExtractImagePatches.update_node_stat(node, attrs) + return cls.enabled diff --git a/model-optimizer/extensions/front/tf/non_max_suppression_normalize.py b/model-optimizer/extensions/front/tf/non_max_suppression_normalize.py index 537389095f1..90807fd39ec 100644 --- a/model-optimizer/extensions/front/tf/non_max_suppression_normalize.py +++ b/model-optimizer/extensions/front/tf/non_max_suppression_normalize.py @@ -62,7 +62,7 @@ class TFNonMaxSuppressionNormalize(FrontReplacementSubgraph): num_of_outputs = len([port for port in nms.out_ports().values() if not port.disconnected()]) if num_of_outputs == 1: - return + continue # prepare output #1 crop_score_indices_name = nms_name + '/Crop_scores_' diff --git a/model-optimizer/extensions/middle/AddMeanScaleValues.py b/model-optimizer/extensions/middle/AddMeanScaleValues.py index ac272451b26..8ff2c60db20 100644 --- a/model-optimizer/extensions/middle/AddMeanScaleValues.py +++ b/model-optimizer/extensions/middle/AddMeanScaleValues.py @@ -7,6 +7,7 @@ import numpy as np from extensions.ops.elementwise import Add, Mul from mo.front.common.layout import get_features_dim +from mo.front.common.partial_infer.utils import compatible_dims from mo.front.extractor import get_node_id_with_ports from mo.front.tf.graph_utils import create_op_with_const_inputs from mo.graph.graph import Graph, Node @@ -42,7 +43,7 @@ class AddMeanScaleValues(MiddleReplacementPattern): return assert input_node.has_valid('shape') features_dim_idx = get_features_dim(graph.graph['layout'], len(input_node.shape)) - assert value.size == input_node.shape[features_dim_idx] or value.size == 1 + assert compatible_dims(value.size, input_node.shape[features_dim_idx]) or value.size == 1 shape = np.ones(len(input_node.shape), dtype=np.int64) shape[features_dim_idx] = value.size diff --git a/model-optimizer/extensions/middle/ApplyPermutations.py b/model-optimizer/extensions/middle/ApplyPermutations.py index 9564ad59679..4ee959c7c81 100644 --- a/model-optimizer/extensions/middle/ApplyPermutations.py +++ b/model-optimizer/extensions/middle/ApplyPermutations.py @@ -10,7 +10,7 @@ from extensions.middle.InsertLayoutPropagationTransposes import is_input_data_in is_output_data_in_correct_layout from extensions.middle.LayoutChangeForConstantShapePaths import LayoutChangeForConstantShapePaths from extensions.middle.pass_separator import PostMiddleStart -from mo.front.common.partial_infer.utils import int64_array +from mo.front.common.partial_infer.utils import int64_array, shape_array from mo.graph.graph import Graph, Node from mo.graph.perm_inputs import get_node_with_permutation from mo.graph.port import Port @@ -88,8 +88,7 @@ class ApplyPermutation(MiddleReplacementPattern): all([attrs.get('input_permutation', False) for u, v, attrs in graph.out_edges(node.id, data=True)]): continue - if len( - node.in_nodes()) != 0: # there are data nodes without input operation node inside the tensor iterator + if len(node.in_nodes()) != 0: # there are data nodes without input operation node inside the TensorIterator edge_attrs = graph.get_edge_data(node.in_node(0).id, node.id)[0] if is_output_data_in_correct_layout(node.in_node(0), edge_attrs['out']): log.debug('Do not permute data node attrs for node "{}" output port "{}"'.format(node.in_node(0).id, @@ -99,7 +98,7 @@ class ApplyPermutation(MiddleReplacementPattern): # Apply permutation for shape and value if exists if len(node.permutation.perm) == 0: continue - node.shape = np.array(node.shape)[node.permutation.perm] + node.shape = shape_array(node.shape)[node.permutation.perm] if node.has_valid('value'): assert len(node.value.shape) == len(node.permutation.perm), \ 'Node {} has shape {} and permutation {} that does not match. Their lengths should be equal' \ diff --git a/model-optimizer/extensions/middle/ConvertGroupedStridedSlice.py b/model-optimizer/extensions/middle/ConvertGroupedStridedSlice.py index 68b8ff54e98..9f7eb2f6f3a 100644 --- a/model-optimizer/extensions/middle/ConvertGroupedStridedSlice.py +++ b/model-optimizer/extensions/middle/ConvertGroupedStridedSlice.py @@ -3,13 +3,12 @@ import logging as log from copy import deepcopy -from typing import Callable import numpy as np from extensions.middle.SliceConverter import ConvertSlice from extensions.ops.split import VariadicSplit -from mo.front.common.partial_infer.utils import int64_array +from mo.front.common.partial_infer.utils import int64_array, shape_array from mo.graph.graph import Graph, Node, add_opoutput from mo.middle.replacement import MiddleReplacementPattern from mo.ops.const import Const @@ -70,16 +69,27 @@ class ConvertGroupedStridedSlice(MiddleReplacementPattern): if input_data.value is not None: continue - input_shape = np.array(input_data.shape) + if input_data.shape is None: + continue + input_shape = shape_array(input_data.shape) # Get all unique StridedSlice consumers - out_nodes = [node for node in input_data.out_nodes() if node.op == 'StridedSlice' and node.in_node(0).name == input_data.name] - sorted_out_nodes = sorted(out_nodes, key=lambda n: list(n.slices)) - out_nodes = unique_by(sorted_out_nodes, strided_slices_equality) + out_nodes = [node for node in input_data.out_nodes() if node.op == 'StridedSlice' and + node.in_node(0).id == input_data.id] + if len(out_nodes) <= 1: continue valid_for_replacement = True + for n in out_nodes: + if any(not isinstance(s, slice) for s in n.slices): + # this is a slice with dynamic dimension. Such operation is not valid for replacement + valid_for_replacement = False + if not valid_for_replacement: + continue + + sorted_out_nodes = sorted(out_nodes, key=lambda n: list(n.slices)) + out_nodes = unique_by(sorted_out_nodes, strided_slices_equality) for node in out_nodes: if len(node.slices) != len(out_nodes[0].slices): @@ -89,7 +99,8 @@ class ConvertGroupedStridedSlice(MiddleReplacementPattern): split_channel_dim = None for dim_id, s in enumerate(out_nodes[0].slices): l, r, stride = s.start, s.stop, s.step - if l != 0 or r != input_shape[dim_id]: + # if both l and r are None then the dimension is not sliced + if (l != 0 or r != input_shape[dim_id]) and (l is not None or r is not None): if split_channel_dim is None: split_channel_dim = dim_id else: diff --git a/model-optimizer/extensions/middle/CustomSubgraphCall.py b/model-optimizer/extensions/middle/CustomSubgraphCall.py index 10cff6fc7f4..6ae0d77fa32 100644 --- a/model-optimizer/extensions/middle/CustomSubgraphCall.py +++ b/model-optimizer/extensions/middle/CustomSubgraphCall.py @@ -7,7 +7,7 @@ import logging as log import numpy as np from mo.front.common.layout import nhwc_to_nchw_permute -from mo.front.common.partial_infer.utils import int64_array +from mo.front.common.partial_infer.utils import shape_array, shape_insert from mo.front.extractor import update_ie_fields from mo.graph.graph import Graph from mo.graph.graph import Node, add_opoutput @@ -113,17 +113,16 @@ class CustomSubgraphCall(MiddleReplacementPattern): :param shape: shape to extend. :return: 4D tensor. """ - new_shape = int64_array(shape) + new_shape = shape_array(shape) old_shape_len = len(shape) - for x in range( - 4 - old_shape_len): # TODO think about proper way to add additional dimensions considering layout - if len( - new_shape) <= 1: # if the shape is 0D or 1D then we should add additional dimensions to batch dimension - new_shape = np.insert(new_shape, 0, 1) - # new_shape = np.array([1, shape[0], 1, 1]) + # TODO think about proper way to add additional dimensions considering layout + for x in range(4 - old_shape_len): + # if the shape is 0D or 1D then we should add additional dimensions to batch dimension + if len(new_shape) <= 1: + new_shape = shape_insert(new_shape, 0, 1) else: - new_shape = np.insert(new_shape, 1, 1) + new_shape = shape_insert(new_shape, 1, 1) return new_shape @staticmethod diff --git a/model-optimizer/extensions/middle/DecomposeBidirectionalRNNSequence.py b/model-optimizer/extensions/middle/DecomposeBidirectionalRNNSequence.py index 094ed402f2b..1be5fe3024b 100644 --- a/model-optimizer/extensions/middle/DecomposeBidirectionalRNNSequence.py +++ b/model-optimizer/extensions/middle/DecomposeBidirectionalRNNSequence.py @@ -4,6 +4,7 @@ import numpy as np from extensions.ops.split import Split +from mo.front.common.partial_infer.utils import shape_array from mo.graph.graph import Node, Graph from mo.middle.replacement import MiddleReplacementPattern from mo.ops.concat import Concat @@ -49,7 +50,7 @@ class DecomposeBidirectionalRNNSequence(MiddleReplacementPattern): node.graph, name=node.name + '/SplittedBiLSTM/{}/'.format(direction), attrs={'value': np.take(node.value, [index], axis), - 'shape': np.array(np.take(node.value, [index], axis).shape, dtype=np.int64)} + 'shape': shape_array(np.take(node.value, [index], axis).shape)} ) def split_data(self, data: Node): diff --git a/model-optimizer/extensions/middle/DilatedConvolution.py b/model-optimizer/extensions/middle/DilatedConvolution.py index 1409d7a7601..6e34bd1cebf 100644 --- a/model-optimizer/extensions/middle/DilatedConvolution.py +++ b/model-optimizer/extensions/middle/DilatedConvolution.py @@ -5,6 +5,7 @@ import logging as log import numpy as np +from mo.front.common.partial_infer.utils import shape_insert from mo.graph.graph import Graph, Node from mo.middle.replacement import MiddleReplacementPattern from mo.ops.const import Const @@ -149,7 +150,7 @@ class DilatedConvolution1DConverter(MiddleReplacementPattern): for port_id in [1, 2]: current_value = pad.in_port(port_id).get_connection().data.get_value() new_value_node = Const(pad.graph, {'name': pad.soft_get('name', pad.id) + '/value_{}'.format(port_id), - 'value': np.insert(current_value, unsqueeze_axis.item(), 0), + 'value': shape_insert(current_value, unsqueeze_axis.item(), 0), 'override_output_shape': True}).create_node() pad.in_port(port_id).disconnect() pad.in_port(port_id).connect(new_value_node.out_port(0)) diff --git a/model-optimizer/extensions/middle/EltwiseChecker.py b/model-optimizer/extensions/middle/EltwiseChecker.py index c9ab5672c43..03fb59e283b 100644 --- a/model-optimizer/extensions/middle/EltwiseChecker.py +++ b/model-optimizer/extensions/middle/EltwiseChecker.py @@ -3,6 +3,7 @@ import numpy as np +from mo.front.common.partial_infer.utils import shape_insert from mo.graph.graph import Node, Graph from mo.middle.passes.fusing.helpers import get_tensor_in_port, get_value_in_port from mo.middle.replacement import MiddleReplacementPattern @@ -57,7 +58,7 @@ class EltwiseChecker(MiddleReplacementPattern): self.set_flags_to_false(node, ['can_be_scaleshift']) return - broadcasted_value_shape = np.insert(value_shape, 0, [1] * (len(tensor_shape) - len(value_shape))) + broadcasted_value_shape = shape_insert(value_shape, 0, [1] * (len(tensor_shape) - len(value_shape))) feature_dim = min(1, tensor_shape.size - 1) if node.graph.graph['layout'] == 'NCHW' else -1 if feature_channel is not None: diff --git a/model-optimizer/extensions/middle/EltwiseInputReshape.py b/model-optimizer/extensions/middle/EltwiseInputReshape.py index 2032cfc7b46..cd2f80cabeb 100644 --- a/model-optimizer/extensions/middle/EltwiseInputReshape.py +++ b/model-optimizer/extensions/middle/EltwiseInputReshape.py @@ -4,7 +4,7 @@ import numpy as np from mo.front.common.layout import get_features_dim, shape_for_layout -from mo.front.common.partial_infer.utils import int64_array +from mo.front.common.partial_infer.utils import int64_array, shape_insert, is_fully_defined from mo.front.tf.graph_utils import create_op_with_const_inputs from mo.graph.graph import Graph, Node from mo.middle.replacement import MiddleReplacementPattern @@ -127,8 +127,8 @@ def normalize_eltwise_inputs(graph: Graph): producer_port_shape = producer_port.data.get_shape() new_shape = producer_port_shape.copy() for unsqueeze_dim in unsqueeze_dims: - new_shape = np.insert(new_shape, unsqueeze_dim, 1) - if producer_port_value is not None: + new_shape = shape_insert(new_shape, unsqueeze_dim, 1) + if producer_port_value is not None and is_fully_defined(new_shape): unsqueeze_node.out_port(0).data.set_value(np.reshape(producer_port_value, new_shape)) else: unsqueeze_node.out_port(0).data.set_shape(new_shape) diff --git a/model-optimizer/extensions/middle/GRURNNSequenceToTensorIterator.py b/model-optimizer/extensions/middle/GRURNNSequenceToTensorIterator.py index 7e22f2a1d1b..75fe3d584d5 100644 --- a/model-optimizer/extensions/middle/GRURNNSequenceToTensorIterator.py +++ b/model-optimizer/extensions/middle/GRURNNSequenceToTensorIterator.py @@ -4,6 +4,7 @@ import numpy as np from extensions.ops.tensor_iterator import TensorIterator +from mo.front.common.partial_infer.utils import shape_delete from mo.graph.graph import Graph, add_opoutput from mo.middle.replacement import MiddleReplacementPattern from mo.ops.const import Const @@ -90,7 +91,7 @@ class GRUAndRNNToTensorIterator(MiddleReplacementPattern): for out in outputs: add_opoutput(body, out.id, 0, False) - outputs[0].shape = np.delete(outputs[0].shape.copy(), rnn_layer.sequence_dim) + outputs[0].shape = shape_delete(outputs[0].shape, rnn_layer.sequence_dim) output_unsqueeze_dim = Const(body, dict(name=rnn_layer.name + '/output_unsqueeze_dim', value=rnn_layer.sequence_dim)).create_node_with_data() output_unsqueeze = Unsqueeze(body, dict(name=rnn_layer.name + '/output_unsqueeze/', internal_layer_id=2)) diff --git a/model-optimizer/extensions/middle/InterpolateSequenceToInterpolate.py b/model-optimizer/extensions/middle/InterpolateSequenceToInterpolate.py index f6ac510cfa0..c360299bcc7 100644 --- a/model-optimizer/extensions/middle/InterpolateSequenceToInterpolate.py +++ b/model-optimizer/extensions/middle/InterpolateSequenceToInterpolate.py @@ -6,7 +6,7 @@ import numpy as np from typing import List from extensions.ops.interpolate import Interpolate -from mo.front.common.partial_infer.utils import int64_array +from mo.front.common.partial_infer.utils import int64_array, shape_array from mo.front.tf.graph_utils import create_op_with_const_inputs from mo.graph.graph import Graph, Node, rename_nodes from mo.middle.replacement import MiddleReplacementPattern @@ -200,7 +200,7 @@ def replace_sequence(seq: List[Node], graph: Graph): axis_to_size = sorted(list(dict(dims_and_scales_).items()), key=lambda x: x[0]) axes_of_node = int64_array([z[0] for z in axis_to_size]) - sizes = int64_array([z[1] for z in axis_to_size]) + sizes = shape_array([z[1] for z in axis_to_size]) scales = np.ones(len(axis_to_size)) else: for interp in seq: @@ -210,7 +210,7 @@ def replace_sequence(seq: List[Node], graph: Graph): axis_to_size = sorted(dims_and_scales_, key=lambda x: x[0]) axes_of_node = int64_array([z[0] for z in axis_to_size]) - sizes = int64_array([z[1] for z in axis_to_size]) + sizes = shape_array([z[1] for z in axis_to_size]) scales = np.array([z[2] for z in axis_to_size]) fst_interp_node = seq[0] diff --git a/model-optimizer/extensions/middle/LSTMRNNSequenceToTensorIterator.py b/model-optimizer/extensions/middle/LSTMRNNSequenceToTensorIterator.py index 7af0d18b388..6c17590be1f 100644 --- a/model-optimizer/extensions/middle/LSTMRNNSequenceToTensorIterator.py +++ b/model-optimizer/extensions/middle/LSTMRNNSequenceToTensorIterator.py @@ -1,11 +1,10 @@ # Copyright (C) 2018-2021 Intel Corporation # SPDX-License-Identifier: Apache-2.0 -import numpy as np - from extensions.middle.RNNSequenceNormalizeToIE import RNNSequenceNormalize from extensions.ops.lstm_cell import LSTMCell from extensions.ops.tensor_iterator import TensorIterator +from mo.front.common.partial_infer.utils import shape_delete from mo.graph.graph import Graph, add_opoutput from mo.middle.replacement import MiddleReplacementPattern from mo.ops.const import Const @@ -84,7 +83,7 @@ class LSTMToTensorIterator(MiddleReplacementPattern): for out in outputs: add_opoutput(body, out.id, 0, False) - outputs[0].shape = np.delete(outputs[0].shape, lstm.sequence_dim) + outputs[0].shape = shape_delete(outputs[0].shape, lstm.sequence_dim) output_unsqueeze = Unsqueeze(body, dict(name=lstm.name + 'output_unsqueeze', internal_layer_id=2)) unsqueeze_dim_data = Const(body, {'name': lstm.name + '/output_unsqueeze_dim', 'value': [lstm.sequence_dim]}).create_node_with_data() diff --git a/model-optimizer/extensions/middle/MXNetRNNSequenceNormalize.py b/model-optimizer/extensions/middle/MXNetRNNSequenceNormalize.py index 85eedec7b06..bc48e52b36d 100644 --- a/model-optimizer/extensions/middle/MXNetRNNSequenceNormalize.py +++ b/model-optimizer/extensions/middle/MXNetRNNSequenceNormalize.py @@ -4,7 +4,7 @@ import numpy as np from extensions.ops.transpose import Transpose -from mo.front.common.partial_infer.utils import int64_array +from mo.front.common.partial_infer.utils import int64_array, shape_insert from mo.graph.graph import Graph from mo.middle.replacement import MiddleReplacementPattern from mo.ops.const import Const @@ -184,14 +184,12 @@ class MXNetRNNSequenceNormalize(MiddleReplacementPattern): mxnet_shape = lstm.out_node(0).shape.copy() if lstm.batch_dim == 0: - mo_shape = np.array([input.shape[lstm.batch_dim], input.shape[lstm.sequence_dim], lstm.hidden_size], - dtype=np.int64) + mo_shape = int64_array([input.shape[lstm.batch_dim], input.shape[lstm.sequence_dim], lstm.hidden_size]) else: - mo_shape = np.array([input.shape[lstm.sequence_dim], input.shape[lstm.batch_dim], lstm.hidden_size], - dtype=np.int64) + mo_shape = int64_array([input.shape[lstm.sequence_dim], input.shape[lstm.batch_dim], lstm.hidden_size]) if lstm.has_num_directions: - mo_shape = np.insert(mo_shape, 1, np.int64(num_directions)) + mo_shape = shape_insert(mo_shape, 1, np.int64(num_directions)) lstm_name = lstm.soft_get('name', lstm.id) diff --git a/model-optimizer/extensions/middle/MXNetSplitMultiLayers.py b/model-optimizer/extensions/middle/MXNetSplitMultiLayers.py index 0df42800747..59249fabb60 100644 --- a/model-optimizer/extensions/middle/MXNetSplitMultiLayers.py +++ b/model-optimizer/extensions/middle/MXNetSplitMultiLayers.py @@ -3,6 +3,7 @@ import numpy as np +from mo.front.common.partial_infer.utils import shape_insert, int64_array from mo.graph.graph import Graph, Node from mo.middle.replacement import MiddleReplacementPattern from mo.ops.concat import Concat @@ -131,9 +132,9 @@ class MXNetSplitLayersToRNNSequence(MiddleReplacementPattern): output_data = rnn_layer.out_node(0) # Output nodes creating: - state_size = np.array([input.shape[rnn_layer.batch_dim], rnn_layer.hidden_size], dtype=np.int64) + state_size = int64_array([input.shape[rnn_layer.batch_dim], rnn_layer.hidden_size]) if rnn_layer.has_num_directions: - state_size = np.insert(state_size, 0, direction) + state_size = shape_insert(state_size, 0, direction) output_hidden = Op._create_data_node( rnn_layer.graph, diff --git a/model-optimizer/extensions/middle/ONNXRNNSequenceNormalize.py b/model-optimizer/extensions/middle/ONNXRNNSequenceNormalize.py index e31cbe3858d..f9ad65c9765 100644 --- a/model-optimizer/extensions/middle/ONNXRNNSequenceNormalize.py +++ b/model-optimizer/extensions/middle/ONNXRNNSequenceNormalize.py @@ -3,6 +3,7 @@ import numpy as np +from mo.front.common.partial_infer.utils import compatible_dims from mo.graph.graph import Graph from mo.middle.replacement import MiddleReplacementPattern from mo.ops.op import Op @@ -105,7 +106,7 @@ class ONNXRNNSequenceNormalize(MiddleReplacementPattern): for x in (W, R)] input_size = match['input'].shape[2] - assert input_size == W.shape[-1] + assert compatible_dims(input_size, W.shape[-1]) # Reorder gates: iofc --> fico gate_reorder = rnn_layer.gate_order diff --git a/model-optimizer/extensions/middle/PartialInfer.py b/model-optimizer/extensions/middle/PartialInfer.py index 6c6f6a60d50..25693b152b3 100644 --- a/model-optimizer/extensions/middle/PartialInfer.py +++ b/model-optimizer/extensions/middle/PartialInfer.py @@ -1,6 +1,8 @@ # Copyright (C) 2018-2021 Intel Corporation # SPDX-License-Identifier: Apache-2.0 +import logging as log +from mo.front.common.partial_infer.utils import is_fully_defined, unmask_shape, shape_array, dynamic_dimension_value from mo.graph.graph import Graph from mo.middle.passes.infer import partial_infer from mo.middle.replacement import MiddleReplacementPattern @@ -18,4 +20,21 @@ class PartialInfer(MiddleReplacementPattern): return [] def find_and_replace_pattern(self, graph: Graph): + dynamic_inputs = {} + for parameter in graph.get_op_nodes(op='Parameter'): + param_shape = parameter.soft_get('shape', shape_array(dynamic_dimension_value)) + if not is_fully_defined(param_shape): + parameter_name = parameter.soft_get('name', parameter.id) + dynamic_inputs[parameter_name] = param_shape + if dynamic_inputs: + log.error('The model contains input(s) with partially defined shapes: {}. ' + 'Starting from the 2022.1 release the Model Optimizer can generate an IR with partially defined ' + 'input shapes ("-1" dimension in the TensorFlow model or dimension with string value in the ONNX ' + 'model). Some of the OpenVINO plugins require model input shapes to be static, so you should ' + 'call "reshape" method in the Inference Engine and specify static input shapes. For optimal ' + 'performance, it is still recommended to update input shapes with fixed ones using "--input" or ' + '"--input_shape" command-line parameters.' + .format(','.join('name="{}" shape="{}"'.format(name, unmask_shape(shape)) + for name, shape in dynamic_inputs.items())), + extra={'is_warning': True}) partial_infer(graph) diff --git a/model-optimizer/extensions/middle/RNNSequenceNormalizeToIE.py b/model-optimizer/extensions/middle/RNNSequenceNormalizeToIE.py index 344af300ff5..40333e51d3f 100644 --- a/model-optimizer/extensions/middle/RNNSequenceNormalizeToIE.py +++ b/model-optimizer/extensions/middle/RNNSequenceNormalizeToIE.py @@ -3,7 +3,7 @@ import numpy as np -from mo.front.common.partial_infer.utils import int64_array +from mo.front.common.partial_infer.utils import int64_array, shape_delete from mo.front.tf.graph_utils import create_op_node_with_second_input from mo.graph.graph import Graph from mo.middle.replacement import MiddleReplacementPattern @@ -142,7 +142,7 @@ class RNNSequenceNormalize(MiddleReplacementPattern): for i in rnn_layer.out_nodes(): old_data_node = rnn_layer.out_node(i) old_shape = old_data_node.shape.copy() - new_shape = np.delete(old_shape, direction_dim[i]) + new_shape = shape_delete(old_shape, direction_dim[i]) data = Op._create_data_node(graph, name=rnn_layer.name + '/Out/{}/'.format(i), attrs={'shape': new_shape}) graph.remove_edge(rnn_layer.id, old_data_node.id) diff --git a/model-optimizer/extensions/middle/SequenceLengthToMask.py b/model-optimizer/extensions/middle/SequenceLengthToMask.py deleted file mode 100644 index d5a2e1ffe5f..00000000000 --- a/model-optimizer/extensions/middle/SequenceLengthToMask.py +++ /dev/null @@ -1,50 +0,0 @@ -# Copyright (C) 2018-2021 Intel Corporation -# SPDX-License-Identifier: Apache-2.0 - -import numpy as np - -from mo.graph.graph import Graph -from mo.middle.replacement import MiddleReplacementPattern -from mo.ops.const import Const -from mo.utils.error import Error - - -class SequenceLengthToMask(MiddleReplacementPattern): - """ - Convert a sequence length to a sequence mask for CTCGreedyDecoder if its value is available. - """ - enabled = True - - def run_before(self): - from extensions.middle.pass_separator import MiddleFinish - return [MiddleFinish] - - def find_and_replace_pattern(self, graph: Graph): - for ctc_greedy_decoder in graph.get_op_nodes(op='CTCGreedyDecoder', use_mask_format=True): - ctc_greedy_decoder_name = ctc_greedy_decoder.soft_get('name', ctc_greedy_decoder.id) - - sequence_length_value = ctc_greedy_decoder.in_port(1).data.get_value() - if sequence_length_value is None: - raise Error('The second input to the CTCGreedyDecoder node "{}" is not constant. This case is not ' - 'supported with the Inference Engine.'.format(ctc_greedy_decoder_name)) - - # transform a sequence length to a sequence mask - logits_shape = ctc_greedy_decoder.in_port(0).data.get_shape() - assert logits_shape is not None and len(logits_shape) == 3, \ - "Incorrect shape for logits input of {} node".format(ctc_greedy_decoder_name) - batch_size = logits_shape[1] - time_size = logits_shape[0] - mask_value = np.zeros([batch_size, time_size], dtype=np.float) - for sample_ind, sample_seq_length in enumerate(sequence_length_value): - mask_value[sample_ind, 0:sample_seq_length] = 1 - mask_value = np.transpose(mask_value) - - # create Const node with computed mask value - mask_node = Const(graph, {'name': ctc_greedy_decoder_name + '/Mask', - 'value': mask_value}).create_node() - - # connect computed mask to CTCGreedyDecoder node - ctc_greedy_decoder.in_port(1).get_connection().set_source(mask_node.out_port(0)) - - # remove attribute-marker - del ctc_greedy_decoder['use_mask_format'] diff --git a/model-optimizer/extensions/middle/StridedSliceNormalizer.py b/model-optimizer/extensions/middle/StridedSliceNormalizer.py index 00ab785847e..bdf442e3efb 100644 --- a/model-optimizer/extensions/middle/StridedSliceNormalizer.py +++ b/model-optimizer/extensions/middle/StridedSliceNormalizer.py @@ -4,7 +4,8 @@ import numpy as np from extensions.ops.split import VariadicSplit -from mo.front.common.partial_infer.utils import int64_array +from mo.front.common.partial_infer.utils import int64_array, dynamic_dimension, dynamic_dimension_value, \ + is_dynamic_slice from mo.front.tf.graph_utils import create_op_with_const_inputs from mo.graph.graph import Graph, Node from mo.graph.perm_inputs import PermuteInputs @@ -115,8 +116,11 @@ class StridedSliceNormalizer(MiddleReplacementPattern): def normalize_strided_slice(graph: Graph, node: Node): input_shape = node.in_port(0).data.get_shape() input_rank = len(input_shape) - begin, _, _ = StridedSlice.validate_inputs_and_get_args(node) - slice_rank = len(begin) + begin = node.in_port(1).data.get_value() + if begin is not None: + slice_rank = len(begin) + else: + slice_rank = input_rank + np.count_nonzero(node.new_axis_mask) - np.count_nonzero(node.shrink_axis_mask) StridedSlice.align_mask_with_slice_rank(node, slice_rank) # if StridedSlice is created after partial_infer StridedSliceNormalizer.normalize_slices_attr(node) @@ -239,6 +243,8 @@ class StridedSliceNormalizer(MiddleReplacementPattern): res_slices.append(s) if not (node.new_axis_mask[i] or node.ellipsis_mask[i]): - res_slices[-1] = slice(*res_slices[-1].indices(data_shape[in_idx])) # convert negative begins/ends + if res_slices[-1] != dynamic_dimension_value and data_shape[in_idx] is not dynamic_dimension and \ + res_slices[-1] is not None and not is_dynamic_slice(res_slices[-1]): + res_slices[-1] = slice(*res_slices[-1].indices(data_shape[in_idx])) # convert negative begins/ends in_idx += 1 node.slices = np.array(res_slices) diff --git a/model-optimizer/extensions/middle/TensorIteratorConditionChecker.py b/model-optimizer/extensions/middle/TensorIteratorConditionChecker.py index 55edb5b4edb..3972c5c1ad0 100644 --- a/model-optimizer/extensions/middle/TensorIteratorConditionChecker.py +++ b/model-optimizer/extensions/middle/TensorIteratorConditionChecker.py @@ -5,6 +5,7 @@ import logging as log import numpy as np +from mo.front.common.partial_infer.utils import compatible_dims from mo.middle.replacement import MiddleReplacementPattern @@ -71,7 +72,7 @@ class ConditionChecks(MiddleReplacementPattern): ''.format(match['minimum_data'].soft_get('name'), match['Strided_slice_data'].value) ) else: - assert match['Strided_slice_data'].value == match['minimum_data'].value, \ + assert compatible_dims(match['Strided_slice_data'].value, match['minimum_data'].value), \ 'Values do not match: {} and {}'.format(match['Strided_slice_data'].value, match['minimum_data'].value) # Check that bound for Condition and Inputs/Outputs sizes match diff --git a/model-optimizer/extensions/middle/TensorIteratorMerge.py b/model-optimizer/extensions/middle/TensorIteratorMerge.py index 3799d1db161..3df05752cfc 100644 --- a/model-optimizer/extensions/middle/TensorIteratorMerge.py +++ b/model-optimizer/extensions/middle/TensorIteratorMerge.py @@ -4,9 +4,8 @@ from collections import deque from copy import deepcopy -import numpy as np - from extensions.ops.tensor_iterator import TensorIterator +from mo.front.common.partial_infer.utils import shape_insert from mo.graph.graph import Node, Graph, add_opoutput from mo.middle.replacement import MiddleReplacementPattern from mo.ops.const import Const @@ -270,7 +269,7 @@ class TensorIteratorMerge(MiddleReplacementPattern): shape = ext_inp['internal_data_id'].shape.copy() assert not ext_inp['internal_data_id'].has_valid('value') new_input_data = Op._create_data_node(body, ext_inp['internal_data_id'].name + '/UnsqueezedInput', - dict(shape=np.insert(shape, ext_inp['axis'], 1))) + dict(shape=shape_insert(shape, ext_inp['axis'], 1))) reshape_op = Squeeze(body, dict(name=ext_inp['internal_data_id'].name + '/InputSqueeze')) reshape_dim_data = Const(body, {'name': ext_inp['internal_data_id'].name + '/ReshapeDim', @@ -304,7 +303,6 @@ class TensorIteratorMerge(MiddleReplacementPattern): if ext_out['axis'] is not None: # Insert unsqueezing resize at output port that has partitioning - assert not ext_out['internal_data_id'].has_valid('value') reshape_op = Unsqueeze(body, dict(name=ext_out['internal_data_id'].name + '/OutputUnsqueeze')) reshape_dim_data = Const(body, {'name': ext_out['internal_data_id'].name + '/ReshapeDim', 'value': ext_out['axis']}).create_node_with_data() diff --git a/model-optimizer/extensions/ops/BlockLSTM.py b/model-optimizer/extensions/ops/BlockLSTM.py index d66a565fda3..2b31375b576 100644 --- a/model-optimizer/extensions/ops/BlockLSTM.py +++ b/model-optimizer/extensions/ops/BlockLSTM.py @@ -8,11 +8,12 @@ from mo.ops.op import Op class BlockLSTM(Op): op = 'BlockLSTM' + enabled = False def __init__(self, graph: Graph, attrs: dict): mandatory_props = { - 'op': __class__.op, - 'infer': __class__.infer, + 'op': self.op, + 'infer': self.infer, 'type': None, } super().__init__(graph, mandatory_props, attrs) @@ -42,7 +43,7 @@ class BlockLSTM(Op): input_shape = node.in_node(0).shape assert len(input_shape) == 3 - out_shape = input_shape - node.out_node(0).shape = out_shape - if len(node.out_nodes()) > 1: - node.out_node(1).shape = out_shape + out_shape = input_shape.copy() + node.out_port(0).data.set_shape(out_shape) + if node.is_out_port_connected(1): + node.out_port(1).data.set_shape(out_shape) diff --git a/model-optimizer/extensions/ops/ClipByValueTF.py b/model-optimizer/extensions/ops/ClipByValueTF.py new file mode 100644 index 00000000000..7bb4a02ddca --- /dev/null +++ b/model-optimizer/extensions/ops/ClipByValueTF.py @@ -0,0 +1,21 @@ +# Copyright (C) 2018-2021 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 + +from mo.graph.graph import Graph +from mo.ops.op import Op + + +class ClibByValueTF(Op): + """ + The ClipByValue from TF which will be replaced with a front transformation. + """ + enabled = False + + def __init__(self, graph: Graph, attrs: dict): + mandatory_props = { + 'op': 'ClipByValueTF', + 'out_ports_count': 1, + 'in_ports_count': 3, + 'infer': None + } + super().__init__(graph, mandatory_props, attrs) diff --git a/model-optimizer/extensions/ops/Enter.py b/model-optimizer/extensions/ops/Enter.py index 4f95837996f..9fa8b677b76 100644 --- a/model-optimizer/extensions/ops/Enter.py +++ b/model-optimizer/extensions/ops/Enter.py @@ -1,8 +1,7 @@ # Copyright (C) 2018-2021 Intel Corporation # SPDX-License-Identifier: Apache-2.0 -import numpy as np - +from mo.front.common.partial_infer.utils import shape_array from mo.graph.graph import Node, Graph from mo.ops.op import Op @@ -13,7 +12,7 @@ class Enter(Op): def __init__(self, graph: Graph, attrs: dict): mandatory_props = { 'type': None, - 'op': __class__.op, + 'op': self.op, 'in_ports_count': 1, 'infer': Enter.enter_infer, } @@ -21,9 +20,9 @@ class Enter(Op): @staticmethod def enter_infer(node: Node): - output_shape = node.in_node(0).shape - output_value = node.in_node(0).value + output_shape = node.in_port(0).data.get_shape() + output_value = node.in_port(0).data.get_value() for _, out_node in node.graph.out_edges(node.id): - node.graph.node[out_node]['shape'] = np.array(output_shape) - node.graph.node[out_node]['value'] = None if output_value is None else np.array(output_value) + node.graph.node[out_node]['shape'] = shape_array(output_shape) + node.graph.node[out_node]['value'] = None if output_value is None else output_value.copy() diff --git a/model-optimizer/extensions/ops/ExtractImagePatches.py b/model-optimizer/extensions/ops/ExtractImagePatches.py index cd1b4eec9eb..bbec081195e 100644 --- a/model-optimizer/extensions/ops/ExtractImagePatches.py +++ b/model-optimizer/extensions/ops/ExtractImagePatches.py @@ -4,13 +4,14 @@ import numpy as np from mo.front.common.layout import shape_for_layout, get_batch_dim, get_features_dim -from mo.front.common.partial_infer.utils import int64_array, tf_window_op_pad_infer +from mo.front.common.partial_infer.utils import tf_window_op_pad_infer, shape_array from mo.graph.graph import Node, Graph from mo.ops.op import Op class ExtractImagePatches(Op): op = "ExtractImagePatches" + enabled = False def __init__(self, graph: Graph, attrs: dict): assert 'spatial_dims' in attrs, \ @@ -47,7 +48,7 @@ class ExtractImagePatches(Op): N = input_shape[get_batch_dim(layout, 4)] C = input_shape[get_features_dim(layout, 4)] - size_spatial = int64_array(node.sizes)[node.spatial_dims] + size_spatial = shape_array(node.sizes)[node.spatial_dims] input_spatial_shape = input_shape[node.spatial_dims] stride_spatial_shape = node.strides[node.spatial_dims] @@ -66,4 +67,4 @@ class ExtractImagePatches(Op): height=output_spatial_shape[0], width=output_spatial_shape[1]) - node.out_port(0).data.set_shape(int64_array(out_shape)) + node.out_port(0).data.set_shape(out_shape) diff --git a/model-optimizer/extensions/ops/GRUCell.py b/model-optimizer/extensions/ops/GRUCell.py index 4b6f935621f..66823e61fd4 100644 --- a/model-optimizer/extensions/ops/GRUCell.py +++ b/model-optimizer/extensions/ops/GRUCell.py @@ -55,17 +55,17 @@ class GRUCell(Op): 'activation_alpha', 'activation_beta', 'clip', - ('linear_before_reset', lambda node: bool_to_str(node, 'linear_before_reset')), + ('linear_before_reset', lambda node: bool_to_str(node, 'linear_before_reset')), ] @staticmethod def infer(node: Node): assert len(node.out_nodes()) in [1, 2] - hidden_shape = node.in_node(1).shape.copy() + hidden_shape = node.in_port(1).data.get_shape().copy() mark_input_bins(node, start_port=2) - node.out_node(0).shape = hidden_shape + node.out_port(0).data.set_shape(hidden_shape) hidden_size = hidden_shape[1] if node.has_valid('hidden_size'): diff --git a/model-optimizer/extensions/ops/GatherTree.py b/model-optimizer/extensions/ops/GatherTree.py index a271b8815d6..2a2c760fdb9 100644 --- a/model-optimizer/extensions/ops/GatherTree.py +++ b/model-optimizer/extensions/ops/GatherTree.py @@ -1,7 +1,7 @@ # Copyright (C) 2018-2021 Intel Corporation # SPDX-License-Identifier: Apache-2.0 - -from mo.graph.graph import Node, Graph +from mo.front.common.partial_infer.elemental import copy_shape_infer +from mo.graph.graph import Graph from mo.ops.op import Op @@ -10,10 +10,10 @@ class GatherTree(Op): def __init__(self, graph: Graph, attrs: dict): mandatory_props = { - 'op': __class__.op, - 'type': __class__.op, + 'op': self.op, + 'type': self.op, 'version': 'opset1', - 'infer': __class__.infer, + 'infer': copy_shape_infer, 'in_ports_count': 4, 'out_ports_count': 1, } @@ -21,7 +21,3 @@ class GatherTree(Op): def supported_attrs(self): return [] - - @staticmethod - def infer(node: Node): - node.out_node().shape = node.in_node(0).shape diff --git a/model-optimizer/extensions/ops/If.py b/model-optimizer/extensions/ops/If.py index 7e930971277..e27bed71232 100644 --- a/model-optimizer/extensions/ops/If.py +++ b/model-optimizer/extensions/ops/If.py @@ -4,7 +4,7 @@ import logging as log import numpy as np -from mo.front.common.partial_infer.utils import int64_array +from mo.front.common.partial_infer.utils import int64_array, is_fully_defined, dynamic_dimension_value from mo.graph.graph import Node, Graph from mo.middle.passes.infer import partial_infer from mo.ops.op import Op @@ -148,6 +148,7 @@ class If(Op): :param if_node: The If node to update output ports and shapes :return: None """ + node_name = if_node.soft_get('name', if_node.id) then_outputs = [node for node in if_node.then_graph.get_op_nodes() if node.has('output_id')] else_outputs = [node for node in if_node.else_graph.get_op_nodes() if node.has('output_id')] @@ -179,20 +180,45 @@ class If(Op): # outputs will have the same shapes as then_body results use_then_shape = else_contains_fake_outputs or not then_contains_fake_outputs + cond_value = if_node.in_port(0).data.get_value() + for port_id in outputs_mapping: then_else_nodes = outputs_mapping[port_id] assert 'then_graph' in then_else_nodes.keys(), 'then_graph does not connect with If.out_port[{0}] ' \ - 'in {1} node!'.format(port_id, if_node.name) + 'in {1} node!'.format(port_id, node_name) assert 'else_graph' in then_else_nodes.keys(), 'else_graph does not connect with If.out_port[{0}] ' \ - 'in {1} node!'.format(port_id, if_node.name) + 'in {1} node!'.format(port_id, node_name) then_shape = then_else_nodes['then_graph'].in_port(0).data.get_shape() + then_value = then_else_nodes['then_graph'].in_port(0).data.get_value() else_shape = then_else_nodes['else_graph'].in_port(0).data.get_shape() + else_value = then_else_nodes['else_graph'].in_port(0).data.get_value() + + if is_fully_defined(cond_value): + if cond_value.item() is True: + if then_value is not None: + if_node.out_port(port_id).data.set_value(then_value) + else: + if_node.out_port(port_id).data.set_shape(then_shape) + else: + if else_value is not None: + if_node.out_port(port_id).data.set_value(else_value) + else: + if_node.out_port(port_id).data.set_shape(else_shape) + else: + if then_contains_fake_outputs ^ else_contains_fake_outputs: + # if exactly one of the outputs is fake then use another one + if_node.out_port(port_id).data.set_shape(then_shape if use_then_shape else else_shape) + else: + # find "intersection" which is equal to the dimension value if corresponding dimensions are equal + # and dynamic otherwise + assert len(then_shape) == len(else_shape), 'Ranks of "then" and "else" output tensors are ' \ + 'different for node {} for port {}'.format(node_name, + port_id) + output_shape = [d1 if is_fully_defined(d1) and is_fully_defined(d2) and d1 == d2 else + dynamic_dimension_value for d1, d2 in zip(then_shape, else_shape)] + if_node.out_port(port_id).data.set_shape(output_shape) - if not (then_shape == else_shape).all(): - log.debug("If node {0} has dynamic output [{1}] because output shape from then_graph is {2} and " - "else_graph {3}".format(if_node.name, port_id, then_shape, else_shape)) - if_node.out_port(port_id).data.set_shape(then_shape if use_then_shape else else_shape) @staticmethod def update_if_output_ports_type(if_node: Node): diff --git a/model-optimizer/extensions/ops/LSTM.py b/model-optimizer/extensions/ops/LSTM.py index 0db068b471c..df91ed4fc19 100644 --- a/model-optimizer/extensions/ops/LSTM.py +++ b/model-optimizer/extensions/ops/LSTM.py @@ -12,11 +12,11 @@ class LSTM(Op): def __init__(self, graph: Graph, attrs: dict): mandatory_props = { 'type': 'RNNSequence', # should be never emitted to IR; for debugging purposes - 'op': __class__.op, + 'op': self.op, 'blobs_wrb': False, # input blobs have three separate components W, R and B like in ONNX/LSTM 'has_num_directions': False, # if True, output shape has 4 dimensions; 3D otherwise 'direction': 'forward', - 'infer': __class__.infer, + 'infer': self.infer, 'multiplier': 4, 'gate_order': None, 'normalized': False, diff --git a/model-optimizer/extensions/ops/LookupTableInsert.py b/model-optimizer/extensions/ops/LookupTableInsert.py index 4284088623b..67498646796 100644 --- a/model-optimizer/extensions/ops/LookupTableInsert.py +++ b/model-optimizer/extensions/ops/LookupTableInsert.py @@ -3,17 +3,16 @@ import numpy as np -from mo.front.common.partial_infer.utils import int64_array from mo.graph.graph import Node, Graph from mo.ops.op import Op class LookupTableInsert(Op): - ''' + """ This operation has only output control flow edges and no output data edges in some models. And for these cases implementation of the shape inference is needed since the shape inference is executed before control flow edges resolving. This operation has non-tensor output so the output shape is empty. - ''' + """ enabled = False op = 'LookupTableInsert' @@ -42,4 +41,4 @@ class LookupTableInsert(Op): # set output shape that must be empty # since output is not a tensor - node.out_port(0).data.set_shape(int64_array([])) + node.out_port(0).data.set_shape([]) diff --git a/model-optimizer/extensions/ops/MatMul.py b/model-optimizer/extensions/ops/MatMul.py index 7fd6cb88937..7fcaa2144ff 100644 --- a/model-optimizer/extensions/ops/MatMul.py +++ b/model-optimizer/extensions/ops/MatMul.py @@ -5,7 +5,8 @@ import logging as log import numpy as np -from mo.front.common.partial_infer.utils import assign_dims_to_weights, int64_array +from mo.front.common.partial_infer.utils import assign_dims_to_weights, int64_array, compatible_dims, compatible_shapes, \ + shape_array, is_fully_defined, shape_delete, shape_insert from mo.front.extractor import bool_to_str from mo.graph.graph import Node, Graph from mo.ops.op import Op @@ -62,14 +63,14 @@ class MatMul(Op): if rank != 1 and ((i == 0 and transpose_a) or (i == 1 and transpose_b)): input_shape[-2], input_shape[-1] = input_shape[-1], input_shape[-2] if rank == 1: - input_shape = np.insert(input_shape, int(i == 1), 1) + input_shape = shape_insert(input_shape, int(i == 1), 1) max_shape_length = max(input_shapes[0].size, input_shapes[1].size) - input_shape = np.insert(input_shape, 0, [1] * (max_shape_length - input_shape.size)) + input_shape = shape_insert(input_shape, 0, [1] * (max_shape_length - input_shape.size)) transformed_shapes.append(input_shape) - A_shape = transformed_shapes[0] - B_shape = transformed_shapes[1] + A_shape = shape_array(transformed_shapes[0]) + B_shape = shape_array(transformed_shapes[1]) assert A_shape.size == B_shape.size, \ "Shapes were not aligned by length for MatMul `{}`. Shapes: `{}`".format(node_name, transformed_shapes) @@ -83,7 +84,7 @@ class MatMul(Op): if B_shape[i] == 1: B_shape[i] = A_shape[i] - assert np.array_equal(A_shape[:-2], B_shape[:-2]), \ + assert compatible_shapes(A_shape[:-2], B_shape[:-2]), \ "MatMul input shapes are incorrect. BATCH_DIMs are not equal. Node: {}. Aligned shapes: {}" \ "".format(node_name, transformed_shapes) @@ -98,11 +99,16 @@ class MatMul(Op): """ a_value = node.in_port(0).get_source().data.get_value() b_value = node.in_port(1).get_source().data.get_value() - if a_value is not None and b_value is not None: + if is_fully_defined(a_value) and is_fully_defined(b_value): if node.transpose_a: a_value = transpose(a_value) if node.transpose_b: b_value = transpose(b_value) + # np.matmul does not work correctly with masked arrays, so need explicitly convert inputs to regular arrays + if isinstance(a_value, np.ma.masked_array): + a_value = a_value.filled() + if isinstance(b_value, np.ma.masked_array): + b_value = b_value.filled() node.out_port(0).data.set_value(np.matmul(a_value, b_value)) @staticmethod @@ -121,18 +127,18 @@ class MatMul(Op): A_shape, B_shape = MatMul.shape_alignment(node) log.debug('MatMul `{}` aligned input shapes: {}'.format(name, [A_shape, B_shape])) - assert A_shape[-1] == B_shape[-2], \ + assert compatible_dims(A_shape[-1], B_shape[-2]), \ "MatMul input shapes are incorrect. COL_INDEX_DIMs are not equal. Node: {}. Shapes: {}" \ "".format(name, [A_shape, B_shape]) - output_shape = np.concatenate((A_shape[:-1], B_shape[-1:])) + output_shape = np.ma.concatenate((A_shape[:-1], B_shape[-1:])) if node.in_port(0).data.get_shape().size == 1: - assert output_shape[-2] == 1 - output_shape = np.delete(output_shape, -2, 0) + assert compatible_dims(output_shape[-2], 1) + output_shape = shape_delete(output_shape, -2) if node.in_port(1).data.get_shape().size == 1: - assert output_shape[-1] == 1 - output_shape = np.delete(output_shape, -1, 0) + assert compatible_dims(output_shape[-1], 1) + output_shape = shape_delete(output_shape, -1) node.out_port(0).data.set_shape(output_shape) @@ -149,8 +155,8 @@ def transpose(value): else: return np.transpose(value, [*range(0, num_of_dims - 2), num_of_dims - 1, num_of_dims - 2]) -# MatMul-like operation from frameworks +# MatMul-like operation from frameworks class GemmONNX(Op): """ Represents Gemm operation from ONNX @@ -163,7 +169,7 @@ class GemmONNX(Op): def __init__(self, graph: Graph, attrs: dict): mandatory_props = { - 'op': __class__.op, + 'op': self.op, 'transpose_a': False, 'transpose_b': False, 'alpha': 1, @@ -182,9 +188,9 @@ class FullyConnected(Op): def __init__(self, graph: Graph, attrs: dict): super().__init__(graph, { - 'op': __class__.op, - 'type': __class__.op, - 'infer': __class__.infer, + 'op': self.op, + 'type': self.op, + 'infer': self.infer, 'in_ports_count': 3, 'out_ports_count': 1, }, attrs) @@ -210,22 +216,21 @@ class FullyConnected(Op): 'Incorrect FullyConnected input shapes. Node: {}. Shapes: {}'.format(name, [input_shape, weights_shape]) assert weights_shape.size == 2 out_size = node.soft_get('out-size') - assert weights_shape[0] == out_size, 'weights_shape={}, out-size={}'.format(weights_shape, out_size) + assert compatible_dims(weights_shape[0], out_size), \ + 'weights_shape={}, out-size={}'.format(weights_shape, out_size) if 2 in connected_in_ports: bias_value = node.in_port(2).data.get_value() bias_shape = node.in_port(2).data.get_shape() assert bias_shape is not None, 'Shape was not inferred for biases of FullyConnected {}'.format(name) assert bias_value is not None, 'Value was not inferred for biases of FullyConnected {}'.format(name) - assert np.array_equal(bias_shape, [out_size]) or np.array_equal(bias_shape, [1, out_size]), \ + assert compatible_shapes(bias_shape, [out_size]) or compatible_shapes(bias_shape, [1, out_size]), \ 'Incorrect FullyConnected bias shape `{}` for node {}. `out-size`={}'.format(bias_shape, node, out_size) - out_shape = int64_array([*input_shape[:-1], out_size]) - node.out_port(0).data.set_shape(out_shape) + node.out_port(0).data.set_shape([*input_shape[:-1], out_size]) # MatMul-like operations for IR V6 - class Gemm(MatMul): """ Represents GEMM operation that is acceptable to appear in v6 IRs diff --git a/model-optimizer/extensions/ops/ONNXResize11.py b/model-optimizer/extensions/ops/ONNXResize11.py index 5476087a3d4..3d9d5e42fb8 100644 --- a/model-optimizer/extensions/ops/ONNXResize11.py +++ b/model-optimizer/extensions/ops/ONNXResize11.py @@ -36,8 +36,8 @@ class ONNXResize11Op(Op): return assert (node.is_in_port_connected(0) and (node.is_in_port_connected(2) or node.is_in_port_connected(3))), \ - "One of the scales or sizes inputs must be connected to Node {} with op {}.".format(node.soft_get("name", node.id), - node.op) + "One of the scales or sizes inputs must be connected to Node {} with op {}." \ + "".format(node.soft_get("name", node.id), node.op) assert node.coordinate_transformation_mode != 'tf_crop_and_resize', \ 'Mode tf_crop_and_resize is not supported for op {} with name {}'.format(node.op, @@ -57,6 +57,6 @@ class ONNXResize11Op(Op): "Node {} with op {} has no value in input port 3".format(node.soft_get("name", node.id), node.op) output_shape = input_shape.copy() spatial_dimension_indices = range(2, len(input_shape)) - output_shape[spatial_dimension_indices] = int64_array(sizes)[2:] + output_shape[spatial_dimension_indices] = sizes[2:] - node.out_port(0).data.set_shape(output_shape.copy()) + node.out_port(0).data.set_shape(output_shape) diff --git a/model-optimizer/extensions/ops/RNN.py b/model-optimizer/extensions/ops/RNN.py index e20c12f0cb3..1f40f20c2aa 100644 --- a/model-optimizer/extensions/ops/RNN.py +++ b/model-optimizer/extensions/ops/RNN.py @@ -3,7 +3,7 @@ import numpy as np -from mo.front.common.partial_infer.utils import mark_input_bins +from mo.front.common.partial_infer.utils import mark_input_bins, shape_array, shape_insert from mo.graph.graph import Node, Graph, add_opoutput from mo.ops.op import Op @@ -14,11 +14,11 @@ class RNN(Op): def __init__(self, graph: Graph, attrs: dict): mandatory_props = { 'type': 'RNNSequence', # should be never emitted to IR; for debugging purposes - 'op': __class__.op, + 'op': self.op, 'blobs_wrb': False, 'has_num_directions': False, 'direction': 'forward', - 'infer': __class__.infer, + 'infer': self.infer, 'multiplier': 1, 'gate_order': np.array([0]), # Only one gate in this cell 'normalized': False, @@ -101,10 +101,10 @@ def rnn_infer(node: Node, out_ports=None): node.in_node(port).value = np.repeat(node.in_node(port).value, input_shape[i], axis=i) node.in_node(port).shape[i] = input_shape[i] - out_shape = np.array([input_shape[node.sequence_dim], input_shape[node.batch_dim], node.hidden_size], dtype=np.int64) + out_shape = [input_shape[node.sequence_dim], input_shape[node.batch_dim], node.hidden_size] if node.batch_dim == 0: - out_shape = np.array([input_shape[node.batch_dim], input_shape[node.sequence_dim], node.hidden_size], dtype=np.int64) + out_shape = [input_shape[node.batch_dim], input_shape[node.sequence_dim], node.hidden_size] num_directions = 2 if node.direction in ['bidirectional'] else 1 if node.has_num_directions: @@ -113,7 +113,7 @@ def rnn_infer(node: Node, out_ports=None): out_shape[-1] *= num_directions else: # ONNX-like, insert extra dimension to output shape for num_directions - out_shape = np.insert(out_shape, 1, np.int64(num_directions)) + out_shape = shape_insert(out_shape, 1, np.int64(num_directions)) # 0 output is required creating it if doesn't exist if 0 not in node.out_nodes(): @@ -129,9 +129,9 @@ def rnn_infer(node: Node, out_ports=None): node.out_port(0).data.set_shape(out_shape) # 3. Extra outputs for hidden/cell states shape calculations (optional) - state_size = np.array([input_shape[node.batch_dim], node.hidden_size], dtype=np.int64) + state_size = [input_shape[node.batch_dim], node.hidden_size] if node.has_num_directions: - state_size = np.insert(state_size, 0, num_directions) + state_size = shape_insert(state_size, 0, num_directions) if node.multilayers: # For multilayer case state sizes from every layer will be concatenated by last axis @@ -152,4 +152,4 @@ def rnn_infer(node: Node, out_ports=None): add_opoutput(node.graph, data_node.id, 0, False) else: data_node = node.out_node(i) - data_node.shape = state_size.copy() + data_node.shape = shape_array(state_size) diff --git a/model-optimizer/extensions/ops/RNNCell.py b/model-optimizer/extensions/ops/RNNCell.py index 065c277ff26..926d44ee393 100644 --- a/model-optimizer/extensions/ops/RNNCell.py +++ b/model-optimizer/extensions/ops/RNNCell.py @@ -25,10 +25,9 @@ class RNNCell(Op): def __init__(self, graph: Graph, attrs: dict): mandatory_props = { - 'type': __class__.op, - 'op': __class__.op, - 'version': 'experimental', - 'infer': __class__.infer, + 'type': self.op, + 'op': self.op, + 'infer': self.infer, 'in_ports_count': 4, 'out_ports_count': 1, 'version': 'opset3', diff --git a/model-optimizer/extensions/ops/ReduceOps.py b/model-optimizer/extensions/ops/ReduceOps.py index 890f7e77ade..c5c77540a8e 100644 --- a/model-optimizer/extensions/ops/ReduceOps.py +++ b/model-optimizer/extensions/ops/ReduceOps.py @@ -3,7 +3,7 @@ import numpy as np -from mo.front.common.partial_infer.utils import int64_array +from mo.front.common.partial_infer.utils import int64_array, is_fully_defined from mo.front.extractor import bool_to_str from mo.graph.graph import Node, Graph from mo.graph.perm_inputs import PermuteInputs @@ -23,6 +23,25 @@ reduce_map = { } +def reduce_helper(func: callable, x: np.array, axis: tuple, keepdims: bool): + """ + Performs the reduction of input data tensor "x" over axis "axis" with function "func" and optionally removes reduced + dimensions (if "keepdims" is False). If the input tensor has dynamic values, all elements of the result tensor + are changed to be dynamic. + + :param func: numpy reduce function + :param x: the data to perform reduction on + :param axis: the axis for reduction + :param keepdims: flag specifying whether keep reduce dimensions or not + :return: the result tensor + """ + result = func(x, axis=axis, keepdims=keepdims) + if is_fully_defined(x): + return result + else: + return np.ma.masked_array(result, mask=np.ones(result.shape, dtype=np.bool)) + + def reduce_infer(node: Node): connected_in_ports = [port for port in node.in_ports().values() if not port.disconnected()] assert len(connected_in_ports) == 2, \ @@ -47,7 +66,7 @@ def reduce_infer(node: Node): in_value = in_data.get_value() if in_value is not None: - value = reduce_map[node.op](in_value.copy(), axis=tuple(axis), keepdims=node.keep_dims) + value = reduce_helper(reduce_map[node.op], in_value.copy(), axis=tuple(axis), keepdims=node.keep_dims) node.out_port(0).data.set_value(value) else: used_dims = np.zeros(len(in_shape), dtype=np.bool) @@ -133,6 +152,7 @@ class ReduceL1(ReduceOp): op_type = 'ReduceL1' version = 'opset4' + class ReduceL2(ReduceOp): op = 'ReduceL2' op_type = 'ReduceL2' diff --git a/model-optimizer/extensions/ops/Reverse.py b/model-optimizer/extensions/ops/Reverse.py index f51be7f29ef..9bc92ffc779 100644 --- a/model-optimizer/extensions/ops/Reverse.py +++ b/model-optimizer/extensions/ops/Reverse.py @@ -13,19 +13,20 @@ class Reverse(Op): def __init__(self, graph: Graph, attrs: dict): mandatory_props = { - # 'type': __class__.op, # Internal MO primitive + 'type': None, 'axis': None, - 'op': __class__.op, + 'op': self.op, 'in_ports_count': 2, 'out_ports_count': 1, - 'infer': __class__.infer, + 'infer': self.infer, } super().__init__(graph, mandatory_props, attrs) @staticmethod def infer(node): - input_data_shape = node.in_node(0).shape - assert input_data_shape is not None + input_shape = node.in_port(0).data.get_shape() + input_value = node.in_port(0).data.get_value() + assert input_shape is not None if not node.has_valid('axis'): assert 1 in node.in_nodes() assert node.in_node(1).has_valid('value') @@ -37,7 +38,7 @@ class Reverse(Op): assert node.has_valid('axis') assert len(node.out_nodes()) == 1 - node.out_node().shape = input_data_shape.copy() - if node.in_node().value is not None: - node.out_node().value = np.flip(node.in_node().value, node['axis']) - assert np.array_equal(int64_array(node.out_node().value.shape), input_data_shape) + if input_value is not None: + node.out_port(0).data.set_value(np.flip(input_value, node.axis)) + else: + node.out_port(0).data.set_shape(input_shape) diff --git a/model-optimizer/extensions/ops/TFResize.py b/model-optimizer/extensions/ops/TFResize.py index c114a36926e..7662cb28e90 100644 --- a/model-optimizer/extensions/ops/TFResize.py +++ b/model-optimizer/extensions/ops/TFResize.py @@ -1,8 +1,6 @@ # Copyright (C) 2018-2021 Intel Corporation # SPDX-License-Identifier: Apache-2.0 -from mo.front.common.layout import get_height_dim, get_width_dim -from mo.front.common.partial_infer.utils import int64_array from mo.graph.graph import Node, Graph from mo.ops.op import Op @@ -45,10 +43,9 @@ class TFResize(Op): len_msg = "Op {} with name {} supports only resize with respect to height and width dimension simultaneously" assert len(new_sizes_value) == 2, len_msg.format(node_name, node.op) - output_shape = int64_array(input_shape.copy()) + output_shape = input_shape.copy() - layout = node.graph.graph['layout'] - output_shape[get_height_dim(layout, input_rank)] = new_sizes_value[0] - output_shape[get_width_dim(layout, input_rank)] = new_sizes_value[1] + output_shape[1] = new_sizes_value[0] + output_shape[2] = new_sizes_value[1] node.out_port(0).data.set_shape(output_shape) diff --git a/model-optimizer/extensions/ops/TensorArray.py b/model-optimizer/extensions/ops/TensorArray.py index 40e8ddbfd28..b0a4bc1fac6 100644 --- a/model-optimizer/extensions/ops/TensorArray.py +++ b/model-optimizer/extensions/ops/TensorArray.py @@ -3,6 +3,7 @@ import numpy as np +from mo.front.common.partial_infer.utils import shape_array from mo.graph.graph import Node, Graph from mo.ops.op import Op @@ -13,7 +14,7 @@ class TensorArray(Op): def __init__(self, graph: Graph, attrs: dict): mandatory_props = { 'type': None, - 'op': __class__.op, + 'op': self.op, 'infer': TensorArray.array_infer, } super().__init__(graph, mandatory_props, attrs) @@ -35,9 +36,9 @@ class TensorArray(Op): node.graph.node[out_node]['value'] = np.array(output_value) output_shape = node.graph.node[out_node]['value'].shape - node.graph.node[out_node]['shape'] = np.array(output_shape) + node.graph.node[out_node]['shape'] = shape_array(output_shape) - node.graph.node[out_node]['element_shape'] = np.array(element_shape) + node.graph.node[out_node]['element_shape'] = shape_array(element_shape) node.graph.node[out_node]['size'] = size.value # 1 port flow if 1 in node.out_nodes().keys(): @@ -45,4 +46,4 @@ class TensorArray(Op): out_node = node.out_node(1).id node.graph.node[out_node]['value'] = None if output_value is None else np.array(output_value) - node.graph.node[out_node]['shape'] = np.array(output_shape) + node.graph.node[out_node]['shape'] = shape_array(output_shape) diff --git a/model-optimizer/extensions/ops/TensorArrayGather.py b/model-optimizer/extensions/ops/TensorArrayGather.py index e3adca7296c..2d6fa9a720b 100644 --- a/model-optimizer/extensions/ops/TensorArrayGather.py +++ b/model-optimizer/extensions/ops/TensorArrayGather.py @@ -1,8 +1,7 @@ # Copyright (C) 2018-2021 Intel Corporation # SPDX-License-Identifier: Apache-2.0 -import numpy as np - +from mo.front.common.partial_infer.utils import shape_array from mo.graph.graph import Node, Graph from mo.ops.op import Op from mo.utils.utils import symm_match_shapes @@ -14,7 +13,7 @@ class TensorArrayGather(Op): def __init__(self, graph: Graph, attrs: dict): mandatory_props = { 'type': None, - 'op': __class__.op, + 'op': self.op, 'infer': TensorArrayGather.array_infer, } super().__init__(graph, mandatory_props, attrs) @@ -24,8 +23,6 @@ class TensorArrayGather(Op): assert len(node.in_nodes()) == 3 handle = node.in_node(0) - indices = node.in_node(1) - flow_in = node.in_node(2) ta_node = Node(node.graph, str(handle.value)) @@ -34,16 +31,12 @@ class TensorArrayGather(Op): else: ta_node['element_shape'] = node.element_shape data_shape = ta_node['element_shape'] - assert -1 not in data_shape or data_shape.size == 2 and data_shape[0] == -1 and data_shape[1] != -1 assert ta_node.has_valid('size') size = ta_node['size'] - assert size > 0 - output_shape = [size] + [data_shape[i] for i in range(len(data_shape))] - output_value = None for _, out_node in node.graph.out_edges(node.id): - node.graph.node[out_node]['shape'] = np.array(output_shape) - node.graph.node[out_node]['value'] = None if output_value is None else np.array(output_value) + node.graph.node[out_node]['shape'] = shape_array(output_shape) + node.graph.node[out_node]['value'] = None diff --git a/model-optimizer/extensions/ops/TensorArrayRead.py b/model-optimizer/extensions/ops/TensorArrayRead.py index d4d24d33469..8b18e9c6c60 100644 --- a/model-optimizer/extensions/ops/TensorArrayRead.py +++ b/model-optimizer/extensions/ops/TensorArrayRead.py @@ -1,8 +1,7 @@ # Copyright (C) 2018-2021 Intel Corporation # SPDX-License-Identifier: Apache-2.0 -import numpy as np - +from mo.front.common.partial_infer.utils import shape_array from mo.graph.graph import Node, Graph from mo.ops.op import Op @@ -13,7 +12,7 @@ class TensorArrayReader(Op): def __init__(self, graph: Graph, attrs: dict): mandatory_props = { 'type': None, - 'op': __class__.op, + 'op': self.op, 'infer': TensorArrayReader.array_infer, } super().__init__(graph, mandatory_props, attrs) @@ -23,17 +22,10 @@ class TensorArrayReader(Op): assert len(node.in_nodes()) == 3 handle = node.in_node(0) - index = node.in_node(1) - flow_in = node.in_node(2) ta_node = Node(node.graph, str(handle.value)) assert ta_node.has_valid('element_shape') - data_shape = ta_node['element_shape'] - - output_shape = data_shape - output_value = None - for _, out_node in node.graph.out_edges(node.id): - node.graph.node[out_node]['shape'] = np.array(output_shape) - node.graph.node[out_node]['value'] = None if output_value is None else np.array(output_value) + node.graph.node[out_node]['shape'] = shape_array(ta_node['element_shape']) + node.graph.node[out_node]['value'] = None diff --git a/model-optimizer/extensions/ops/TensorArrayScatter.py b/model-optimizer/extensions/ops/TensorArrayScatter.py index 0ef26a20c56..dd6683b403f 100644 --- a/model-optimizer/extensions/ops/TensorArrayScatter.py +++ b/model-optimizer/extensions/ops/TensorArrayScatter.py @@ -3,6 +3,7 @@ import numpy as np +from mo.front.common.partial_infer.utils import shape_array from mo.graph.graph import Node, Graph from mo.ops.op import Op from mo.utils.utils import match_shapes @@ -14,7 +15,7 @@ class TensorArrayScatter(Op): def __init__(self, graph: Graph, attrs: dict): mandatory_props = { 'type': None, - 'op': __class__.op, + 'op': self.op, 'infer': TensorArrayScatter.array_infer, } super().__init__(graph, mandatory_props, attrs) @@ -22,7 +23,6 @@ class TensorArrayScatter(Op): @staticmethod def array_infer(node: Node): handle = node.in_node(0) - indices = node.in_node(1) value = node.in_node(2) flow_in = node.in_node(3) @@ -36,9 +36,7 @@ class TensorArrayScatter(Op): # Assign element_shape anyway, because the original element_shape can contain -1 ta_node['element_shape'] = value.shape[1:] - output_shape = flow_in.shape output_value = flow_in.value - #flow_out for _, out_node in node.graph.out_edges(node.id): - node.graph.node[out_node]['shape'] = np.array(output_shape) + node.graph.node[out_node]['shape'] = shape_array(flow_in.shape) node.graph.node[out_node]['value'] = None if output_value is None else np.array(output_value) diff --git a/model-optimizer/extensions/ops/TensorArraySize.py b/model-optimizer/extensions/ops/TensorArraySize.py index 4281bebdb64..4548a9664e7 100644 --- a/model-optimizer/extensions/ops/TensorArraySize.py +++ b/model-optimizer/extensions/ops/TensorArraySize.py @@ -3,6 +3,7 @@ import numpy as np +from mo.front.common.partial_infer.utils import shape_array from mo.graph.graph import Node, Graph from mo.ops.op import Op @@ -13,7 +14,7 @@ class TensorArraySize(Op): def __init__(self, graph: Graph, attrs: dict): mandatory_props = { 'type': None, - 'op': __class__.op, + 'op': self.op, 'infer': TensorArraySize.array_infer, } super().__init__(graph, mandatory_props, attrs) @@ -23,14 +24,12 @@ class TensorArraySize(Op): assert len(node.in_nodes()) == 2 handle = node.in_node(0) - flow_in = node.in_node(1) ta_node = Node(node.graph, str(handle.value)) assert ta_node.has_valid('size') output_value = np.array(ta_node['size']) - output_shape = output_value.shape for _, out_node in node.graph.out_edges(node.id): - node.graph.node[out_node]['shape'] = np.array(output_shape) - node.graph.node[out_node]['value'] = None if output_value is None else np.array(output_value) + node.graph.node[out_node]['shape'] = shape_array(output_value.shape) + node.graph.node[out_node]['value'] = output_value.copy() diff --git a/model-optimizer/extensions/ops/TensorArrayWrite.py b/model-optimizer/extensions/ops/TensorArrayWrite.py index d35ebaa1264..d04758ed244 100644 --- a/model-optimizer/extensions/ops/TensorArrayWrite.py +++ b/model-optimizer/extensions/ops/TensorArrayWrite.py @@ -1,8 +1,7 @@ # Copyright (C) 2018-2021 Intel Corporation # SPDX-License-Identifier: Apache-2.0 -import numpy as np - +from mo.front.common.partial_infer.utils import shape_array from mo.graph.graph import Node, Graph from mo.ops.op import Op from mo.utils.utils import match_shapes @@ -14,7 +13,7 @@ class TensorArrayWriter(Op): def __init__(self, graph: Graph, attrs: dict): mandatory_props = { 'type': None, - 'op': __class__.op, + 'op': self.op, 'infer': TensorArrayWriter.array_infer, } super().__init__(graph, mandatory_props, attrs) @@ -36,10 +35,8 @@ class TensorArrayWriter(Op): 'Shapes are not compatible: {} and {}'.format(ta_node['element_shape'], value.shape) ta_node['element_shape'] = value_shape - output_shape = flow_in.shape output_value = flow_in.value - # flow_out for _, out_node in node.graph.out_edges(node.id): - node.graph.node[out_node]['shape'] = np.array(output_shape) - node.graph.node[out_node]['value'] = None if output_value is None else np.array(output_value) + node.graph.node[out_node]['shape'] = shape_array(flow_in.shape) + node.graph.node[out_node]['value'] = None if output_value is None else output_value.copy() diff --git a/model-optimizer/extensions/ops/accum.py b/model-optimizer/extensions/ops/accum.py deleted file mode 100644 index c283df30d01..00000000000 --- a/model-optimizer/extensions/ops/accum.py +++ /dev/null @@ -1,78 +0,0 @@ -# Copyright (C) 2018-2021 Intel Corporation -# SPDX-License-Identifier: Apache-2.0 - -import numpy as np - -from mo.graph.graph import Node, Graph -from mo.ops.op import Op - - -class AccumOp(Op): - op = 'Accum' - - def __init__(self, graph: Graph, attrs: dict): - mandatory_props = { - 'type': __class__.op, - 'op': __class__.op, - 'version': 'extension', - 'top_height': 0, - 'top_width': 0, - 'size_divisible_by': 0, - 'have_reference': 0, - 'out_ports_count': 1, - 'infer': AccumOp.accum_infer - } - super().__init__(graph, mandatory_props, attrs) - - def supported_attrs(self): - return [ - 'top_height', - 'top_width', - 'size_divisible_by', - 'have_reference' - ] - - @staticmethod - def accum_infer(node: Node): - - batch = node.in_node(0).shape[0] - num_inputs = len(node.in_nodes()) - - if node.have_reference: - assert num_inputs >= 2, "Need at least two bottom blobs (one as reference)" - total_channels = 0 - for i in range(num_inputs): - total_channels += node.in_node(i).shape[1] - assert node.in_node(i).shape[0] == batch, "All accumulated layers must have same number of images" - assert total_channels >= 1, "Accumulated layers must have some channels in total" - top_height_ = node.in_node(num_inputs - 1).shape[2] # height - top_width_ = node.in_node(num_inputs - 1).shape[3] # width - height_ = top_height_ - width_ = top_width_ - else: - max_height = -1 - max_width = -1 - total_channels = 0 - - for i in range(num_inputs): - total_channels += node.in_node(i).shape[1] - max_height = node.in_node(i).shape[2] if node.in_node(i).shape[2] > max_height else max_height - max_width = node.in_node(i).shape[3] if node.in_node(i).shape[3] > max_width else max_width - assert node.in_node(i).shape[0] == batch, "All accumulated layers must have same number of images" - assert total_channels >= 1, "Accumulated layers must have some channels in total" - - if node.size_divisible_by: - sdb = node.size_divisible_by - top_height_ = int(np.ceil(max_height / sdb) * sdb) - top_width_ = int(np.ceil(max_width / sdb) * sdb) - else: - top_height_ = node.top_height - top_width_ = node.top_width - if top_height_ > max_height and top_width_ > max_width: # Layer can specify custom top size which is larger than default - height_ = top_height_ - width_ = top_width_ - else: # Otherwise maximum of bottom sizes will be used - height_ = max_height - width_ = max_width - channels_ = total_channels - node.out_node(0).shape = np.array([batch, channels_, height_, width_]) diff --git a/model-optimizer/extensions/ops/activation_ops.py b/model-optimizer/extensions/ops/activation_ops.py index b9894d529b0..07be5469971 100644 --- a/model-optimizer/extensions/ops/activation_ops.py +++ b/model-optimizer/extensions/ops/activation_ops.py @@ -35,22 +35,22 @@ class Activation(Op): class Sigmoid(Activation): op = 'Sigmoid' - operation = staticmethod(lambda x: 1 / (1 + np.exp(-x))) + operation = staticmethod(lambda x: 1 / (1 + np.ma.exp(-x))) class Sin(Activation): op = 'Sin' - operation = staticmethod(lambda x: np.sin(x)) + operation = staticmethod(lambda x: np.ma.sin(x)) class Sinh(Activation): op = 'Sinh' - operation = staticmethod(lambda x: np.sinh(x)) + operation = staticmethod(lambda x: np.ma.sinh(x)) class Asin(Activation): op = 'Asin' - operation = staticmethod(lambda x: np.arcsin(x)) + operation = staticmethod(lambda x: np.ma.arcsin(x)) class Asinh(Activation): @@ -61,44 +61,44 @@ class Asinh(Activation): class Cos(Activation): op = 'Cos' - operation = staticmethod(lambda x: np.cos(x)) + operation = staticmethod(lambda x: np.ma.cos(x)) class Cosh(Activation): op = 'Cosh' - operation = staticmethod(lambda x: np.cosh(x)) + operation = staticmethod(lambda x: np.ma.cosh(x)) class Acos(Activation): op = 'Acos' - operation = staticmethod(lambda x: np.arccos(x)) + operation = staticmethod(lambda x: np.ma.arccos(x)) class Acosh(Activation): op = 'Acosh' version = 'opset4' - operation = staticmethod(lambda x: np.arccosh(x)) + operation = staticmethod(lambda x: np.ma.arccosh(x)) class Tan(Activation): op = 'Tan' - operation = staticmethod(lambda x: np.tan(x)) + operation = staticmethod(lambda x: np.ma.tan(x)) class Tanh(Activation): op = 'Tanh' - operation = staticmethod(lambda x: np.tanh(x)) + operation = staticmethod(lambda x: np.ma.tanh(x)) class Atan(Activation): op = 'Atan' - operation = staticmethod(lambda x: np.arctan(x)) + operation = staticmethod(lambda x: np.ma.arctan(x)) class Atanh(Activation): op = 'Atanh' version = 'opset4' - operation = staticmethod(lambda x: np.arctanh(x)) + operation = staticmethod(lambda x: np.ma.arctanh(x)) class ReLU6(AttributedClamp): @@ -110,12 +110,12 @@ class ReLU6(AttributedClamp): class Exp(Activation): op = 'Exp' - operation = staticmethod(lambda x: np.exp(x)) + operation = staticmethod(lambda x: np.ma.exp(x)) class ReLU(Activation): op = 'ReLU' - operation = staticmethod(lambda x: np.maximum(0, x)) + operation = staticmethod(lambda x: np.ma.maximum(0, x)) class Erf(Activation): @@ -125,17 +125,17 @@ class Erf(Activation): class Floor(Activation): op = 'Floor' - operation = staticmethod(lambda x: np.floor(x)) + operation = staticmethod(lambda x: np.ma.floor(x)) class Ceiling(Activation): op = 'Ceiling' - operation = staticmethod(lambda x: np.ceil(x)) + operation = staticmethod(lambda x: np.ma.ceil(x)) class Abs(Activation): op = 'Abs' - operation = staticmethod(lambda x: np.abs(x)) + operation = staticmethod(lambda x: np.ma.abs(x)) class Sign(Activation): @@ -156,7 +156,7 @@ class Elu(Activation): values = values.astype(float) for index, x in np.ndenumerate(values): if x < 0: - values[index] = alpha * (np.exp(x) - 1) + values[index] = alpha * (np.ma.exp(x) - 1) return values @classmethod @@ -226,7 +226,7 @@ class LogicalNot(Activation): not_attrs.update(attrs) super().__init__(graph, not_attrs) - operation = staticmethod(lambda x: np.logical_not(x)) + operation = staticmethod(lambda x: np.ma.logical_not(x)) @staticmethod def type_infer(node: Node): @@ -235,31 +235,31 @@ class LogicalNot(Activation): class Log(Activation): op = 'Log' - operation = staticmethod(lambda x: np.log(x)) + operation = staticmethod(lambda x: np.ma.log(x)) class SoftPlus(Activation): op = 'SoftPlus' version = 'opset4' - operation = staticmethod(lambda x: np.log(np.exp(x) + 1.0)) + operation = staticmethod(lambda x: np.ma.log(np.ma.exp(x) + 1.0)) class Mish(Activation): op = 'Mish' version = 'opset4' - operation = staticmethod(lambda x: x * np.tanh(np.log(np.exp(x) + 1.0))) + operation = staticmethod(lambda x: x * np.ma.tanh(np.ma.log(np.ma.exp(x) + 1.0))) class HSwish(Activation): op = 'HSwish' version = 'opset4' - operation = staticmethod(lambda x: x * np.minimum(np.maximum(x + 3.0, 0.0), 6.0) / 6.0) + operation = staticmethod(lambda x: x * np.ma.minimum(np.ma.maximum(x + 3.0, 0.0), 6.0) / 6.0) class HSigmoid(Activation): op = 'HSigmoid' version = 'opset5' - operation = staticmethod(lambda x: np.minimum(np.maximum(x + 3.0, 0.0), 6.0) / 6.0) + operation = staticmethod(lambda x: np.ma.minimum(np.ma.maximum(x + 3.0, 0.0), 6.0) / 6.0) class Swish(Op): diff --git a/model-optimizer/extensions/ops/argmax.py b/model-optimizer/extensions/ops/argmax.py index d3b5a76adaf..15baf7efe10 100644 --- a/model-optimizer/extensions/ops/argmax.py +++ b/model-optimizer/extensions/ops/argmax.py @@ -6,7 +6,6 @@ import logging as log import numpy as np from mo.front.caffe.extractors.utils import get_canonical_axis_index -from mo.front.common.partial_infer.utils import int64_array from mo.graph.graph import Node, Graph from mo.ops.op import Op, PermuteAttrs @@ -36,7 +35,7 @@ def arg_ops_infer(node: Node): if node.has_valid('axis'): axis = get_canonical_axis_index(shape, node.axis) node.axis = axis - out_shape = int64_array(shape) + out_shape = shape.copy() out_shape[axis] = node.top_k PermuteAttrs.create_permute_attrs(node, attrs=[('axis', 'input:0')]) else: diff --git a/model-optimizer/extensions/ops/assert_op.py b/model-optimizer/extensions/ops/assert_op.py index 392f528e8fb..043c45f0152 100644 --- a/model-optimizer/extensions/ops/assert_op.py +++ b/model-optimizer/extensions/ops/assert_op.py @@ -19,7 +19,7 @@ class Assert(Op): @staticmethod def assert_infer(node: Node): assert_value = node.in_node(0).value - node.out_node().value = assert_value + node.out_node().value = assert_value.copy() node.out_node().shape = [] @staticmethod diff --git a/model-optimizer/extensions/ops/box_nms.py b/model-optimizer/extensions/ops/box_nms.py index d42e68b42ac..448a1b73df5 100644 --- a/model-optimizer/extensions/ops/box_nms.py +++ b/model-optimizer/extensions/ops/box_nms.py @@ -8,14 +8,15 @@ from mo.utils.utils import refer_to_faq_msg class BoxNms(Op): - ''' It is assumed that there is no equivalent of this op in IE. - ''' + """ + It is assumed that there is no equivalent of this op in IE. + """ op = '_contrib_box_nms' def __init__(self, graph: Graph, attrs: dict): mandatory_props = { 'type': None, - 'op': __class__.op, + 'op': self.op, 'coord_start': 2, 'force_suppress': False, 'id_index': 0, @@ -23,7 +24,7 @@ class BoxNms(Op): 'score_index': 1, 'topk': 400, 'valid_thresh': 0.01, - 'infer': __class__.infer + 'infer': self.infer } super().__init__(graph, mandatory_props, attrs) diff --git a/model-optimizer/extensions/ops/bucketize.py b/model-optimizer/extensions/ops/bucketize.py index c7e6ad8fa96..d5dc8f5b5f4 100644 --- a/model-optimizer/extensions/ops/bucketize.py +++ b/model-optimizer/extensions/ops/bucketize.py @@ -15,8 +15,8 @@ class Bucketize(Op): def __init__(self, graph: Graph, attrs: dict): mandatory_props = { 'kind': 'op', - 'type': __class__.op, - 'op': __class__.op, + 'type': self.op, + 'op': self.op, 'version': 'opset3', 'type_infer': self.type_infer, @@ -44,7 +44,8 @@ class Bucketize(Op): node.out_port(0).set_data_type(np.int32) else: assert node.output_type in [np.int64, np.int32], \ - 'Bucketize `output_type` attribute must be int32 or int64, `{}` found'.format(np.dtype(node.output_type).name) + 'Bucketize `output_type` attribute must be int32 or int64, `{}` found' \ + ''.format(np.dtype(node.output_type).name) node.out_port(0).set_data_type(node.output_type) @staticmethod @@ -54,14 +55,11 @@ class Bucketize(Op): "Attribute \"with_right_bound\" is not defined" assert len(node.in_nodes()) == 2, \ "Incorrect number of inputs for {} node".format(node.id) - if node.get_opset() == "extension": - output_type = np.int32 - else: + if node.get_opset() != "extension": assert node.has_valid('output_type'), \ '`output_type` attribute is not set for Bucketize node `{}`'.format(node_name) assert node.output_type in [np.int64, np.int32], \ 'Bucketize `output_type` attribute must be int32 or int64, `{}` found'.format(np.dtype(node.output_type).name) - output_type = node.output_type output_shape = node.in_port(0).data.get_shape() node.out_port(0).data.set_shape(output_shape) diff --git a/model-optimizer/extensions/ops/constant_fill.py b/model-optimizer/extensions/ops/constant_fill.py index fcbc93d8eaa..b98d61947ed 100644 --- a/model-optimizer/extensions/ops/constant_fill.py +++ b/model-optimizer/extensions/ops/constant_fill.py @@ -3,6 +3,7 @@ import numpy as np +from mo.front.common.partial_infer.utils import is_fully_defined from mo.graph.graph import Node, Graph from mo.ops.op import Op @@ -14,15 +15,16 @@ class ConstantFill(Op): so it is usually relevant to constant folding. """ op = 'ConstantFill' + enabled = False def __init__(self, graph: Graph, attrs: dict): mandatory_props = { 'type': None, - 'op': __class__.op, + 'op': self.op, 'input_as_shape': 1, 'in_ports_count': 1, 'out_ports_count': 1, - 'infer': __class__.infer + 'infer': self.infer } super().__init__(graph, mandatory_props, attrs) @@ -38,8 +40,10 @@ class ConstantFill(Op): assert node.fill_value is not None assert node.input_as_shape - shape = node.in_node(0).value + shape = node.in_port(0).data.get_value() assert shape is not None - node.out_node(0).value = np.full(shape, node.fill_value, np.float32) - node.out_node(0).shape = np.array(node.out_node(0).value.shape, dtype=np.int64) + if is_fully_defined(shape): + node.out_port(0).data.set_value(np.full(shape, node.fill_value, np.float32)) + else: + node.out_port(0).data.set_shape(shape) diff --git a/model-optimizer/extensions/ops/correlation.py b/model-optimizer/extensions/ops/correlation.py deleted file mode 100644 index fa15707ccf0..00000000000 --- a/model-optimizer/extensions/ops/correlation.py +++ /dev/null @@ -1,66 +0,0 @@ -# Copyright (C) 2018-2021 Intel Corporation -# SPDX-License-Identifier: Apache-2.0 - -from math import ceil - -# Concat infer : N - number of inputs to concat -# axis - dimension number for tensors concatenation -import numpy as np - -from mo.graph.graph import Node, Graph -from mo.ops.op import Op - - -class CorrelationOp(Op): - op = 'Correlation' - - def __init__(self, graph: Graph, attrs: dict): - mandatory_props = { - 'type': __class__.op, - 'op': __class__.op, - 'version': 'extension', - 'in_ports_count': 1, - 'out_ports_count': 1, - 'infer': CorrelationOp.corr_infer - } - super().__init__(graph, mandatory_props, attrs) - - def supported_attrs(self): - return [ - 'pad', - 'kernel_size', - 'max_displacement', - 'stride_1', - 'stride_2', - 'single_direction', - 'do_abs', - 'correlation_type' - ] - - @staticmethod - def corr_infer(node: Node): - outn = node.out_node(0) - inn = node.in_node(0) - - outn.shape = np.zeros(4, dtype=int) - outn.shape[0] = inn.shape[0] - - bottomchannels = inn.shape[1] - - paddedbottomheight = inn.shape[2] - paddedbottomwidth = inn.shape[3] + 2 * node.pad - - kernel_radius_ = (node.kernel_size - 1) / 2; - border_size_ = node.max_displacement + kernel_radius_ - - outn.shape[3] = ceil((float)(paddedbottomwidth - border_size_ * 2) / node.stride_1) - outn.shape[2] = ceil((float)(paddedbottomheight - kernel_radius_ * 2) / node.stride_1) - - neighborhood_grid_radius_ = node.max_displacement / node.stride_2 - - if node.single_direction != 0: - neighborhood_grid_width_ = neighborhood_grid_radius_ + 1 - else: - neighborhood_grid_width_ = neighborhood_grid_radius_ * 2 + 1 - - outn.shape[1] = neighborhood_grid_width_ * neighborhood_grid_width_ diff --git a/model-optimizer/extensions/ops/ctc_greedy_decoder.py b/model-optimizer/extensions/ops/ctc_greedy_decoder.py index 84f9fba72d3..073445c6015 100644 --- a/model-optimizer/extensions/ops/ctc_greedy_decoder.py +++ b/model-optimizer/extensions/ops/ctc_greedy_decoder.py @@ -1,7 +1,7 @@ # Copyright (C) 2018-2021 Intel Corporation # SPDX-License-Identifier: Apache-2.0 -from mo.front.common.partial_infer.utils import int64_array +from mo.front.common.partial_infer.utils import int64_array, compatible_dims from mo.front.extractor import bool_to_str from mo.graph.graph import Node, Graph from mo.ops.op import Op @@ -44,21 +44,13 @@ class CTCGreedyDecoderOp(Op): # check shapes of input tensors assert len(logits_shape) == 3, \ 'Incorrect rank of logits for {} node'.format(node_name) - if node.has_valid('use_mask_format') and node.use_mask_format is True: - # it is a case when CTCGreedyDecoder still uses an original format for sequence_length - assert len(sequence_mask_shape) == 1, \ - 'Incorrect rank of sequence length tensor for {} node'.format(node_name) - assert logits_shape[1] == sequence_mask_shape[0], \ - 'Batch dimensions of input tensors must be the same for {} node'.format(node_name) - else: - # it is a case when CTCGreedyDecoder uses a sequence mask - assert len(sequence_mask_shape) == 2, \ - 'Incorrect rank of sequence length tensor for {} node'.format(node_name) - assert logits_shape[1] == sequence_mask_shape[1], \ - 'Batch dimensions of input tensors must be the same for {} node'.format(node_name) - assert logits_shape[0] == sequence_mask_shape[0], \ - 'Time dimensions of input tensors must be the same for {} node'.format(node_name) + assert len(sequence_mask_shape) == 2, \ + 'Incorrect rank of sequence length tensor for {} node'.format(node_name) + assert compatible_dims(logits_shape[1], sequence_mask_shape[1]), \ + 'Batch dimensions of input tensors must be the same for {} node'.format(node_name) + assert compatible_dims(logits_shape[0], sequence_mask_shape[0]), \ + 'Time dimensions of input tensors must be the same for {} node'.format(node_name) batch_size = logits_shape[1] time_size = logits_shape[0] - node.out_port(0).data.set_shape(int64_array([batch_size, time_size, 1, 1])) + node.out_port(0).data.set_shape([batch_size, time_size, 1, 1]) diff --git a/model-optimizer/extensions/ops/ctc_greedy_decoder_seq_len.py b/model-optimizer/extensions/ops/ctc_greedy_decoder_seq_len.py index bf6d4edec8d..4c4501cef9c 100644 --- a/model-optimizer/extensions/ops/ctc_greedy_decoder_seq_len.py +++ b/model-optimizer/extensions/ops/ctc_greedy_decoder_seq_len.py @@ -3,7 +3,7 @@ import numpy as np -from mo.front.common.partial_infer.utils import int64_array +from mo.front.common.partial_infer.utils import int64_array, compatible_dims from mo.front.extractor import bool_to_str from mo.graph.graph import Node, Graph from mo.middle.passes.convert_data_type import np_data_type_to_destination_type @@ -68,12 +68,12 @@ class CTCGreedyDecoderSeqLenOp(Op): assert len(sequence_len_shape) == 1, \ 'Incorrect rank of sequence length tensor for {} node'.format(node_name) - assert logits_shape[0] == sequence_len_shape[0], \ + assert compatible_dims(logits_shape[0], sequence_len_shape[0]), \ 'Batch dimensions of input tensors must be the same for {} node'.format(node_name) batch_size = logits_shape[0] time_size = logits_shape[1] if node.is_out_port_connected(0): - node.out_port(0).data.set_shape(int64_array([batch_size, time_size])) + node.out_port(0).data.set_shape([batch_size, time_size]) if node.is_out_port_connected(1): - node.out_port(1).data.set_shape(int64_array([batch_size])) + node.out_port(1).data.set_shape([batch_size]) diff --git a/model-optimizer/extensions/ops/ctc_loss.py b/model-optimizer/extensions/ops/ctc_loss.py index d4751d5cdb8..1026022a75c 100644 --- a/model-optimizer/extensions/ops/ctc_loss.py +++ b/model-optimizer/extensions/ops/ctc_loss.py @@ -3,7 +3,7 @@ import numpy as np -from mo.front.common.partial_infer.utils import int64_array +from mo.front.common.partial_infer.utils import int64_array, compatible_dims from mo.front.extractor import bool_to_str from mo.graph.graph import Node, Graph from mo.ops.op import Op @@ -73,11 +73,12 @@ class CTCLoss(Op): assert len(logits_shape) == 3 and len(logit_length_shape) == 1 and len(labels_shape) == 2\ and len(label_length_shape) == 1 and len(blank_index_shape) == 0, \ 'Incorrect rank of some input tensor for {} node'.format(node_name) - assert logits_shape[0] == logit_length_shape[0] and logits_shape[0] == labels_shape[0]\ - and logits_shape[0] == label_length_shape[0], \ + assert compatible_dims(logits_shape[0], logit_length_shape[0]) and \ + compatible_dims(logits_shape[0], labels_shape[0]) and \ + compatible_dims(logits_shape[0], label_length_shape[0]), \ 'Batch dimensions of input tensors must be the same for {} node'.format(node_name) - assert logits_shape[1] == labels_shape[1], \ + assert compatible_dims(logits_shape[1], labels_shape[1]), \ 'Time dimensions of input tensors must be the same for {} node'.format(node_name) batch_size = logits_shape[0] - node.out_port(0).data.set_shape(int64_array([batch_size])) + node.out_port(0).data.set_shape([batch_size]) diff --git a/model-optimizer/extensions/ops/data_augmentation.py b/model-optimizer/extensions/ops/data_augmentation.py deleted file mode 100644 index d315031717b..00000000000 --- a/model-optimizer/extensions/ops/data_augmentation.py +++ /dev/null @@ -1,53 +0,0 @@ -# Copyright (C) 2018-2021 Intel Corporation -# SPDX-License-Identifier: Apache-2.0 - -# Concat infer : N - number of inputs to concat -# axis - dimension number for tensors concatenation -import copy - -from mo.graph.graph import Node, Graph -from mo.ops.op import Op - - -class DataAugmentationOp(Op): - op = 'DataAugmentation' - - def __init__(self, graph: Graph, attrs: dict): - mandatory_props = { - 'type': __class__.op, - 'op': __class__.op, - 'version': 'extension', - 'in_ports_count': 1, - 'out_ports_count': 1, - 'infer': DataAugmentationOp.data_augmentation_infer - } - super().__init__(graph, mandatory_props, attrs) - - def supported_attrs(self): - return [ - 'crop_width', - 'crop_height', - 'write_augmented', - 'max_multiplier', - 'augment_during_test', - 'recompute_mean', - 'write_mean', - 'mean_per_pixel', - 'mean', - 'mode', - 'bottomwidth', - 'bottomheight', - 'num', - 'chromatic_eigvec' - ] - - @staticmethod - def data_augmentation_infer(node: Node): - outn = node.out_node(0) - inn = node.in_node(0) - - outn.shape = copy.copy(inn.shape) - - if node.crop_width != 0 or node.crop_height != 0: - outn.shape[2] = node.crop_height - outn.shape[3] = node.crop_width diff --git a/model-optimizer/extensions/ops/depth_to_space.py b/model-optimizer/extensions/ops/depth_to_space.py index 831252ffe68..cd7eb8671b2 100644 --- a/model-optimizer/extensions/ops/depth_to_space.py +++ b/model-optimizer/extensions/ops/depth_to_space.py @@ -4,7 +4,7 @@ import numpy as np from mo.front.common.layout import shape_for_layout, get_height_dim, get_batch_dim, get_features_dim, get_width_dim -from mo.front.common.partial_infer.utils import int64_array +from mo.front.common.partial_infer.utils import dynamic_dimension, is_fully_defined from mo.graph.graph import Node, Graph from mo.ops.op import Op from mo.utils.error import Error @@ -33,7 +33,7 @@ class DepthToSpaceOp(Op): @staticmethod def infer(node: Node): - in_shape = node.in_node().shape + in_shape = node.in_port(0).data.get_shape() if in_shape.size != 4: raise Error('TensorFlow DepthToSpace operation is supported for 4D \'NHWC\' input layout only. ' 'Current input shape is \'{}\''.format(in_shape)) @@ -46,16 +46,18 @@ class DepthToSpaceOp(Op): C = in_shape[get_features_dim(layout, 4)] block_size = node['block_size'] - if C % (block_size ** 2): + if C is not dynamic_dimension and C % (block_size ** 2): raise Error('Feature dimensions of input tensor of DepthToSpace operation have to be divisible by square ' 'of DepthToSpace \'block_size\' parameter. Input tensor shape = {}. Feature dimension = {}. ' 'block_size = {}'.format(in_shape, C, block_size)) out_shape = shape_for_layout(layout, batch=N, - features=int(C / (block_size ** 2)), - height=int(H * block_size), - width=int(W * block_size)) + features=C // (block_size * block_size), + height=H * block_size, + width=W * block_size) - assert np.prod(in_shape) == np.prod(out_shape) - node.out_node().shape = int64_array(out_shape) + if is_fully_defined(in_shape) and is_fully_defined(out_shape) and np.prod(in_shape) != np.prod(out_shape): + raise Error('Number of input elements "{}" is not equal to number of output elements "" for node "{}"' + ''.format(in_shape, out_shape, node.soft_get('name', node.id))) + node.out_port(0).data.set_shape(out_shape) diff --git a/model-optimizer/extensions/ops/detectionoutput_onnx.py b/model-optimizer/extensions/ops/detectionoutput_onnx.py index bae3f743afd..5ef02d85f06 100644 --- a/model-optimizer/extensions/ops/detectionoutput_onnx.py +++ b/model-optimizer/extensions/ops/detectionoutput_onnx.py @@ -3,7 +3,6 @@ import numpy as np -from mo.front.common.partial_infer.utils import int64_array from mo.ops.op import Op @@ -13,10 +12,10 @@ class ExperimentalDetectronDetectionOutput(Op): def __init__(self, graph, attrs): mandatory_props = dict( - type=__class__.op, - op=__class__.op, + type=self.op, + op=self.op, version='opset6', - infer=__class__.infer, + infer=self.infer, type_infer=self.type_infer, in_ports_count=4, out_ports_count=3, @@ -39,13 +38,13 @@ class ExperimentalDetectronDetectionOutput(Op): def infer(node): rois_num = node.max_detections_per_image # boxes - node.out_node(0).shape = np.array([rois_num, 4], dtype=np.int64) + node.out_port(0).data.set_shape([rois_num, 4]) # classes, scores, batch indices # We use range(1, 1 + max(node.out_ports().keys())) instead of range(1, 3), because there are incorrectly # generated models where ExperimentalDetectronDetectionOutput has 4 outputs. for port_ind in range(1, 1 + max(node.out_ports().keys())): if not node.out_port(port_ind).disconnected(): - node.out_port(port_ind).data.set_shape(int64_array([rois_num])) + node.out_port(port_ind).data.set_shape([rois_num]) @staticmethod def type_infer(node): diff --git a/model-optimizer/extensions/ops/dft.py b/model-optimizer/extensions/ops/dft.py index 4ddeaac1f86..26bf09a5901 100644 --- a/model-optimizer/extensions/ops/dft.py +++ b/model-optimizer/extensions/ops/dft.py @@ -41,7 +41,7 @@ class FFTBase(Op): assert (input_rank - 1) not in axes, '(I)DFT node {} axes cannot contain the last axis'.format(node_name) assert len(set(axes)) == len(axes), '(I)DFT node {} axes must be unique.'.format(node_name) - output_shape = int64_array(src_shape) + output_shape = src_shape.copy() if node.is_in_port_connected(2): signal_size = FFTBase.get_signal_size(node) signal_size = FFTBase.canonicalize_signal_size(signal_size, axes, src_shape) diff --git a/model-optimizer/extensions/ops/einsum.py b/model-optimizer/extensions/ops/einsum.py index a37c60def7c..2c335cd0022 100644 --- a/model-optimizer/extensions/ops/einsum.py +++ b/model-optimizer/extensions/ops/einsum.py @@ -5,7 +5,7 @@ import re import numpy as np -from mo.front.common.partial_infer.utils import int64_array +from mo.front.common.partial_infer.utils import int64_array, shape_array from mo.graph.graph import Node, Graph from mo.ops.op import Op from mo.utils.broadcasting import bi_directional_shape_broadcasting @@ -240,7 +240,7 @@ class Einsum(Op): dim_ind += num_broadcasted_dims else: dim_size = input_shape[dim_ind] - sub_shape = int64_array([dim_size]) + sub_shape = shape_array([dim_size]) assert label not in label_to_shape.keys() or np.array_equal(label_to_shape[label], sub_shape), \ "Sizes of dimensions with the same label of Einsum node {} " \ "must be compatible".format(node_name) @@ -249,12 +249,12 @@ class Einsum(Op): label_ind += 1 # generate output shape based on the output subscript - output_shape = int64_array([]) + output_shape = shape_array([]) labels = Einsum.extract_subscript_labels(node_name, output_subscript) for label in labels: assert label in label_to_shape.keys(), "The label in the output subscript must appear" \ " in input subscripts in equation {} " \ "of Einsum node {}".format(equation, node_name) - output_shape = np.concatenate((output_shape, label_to_shape[label])) + output_shape = np.ma.concatenate((output_shape, label_to_shape[label])) node.out_port(0).data.set_shape(output_shape) diff --git a/model-optimizer/extensions/ops/elementwise.py b/model-optimizer/extensions/ops/elementwise.py index 0236004ee0e..af82ace1fe0 100644 --- a/model-optimizer/extensions/ops/elementwise.py +++ b/model-optimizer/extensions/ops/elementwise.py @@ -147,49 +147,49 @@ class LogicalElementwise(Elementwise): class Greater(LogicalElementwise): op = 'Greater' op_type = 'Greater' - operation = staticmethod(lambda a, b: a > b) + operation = staticmethod(lambda a, b: np.ma.greater(a, b)) class GreaterEqual(LogicalElementwise): op = 'GreaterEqual' op_type = 'GreaterEqual' - operation = staticmethod(lambda a, b: a >= b) + operation = staticmethod(lambda a, b: np.ma.greater_equal(a, b)) class Less(LogicalElementwise): op = 'Less' op_type = 'Less' - operation = staticmethod(lambda a, b: a < b) + operation = staticmethod(lambda a, b: np.ma.less(a, b)) class LessEqual(LogicalElementwise): op = 'LessEqual' op_type = 'LessEqual' - operation = staticmethod(lambda a, b: a <= b) + operation = staticmethod(lambda a, b: np.ma.less_equal(a, b)) class Equal(LogicalElementwise): op = 'Equal' op_type = 'Equal' - operation = staticmethod(lambda a, b: a == b) + operation = staticmethod(lambda a, b: np.ma.equal(a, b)) class NotEqual(LogicalElementwise): op = 'NotEqual' op_type = 'NotEqual' - operation = staticmethod(lambda a, b: a != b) + operation = staticmethod(lambda a, b: np.ma.not_equal(a, b)) class Maximum(Elementwise): op = 'Maximum' op_type = 'Maximum' - operation = staticmethod(lambda a, b: np.maximum(a, b)) + operation = staticmethod(lambda a, b: np.ma.maximum(a, b)) class Minimum(Elementwise): op = 'Minimum' op_type = 'Minimum' - operation = staticmethod(lambda a, b: np.minimum(a, b)) + operation = staticmethod(lambda a, b: np.ma.minimum(a, b)) class Round(UnaryElementwise): @@ -218,36 +218,42 @@ class Round(UnaryElementwise): node.soft_get('mode')) if node.mode == 'half_away_from_zero': mask = (a >= 0) - out = np.empty_like(a) - out[mask] = np.floor(a[mask] + 0.5) - out[~mask] = np.ceil(a[~mask] - 0.5) + out = np.ma.empty_like(a) + out[mask] = np.ma.floor(a[mask] + 0.5) + out[~mask] = np.ma.ceil(a[~mask] - 0.5) else: - out = np.round(a) + out = np.ma.round(a) node.out_port(0).data.set_value(out) class LogicalOr(LogicalElementwise): op = 'LogicalOr' op_type = 'LogicalOr' - operation = staticmethod(lambda a, b: np.logical_or(a, b)) + operation = staticmethod(lambda a, b: np.ma.logical_or(a, b)) class LogicalXor(Elementwise): op = 'LogicalXor' op_type = 'LogicalXor' - operation = staticmethod(lambda a, b: np.logical_xor(a, b)) + operation = staticmethod(lambda a, b: np.ma.logical_xor(a, b)) class LogicalAnd(LogicalElementwise): op = 'LogicalAnd' op_type = 'LogicalAnd' - operation = staticmethod(lambda a, b: np.logical_and(a, b)) + operation = staticmethod(lambda a, b: np.ma.logical_and(a, b)) class FloorMod(Elementwise): op = 'FloorMod' op_type = 'FloorMod' - operation = staticmethod(lambda a, b: a % b) + operation = staticmethod(lambda a, b: np.ma.fmod(a, b)) + + +class Mod(Elementwise): + op = 'Mod' + op_type = 'Mod' + operation = staticmethod(lambda a, b: np.ma.mod(a, b)) class Negative(UnaryElementwise): diff --git a/model-optimizer/extensions/ops/embedding_bag.py b/model-optimizer/extensions/ops/embedding_bag.py index d5e0623d36c..8075b459ea3 100644 --- a/model-optimizer/extensions/ops/embedding_bag.py +++ b/model-optimizer/extensions/ops/embedding_bag.py @@ -52,7 +52,7 @@ class EmbeddingBagOffsetsSum(EmbeddingBagBase): assert offsets_shape is not None and len(offsets_shape) == 1,\ "Rank of the offsets in EmbeddingBagOffsetsSum should be equal to 1 for node: `{}`".format(name) - node.out_port(0).data.set_shape(np.concatenate((offsets_shape[:1], weights_shape[1:]))) + node.out_port(0).data.set_shape(np.ma.concatenate((offsets_shape[:1], weights_shape[1:]))) class EmbeddingBagPackedSum(EmbeddingBagBase): @@ -74,7 +74,7 @@ class EmbeddingBagPackedSum(EmbeddingBagBase): "EmbeddingBagPackedSum should have at least 2D weights for node: `{}`".format(name) input_shape = node.in_port(1).data.get_shape() - node.out_port(0).data.set_shape(np.concatenate((input_shape[:1], weights_shape[1:]))) + node.out_port(0).data.set_shape(np.ma.concatenate((input_shape[:1], weights_shape[1:]))) class EmbeddingSegmentsSum(EmbeddingBagBase): @@ -101,5 +101,5 @@ class EmbeddingSegmentsSum(EmbeddingBagBase): num_segments = node.in_port(3).data.get_value() assert num_segments is not None, "EmbeddingSegmentsSum should have a constant num_segments provided, but it " \ "doesn't for node: `{}`.".format(name) - output_shape = np.concatenate(([num_segments], weights_shape[1:])) + output_shape = np.ma.concatenate(([num_segments], weights_shape[1:])) node.out_port(0).data.set_shape(output_shape) diff --git a/model-optimizer/extensions/ops/gather.py b/model-optimizer/extensions/ops/gather.py index 30b45735965..619f3dba4b2 100644 --- a/model-optimizer/extensions/ops/gather.py +++ b/model-optimizer/extensions/ops/gather.py @@ -4,7 +4,7 @@ import numpy as np from mo.front.caffe.extractors.utils import get_canonical_axis_index -from mo.front.common.partial_infer.utils import int64_array +from mo.front.common.partial_infer.utils import int64_array, is_fully_defined from mo.graph.graph import Node, Graph from mo.ops.op import Op, PermuteAttrs from mo.utils.error import Error @@ -67,7 +67,7 @@ class Gather(Op): axis = axis + len(data_shape) if axis < 0 else axis batch_dims = batch_dims + len(indices_shape) if batch_dims < 0 else batch_dims - assert np.array_equal(data_shape[:batch_dims], indices_shape[:batch_dims]), \ + assert np.ma.allequal(data_shape[:batch_dims], indices_shape[:batch_dims]), \ 'data and indices inputs must have equal first dimensions until batch_dims' assert batch_dims <= axis, \ @@ -82,16 +82,17 @@ class Gather(Op): data_value = node.in_port(0).data.get_value() indices_value = node.in_port(1).data.get_value() - if data_value is not None and indices_value is not None: + if data_value is not None and indices_value is not None and is_fully_defined(indices_value): if batch_dims == 0: - node.out_port(0).data.set_value(np.take(data_value, indices_value, axis)) + node.out_port(0).data.set_value(np.ma.take(data_value, indices_value, axis)) else: out_value = np.empty(out_shape) for batch_idx in np.ndindex(tuple(batch_dims_range)): - out_value[batch_idx] = np.take(data_value[batch_idx], indices_value[batch_idx], axis - batch_dims) + out_value[batch_idx] = np.ma.take(data_value[batch_idx], indices_value[batch_idx], + axis - batch_dims) node.out_port(0).data.set_value(out_value) else: - node.out_port(0).data.set_shape(int64_array(out_shape)) + node.out_port(0).data.set_shape(out_shape) class AttributedGather(Op): diff --git a/model-optimizer/extensions/ops/gathernd.py b/model-optimizer/extensions/ops/gathernd.py index e61757d4a88..1175698fa96 100644 --- a/model-optimizer/extensions/ops/gathernd.py +++ b/model-optimizer/extensions/ops/gathernd.py @@ -3,7 +3,8 @@ import numpy as np -from mo.front.common.partial_infer.utils import int64_array +from mo.front.common.partial_infer.utils import int64_array, is_fully_defined, dynamic_dimension_value, \ + compatible_dims from mo.graph.graph import Node, Graph from mo.ops.op import Op @@ -47,7 +48,7 @@ class GatherND(Op): # check that batch dimensions of data and indices are the same for batch_dim in range(batch_dims): - assert data_shape[batch_dim] == indices_shape[batch_dim], \ + assert compatible_dims(data_shape[batch_dim], indices_shape[batch_dim]), \ "The dimension {} for data and indices tensors must be the same".format(batch_dim) # check ranks of input tensors @@ -57,13 +58,19 @@ class GatherND(Op): "Length of a tuple with indices must not exceed a rank of data tensor excluding batch dimensions" # compute output shape - number_batches = [np.prod(data_shape[:batch_dims]).tolist()] if batch_dims > 0 else list() + if batch_dims > 0: + if is_fully_defined(data_shape[:batch_dims]): + batch = [np.prod(data_shape[:batch_dims]).tolist()] + else: + batch = [dynamic_dimension_value] + else: + batch = [] slice_shape = list(data_shape[(batch_dims + indices_shape[-1]):]) - output_shape = number_batches + list(indices_shape[batch_dims:-1]) + slice_shape - node.out_port(0).data.set_shape(int64_array(output_shape)) + output_shape = batch + list(indices_shape[batch_dims:-1]) + slice_shape + node.out_port(0).data.set_shape(output_shape) # compute output value if all input values are defined - if data_value is not None and indices_value is not None: + if is_fully_defined(indices_value) and is_fully_defined(data_value): output_value = np.zeros(output_shape, dtype=data_value.dtype) if batch_dims == 0: output_indices_range = int64_array(indices_shape[:-1]) diff --git a/model-optimizer/extensions/ops/interpolate.py b/model-optimizer/extensions/ops/interpolate.py index fca0cac53ec..6c7b65ec2a7 100644 --- a/model-optimizer/extensions/ops/interpolate.py +++ b/model-optimizer/extensions/ops/interpolate.py @@ -5,7 +5,7 @@ import math import numpy as np -from mo.front.common.partial_infer.utils import int64_array +from mo.front.common.partial_infer.utils import int64_array, dynamic_dimension, dynamic_dimension_value from mo.front.extractor import bool_to_str from mo.graph.graph import Node, Graph from mo.graph.perm_inputs import PermuteInputs @@ -46,7 +46,10 @@ def infer_for_opset4(node: Node): scales = node.in_port(2).data.get_value() assert scales is not None for i, axis in enumerate(axes): - output_shape[axis] = math.floor(scales[i] * output_shape[axis] + 1.0e-5) + if output_shape[axis] is not dynamic_dimension and scales[i] is not dynamic_dimension: + output_shape[axis] = math.floor(scales[i] * output_shape[axis] + 1.0e-5) + else: + output_shape[axis] = dynamic_dimension_value if node.is_in_port_connected(3): PermuteInputs().set_input_permutation(node.in_node(3), node, 'input:0', 'axis') diff --git a/model-optimizer/extensions/ops/loop.py b/model-optimizer/extensions/ops/loop.py index 4089983bc3b..c3252117677 100644 --- a/model-optimizer/extensions/ops/loop.py +++ b/model-optimizer/extensions/ops/loop.py @@ -6,7 +6,7 @@ import logging as log import numpy as np from extensions.ops.tensor_iterator import TensorIterator -from mo.front.common.partial_infer.utils import int64_array +from mo.front.common.partial_infer.utils import shape_array, is_fully_defined, dynamic_dimension_value from mo.graph.graph import Node, Graph from mo.middle.passes.fusing.helpers import common_bfs from mo.middle.passes.infer import partial_infer @@ -99,7 +99,7 @@ class Loop(TensorIterator): if body_node is not None: assert body_node.soft_get('type') == 'Parameter' - input_shape = int64_array([]) # this is a current iteration number input shape + input_shape = shape_array([]) # this is a current iteration number input shape loop_port_idx = record['external_port_id'] if loop_port_idx != -1: input_shape = loop_node.in_port(loop_port_idx).get_connection().get_source().data.get_shape() @@ -135,12 +135,7 @@ class Loop(TensorIterator): assert output_shape[concat_axis] == 1, 'Dimension for concatenation is not equal to 1 for scan ' \ 'output for Loop node "{}" for loop output port "{}"'.\ format(loop_name, loop_port_idx) - num_iters = Loop.iterations_count(loop_node) - if num_iters is None: - log.error('Dynamic number of iterations for Loop node "{}". Consider number to be 1 to be able' - ' to generate the IR.'.format(loop_name), extra={'is_warning': True}) - num_iters = 1 - output_shape[concat_axis] = num_iters + output_shape[concat_axis] = Loop.iterations_count(loop_node) # MO does not support evaluation of Loop scan outputs with const values if concat_axis is None and output_value is not None: loop_node.out_port(loop_port_idx).data.set_value(output_value) @@ -153,22 +148,25 @@ class Loop(TensorIterator): Try to determine the number of loop iterations. If we detect that the number is dynamic then return None. :param loop_node: Loop operation node - :return: number of iterations or None if the number depends on runtime values. + :return: number of iterations or dynamic_dimensions if the number depends on runtime values. """ assert loop_node.soft_get('type') == 'Loop' if loop_node.is_in_port_connected(1): execution_condition = loop_node.in_port(1).data.get_value() - if execution_condition is None: # dynamic execution condition - return None + if not is_fully_defined(execution_condition): # dynamic execution condition + return dynamic_dimension_value execution_condition = execution_condition.item() if not execution_condition: # 0 iterations return 0 num_iterations = loop_node.in_port(0).data.get_value() + if not is_fully_defined(num_iterations): + return dynamic_dimension_value if num_iterations is not None: num_iterations = num_iterations.item(0) - if num_iterations < 0: - return None + # in some ONNX models the num_iterations input is equal to max(int64) meaning dynamic number of iterations + if num_iterations < 0 or num_iterations == np.iinfo(np.int64).max: + return dynamic_dimension_value return num_iterations @staticmethod @@ -511,7 +509,8 @@ class Loop(TensorIterator): port_to_remove = port_map[record_id_to_remove]['external_port_id'] if port_to_remove != -1: if dir == 'in': - if port_to_remove not in [0, 1] and port_to_remove in loop_node.in_ports().keys(): # input port 0 and 1 are mandatory for the Loop node + # input port 0 and 1 are mandatory for the Loop node + if port_to_remove not in [0, 1] and port_to_remove in loop_node.in_ports().keys(): loop_node.delete_input_port(port_to_remove) elif dir == 'out' and port_to_remove in loop_node.out_ports(): loop_node.delete_output_port(port_to_remove) diff --git a/model-optimizer/extensions/ops/lstm_cell.py b/model-optimizer/extensions/ops/lstm_cell.py index 7dc091f2b69..0dd893afd6f 100644 --- a/model-optimizer/extensions/ops/lstm_cell.py +++ b/model-optimizer/extensions/ops/lstm_cell.py @@ -1,7 +1,7 @@ # Copyright (C) 2018-2021 Intel Corporation # SPDX-License-Identifier: Apache-2.0 -from mo.front.common.partial_infer.utils import mark_input_bins +from mo.front.common.partial_infer.utils import mark_input_bins, compatible_dims from mo.graph.graph import Node, Graph from mo.ops.op import Op from mo.utils.error import Error @@ -27,10 +27,10 @@ class LSTMCell(Op): def __init__(self, graph: Graph, attrs: dict): mandatory_props = { - 'type': __class__.op, - 'op': __class__.op, + 'type': self.op, + 'op': self.op, 'version': 'opset4', - 'infer': __class__.infer, + 'infer': self.infer, 'in_ports_count': 5, 'out_ports_count': 2, 'wr_input_id': 3, @@ -85,4 +85,6 @@ class LSTMCell(Op): input_shape = node.in_node(0).shape assert input_shape is not None - assert hidden_shape[0] == cell_shape[0] == input_shape[0], 'States are not broadcastable by batch' + assert compatible_dims(hidden_shape[0], cell_shape[0]) and \ + compatible_dims(cell_shape[0], input_shape[0]), 'States are not broadcast-able by batch for node {}' \ + ''.format(node.soft_get('name', node.id)) diff --git a/model-optimizer/extensions/ops/lstm_sequence.py b/model-optimizer/extensions/ops/lstm_sequence.py index 0fce701ff99..55e9c5ad548 100644 --- a/model-optimizer/extensions/ops/lstm_sequence.py +++ b/model-optimizer/extensions/ops/lstm_sequence.py @@ -3,7 +3,7 @@ import numpy as np -from mo.front.common.partial_infer.utils import mark_input_bins +from mo.front.common.partial_infer.utils import mark_input_bins, shape_array, shape_insert from mo.graph.graph import Node, add_opoutput, Graph from mo.ops.op import Op @@ -31,13 +31,13 @@ class LSTMSequence(Op): def __init__(self, graph: Graph, attrs: dict): mandatory_props = { - 'type': '__LSTMSequence', # should be never emitted to IR; for debugging purposes - 'op': __class__.op, + 'type': None, # should be never emitted to IR; for debugging purposes + 'op': self.op, 'blobs_wrb': False, 'has_num_directions': False, 'direction': 'forward', 'num_layers': 1, - 'infer': __class__.infer, + 'infer': self.infer, 'blob_bidirectional_split': lambda node: ( LSTMSequence.split_helper(node, 0, 'forward'), LSTMSequence.split_helper(node, 1, 'reverse') @@ -96,7 +96,7 @@ class LSTMSequence(Op): node.in_node(port).value = np.repeat(node.in_node(port).value, input_shape[i], axis=i) node.in_node(port).shape[i] = input_shape[i] - out_shape = np.array([input_shape[node.sequence_dim], input_shape[node.batch_dim], node.hidden_size], dtype=np.int64) + out_shape = shape_array([input_shape[node.sequence_dim], input_shape[node.batch_dim], node.hidden_size]) assert not node.has_num_directions or node.sequence_dim == 0, \ 'If has_num_directions == True, then node.sequence_dim should be equal 0, but it is {}'.format( node.sequence_dim) @@ -104,12 +104,12 @@ class LSTMSequence(Op): num_layers = node.num_layers if node.has_num_directions: # insert extra dimension to output shape for num_directions - out_shape = np.insert(out_shape, 1, np.int64(num_directions)) + out_shape = shape_insert(out_shape, 1, np.int64(num_directions)) node.out_node(0).shape = out_shape # extra outputs for hidden/cell states - state_size = np.array([input_shape[1], node.hidden_size], dtype=np.int64) + state_size = shape_array([input_shape[1], node.hidden_size]) if node.has_num_directions: - state_size = np.insert(state_size, 0, num_directions*num_layers) + state_size = shape_insert(state_size, 0, num_directions * num_layers) for i in [1,2]: if i not in node.out_nodes(): data_node = Op._create_data_node( diff --git a/model-optimizer/extensions/ops/merge.py b/model-optimizer/extensions/ops/merge.py index e0a992dc4cf..3c21628b254 100644 --- a/model-optimizer/extensions/ops/merge.py +++ b/model-optimizer/extensions/ops/merge.py @@ -3,7 +3,7 @@ import numpy as np -from mo.front.common.partial_infer.utils import int64_array +from mo.front.common.partial_infer.utils import compatible_shapes, shape_array, strict_compare_tensors from mo.graph.graph import Node, Graph from mo.ops.op import Op @@ -13,9 +13,9 @@ class Merge(Op): def __init__(self, graph: Graph, attrs: dict): mandatory_props = { - 'op': __class__.op, - 'infer': __class__.merge_infer, - 'cf_infer': __class__.control_flow_infer, + 'op': self.op, + 'infer': self.merge_infer, + 'cf_infer': self.control_flow_infer, } super().__init__(graph, mandatory_props, attrs) @@ -30,21 +30,24 @@ class Merge(Op): node['is_not_fully_inferred'] = True else: node['is_not_fully_inferred'] = False - assert np.all(node.shape == inferred_nodes[0].shape for node in inferred_nodes) + assert np.all(compatible_shapes(node.shape, inferred_nodes[0].shape) for node in inferred_nodes) inferred_and_executable = [n for n in node.in_nodes().values() if n['is_partial_inferred'] and 'executable' in n and n['executable']] tensor = inferred_and_executable[0] - if all([np.all(tensor.value == n.value) for n in inferred_and_executable]): - node.out_node().value = tensor.value.copy() if tensor.has_valid('value') else None + if all([tensor.has_valid('value') and n.has_valid('value') and strict_compare_tensors(tensor.value, n.value) + for n in inferred_and_executable]): + node.out_node().value = tensor.value.copy() + else: + node.out_node().value = None - node.out_node().shape = int64_array(tensor.shape) + # do not use set_shape(tensor.shape) here because input port shape may be different from the calculated output + # shape and `set_shape` will raise an error that shape has changed + node.out_node(0).shape = shape_array(tensor.shape) @staticmethod def control_flow_infer(node: Node, is_executable: bool, mark_executability: callable): - graph = node.graph - in_data_nodes = node.in_nodes(control_flow=True) out_data_nodes = node.out_nodes(control_flow=True) diff --git a/model-optimizer/extensions/ops/mvn.py b/model-optimizer/extensions/ops/mvn.py index 506522d9aae..fccc3c55ae2 100644 --- a/model-optimizer/extensions/ops/mvn.py +++ b/model-optimizer/extensions/ops/mvn.py @@ -1,11 +1,9 @@ # Copyright (C) 2018-2021 Intel Corporation # SPDX-License-Identifier: Apache-2.0 -from mo.front.caffe.extractors.utils import get_canonical_axis_index -from mo.front.common.layout import get_features_dim from mo.front.common.partial_infer.elemental import copy_shape_infer from mo.front.extractor import bool_to_str -from mo.graph.graph import Graph +from mo.graph.graph import Graph, Node from mo.graph.perm_inputs import PermuteInputs from mo.ops.op import Op from mo.utils.error import Error @@ -44,7 +42,7 @@ class MVN(Op): raise Error('Unsupported MVN opset version "{}"'.format(version)) @staticmethod - def infer(node: None): + def infer(node: Node): name = node.soft_get('name', node.id) assert node.eps is not None, 'MVN required attribute `eps` unspecified for node {}'.format(name) diff --git a/model-optimizer/extensions/ops/mxfft.py b/model-optimizer/extensions/ops/mxfft.py index 1592d9c653e..97acb781cb7 100644 --- a/model-optimizer/extensions/ops/mxfft.py +++ b/model-optimizer/extensions/ops/mxfft.py @@ -1,7 +1,6 @@ # Copyright (C) 2018-2021 Intel Corporation # SPDX-License-Identifier: Apache-2.0 -from mo.front.common.partial_infer.utils import int64_array from mo.graph.graph import Graph, Node from mo.ops.op import Op @@ -39,4 +38,4 @@ class MXFFT(Op): output_shape[-1] = output_shape[-1] // 2 else: output_shape[-1] = output_shape[-1] * 2 - node.out_port(0).data.set_shape(int64_array(output_shape)) + node.out_port(0).data.set_shape(output_shape) diff --git a/model-optimizer/extensions/ops/non_max_suppression.py b/model-optimizer/extensions/ops/non_max_suppression.py index e863bc84fed..86b0513b916 100644 --- a/model-optimizer/extensions/ops/non_max_suppression.py +++ b/model-optimizer/extensions/ops/non_max_suppression.py @@ -5,7 +5,7 @@ import logging as log import numpy as np -from mo.front.common.partial_infer.utils import int64_array +from mo.front.common.partial_infer.utils import dynamic_dimension, shape_array, dynamic_dimension_value from mo.front.extractor import bool_to_str from mo.graph.graph import Node, Graph from mo.middle.passes.convert_data_type import np_data_type_to_destination_type @@ -57,7 +57,8 @@ class NonMaxSuppression(Op): opset = node.get_opset() max_num_of_inputs = 6 if opset == 'opset5' else 5 input_msg_fmt = 'NonMaxSuppression node {} from {} must have from 2 to {} inputs' - inputs_msg = input_msg_fmt.format(node.soft_get('name', node.id), opset, max_num_of_inputs) + node_name = node.soft_get('name', node.id) + inputs_msg = input_msg_fmt.format(node_name, opset, max_num_of_inputs) assert 2 <= num_of_inputs <= max_num_of_inputs, inputs_msg boxes_shape = node.in_port(0).data.get_shape() @@ -78,22 +79,29 @@ class NonMaxSuppression(Op): log.info('Set default "max_output_boxes_per_class" for node {} to number of boxes'.format(node.name)) max_output_boxes_per_class = boxes_shape[1] + # convert the np.array value to a scalar to avoid issue with ragged numpy array generation in the shape + # calculation formulas below + if isinstance(max_output_boxes_per_class, np.ndarray): + max_output_boxes_per_class = max_output_boxes_per_class.item() + num_classes = scores_shape[1] num_input_boxes = boxes_shape[1] - assert scores_shape[2] == num_input_boxes, 'Number of boxes mismatch' + assert scores_shape[2] is dynamic_dimension or scores_shape[2] == num_input_boxes or scores_shape[2] is None \ + or num_input_boxes is None, 'Number of boxes mismatch for operation {}'.format(node_name) if node.get_opset() in ['opset4', 'opset5']: max_number_of_boxes = min(num_input_boxes, max_output_boxes_per_class) * boxes_shape[0] * num_classes else: max_number_of_boxes = min(num_input_boxes, boxes_shape[0] * max_output_boxes_per_class * num_classes) - node.out_port(0).data.set_shape(int64_array([max_number_of_boxes, 3])) + node.out_port(0).data.set_shape(shape_array([max_number_of_boxes, 3])) if opset == 'opset5': + node.out_port(0).data.set_shape(shape_array([dynamic_dimension_value, 3])) num_of_outputs = len([port for port in node.out_ports().values() if not port.disconnected()]) if num_of_outputs >= 2 and node.has_port('out', 1): - node.out_port(1).data.set_shape(int64_array([max_number_of_boxes, 3])) + node.out_port(1).data.set_shape(shape_array([dynamic_dimension_value, 3])) if num_of_outputs >= 3 and node.has_port('out', 2): - node.out_port(2).data.set_shape(int64_array(1)) + node.out_port(2).data.set_shape(shape_array(1)) @staticmethod def type_infer(node): diff --git a/model-optimizer/extensions/ops/non_zero.py b/model-optimizer/extensions/ops/non_zero.py index 8860870a3ae..a8df23bef5a 100644 --- a/model-optimizer/extensions/ops/non_zero.py +++ b/model-optimizer/extensions/ops/non_zero.py @@ -3,7 +3,7 @@ import numpy as np -from mo.front.common.partial_infer.utils import int64_array +from mo.front.common.partial_infer.utils import is_fully_defined, dynamic_dimension_value from mo.graph.graph import Node, Graph from mo.middle.passes.convert_data_type import np_data_type_to_destination_type from mo.ops.op import Op @@ -44,12 +44,14 @@ class NonZero(Op): 'NonZero `output_type` attribute must be int32 or int64, `{}` found'.format(np.dtype(node.output_type).name) input_value = node.in_port(0).data.get_value() - if input_value is not None: + if is_fully_defined(input_value): node.out_port(0).data.set_value(np.array(np.nonzero(input_value), dtype=node.output_type)) else: - # output shape of NonZero should be [input_rank, dynamic] - # having restriction to save IR with static shape only we count upper-bound shape value here - node.out_port(0).data.set_shape(int64_array([len(input_shape), np.prod(input_shape)])) + if is_fully_defined(input_shape): + # output shape of NonZero is still static (upper bound) + node.out_port(0).data.set_shape([len(input_shape), np.prod(input_shape)]) + else: + node.out_port(0).data.set_shape([len(input_shape), dynamic_dimension_value]) @staticmethod def type_infer(node): diff --git a/model-optimizer/extensions/ops/one_hot.py b/model-optimizer/extensions/ops/one_hot.py index 12e1390a5fc..68073390742 100644 --- a/model-optimizer/extensions/ops/one_hot.py +++ b/model-optimizer/extensions/ops/one_hot.py @@ -3,6 +3,7 @@ import numpy as np +from mo.front.common.partial_infer.utils import shape_insert from mo.graph.graph import Node, Graph from mo.ops.op import Op @@ -52,7 +53,7 @@ class OneHot(Op): output_shape = [depth] else: # dim >= 1 # vector/matrix indices case - output_shape = np.insert(indices_shape, axis, depth) + output_shape = shape_insert(indices_shape, axis, depth) node.out_port(0).data.set_shape(output_shape) diff --git a/model-optimizer/extensions/ops/parameter.py b/model-optimizer/extensions/ops/parameter.py index 25bf0be1bfd..9a1b3a93a85 100644 --- a/model-optimizer/extensions/ops/parameter.py +++ b/model-optimizer/extensions/ops/parameter.py @@ -3,6 +3,7 @@ import numpy as np +from mo.front.common.partial_infer.utils import unmask_shape from mo.graph.graph import Graph from mo.middle.passes.convert_data_type import np_data_type_to_destination_type from mo.ops.op import Op, PermuteAttrs @@ -35,7 +36,7 @@ class Parameter(Op): def supported_attrs(self): return [ - ('shape', lambda node: ','.join([str(i) for i in node.shape])), + ('shape', lambda node: ','.join([str(i) for i in unmask_shape(node.shape)])), ('element_type', lambda node: np_data_type_to_destination_type(node.data_type)), ] diff --git a/model-optimizer/extensions/ops/pnorm.py b/model-optimizer/extensions/ops/pnorm.py index 6f0b83f9c7e..e1079837834 100644 --- a/model-optimizer/extensions/ops/pnorm.py +++ b/model-optimizer/extensions/ops/pnorm.py @@ -15,15 +15,15 @@ class PNormOp(Op): def __init__(self, graph: Graph, attrs: dict): mandatory_props = { 'type': None, - 'op': __class__.op, + 'op': self.op, 'in_ports_count': 1, 'out_ports_count': 1, - 'infer': __class__.infer + 'infer': self.infer } super().__init__(graph, mandatory_props, attrs) @staticmethod def infer(node: Node): shape = node.in_port(0).data.get_shape().copy() - shape[1] = shape[1] / node.group + shape[1] = shape[1] // node.group node.out_port(0).data.set_shape(shape) diff --git a/model-optimizer/extensions/ops/power_file.py b/model-optimizer/extensions/ops/power_file.py deleted file mode 100644 index dc0158b515f..00000000000 --- a/model-optimizer/extensions/ops/power_file.py +++ /dev/null @@ -1,24 +0,0 @@ -# Copyright (C) 2018-2021 Intel Corporation -# SPDX-License-Identifier: Apache-2.0 - -from mo.front.common.partial_infer.elemental import copy_shape_infer -from mo.graph.graph import Graph -from mo.ops.op import Op - - -class PowerFileOp(Op): - op = 'PowerFile' - enabled = True - - def __init__(self, graph: Graph, attrs: dict): - super().__init__(graph, { - 'type': __class__.op, - 'op': __class__.op, - 'version': 'extension', - 'in_ports_count': 1, - 'out_ports_count': 1, - 'infer': copy_shape_infer - }, attrs) - - def supported_attrs(self): - return ['shift_file'] diff --git a/model-optimizer/extensions/ops/prediction_heatmap.py b/model-optimizer/extensions/ops/prediction_heatmap.py deleted file mode 100644 index f614c8601f6..00000000000 --- a/model-optimizer/extensions/ops/prediction_heatmap.py +++ /dev/null @@ -1,32 +0,0 @@ -# Copyright (C) 2018-2021 Intel Corporation -# SPDX-License-Identifier: Apache-2.0 - -import numpy as np - -from mo.graph.graph import Node, Graph -from mo.ops.op import Op - - -class PredictionHeatmapOp(Op): - op = 'PredictionHeatmap' - - def __init__(self, graph: Graph, attrs: dict): - mandatory_props = { - 'type': __class__.op, - 'op': __class__.op, - 'version': 'extension', - 'in_ports_count': 1, - 'out_ports_count': 1, - 'infer': PredictionHeatmapOp.infer - } - super().__init__(graph, mandatory_props, attrs) - - @staticmethod - def infer(node: Node): - in_node_shape = node.in_nodes()[0].shape.copy() - top_shape = np.array([1, 1, 1, 1]) - num_person = in_node_shape[0] - num_joints = in_node_shape[1] - top_shape[2] = num_person - top_shape[3] = 3 * num_joints - node.out_node().shape = top_shape diff --git a/model-optimizer/extensions/ops/priorbox.py b/model-optimizer/extensions/ops/priorbox.py index c27a128bf69..3dd6ba823bb 100644 --- a/model-optimizer/extensions/ops/priorbox.py +++ b/model-optimizer/extensions/ops/priorbox.py @@ -108,7 +108,7 @@ class PriorBoxOp(Op): if node.has_and_set('V10_infer'): assert node.in_node(0).value is not None - node.out_node(0).shape = np.array([2, np.prod(node.in_node(0).value) * num_ratios * 4], dtype=np.int64) + node.out_port(0).data.set_shape([2, np.prod(node.in_node(0).value) * num_ratios * 4]) else: res_prod = data_shape[get_height_dim(layout, 4)] * data_shape[get_width_dim(layout, 4)] * num_ratios * 4 - node.out_node(0).shape = np.array([1, 2, res_prod], dtype=np.int64) + node.out_port(0).data.set_shape([1, 2, res_prod]) diff --git a/model-optimizer/extensions/ops/priorbox_clustered.py b/model-optimizer/extensions/ops/priorbox_clustered.py index cedf74c1fd3..543c220925e 100644 --- a/model-optimizer/extensions/ops/priorbox_clustered.py +++ b/model-optimizer/extensions/ops/priorbox_clustered.py @@ -68,7 +68,7 @@ class PriorBoxClusteredOp(Op): if node.has_and_set('V10_infer'): assert node.in_node(0).value is not None - node.out_node(0).shape = np.array([2, np.prod(node.in_node(0).value) * num_ratios * 4], dtype=np.int64) + node.out_port(0).data.set_shape([2, np.prod(node.in_node(0).value) * num_ratios * 4]) else: res_prod = data_shape[get_height_dim(layout, 4)] * data_shape[get_width_dim(layout, 4)] * num_ratios * 4 - node.out_node(0).shape = np.array([1, 2, res_prod], dtype=np.int64) + node.out_port(0).data.set_shape([1, 2, res_prod]) diff --git a/model-optimizer/extensions/ops/priorgridgenerator_onnx.py b/model-optimizer/extensions/ops/priorgridgenerator_onnx.py index 3d4e3a7b540..269376465d9 100644 --- a/model-optimizer/extensions/ops/priorgridgenerator_onnx.py +++ b/model-optimizer/extensions/ops/priorgridgenerator_onnx.py @@ -1,8 +1,6 @@ # Copyright (C) 2018-2021 Intel Corporation # SPDX-License-Identifier: Apache-2.0 -import numpy as np - from mo.ops.op import Op @@ -11,10 +9,10 @@ class ExperimentalDetectronPriorGridGenerator(Op): def __init__(self, graph, attrs): mandatory_props = dict( - type=__class__.op, - op=__class__.op, + type=self.op, + op=self.op, version='opset6', - infer=__class__.infer, + infer=self.infer, ) super().__init__(graph, mandatory_props, attrs) @@ -29,12 +27,12 @@ class ExperimentalDetectronPriorGridGenerator(Op): @staticmethod def infer(node): - input_shape = node.in_node(0).shape + input_shape = node.in_port(0).data.get_shape() priors_num = input_shape[0] - grid_h = node.in_node(1).shape[2] - grid_w = node.in_node(1).shape[3] + grid_h = node.in_port(1).data.get_shape()[2] + grid_w = node.in_port(1).data.get_shape()[3] if node.flatten: - out_shape = np.array([grid_h * grid_w * priors_num, 4], dtype=np.int64) + out_shape = [grid_h * grid_w * priors_num, 4] else: - out_shape = np.array([grid_h, grid_w, priors_num, 4], dtype=np.int64) - node.out_node(0).shape = out_shape + out_shape = [grid_h, grid_w, priors_num, 4] + node.out_port(0).data.set_shape(out_shape) diff --git a/model-optimizer/extensions/ops/proposal.py b/model-optimizer/extensions/ops/proposal.py index 0da312caf04..39bdcb24da7 100644 --- a/model-optimizer/extensions/ops/proposal.py +++ b/model-optimizer/extensions/ops/proposal.py @@ -12,8 +12,8 @@ class ProposalOp(Op): def __init__(self, graph: Graph, attrs: dict): mandatory_props = { - 'type': __class__.op, - 'op': __class__.op, + 'type': self.op, + 'op': self.op, 'version': 'opset4', 'post_nms_topn': 300, # default in caffe-shared 'infer': ProposalOp.proposal_infer, @@ -58,12 +58,11 @@ class ProposalOp(Op): @staticmethod def proposal_infer(node: Node): input_shape = node.in_node(0).shape - out_shape = int64_array([input_shape[0] * node.post_nms_topn, 5]) # rois blob: holds R regions of interest, each is a 5 - tuple # (n, x1, y1, x2, y2) specifying an image batch index n and a # rectangle(x1, y1, x2, y2) - node.out_port(0).data.set_shape(out_shape) + node.out_port(0).data.set_shape([input_shape[0] * node.post_nms_topn, 5]) # the second optional output contains box probabilities if len(node.out_ports()) == 2 and not node.out_port(1).disconnected(): - node.out_port(1).data.set_shape(int64_array([input_shape[0] * node.post_nms_topn])) + node.out_port(1).data.set_shape([input_shape[0] * node.post_nms_topn]) diff --git a/model-optimizer/extensions/ops/proposal_onnx.py b/model-optimizer/extensions/ops/proposal_onnx.py index e7a2c6f6837..8fff6d65f3f 100644 --- a/model-optimizer/extensions/ops/proposal_onnx.py +++ b/model-optimizer/extensions/ops/proposal_onnx.py @@ -1,8 +1,6 @@ # Copyright (C) 2018-2021 Intel Corporation # SPDX-License-Identifier: Apache-2.0 -import numpy as np - from mo.ops.op import Op @@ -11,10 +9,10 @@ class ExperimentalDetectronGenerateProposalsSingleImage(Op): def __init__(self, graph, attrs): mandatory_props = dict( - type=__class__.op, - op=__class__.op, + type=self.op, + op=self.op, version='experimental', - infer=__class__.infer + infer=self.infer ) super().__init__(graph, mandatory_props, attrs) @@ -29,5 +27,5 @@ class ExperimentalDetectronGenerateProposalsSingleImage(Op): @staticmethod def infer(node): - node.out_node(0).shape = np.array([node.post_nms_count, 4], dtype=np.int64) - node.out_node(1).shape = np.array([node.post_nms_count], dtype=np.int64) + node.out_port(0).data.set_shape([node.post_nms_count, 4]) + node.out_port(1).data.set_shape([node.post_nms_count]) diff --git a/model-optimizer/extensions/ops/range.py b/model-optimizer/extensions/ops/range.py index 4b9e8523766..ae0ed22433a 100644 --- a/model-optimizer/extensions/ops/range.py +++ b/model-optimizer/extensions/ops/range.py @@ -3,6 +3,7 @@ import numpy as np +from mo.front.common.partial_infer.utils import shape_array, dynamic_dimension_value, is_fully_defined from mo.graph.graph import Node, Graph from mo.middle.passes.convert_data_type import np_data_type_to_destination_type from mo.ops.op import Op @@ -70,10 +71,11 @@ class Range(Op): limit = node.in_port(1).data.get_value() delta = node.in_port(2).data.get_value() - assert start is not None and limit is not None and delta is not None, \ - 'Range operation {} with dynamic inputs is not supported'.format(name) + for input in (start, limit, delta): + if input is not None and not node.has_valid('output_type'): + node['output_type'] = input.dtype - if not node.has_valid('output_type'): - node['output_type'] = start.dtype - - node.out_port(0).data.set_value(np.arange(start, limit, delta, dtype=node['output_type'])) + if not is_fully_defined(start) or not is_fully_defined(limit) or not is_fully_defined(delta): + node.out_port(0).data.set_shape(shape_array([dynamic_dimension_value])) + else: + node.out_port(0).data.set_value(np.arange(start, limit, delta, dtype=node['output_type'])) diff --git a/model-optimizer/extensions/ops/regionyolo.py b/model-optimizer/extensions/ops/regionyolo.py index ed002c0e2ba..b9aa70cefa6 100644 --- a/model-optimizer/extensions/ops/regionyolo.py +++ b/model-optimizer/extensions/ops/regionyolo.py @@ -5,6 +5,7 @@ import numpy as np from mo.front.caffe.extractors.utils import get_canonical_axis_index from mo.front.common.layout import get_batch_dim, get_height_dim, get_width_dim, shape_for_layout +from mo.front.common.partial_infer.utils import is_fully_defined, dynamic_dimension_value from mo.front.extractor import attr_getter, bool_to_str from mo.graph.graph import Node, Graph from mo.ops.op import Op @@ -12,11 +13,12 @@ from mo.ops.op import Op class RegionYoloOp(Op): op = 'RegionYolo' + enabled = False - def __init__(self, graph: Graph, attrs: Node): + def __init__(self, graph: Graph, attrs: dict): mandatory_props = { - 'type': __class__.op, - 'op': __class__.op, + 'type': self.op, + 'op': self.op, 'version': 'opset1', 'in_ports_count': 1, 'out_ports_count': 1, @@ -50,22 +52,24 @@ class RegionYoloOp(Op): @staticmethod def regionyolo_infer(node: Node): - input_shape = node.in_node(0).shape - if input_shape is None: - return + input_shape = node.in_port(0).data.get_shape() axis = get_canonical_axis_index(input_shape, node.axis) end_axis = get_canonical_axis_index(input_shape, node.end_axis) node.axis = axis node.end_axis = end_axis if node.do_softmax: - flat_dim = np.prod(input_shape[axis: end_axis + 1]) - node.out_node().shape = np.array([*input_shape[:axis], flat_dim, *input_shape[end_axis + 1:]]) + dims_to_flatten = input_shape[axis: end_axis + 1] + if is_fully_defined(dims_to_flatten): + flat_dim = np.ma.prod(dims_to_flatten) + else: + flat_dim = dynamic_dimension_value + node.out_port(0).data.set_shape([*input_shape[:axis], flat_dim, *input_shape[end_axis + 1:]]) else: layout = node.graph.graph['layout'] assert len(layout) == 4 - node.out_node().shape = shape_for_layout(layout, - batch=input_shape[get_batch_dim(layout, 4)], - features=(node.classes + node.coords + 1) * len(node.mask), - height=input_shape[get_height_dim(layout, 4)], - width=input_shape[get_width_dim(layout, 4)]) + node.out_port(0).data.set_shape(shape_for_layout(layout, + batch=input_shape[get_batch_dim(layout, 4)], + features=(node.classes + node.coords + 1) * len(node.mask), + height=input_shape[get_height_dim(layout, 4)], + width=input_shape[get_width_dim(layout, 4)])) diff --git a/model-optimizer/extensions/ops/reorgyolo.py b/model-optimizer/extensions/ops/reorgyolo.py index 6c87804b1f4..ff6bc3350e3 100644 --- a/model-optimizer/extensions/ops/reorgyolo.py +++ b/model-optimizer/extensions/ops/reorgyolo.py @@ -5,6 +5,7 @@ import numpy as np from mo.graph.graph import Node, Graph from mo.ops.op import Op, PermuteAttrs +from mo.utils.error import Error class ReorgYoloOp(Op): @@ -12,8 +13,8 @@ class ReorgYoloOp(Op): def __init__(self, graph: Graph, attrs: dict): mandatory_props = { - 'type': __class__.op, - 'op': __class__.op, + 'type': self.op, + 'op': self.op, 'version': 'opset2', 'infer': ReorgYoloOp.reorgyolo_infer } @@ -28,15 +29,15 @@ class ReorgYoloOp(Op): def reorgyolo_infer(node: Node): input_shape = node.in_node(0).shape if input_shape is None: - return + raise Error('Input shape for operation "{}" is None'.format(node.soft_get('name', node.id))) stride = node.stride - output_shape = np.full_like(input_shape, -1, dtype=np.int64) + output_shape = input_shape.copy() output_shape[node.batch_dims] = input_shape[node.batch_dims] # pylint: disable=unsupported-assignment-operation output_shape[node.channel_dims] = input_shape[node.channel_dims] * stride ** 2 # pylint: disable=unsupported-assignment-operation # Round as in caffe - output_shape[node.spatial_dims] = np.round(input_shape[node.spatial_dims] / stride) # pylint: disable=unsupported-assignment-operation + output_shape[node.spatial_dims] = np.ma.round(input_shape[node.spatial_dims] / stride) # pylint: disable=unsupported-assignment-operation - node.out_node().shape = output_shape + node.out_port(0).data.set_shape(output_shape) PermuteAttrs.create_permute_attrs(node, attrs=[('channel_dims', 'input:0'), ('spatial_dims', 'input:0')]) diff --git a/model-optimizer/extensions/ops/resize.py b/model-optimizer/extensions/ops/resize.py index cffff036043..8de918ded24 100644 --- a/model-optimizer/extensions/ops/resize.py +++ b/model-optimizer/extensions/ops/resize.py @@ -1,9 +1,9 @@ # Copyright (C) 2018-2021 Intel Corporation # SPDX-License-Identifier: Apache-2.0 -from mo.front.common.partial_infer.utils import int64_array from mo.graph.graph import Node, Graph from mo.ops.op import Op +from mo.utils.error import Error class ResizeOp(Op): @@ -13,10 +13,10 @@ class ResizeOp(Op): def __init__(self, graph: Graph, attrs: dict): mandatory_props = { 'type': None, - 'op': __class__.op, + 'op': self.op, 'in_ports_count': 2, 'out_ports_count': 1, - 'infer': __class__.resize_infer + 'infer': self.resize_infer } super().__init__(graph, mandatory_props, attrs) @@ -37,9 +37,9 @@ class ResizeOp(Op): input_shape = node.in_node(0).shape if input_shape is None: - return + raise Error('Input shape for operation "{}" is None'.format(node.soft_get('name', node.id))) scale_value = node.in_node(1).value - node.out_node().shape = int64_array(input_shape * scale_value) + node.out_port(0).data.set_shape(input_shape * scale_value) diff --git a/model-optimizer/extensions/ops/reverse_sequence.py b/model-optimizer/extensions/ops/reverse_sequence.py index fa6d946619b..06509ec0e59 100644 --- a/model-optimizer/extensions/ops/reverse_sequence.py +++ b/model-optimizer/extensions/ops/reverse_sequence.py @@ -10,14 +10,14 @@ class ReverseSequence(Op): def __init__(self, graph: Graph, attrs: dict): mandatory_props = { - 'type': __class__.op, + 'type': self.op, 'version': 'opset1', 'seq_axis': None, 'batch_axis': 0, - 'op': __class__.op, + 'op': self.op, 'in_ports_count': 2, 'out_ports_count': 1, - 'infer': __class__.infer, + 'infer': self.infer, } super().__init__(graph, mandatory_props, attrs) @@ -28,10 +28,10 @@ class ReverseSequence(Op): @staticmethod def infer(node): - input_data_shape = node.in_node(0).shape + input_data_shape = node.in_port(0).data.get_shape() assert input_data_shape is not None assert node.has_valid('seq_axis') assert node.has_valid('batch_axis') assert len(node.out_nodes()) == 1 - node.out_node().shape = input_data_shape.copy() + node.out_port(0).data.set_shape(input_data_shape) diff --git a/model-optimizer/extensions/ops/roialign.py b/model-optimizer/extensions/ops/roialign.py index 4f7bb489348..c1dcc5f17c4 100644 --- a/model-optimizer/extensions/ops/roialign.py +++ b/model-optimizer/extensions/ops/roialign.py @@ -2,6 +2,7 @@ # SPDX-License-Identifier: Apache-2.0 from mo.front.common.layout import get_features_dim, shape_for_layout +from mo.front.common.partial_infer.utils import compatible_dims from mo.graph.graph import Graph from mo.ops.op import Op @@ -56,9 +57,9 @@ class ROIAlign(Op): indices_shape = node.in_port(2).data.get_shape() assert input_shape is not None and rois_shape is not None and indices_shape is not None, \ 'The node "{}" input shape is None'.format(node_name) - assert rois_shape[0] == indices_shape[0], 'The number of batch indices does not correspond to number of ROIs ' \ - 'for node "{}"'.format(node_name) - assert rois_shape[1] == 4, 'The size of ROI element must be 4 for node "{}"'.format(node_name) + assert compatible_dims(rois_shape[0], indices_shape[0]), 'The number of batch indices does not correspond ' \ + 'to number of ROIs for node "{}"'.format(node_name) + assert compatible_dims(rois_shape[1], 4), 'The size of ROI element must be 4 for node "{}"'.format(node_name) assert len(input_shape) == 4, 'The rank of port 0 input tensor of node "{}" must be 4.'.format(node_name) node.out_port(0).data.set_shape( diff --git a/model-optimizer/extensions/ops/roifeatureextractor_onnx.py b/model-optimizer/extensions/ops/roifeatureextractor_onnx.py index 71783b0c733..5f112e5f8a3 100644 --- a/model-optimizer/extensions/ops/roifeatureextractor_onnx.py +++ b/model-optimizer/extensions/ops/roifeatureextractor_onnx.py @@ -1,8 +1,6 @@ # Copyright (C) 2018-2021 Intel Corporation # SPDX-License-Identifier: Apache-2.0 -import numpy as np - from mo.ops.op import Op @@ -11,10 +9,10 @@ class ExperimentalDetectronROIFeatureExtractor(Op): def __init__(self, graph, attrs): mandatory_props = dict( - type=__class__.op, - op=__class__.op, + type=self.op, + op=self.op, version='opset6', - infer=__class__.infer, + infer=self.infer, out_ports_count=2, ) @@ -29,10 +27,10 @@ class ExperimentalDetectronROIFeatureExtractor(Op): @staticmethod def infer(node): - input_rois_shape = node.in_node(0).shape + input_rois_shape = node.in_port(0).data.get_shape() rois_num = input_rois_shape[0] - input_features_level_0_shape = node.in_node(1).shape + input_features_level_0_shape = node.in_port(1).data.get_shape() channels_num = input_features_level_0_shape[1] - node.out_node(0).shape = np.array([rois_num, channels_num, node.output_size, node.output_size], dtype=np.int64) + node.out_port(0).data.set_shape([rois_num, channels_num, node.output_size, node.output_size]) if not node.out_port(1).disconnected(): - node.out_node(1).shape = np.array([rois_num, 4], dtype=np.int64) + node.out_port(1).data.set_shape([rois_num, 4]) diff --git a/model-optimizer/extensions/ops/scatter.py b/model-optimizer/extensions/ops/scatter.py index 4349b4242b0..56e73637417 100644 --- a/model-optimizer/extensions/ops/scatter.py +++ b/model-optimizer/extensions/ops/scatter.py @@ -3,6 +3,7 @@ import numpy as np +from mo.front.common.partial_infer.utils import compatible_shapes from mo.graph.graph import Node, Graph from mo.ops.op import Op @@ -39,10 +40,11 @@ class Scatter(Op): updates_shape = node.in_port(2).data.get_shape() assert input_shape is not None and updates_shape is not None and indices_shape is not None, \ 'The node "{}" input shape is None'.format(node_name) - assert len(input_shape) == len(indices_shape), 'data and indices inputs for node {} must be of the ' \ + assert len(input_shape) == len(indices_shape), 'data and indices inputs for node "{}" must be of the ' \ 'same rank. Instead got {} and {}'.format(node_name, len(input_shape), len(indices_shape)) - assert np.array_equal(indices_shape, updates_shape), 'updates and indices shapes for node {} must be equal. ' \ - 'Instead got {} and {}'.format(node_name, indices_shape, updates_shape) + assert compatible_shapes(indices_shape, updates_shape), \ + 'updates and indices shapes for node "{}" must be equal. Instead got {} and {}.' \ + ''.format(node_name, indices_shape, updates_shape) node.out_port(0).data.set_shape(input_shape) diff --git a/model-optimizer/extensions/ops/scatternd.py b/model-optimizer/extensions/ops/scatternd.py index 8917d11cfb8..c0fd7373e61 100644 --- a/model-optimizer/extensions/ops/scatternd.py +++ b/model-optimizer/extensions/ops/scatternd.py @@ -3,7 +3,7 @@ import numpy as np -from mo.front.common.partial_infer.utils import int64_array +from mo.front.common.partial_infer.utils import compatible_shapes, strict_compare_tensors, is_fully_defined from mo.graph.graph import Node, Graph from mo.ops.op import Op @@ -46,15 +46,18 @@ class ScatterNDBase(Op): 'The node "{}" input and indices ranks must be at least 1'.format(node_name) # 2. the last dimension of indices shape must be at most a rank of input - assert indices_shape[-1] <= len(input_shape), \ + assert not is_fully_defined(indices_shape[-1]) or indices_shape[-1] <= len(input_shape), \ 'The last dimension of indices shape must be at most a rank of input for the node "{}"'.format(node_name) # 3. updates is a tensor of shape indices_shape[:-1] + input_shape[indices_shape[-1]:] - # if expected updates shape is scalar, updates can be tensor with the single element (for example, of shape [1], [[1]], etc.) - expected_updates_shape = np.concatenate((indices_shape[:-1], input_shape[indices_shape[-1]:]), axis=0) - assert np.array_equal(updates_shape, expected_updates_shape) or\ - np.array_equal(expected_updates_shape, []) and np.array_equal(updates_shape, np.ones(len(updates_shape))), \ - 'The updates shape must be equal to indices_shape[:-1] + input_shape[indices_shape[-1]:] for the node "{}"'.format(node_name) + # if expected updates shape is scalar, updates can be tensor with the single element (for example, of shape + # [1], [[1]], etc.) + expected_updates_shape = np.ma.concatenate((indices_shape[:-1], input_shape[indices_shape[-1]:]), axis=0) + assert compatible_shapes(updates_shape, expected_updates_shape) or \ + (strict_compare_tensors(expected_updates_shape, []) and + strict_compare_tensors(updates_shape, np.ones(len(updates_shape)))), \ + 'The updates shape must be equal to indices_shape[:-1] + input_shape[indices_shape[-1]:] for the node ' \ + '"{}"'.format(node_name) node.out_port(0).data.set_shape(input_shape) @@ -79,9 +82,9 @@ class ScatterNDUpdate(ScatterNDBase): updates_value = node.in_port(2).data.get_value() # compute output value if all inputs are constant - if input_value is not None and indices_value is not None and updates_value is not None: + if input_value is not None and is_fully_defined(indices_value) and updates_value is not None: output_value = input_value.copy() - indx_range = int64_array(indices_shape[:-1]) + indx_range = indices_shape[:-1] for indx in np.ndindex(tuple(indx_range)): if indx == (): # a case when updates is a scalar diff --git a/model-optimizer/extensions/ops/select.py b/model-optimizer/extensions/ops/select.py index 31d602195d5..e79df5e53eb 100644 --- a/model-optimizer/extensions/ops/select.py +++ b/model-optimizer/extensions/ops/select.py @@ -3,9 +3,10 @@ import numpy as np -from mo.front.common.partial_infer.utils import int64_array, broadcast_shape +from mo.front.common.partial_infer.utils import is_fully_defined from mo.graph.graph import Node, Graph from mo.ops.op import Op +from mo.utils.broadcasting import bi_directional_shape_broadcasting, bi_directional_broadcasting class Select(Op): @@ -13,13 +14,13 @@ class Select(Op): def __init__(self, graph: Graph, attrs: dict): mandatory_props = { - 'op': __class__.op, - 'type': __class__.op, + 'op': self.op, + 'type': self.op, 'version': 'opset1', 'in_ports_count': 3, 'out_ports_count': 1, - 'infer': __class__.infer, - 'type_infer': __class__.type_infer, + 'infer': self.infer, + 'type_infer': self.type_infer, 'auto_broadcast': 'numpy' } super().__init__(graph, mandatory_props, attrs) @@ -29,28 +30,37 @@ class Select(Op): @staticmethod def infer(node: Node): - assert len([port for port in node.in_ports().values() if not port.disconnected()]) == 3, "Select operation must have 3 inputs:" \ - " \'condition\', \'then\' and \'else\' tensors" + node_name = node.soft_get('name', node.id) + assert len([port for port in node.in_ports().values() if not port.disconnected()]) == 3, \ + "Select operation must have 3 inputs: 'condition', 'then' and 'else' tensors for node {}".format(node_name) condition_value = node.in_port(0).data.get_value() resulting_tensors = [node.in_port(1).data.get_value(), node.in_port(2).data.get_value()] a_shape = node.in_port(1).data.get_shape() b_shape = node.in_port(2).data.get_shape() - node.out_port(0).data.set_shape(broadcast_shape(a_shape, b_shape)) - # Case with unknown condition + output_shape = bi_directional_shape_broadcasting(a_shape, b_shape) + assert output_shape is not None, 'Input shapes for node {} are not broadcast-able'.format(node_name) + node.out_port(0).data.set_shape(output_shape) + if condition_value is not None: - output_value = np.where(condition_value, resulting_tensors[0], resulting_tensors[1]) + if resulting_tensors[0] is not None: + resulting_tensors[0] = bi_directional_broadcasting(resulting_tensors[0], b_shape) + if resulting_tensors[1] is not None: + resulting_tensors[1] = bi_directional_broadcasting(resulting_tensors[1], a_shape) + condition_value = bi_directional_broadcasting(condition_value, output_shape) + + output_value = np.ma.where(condition_value, resulting_tensors[0], resulting_tensors[1]) if condition_value.size != 1: if np.any(output_value == None): - # If any element of output value is None that means that we use the value from 'then' or 'else' tensor - # which is not defined, this means that we cannot perform value propagation. + # If any element of output value is None that means that we use the value from the 'then' or the + # 'else' tensor which is not defined, this means that we cannot perform value propagation. output_value = None else: - output_value = np.array(output_value, dtype=resulting_tensors[not np.bool(condition_value.item(0))].dtype) + output_value = output_value.astype(resulting_tensors[not np.bool(condition_value.item(0))].dtype) if output_value is not None: - node.out_port(0).data.set_value(np.array(output_value)) + node.out_port(0).data.set_value(output_value) @staticmethod def type_infer(node: Node): diff --git a/model-optimizer/extensions/ops/simplernms.py b/model-optimizer/extensions/ops/simplernms.py deleted file mode 100644 index 9763dfee358..00000000000 --- a/model-optimizer/extensions/ops/simplernms.py +++ /dev/null @@ -1,71 +0,0 @@ -# Copyright (C) 2018-2021 Intel Corporation -# SPDX-License-Identifier: Apache-2.0 - -import logging as log - -import numpy as np - -from mo.front.extractor import attr_getter -from mo.graph.graph import Node, Graph -from mo.ops.op import Op - - -class SimplerNMSOp(Op): - op = 'SimplerNMS' - - def __init__(self, graph: Graph, attrs: dict): - mandatory_props = { - 'type': __class__.op, - 'op': __class__.op, - 'version': 'experimental', - 'in_ports_count': 3, - 'out_ports_count': 1, - 'infer': SimplerNMSOp.simplernms_infer - } - super().__init__(graph, mandatory_props, attrs) - - def supported_attrs(self): - return [ - 'cls_threshold', - 'max_num_proposals', - 'iou_threshold', - 'min_bbox_size', - 'feat_stride', - 'pre_nms_topn', - 'post_nms_topn', - 'scale' - ] - - def backend_attrs(self): - return [ - 'cls_threshold', - 'max_num_proposals', - 'iou_threshold', - 'min_bbox_size', - 'feat_stride', - 'pre_nms_topn', - 'post_nms_topn', - ('scale', lambda node: attr_getter(node, 'scale')) - ] - - @staticmethod - def simplernms_infer(node: Node): - """ - Sets shape of output node according to specified param of post_nms_topn - and number of the following params: [is_obj, x, y, w, h] - Parameters - ---------- - node - - """ - if node.feat_stride != 16: - log.error("SimplerNMS layer doesn't support other feat_stride value that 16") - return - - scale_list = [] - for i in range(0, len(node.scale)): - scale_list.append(str(node.scale[i])) - - node.scale = scale_list - - node.out_node().shape = np.array([node.post_nms_topn, 5]) diff --git a/model-optimizer/extensions/ops/size.py b/model-optimizer/extensions/ops/size.py index a1bd0db210f..40cf5efcab1 100644 --- a/model-optimizer/extensions/ops/size.py +++ b/model-optimizer/extensions/ops/size.py @@ -3,6 +3,7 @@ import numpy as np +from mo.front.common.partial_infer.utils import is_fully_defined, shape_array, dynamic_dimension_value from mo.graph.graph import Node, Graph from mo.ops.op import Op @@ -39,4 +40,7 @@ class Size(Op): assert node.output_type in [np.int64, np.int32], \ 'Size `output_type` attribute must be int32 or int64, `{}` found'.format(np.dtype(node.output_type).name) - node.out_port(0).data.set_value(np.array(np.prod(input_shape), dtype=node.output_type)) + if is_fully_defined(input_shape): + node.out_port(0).data.set_value(np.array(np.prod(input_shape), dtype=node.output_type)) + else: + node.out_port(0).data.set_value(shape_array(dynamic_dimension_value)) diff --git a/model-optimizer/extensions/ops/slice_like.py b/model-optimizer/extensions/ops/slice_like.py index db2077398e0..1bc45ae208e 100644 --- a/model-optimizer/extensions/ops/slice_like.py +++ b/model-optimizer/extensions/ops/slice_like.py @@ -26,6 +26,7 @@ class SliceLike(Op): @staticmethod def infer(node): input_shape = node.in_port(0).data.get_shape() + input_value = node.in_port(0).data.get_value() shape_like = node.in_port(1).data.get_shape() new_shape = np.copy(input_shape) @@ -40,8 +41,8 @@ class SliceLike(Op): new_shape = np.copy(shape_like) node.out_port(0).data.set_shape(new_shape) - if node.in_port(0).get_connection().data.get_value() is not None: - out_value = np.copy(node.in_port(0).data.get_value()) + if input_value is not None: + out_value = np.copy(input_value) slice_indexes = [] for s in out_value.shape: diff --git a/model-optimizer/extensions/ops/space_to_depth.py b/model-optimizer/extensions/ops/space_to_depth.py index 8a116c53c5a..f39bd563d4d 100644 --- a/model-optimizer/extensions/ops/space_to_depth.py +++ b/model-optimizer/extensions/ops/space_to_depth.py @@ -4,7 +4,7 @@ import numpy as np from mo.front.common.layout import shape_for_layout, get_height_dim, get_batch_dim, get_features_dim, get_width_dim -from mo.front.common.partial_infer.utils import int64_array +from mo.front.common.partial_infer.utils import dynamic_dimension, is_fully_defined from mo.graph.graph import Node, Graph from mo.ops.op import Op from mo.utils.error import Error @@ -45,16 +45,15 @@ class SpaceToDepth(Op): C = in_shape[get_features_dim(layout, 4)] block_size = node['block_size'] - if H % block_size or W % block_size: + if (H is not dynamic_dimension and H % block_size) or (W is not dynamic_dimension and W % block_size): raise Error('Spatial dimensions of input tensor of SpaceToDepth operation have to be divisible by ' 'SpaceToDepth \'block_size\' parameter. Input tensor shape = {}. Spatial dimensions = {},{}. ' 'block_size = {}'.format(in_shape, H, W, block_size)) out_shape = shape_for_layout(layout, batch=N, - features=int(C * (block_size ** 2)), - height=int(H / block_size), - width=int(W / block_size)) + features=C * (block_size ** 2), + height=H // block_size, + width=W // block_size) - assert np.prod(in_shape) == np.prod(out_shape) - node.out_node().shape = int64_array(out_shape) + node.out_port(0).data.set_shape(out_shape) diff --git a/model-optimizer/extensions/ops/sparse_fill_empty_rows.py b/model-optimizer/extensions/ops/sparse_fill_empty_rows.py index 4129b941098..f9bc02829dc 100644 --- a/model-optimizer/extensions/ops/sparse_fill_empty_rows.py +++ b/model-optimizer/extensions/ops/sparse_fill_empty_rows.py @@ -1,37 +1,38 @@ # Copyright (C) 2018-2021 Intel Corporation # SPDX-License-Identifier: Apache-2.0 -import logging as log - import numpy as np +from mo.front.common.partial_infer.utils import dynamic_dimension_value, is_fully_defined from mo.graph.graph import Node, Graph from mo.ops.op import Op class SparseFillEmptyRows(Op): - ''' The operation fills empty rows in the input 2-D sparse tensor with a default value. - For more details see https://www.tensorflow.org/api_docs/cc/class/tensorflow/ops/sparse-fill-empty-rows + """ + The operation fills empty rows in the input 2-D sparse tensor with a default value. + For more details see https://www.tensorflow.org/api_docs/cc/class/tensorflow/ops/sparse-fill-empty-rows - 4 inputs: - - [0, required] input indices of the sparse tensor (2D), - - [1, required] input values of the sparse tensor (1D), - - [2, required] shape of the sparse tensor. Value of this input is required for the Model Optimizer (1D), - - [3, required] default value to insert at rows missing from the input sparse tensor (0D), - - 3 outputs: - - [0, optional] indices of the filled sparse tensor (2D) - - [1, optional] values of the filled sparse tensor (1D) - - [2, optional] indicator of whether the dense row was missing in the input sparse tensor (1D) - ''' + 4 inputs: + - [0, required] input indices of the sparse tensor (2D), + - [1, required] input values of the sparse tensor (1D), + - [2, required] shape of the sparse tensor. Value of this input is required for the Model Optimizer (1D), + - [3, required] default value to insert at rows missing from the input sparse tensor (0D), + + 3 outputs: + - [0, optional] indices of the filled sparse tensor (2D) + - [1, optional] values of the filled sparse tensor (1D) + - [2, optional] indicator of whether the dense row was missing in the input sparse tensor (1D) + """ op = 'SparseFillEmptyRows' + enabled = False def __init__(self, graph: Graph, attrs: dict): mandatory_props = { - 'type': __class__.op, - 'op': __class__.op, + 'type': None, + 'op': self.op, 'version': 'experimental', - 'infer': __class__.infer, + 'infer': self.infer, 'in_ports_count': 4, 'out_ports_count': 3 } @@ -56,16 +57,15 @@ class SparseFillEmptyRows(Op): assert default_value.shape is not None and len(default_value.shape) == 0, \ "Default value for SparseFillEmptyRows must be scalar" - for out_node_ind in node.out_nodes(): - if out_node_ind == 0: # set a shape for output indices - node.out_node(0).shape = np.array([np.prod(shape_value), 2], dtype=np.int64) - continue - elif out_node_ind == 1: # set a shape for output values - node.out_node(1).shape = np.array([np.prod(shape_value)], dtype=np.int64) - continue - elif out_node_ind == 2: # set a shape for empty row indicator - node.out_node(2).shape = np.array([shape_value[0]], dtype=np.int64) - continue + if node.is_out_port_connected(0): # set a shape for output indices + if is_fully_defined(shape_value): + node.out_port(0).data.set_shape([np.prod(shape_value), 2]) else: - log.error("SparseFillEmptyRows has only three outputs") - return + node.out_port(0).data.set_shape([dynamic_dimension_value, 2]) + if node.is_out_port_connected(1): # set a shape for output values + if is_fully_defined(shape_value): + node.out_port(1).data.set_shape([np.prod(shape_value)]) + else: + node.out_port(1).data.set_shape([dynamic_dimension_value]) + if node.is_out_port_connected(2): # set a shape for empty row indicator + node.out_port(2).data.set_shape([shape_value[0]]) diff --git a/model-optimizer/extensions/ops/spatial_transformer.py b/model-optimizer/extensions/ops/spatial_transformer.py deleted file mode 100644 index 692562e6491..00000000000 --- a/model-optimizer/extensions/ops/spatial_transformer.py +++ /dev/null @@ -1,47 +0,0 @@ -# Copyright (C) 2018-2021 Intel Corporation -# SPDX-License-Identifier: Apache-2.0 - -import copy - -from mo.graph.graph import Node, Graph -from mo.ops.op import Op - - -class SpatialTransformOp(Op): - op = 'SpatialTransformer' - - def __init__(self, graph: Graph, attrs: dict): - mandatory_props = { - 'type': __class__.op, - 'op': __class__.op, - 'version': 'experimental', - 'in_ports_count': 1, - 'out_ports_count': 1, - 'infer': SpatialTransformOp.sp_infer - } - super().__init__(graph, mandatory_props, attrs) - - def supported_attrs(self): - return [ - 'transform_type', - 'sampler_type', - 'output_H', - 'output_W', - 'to_compute_dU', - 'theta_1_1', - 'theta_1_2', - 'theta_1_3', - 'theta_2_1', - 'theta_2_2', - 'theta_2_3' - ] - - @staticmethod - def sp_infer(node: Node): - input_shape = node.in_node(0).shape - output_shape = copy.copy(input_shape) - if node.has_valid('output_H'): - output_shape[2] = node.output_H - if node.has_valid('output_W'): - output_shape[3] = node.output_W - node.out_node().shape = output_shape diff --git a/model-optimizer/extensions/ops/splice.py b/model-optimizer/extensions/ops/splice.py index 5a861e5a8a9..3b1075e21e2 100644 --- a/model-optimizer/extensions/ops/splice.py +++ b/model-optimizer/extensions/ops/splice.py @@ -11,16 +11,17 @@ class Splice(Op): def __init__(self, graph: Graph, attrs: dict): mandatory_props = { 'type': None, - 'op': __class__.op, + 'op': self.op, 'const_dim': 0, 'in_ports_count': 1, 'out_ports_count': 1, - 'infer': __class__.infer, + 'infer': self.infer, } super().__init__(graph, mandatory_props, attrs) @staticmethod def infer(node: Node): - out_node = node.out_node() - out_node.shape = node.in_node().shape.copy() - out_node.shape[1] = node.const_dim + (node.in_node().shape[1] - node.const_dim) * len(node.context) + input_shape = node.in_port(0).data.get_shape() + output_shape = input_shape.copy() + output_shape[1] = node.const_dim + (input_shape[1] - node.const_dim) * len(node.context) + node.out_port(0).data.set_shape(output_shape) diff --git a/model-optimizer/extensions/ops/split.py b/model-optimizer/extensions/ops/split.py index 6c25aa7ef20..6cb031a8264 100644 --- a/model-optimizer/extensions/ops/split.py +++ b/model-optimizer/extensions/ops/split.py @@ -5,7 +5,7 @@ import logging as log import numpy as np -from mo.front.common.partial_infer.utils import int64_array +from mo.front.common.partial_infer.utils import int64_array, is_fully_defined, dynamic_dimension, shape_delete from mo.graph.graph import Graph, Node from mo.graph.perm_inputs import PermuteInputs from mo.ops.op import Op, PermuteAttrs @@ -57,9 +57,9 @@ class VariadicSplitBase(Op): ''.format(op, split_lengths, name) input_elements = input_shape[axis] - assert undefined_elements.size != 0 or input_elements == np.sum(split_lengths), \ - 'The sum of split_lengths=`{}` must match data.shape[axis]=`{}`. Node: {}' \ - ''.format(split_lengths, input_elements, name) + assert undefined_elements.size != 0 or input_elements is dynamic_dimension or \ + input_elements == np.sum(split_lengths), 'The sum of split_lengths=`{}` must match data.shape[axis]=' \ + '`{}`. Node: {}'.format(split_lengths, input_elements, name) assert len(split_lengths) >= len([port for i, port in node.out_ports().items() if not port.disconnected()]), \ 'Number of split_lengths=`{}` is less than connected output ports. Node: {}'.format(split_lengths, name) @@ -70,8 +70,7 @@ class VariadicSplitBase(Op): for i in reversed(range(len(split_lengths))): if split_lengths[i] == 0: if node.out_port(i).disconnected(): - size_splits = list(split_lengths) - split_lengths = np.delete(int64_array(split_lengths), i) + split_lengths = shape_delete(split_lengths, i) if op == 'VariadicSplit': node.in_port(2).data.set_value(split_lengths) else: @@ -191,12 +190,12 @@ class SplitBase(Op): assert axis is not None, '{} `axis` is unknown for node {}'.format(op, name) assert axis.ndim == 0, '{} `axis` should be scalar, but it`s not for node {}'.format(op, name) - assert input_shape[axis] % num_splits == 0, \ + assert not is_fully_defined(input_shape[axis]) or input_shape[axis] % num_splits == 0, \ 'Input shape is not evenly divided by `num_splits` of {} node {}. `input_shape`={}, `axis`={}, ' \ '`num_splits`={}'.format(op, name, input_shape, axis, num_splits) out_shape = input_shape.copy() - out_shape[axis] = np.int64(input_shape[axis] / num_splits) + out_shape[axis] = input_shape[axis] // num_splits input_value = node.in_port(0).data.get_value() output_value = np.split(input_value.copy(), axis=axis, indices_or_sections=num_splits) \ diff --git a/model-optimizer/extensions/ops/stop_gradient.py b/model-optimizer/extensions/ops/stop_gradient.py index 81f1d483a67..eeaed3348f7 100644 --- a/model-optimizer/extensions/ops/stop_gradient.py +++ b/model-optimizer/extensions/ops/stop_gradient.py @@ -13,14 +13,10 @@ class StopGradientOp(Op): def __init__(self, graph: Graph, attrs: dict): super().__init__(graph, { 'type': None, - 'op': __class__.op, + 'op': self.op, 'identity': True, 'in_ports_count': 1, 'out_ports_count': 1, - 'infer': StopGradientOp.shape_infer + 'infer': copy_shape_infer }, attrs) - @staticmethod - def shape_infer(node): - copy_shape_infer(node) - diff --git a/model-optimizer/extensions/ops/swapaxis.py b/model-optimizer/extensions/ops/swapaxis.py index cfbff60dc75..5399db556dc 100644 --- a/model-optimizer/extensions/ops/swapaxis.py +++ b/model-optimizer/extensions/ops/swapaxis.py @@ -13,8 +13,8 @@ class SwapAxis(Op): def __init__(self, graph: Graph, attrs: dict): super().__init__(graph, { - 'op': __class__.op, - 'infer': __class__.infer, + 'op': self.op, + 'infer': self.infer, 'in_ports_count': 1, 'out_ports_count': 1, }, attrs) diff --git a/model-optimizer/extensions/ops/switch.py b/model-optimizer/extensions/ops/switch.py index 17a2a432b09..6c8f21705a5 100644 --- a/model-optimizer/extensions/ops/switch.py +++ b/model-optimizer/extensions/ops/switch.py @@ -1,8 +1,7 @@ # Copyright (C) 2018-2021 Intel Corporation # SPDX-License-Identifier: Apache-2.0 -import numpy as np - +from mo.front.common.partial_infer.utils import shape_array, is_fully_defined from mo.graph.graph import Node, Graph from mo.ops.op import Op @@ -12,9 +11,9 @@ class Switch(Op): def __init__(self, graph: Graph, attrs: dict): mandatory_props = { - 'op': __class__.op, - 'infer': __class__.infer, - 'cf_infer': __class__.control_flow_infer + 'op': self.op, + 'infer': self.infer, + 'cf_infer': self.control_flow_infer } super().__init__(graph, mandatory_props, attrs) @@ -24,17 +23,17 @@ class Switch(Op): tensor = node.in_node(0) port_id = node.in_node(1) - output_shape = tensor.shape - # Case with variable predicate - if not port_id.has_valid('value'): - # infer only shapes - for _, out_node in node.graph.out_edges(node.id): - node.graph.node[out_node]['shape'] = np.array(output_shape) - return - output_value = tensor.value - for _, out_node in node.graph.out_edges(node.id): - node.graph.node[out_node]['shape'] = np.array(output_shape) - node.graph.node[out_node]['value'] = None if output_value is None else np.array(output_value) + output_shape = shape_array(tensor.shape) + for out_port_id in range(2): + if node.is_out_port_connected(out_port_id): + node.out_port(out_port_id).data.set_shape(output_shape) + + if port_id.has_valid('value'): + output_value = tensor.value + if output_value is not None: + for out_port_id in range(2): + if node.is_out_port_connected(out_port_id): + node.out_port(out_port_id).data.set_value(output_value.copy()) @staticmethod def control_flow_infer(node: Node, is_executable: bool, mark_executability: callable): @@ -52,7 +51,7 @@ class Switch(Op): switch_data_1_port_node_id = [out_data_nodes[1].id] if 1 in out_data_nodes else [] assert 1 <= len(switch_data_0_port_node_id) + len(switch_data_1_port_node_id) <= 2 - if not node_with_switch_value.has_valid('value'): + if not node_with_switch_value.has_valid('value') or not is_fully_defined(node_with_switch_value.value): # Mark both ports as executable resulting_switch_data_node_ids = switch_data_0_port_node_id + switch_data_1_port_node_id for n in resulting_switch_data_node_ids: diff --git a/model-optimizer/extensions/ops/tensor_iterator.py b/model-optimizer/extensions/ops/tensor_iterator.py index 7be9107d559..0d62d4ad544 100644 --- a/model-optimizer/extensions/ops/tensor_iterator.py +++ b/model-optimizer/extensions/ops/tensor_iterator.py @@ -4,6 +4,7 @@ from copy import copy, deepcopy from extensions.ops.parameter import Parameter +from mo.front.common.partial_infer.utils import shape_array from mo.graph.graph import Node, dict_includes, Graph from mo.ops.const import Const from mo.ops.op import Op @@ -51,7 +52,7 @@ class TensorIterator(Op): assert data_node.has_valid('shape'), \ 'Data node should have `shape` attribute set, but it`s not for node {}'.format(data_node.id) shape = data_node['shape'].copy() - parameter_data_node = Parameter(body, {'shape': shape}).create_node_with_data() + parameter_data_node = Parameter(body, {'shape': shape_array(shape)}).create_node_with_data() body.create_edge(src_node=parameter_data_node, dst_node=operation_node, out_port=0, in_port=in_port, edge_attrs=attrs) diff --git a/model-optimizer/extensions/ops/topk.py b/model-optimizer/extensions/ops/topk.py index f25d8eff03a..6e7c4a996c1 100644 --- a/model-optimizer/extensions/ops/topk.py +++ b/model-optimizer/extensions/ops/topk.py @@ -15,8 +15,8 @@ class TopK(Op): def __init__(self, graph: Graph, attrs: dict): super().__init__(graph, { - 'type': __class__.op, - 'op': __class__.op, + 'type': self.op, + 'op': self.op, 'version': 'opset3', 'infer': self.infer, 'type_infer': self.type_infer, diff --git a/model-optimizer/extensions/ops/topkrois_onnx.py b/model-optimizer/extensions/ops/topkrois_onnx.py index 5f907bbffb2..613b7b27149 100644 --- a/model-optimizer/extensions/ops/topkrois_onnx.py +++ b/model-optimizer/extensions/ops/topkrois_onnx.py @@ -1,8 +1,6 @@ # Copyright (C) 2018-2021 Intel Corporation # SPDX-License-Identifier: Apache-2.0 -import numpy as np - from mo.ops.op import Op @@ -11,10 +9,10 @@ class ExperimentalDetectronTopKROIs(Op): def __init__(self, graph, attrs): mandatory_props = dict( - type=__class__.op, - op=__class__.op, + type=self.op, + op=self.op, version='experimental', - infer=__class__.infer + infer=self.infer ) super().__init__(graph, mandatory_props, attrs) @@ -23,4 +21,4 @@ class ExperimentalDetectronTopKROIs(Op): @staticmethod def infer(node): - node.out_node(0).shape = np.array([node.max_rois, 4], dtype=np.int64) + node.out_port(0).data.set_shape([node.max_rois, 4]) diff --git a/model-optimizer/extensions/ops/transpose.py b/model-optimizer/extensions/ops/transpose.py index ea686505bce..d5436d88119 100644 --- a/model-optimizer/extensions/ops/transpose.py +++ b/model-optimizer/extensions/ops/transpose.py @@ -13,8 +13,8 @@ class Transpose(Op): def __init__(self, graph: Graph, attrs: dict): super().__init__(graph, { - 'type': __class__.op, - 'op': __class__.op, + 'type': self.op, + 'op': self.op, 'version': 'opset1', 'infer': self.infer, 'force_precision_in_ports': {1: 'int64'}, diff --git a/model-optimizer/extensions/ops/upsample.py b/model-optimizer/extensions/ops/upsample.py index d5a62d02193..6e11edc5ee6 100644 --- a/model-optimizer/extensions/ops/upsample.py +++ b/model-optimizer/extensions/ops/upsample.py @@ -2,9 +2,9 @@ # SPDX-License-Identifier: Apache-2.0 import math -import numpy as np from mo.front.common.layout import get_batch_dim, get_features_dim, get_height_dim, get_width_dim, shape_for_layout +from mo.front.common.partial_infer.utils import dynamic_dimension, shape_array, dynamic_dimension_value from mo.graph.graph import Node, Graph from mo.ops.op import Op @@ -14,7 +14,7 @@ class UpsampleOp(Op): def __init__(self, graph: Graph, attrs: dict): mandatory_props = { - 'op': __class__.op, + 'op': self.op, 'in_ports_count': 2, 'out_ports_count': 1, 'infer': UpsampleOp.upsample_infer @@ -30,26 +30,38 @@ class UpsampleOp(Op): @staticmethod def upsample_infer(node: Node): + node_name = node.soft_get('name', node.id) layout = node.graph.graph['layout'] - assert len(layout) == 4 + assert len(layout) == 4, 'Input tensor rank must be equal to 4 for node "{}"'.format(node_name) - input_shape = node.in_node(0).shape - if input_shape is None: - return + input_shape = node.in_port(0).data.get_shape() if len(node.in_nodes()) == 1: in_height = input_shape[get_height_dim(layout, 4)] in_width = input_shape[get_width_dim(layout, 4)] assert node.has('width_scale') is not None and node.has('height_scale') is not None - out_height = math.floor(in_height * node.height_scale) - out_width = math.floor(in_width * node.width_scale) - node.out_node().shape = shape_for_layout(layout, - batch=input_shape[get_batch_dim(layout, 4)], - features=input_shape[get_features_dim(layout, 4)], - height=out_height, - width=out_width) + if in_height is not dynamic_dimension: + out_height = math.floor(in_height * node.height_scale) + else: + out_height = dynamic_dimension + if in_width is not dynamic_dimension: + out_width = math.floor(in_width * node.width_scale) + else: + out_width = dynamic_dimension + node.out_port(0).data.set_shape(shape_for_layout(layout, + batch=input_shape[get_batch_dim(layout, 4)], + features=input_shape[get_features_dim(layout, 4)], + height=out_height, + width=out_width)) else: - assert node.in_node(1).value is not None + scales = node.in_port(1).data.get_value() + assert scales is not None, 'The input with scales for node "{}" is not constant'.format(node_name) eps = 1e-5 # This is to make rounding in case of very close number to round to closest instead of down # generic output shape calculation to support 5D input shape case - node.out_node().shape = np.array((input_shape + eps) * node.in_node(1).value).astype(np.int64) + output_shape = shape_array([dynamic_dimension for _ in range(len(input_shape))]) + for idx in range(len(output_shape)): + if input_shape[idx] is not dynamic_dimension: + output_shape[idx] = int((input_shape[idx] + eps) * scales[idx]) + else: + output_shape[idx] = dynamic_dimension_value + node.out_port(0).data.set_shape(output_shape) diff --git a/model-optimizer/mo/back/ie_ir_ver_2/emitter.py b/model-optimizer/mo/back/ie_ir_ver_2/emitter.py index ec9b737e464..73e4dd040ca 100644 --- a/model-optimizer/mo/back/ie_ir_ver_2/emitter.py +++ b/model-optimizer/mo/back/ie_ir_ver_2/emitter.py @@ -3,10 +3,11 @@ import hashlib -from defusedxml import defuse_stdlib import defusedxml.ElementTree as ET +from defusedxml import defuse_stdlib from defusedxml.minidom import parseString +from mo.front.common.partial_infer.utils import unmask_shape, is_fully_defined from mo.graph.graph import * from mo.middle.passes.convert_data_type import np_data_type_to_precision from mo.utils.unsupported_ops import UnsupportedOps @@ -59,6 +60,9 @@ def serialize_constants_recursively(graph: Graph, bin_file, data_type, bin_hashe any('bin' in d for u, v, d in graph.out_edges(node.node, data=True)): # avoid array copying while taking hash blob = node.value if node.value.ndim > 0 else node.value.reshape((1)) + assert is_fully_defined(blob), 'The constant value cannot contain dynamic values' + if isinstance(blob, np.ma.masked_array): + blob = np.ma.getdata(blob) blob_hash = hashlib.sha512(np.ascontiguousarray(blob).view(np.uint8)).hexdigest() if blob_hash in bin_hashes and np.array_equal(blob, bin_hashes[blob_hash]['blob']): @@ -112,11 +116,10 @@ def serialize_mean_image(bin_file_name: str, mean_data=[]): def xml_shape(shape: np.ndarray, element: Element): - for d in shape: + for d in unmask_shape(shape): + if d < -1: + raise Error('The value "{}" for shape is not valid value.'.format(d)) dim = SubElement(element, 'dim') - if d < 0: - raise Error('The value "{}" for shape is less 0. May be the input shape of the topology is ' - 'wrong.'.format(d)) if int(d) != d: raise Error('The value "{}" for shape is not integer.'.format(d)) if not isinstance(d, np.int64): diff --git a/model-optimizer/mo/front/common/layout.py b/model-optimizer/mo/front/common/layout.py index cfa9c1038d1..bcb78dc2189 100644 --- a/model-optimizer/mo/front/common/layout.py +++ b/model-optimizer/mo/front/common/layout.py @@ -3,6 +3,7 @@ import numpy as np +from mo.front.common.partial_infer.utils import dynamic_dimension_value from mo.utils.error import Error nchw_to_nhwc_permute = np.array([0, 2, 3, 1], dtype=np.int64) @@ -90,7 +91,7 @@ def shape_for_layout(layout: str, **kwargs): :param layout: layout string. :param kwargs: dictionary that contains the dimension sizes using the following keys: 'batch', 'features', 'depth', 'height', 'width'. - :return: np.array of type np.int64 with 4 or 5 elements. + :return: shape_array of type np.int64 with 4 or 5 elements. """ assert layout in supported_layouts for required_key in ('batch', 'features', 'height', 'width'): @@ -102,7 +103,7 @@ def shape_for_layout(layout: str, **kwargs): depth = kwargs.get('depth', None) shape_len = 4 + (depth is not None) - output_shape = np.ones(shape=[shape_len], dtype=np.int64) + output_shape = np.ma.ones(shape=[shape_len], dtype=np.int64, fill_value=dynamic_dimension_value) output_shape[get_batch_dim(layout, shape_len)] = kwargs['batch'] output_shape[get_height_dim(layout, shape_len)] = kwargs['height'] output_shape[get_width_dim(layout, shape_len)] = kwargs['width'] diff --git a/model-optimizer/mo/front/common/partial_infer/concat.py b/model-optimizer/mo/front/common/partial_infer/concat.py index 47bfd4ba51e..4f588e0c356 100644 --- a/model-optimizer/mo/front/common/partial_infer/concat.py +++ b/model-optimizer/mo/front/common/partial_infer/concat.py @@ -1,18 +1,16 @@ # Copyright (C) 2018-2021 Intel Corporation # SPDX-License-Identifier: Apache-2.0 -import logging as log - -# Concat infer : N - number of inputs to concat -# axis - dimension number for tensors concatenation import numpy as np from mo.front.caffe.extractors.utils import get_canonical_axis_index -from mo.front.common.partial_infer.utils import int64_array +from mo.front.common.partial_infer.utils import shape_array, is_fully_defined, dynamic_dimension from mo.ops.op import PermuteAttrs +from mo.utils.error import Error def concat_infer(node): + node_name = node.soft_get('name', node.id) if not node.has('axis'): N = node.N axis_input = node.in_node(N) @@ -20,15 +18,15 @@ def concat_infer(node): node['axis'] = axis_input.value.item() node.graph.remove_edge(axis_input.node, node.node) # TODO add skip attribute instead of deleting else: - return + raise Error('Input with value is not specified for node "{}"'.format(node_name)) else: N = len(node.in_nodes()) shapes = [node.in_node(i).shape for i in range(N)] if any(s is None for s in shapes): - return + raise Error('One of the input shapes is not defined for node "{}"'.format(node_name)) - shape = np.array(shapes[0]) + shape = shape_array(shapes[0]) axis = get_canonical_axis_index(shape, node.axis) node.axis = axis @@ -37,33 +35,34 @@ def concat_infer(node): mask[axis] = True # pylint: disable=unsupported-assignment-operation not_mask = np.logical_not(mask) # pylint: disable=assignment-from-no-return for s in shapes[1:]: - s = int64_array(s) - if np.all(shape[not_mask] == s[not_mask]): # TODO handle -1 in a special way + s = shape_array(s) + if np.ma.allequal(shape[not_mask], s[not_mask]): shape[mask] += s[mask] else: - log.error('Concat input shapes do not match') - return + raise Error('Concat input shapes do not match for node "{}" with axis {}'.format(node_name, axis)) - node.out_node(0).shape = shape - if len(shape) != 4: - # exclude it from NHWC to NCHW conversion - if 'axis' in node.dim_attrs: - node.dim_attrs.remove('axis') + # dynamic dimensions in the output (except the concat axis) can be deduced from input shape + for pos in range(len(shape)): + if shape[pos] is dynamic_dimension and pos != axis: + for in_shape in shapes: + if in_shape[pos] is not dynamic_dimension: + shape[pos] = in_shape[pos] + node.out_port(0).data.set_shape(shape) PermuteAttrs.create_permute_attrs(node, attrs=[('axis', 'input:0')]) values = [node.in_node(i).value for i in range(N)] - if any(v is None for v in values): + if any([v is None for v in values]): return - node.out_node(0).value = np.concatenate(values, axis=node.axis).astype(values[0].dtype, copy=False) - node.out_node(0).shape = np.array(node.out_node(0).value.shape, dtype=np.int64) + # if one of the input values are dynamic, the output tensor type is inferred from one of the fully defined inputs + output_dtype = np.int64 + for input in values: + if is_fully_defined(input): + output_dtype = input.dtype - -def tf_pack_infer(node): - # Constant path is supported only - values = [node.in_node(i).value for i in range(node.N)] - if any(v is None for v in values): - return - node.out_node().value = np.stack(values, node.axis) - node.out_node().shape = np.array(node.out_node().value.shape, dtype=np.int64) + if any(not is_fully_defined(v) for v in values): + node.out_port(0).data.set_value(np.ma.concatenate(values, axis=node.axis).astype(output_dtype)) + else: # there is a serious performance benefit to use concatenation as it is implemented below + node.out_node(0).value = np.concatenate(values, axis=node.axis).astype(values[0].dtype, copy=False) + node.out_node(0).shape = shape_array(node.out_node(0).value.shape) diff --git a/model-optimizer/mo/front/common/partial_infer/eltwise.py b/model-optimizer/mo/front/common/partial_infer/eltwise.py index 47b40eb857e..491da7f2c94 100644 --- a/model-optimizer/mo/front/common/partial_infer/eltwise.py +++ b/model-optimizer/mo/front/common/partial_infer/eltwise.py @@ -3,21 +3,38 @@ import numpy as np -from mo.front.common.partial_infer.utils import int64_array +from mo.front.common.partial_infer.utils import dynamic_dimension, dynamic_dimension_value +from mo.utils.error import Error def eltwise_infer(node, op=None, **kwargs): + def broadcast_dims(dim1, dim2): + if dim1 is not dynamic_dimension and dim2 is not dynamic_dimension: + mind = min(dim1, dim2) + maxd = max(dim1, dim2) + if mind == 1: + return maxd + elif mind != maxd: + raise Error('Input shapes mismatch for node {}: {}'.format(node_name, shapes)) + return mind + elif dim1 is dynamic_dimension and dim2 is dynamic_dimension: + return dynamic_dimension_value + elif dim1 is dynamic_dimension and dim2 is not dynamic_dimension: + return broadcast_dims(dim2, dim1) + else: # dim1 is static, dim2 is dynamic + if dim1 != 1: + return dim1 + else: + return dim2 + raw_inputs = [(inp, attr) for inp, attr in node.get_sorted_inputs() if 'control_flow_edge' not in attr or not attr['control_flow_edge']] shapes = [node.graph.node[inp]['shape'] for inp, attr in raw_inputs] values = [node.graph.node[inp]['value'] for inp, attr in raw_inputs] - - # infer output shape based on input shapes without op involvement - # based on repeated application of rules https://docs.scipy.org/doc/numpy/user/basics.broadcasting.html + node_name = node.soft_get('name', node.id) if any([s is None for s in shapes]): - # nothing is known - return + raise Error('One of the input shapes for node "{}" is None'.format(node_name)) max_dims = None for id, s in enumerate(shapes): @@ -33,28 +50,21 @@ def eltwise_infer(node, op=None, **kwargs): # Extend shape with 1's for cnt in range(axis + len(shape), max_dims): - new_shape = np.append(new_shape, 1) + new_shape = np.ma.append(new_shape, 1) shapes[id] = new_shape # Reshape value to correctly calculate output shape if values[id] is not None: - values[id] = np.reshape(values[id], new_shape) + values[id] = np.ma.reshape(values[id], new_shape) - extended_shapes = int64_array([np.concatenate((np.ones(max_dims - len(s), dtype=np.int64), s)) for s in shapes]) - # ugly but clear solution + extended_shapes = [np.ma.concatenate((np.ma.ones(max_dims - len(s), dtype=np.int64), s)) for s in shapes] output_shape = extended_shapes[0] for si in range(1, len(extended_shapes)): for ei in range(max_dims): - mind = min(output_shape[ei], extended_shapes[si][ei]) - maxd = max(output_shape[ei], extended_shapes[si][ei]) - if mind == -1: - output_shape[ei] = -1 - elif mind == 1: - output_shape[ei] = maxd - elif mind != maxd: - output_shape[ei] = -1 - node.out_node().shape = output_shape + output_shape[ei] = broadcast_dims(output_shape[ei], extended_shapes[si][ei]) + + node.out_port(0).data.set_shape(output_shape) if node.has_and_set('stop_value_propagation'): return @@ -63,11 +73,11 @@ def eltwise_infer(node, op=None, **kwargs): return if len(values) <= 2: - node.out_node().value = op(*values, **kwargs) + node.out_port(0).data.set_value(op(*values, **kwargs)) else: - node.out_node().value = values[0] + node.out_port(0).data.set_value(values[0]) for i in range(len(values) - 1): - node.out_node().value = op(node.out_node().value, values[i + 1]) + node.out_port(0).data.set_value(op(node.out_node().value, values[i + 1])) def bias_add_infer(node, op): diff --git a/model-optimizer/mo/front/common/partial_infer/multi_box_detection.py b/model-optimizer/mo/front/common/partial_infer/multi_box_detection.py index a02dc637fd0..67b6f5fdb09 100644 --- a/model-optimizer/mo/front/common/partial_infer/multi_box_detection.py +++ b/model-optimizer/mo/front/common/partial_infer/multi_box_detection.py @@ -3,51 +3,54 @@ import logging as log -import numpy as np - +from mo.front.common.partial_infer.utils import is_fully_defined, compatible_dims from mo.graph.graph import Node +from mo.utils.error import Error def multi_box_detection_infer(node: Node): loc_shape = node.in_node(0).shape conf_shape = node.in_node(1).shape prior_boxes_shape = node.in_node(2).shape + node_name = node.soft_get('name', node.id) if loc_shape is None or conf_shape is None or prior_boxes_shape is None: - log.warning('Shapes for the Detection Output are not defined') - return + raise Error('Shapes for the Detection Output node "{}" are not defined'.format(node_name)) prior_size = 4 if node.has('normalized') and not node.normalized: prior_size = 5 - if prior_boxes_shape[-1] % prior_size != 0: - log.warning('Amount of confidences "{}" is not divisible by {}'.format(conf_shape[-1], prior_size)) - return + if is_fully_defined(prior_boxes_shape[-1]) and prior_boxes_shape[-1] % prior_size != 0: + raise Error('Amount of confidences "{}" is not divisible by {} for node "{}"' + ''.format(prior_boxes_shape[-1], prior_size, node_name)) num_priors = prior_boxes_shape[-1] // prior_size if not node.has_valid('keep_top_k') or node.keep_top_k == -1: node['keep_top_k'] = num_priors - node.graph.node[node.id]['num_classes'] = conf_shape[-1] // num_priors + + # do not try to infer number of classes because it is not possible in case when input shapes are partially defined + if not node.has_valid('num_classes'): + node['num_classes'] = conf_shape[-1] // num_priors + log.debug('Inferred amount of classes "{}"'.format(node.num_classes)) + num_loc_classes = node.num_classes if node.has_and_set('share_location') and node.share_location: num_loc_classes = 1 - if num_priors * num_loc_classes * 4 != loc_shape[-1]: - log.warning('Locations and prior boxes shapes mismatch: "{}" vs "{}"'.format(loc_shape, prior_boxes_shape)) - return + if not compatible_dims(num_priors * num_loc_classes * 4, loc_shape[-1]): + raise Error('Locations and prior boxes shapes mismatch: "{}" vs "{}" for node "{}"' + ''.format(loc_shape, prior_boxes_shape, node_name)) - if not node.variance_encoded_in_target and prior_boxes_shape[-2] != 2: - log.warning('The "-2" dimension of the prior boxes must be 2 but it is "{}".'.format(prior_boxes_shape[-2])) - return + if not node.variance_encoded_in_target and not compatible_dims(prior_boxes_shape[-2], 2): + raise Error('The "-2" dimension of the prior boxes must be 2 but it is "{}" for node "{}".' + ''.format(prior_boxes_shape[-2], node_name)) - if conf_shape[-1] % num_priors != 0: - log.warning('Amount of confidences "{}" is not divisible by amount of priors "{}".'.format( - conf_shape[-1], num_priors)) - return + if is_fully_defined(conf_shape[-1]) and is_fully_defined(num_priors) and conf_shape[-1] % num_priors != 0: + raise Error('Amount of confidences "{}" is not divisible by amount of priors "{}" for node "{}".' + ''.format(conf_shape[-1], num_priors, node_name)) - log.debug('Inferred amount of classes "{}"'.format(node.num_classes)) - node.out_node(0).shape = np.array([1, 1, conf_shape[0] * node.keep_top_k, 7], dtype=np.int64) + node.out_port(0).data.set_shape([1, 1, conf_shape[0] * node.keep_top_k, 7]) # the line below is needed for the TF framework so the MO will not change the layout node.graph.node[node.out_node(0).id]['nchw_layout'] = True diff --git a/model-optimizer/mo/front/common/partial_infer/random_uniform.py b/model-optimizer/mo/front/common/partial_infer/random_uniform.py index b31d71ed328..542432fc5f8 100644 --- a/model-optimizer/mo/front/common/partial_infer/random_uniform.py +++ b/model-optimizer/mo/front/common/partial_infer/random_uniform.py @@ -1,12 +1,6 @@ # Copyright (C) 2018-2021 Intel Corporation # SPDX-License-Identifier: Apache-2.0 -import numpy as np - def tf_random_uniform_infer(node): - if node.in_node(0).value is None: - return - - output_shape = node.in_node(0).value - node.out_node().shape = np.array(output_shape) + node.out_port(0).data.set_shape(node.in_port(0).data.get_value()) diff --git a/model-optimizer/mo/front/common/partial_infer/reshape.py b/model-optimizer/mo/front/common/partial_infer/reshape.py deleted file mode 100644 index f93f160b88b..00000000000 --- a/model-optimizer/mo/front/common/partial_infer/reshape.py +++ /dev/null @@ -1,58 +0,0 @@ -# Copyright (C) 2018-2021 Intel Corporation -# SPDX-License-Identifier: Apache-2.0 - -from mo.front.common.partial_infer.utils import int64_array -from mo.graph.perm_inputs import PermuteInputs -from mo.utils.error import Error - - -def tf_reshape_shape_infer(node): - # TODO Make sure that all -1 are handled correctly - # We cannot simply copy shape argument to the output, - # because if -1 appears, it should be substituted by a real - # value from input shape if input shape is completely defined. - if node.in_node(0).shape is None: - return None - - assert len(node.in_nodes()) == 2, 'The Reshape operation {} must have 2 inputs'.format(node.name) - - input_shape = node.in_port(0).data.get_shape() - reshape_output = node.in_port(1).data.get_value() - - if node.in_node(0).shape is None: - return None - - total = 1 - for index, i in enumerate(input_shape): - total *= i - - res = 1 - for index, x in enumerate(reshape_output): - if x == 0: - res *= input_shape[index] - elif x != -1: - res *= x - - new_dim = total // res - output_shape = [] - for index, x in enumerate(reshape_output): - if x == 0 and node.has_and_set('special_zero'): - output_shape.append(input_shape[index]) - elif x == -1: - output_shape.append(new_dim) - else: - output_shape.append(x) - - out_shape_total = 1 - for index, i in enumerate(output_shape): - assert i != -1 - out_shape_total *= i - - if total != out_shape_total: - raise Error("Number of elements in input {} and output {} of reshape node {} mismatch" - "".format(input_shape, output_shape, node.name)) - - PermuteInputs().set_input_permutation(node.in_node(1), node, 'output:0', 'shape') - - output_shape = int64_array(output_shape) - return output_shape diff --git a/model-optimizer/mo/front/common/partial_infer/roipooling.py b/model-optimizer/mo/front/common/partial_infer/roipooling.py index 2b5f35e9485..300a19bdefe 100644 --- a/model-optimizer/mo/front/common/partial_infer/roipooling.py +++ b/model-optimizer/mo/front/common/partial_infer/roipooling.py @@ -35,8 +35,8 @@ def roipooling_infer(node: Node): layout = node.graph.graph['layout'] assert len(layout) == 4 - node.out_node().shape = shape_for_layout(layout, - batch=shapes[1][get_batch_dim(layout, 4)], - features=shapes[0][get_features_dim(layout, 4)], - height=node.pooled_h, - width=node.pooled_w) + node.out_port(0).data.set_shape(shape_for_layout(layout, + batch=shapes[1][get_batch_dim(layout, 4)], + features=shapes[0][get_features_dim(layout, 4)], + height=node.pooled_h, + width=node.pooled_w)) diff --git a/model-optimizer/mo/front/common/partial_infer/utils.py b/model-optimizer/mo/front/common/partial_infer/utils.py index cb3c96652ac..ce0a35553a8 100644 --- a/model-optimizer/mo/front/common/partial_infer/utils.py +++ b/model-optimizer/mo/front/common/partial_infer/utils.py @@ -6,6 +6,159 @@ from typing import Iterable, List, Union import numpy as np +from mo.utils.error import Error + +dynamic_dimension = np.ma.masked +# numpy masked array for integer values forces us to select one integer number to be considered as a missing/invalid +# value. Since the primary purpose of usage of masked arrays in the MO is to specify dynamic dimension, the big prime +# (by modulo) negative number is selected as such a value +dynamic_dimension_value = -1000000007 + + +def shape_array(value, dtype=np.int64): + # if the input tensor has masked values then they should be explicitly converted to dynamic_dimension_value and + # a masked array should be created from scratch, otherwise, method "masked_equal" will convert masked elements to + # "nan" values + if isinstance(value, Iterable) and (not isinstance(value, np.ndarray) or value.ndim != 0): + value = [item if item is not dynamic_dimension else dynamic_dimension_value for item in value] + return np.ma.masked_equal(value, dynamic_dimension_value).astype(dtype=dtype) + + +def compatible_dims(dim1, dim2): + """ + Compare if dim1 is equal to dim2 or any of them is dynamic + + :param dim1: dimension to compare + :param dim2: dimension to compare + :return: boolean result of the comparison + """ + return dim1 is dynamic_dimension or dim2 is dynamic_dimension or dim1 == dim2 + + +def compatible_shapes(shape1, shape2): + """ + Compares two shape tensors. The shapes are considered equal if they have the same rank and the corresponding + dimensions are either equal or at least one of them is dynamic. + + :param shape1: the first shape to compare + :param shape2: the second shape to compare + :return: boolean result of the comparison + """ + if shape1.ndim != shape2.ndim: + return False + if shape1.size != shape2.size: + return False + for d1, d2 in zip(shape1, shape2): + if not compatible_dims(d1, d2): + return False + return True + + +def strict_compare_tensors(tensor1, tensor2): + """ + Strict comparison of two tensors. The tensors are equal iff their corresponding elements are equal or both are + dynamic. + + :param tensor1: the first tensor to compare + :param tensor2: the second tensor to compare + :return: boolean result of the comparison + """ + if not isinstance(tensor1, np.ma.masked_array): + tensor1 = shape_array(tensor1) + if not isinstance(tensor2, np.ma.masked_array): + tensor2 = shape_array(tensor2) + + if tensor1.ndim != tensor2.ndim: + return False + if tensor1.size != tensor2.size: + return False + if tensor1.ndim == 0: + return tensor1.item() == tensor2.item() + if not np.array_equal(tensor1.shape, tensor2.shape): + return False + for d1, d2 in zip(tensor1.flatten(), tensor2.flatten()): + if (d1 is not dynamic_dimension) ^ (d2 is not dynamic_dimension): + return False + elif d1 is not dynamic_dimension and d1 != d2: + return False + return True + + +def shape_delete(shape: np.ma.masked_array, obj: [int, list]): + """ + Removes element in the input tensor shape (presumably the numpy masked array) specified by index/indices obj. + The function is implemented to avoid usage of np.delete which corrupts information about the masked elements. + + :param shape: the shape object to remove elements from + :param obj: the list or a single integer defining index(es) of elements to remove + :return: shape with removed selected elements + """ + if isinstance(obj, (int, np.int64, np.int32)): + return shape_delete(shape, [obj]) + elif isinstance(obj, np.ndarray): + return shape_delete(shape, obj.tolist()) + elif isinstance(obj, list): + result = shape.copy() + obj = [item if item >= 0 else len(shape) + item for item in obj] + for index in sorted(obj, reverse=True): + assert 0 <= index < len(result), 'Incorrect element index {} to remove from {}'.format(index, result) + result = np.ma.concatenate((result[:index], result[index + 1:])) + return result + else: + raise Error('Incorrect parameter type of "obj": {}'.format(type(obj))) + + +def shape_insert(shape: [np.ndarray, list], pos: int, obj: [int, list, np.ndarray, dynamic_dimension]): + """ + Insert element(s) in the input tensor shape (presumably the numpy masked array) specified by position pos. + The function is implemented to avoid usage of np.insert which corrupts information about the masked elements. + + :param shape: the shape object to insert element(s) to + :param pos: the position to insert the elements into + :param obj: the list or a single integer or the dynamic_dimension_value or numpy array to insert + :return: shape with inserted elements + """ + if isinstance(obj, (int, np.int64, np.int32)) or obj is dynamic_dimension_value: + return shape_insert(shape, pos, [obj]) + elif isinstance(obj, (np.ndarray, list)): + return np.ma.concatenate((shape_array(shape[:pos]), shape_array(obj), shape_array(shape[pos:]))) + else: + raise Error('Incorrect parameter type of "obj": {}'.format(type(obj))) + + +def unmask_shape(value: [np.ma.masked_array, np.array]): + """ + Converts all dynamic_dimension values from the input tensor to -1. Used to generate shapes for the IR. + + :param value: the value to be unmasked. + :return: the value where dynamic_dimension elements are converted to -1. + """ + if not isinstance(value, np.ma.masked_array): + return value + else: + return value.tolist(-1) + + +def is_fully_defined(value): + """ + Checks that provided input tensor is fully defined. The input value can be of different types: scalar, list, array, + masked array. + + :param value: the value to check + :return: the result of the check + """ + if value is None: + return False + elif isinstance(value, np.ma.masked_array): + return not np.ma.is_masked(value) + elif isinstance(value, np.ndarray): # numpy array cannot contain dynamic values + return True + elif isinstance(value, list) or isinstance(value, tuple): + return dynamic_dimension not in value + elif value is dynamic_dimension: + return False + return True + def int64_array(value: Union[Iterable[Union[float, int]], float, int]) -> np.ndarray: return np.array(value, dtype=np.int64) @@ -60,24 +213,24 @@ def convert_deconv_tf_padding_to_str(padding): # TODO eliminate this dependency and pass necessary function as an argument def tf_window_op_pad_infer(input, window, stride, auto_pad, is_deconv=False): if input is None or window is None or stride is None or auto_pad is None: - return (None, None) + return None, None normalized_stride = stride if is_deconv: normalized_stride = 1 / stride if auto_pad in ['same_lower', 'same_upper']: - output = np.int64(np.ceil(input / normalized_stride)) + output = np.ma.ceil(input / normalized_stride) residual = input % stride mask = residual == 0 full_pad = window.copy() full_pad[mask] -= stride[mask] mask = np.logical_not(mask) # pylint: disable=assignment-from-no-return full_pad[mask] -= input[mask] % stride[mask] - full_pad = np.maximum(full_pad, 0) # pylint: disable=assignment-from-no-return + full_pad = np.ma.maximum(full_pad, 0) # pylint: disable=assignment-from-no-return low_pad = np.int64(full_pad / 2) high_pad = full_pad - low_pad - pad = np.array([low_pad, high_pad]).transpose() + pad = shape_array([low_pad, high_pad]).transpose() elif auto_pad == 'valid': output = np.int64(np.ceil((input - window + 1) / normalized_stride)) pad = np.zeros((len(output), 2), dtype=np.int64) @@ -85,22 +238,7 @@ def tf_window_op_pad_infer(input, window, stride, auto_pad, is_deconv=False): log.error("Unsupported padding scheme: {}".format(auto_pad)) pad = None output = None - return (pad, output) - - -def broadcast_shape(first_shape, second_shape): - """ - Perform broadcasting of one shape to another for different shapes - """ - shape = first_shape if len(first_shape) > len(second_shape) else second_shape - new_shape = int64_array(shape) - for i in range(len(shape)): - a_val = first_shape[-i - 1] if i < len(first_shape) else 1 - b_val = second_shape[-i - 1] if i < len(second_shape) else 1 - assert a_val == 1 or b_val == 1 or a_val == b_val, "Input shape do not broadcast" - new_val = b_val if a_val == 1 else a_val - new_shape[-i - 1] = new_val - return int64_array(new_shape) + return pad, output def get_shape_from_slice(input_shape: np.ndarray, slices: List) -> np.ndarray: @@ -114,8 +252,14 @@ def get_shape_from_slice(input_shape: np.ndarray, slices: List) -> np.ndarray: in_idx = 0 for i, s in enumerate(slices): - if isinstance(s, slice): - output_shape.append(len(range(*s.indices(input_shape[in_idx])))) + if s is dynamic_dimension or s == dynamic_dimension_value: + output_shape.append(dynamic_dimension_value) + in_idx += 1 + elif isinstance(s, slice): + if input_shape[in_idx] is not dynamic_dimension and not is_dynamic_slice(s): + output_shape.append(len(range(*s.indices(input_shape[in_idx])))) + else: + output_shape.append(dynamic_dimension_value) in_idx += 1 elif s is np.newaxis: output_shape.append(1) @@ -126,8 +270,18 @@ def get_shape_from_slice(input_shape: np.ndarray, slices: List) -> np.ndarray: output_shape.append(input_shape[in_idx]) in_idx += 1 else: - raise Exception('Element type of a slice List is unacceptable. ' - 'Allowed types are: Ellipsis, slice, int, and None. Instead got: '. format(type(s))) + raise Exception('Element type of a slice list is unacceptable: "{}"'.format(type(s))) for i in range(in_idx, len(input_shape)): output_shape.append(input_shape[i]) - return int64_array(output_shape) + return shape_array(output_shape) + + +def is_dynamic_slice(s: [slice, int, None]): + """ + The function checks that the specified slice produces dynamic value. + :param s: slice object + :return: the result of the check + """ + return isinstance(s, slice) and (s.start is dynamic_dimension or + s.stop is dynamic_dimension or + s.step is dynamic_dimension) diff --git a/model-optimizer/mo/front/extractor.py b/model-optimizer/mo/front/extractor.py index 139dc6503eb..f3110480597 100644 --- a/model-optimizer/mo/front/extractor.py +++ b/model-optimizer/mo/front/extractor.py @@ -9,6 +9,7 @@ from copy import copy import numpy as np +from mo.front.common.partial_infer.utils import dynamic_dimension_value, shape_array from mo.front.onnx.extractors.utils import get_backend_pad from mo.graph.graph import Node, Graph, add_opoutput from mo.middle.passes.eliminate import reverse_dfs @@ -579,7 +580,8 @@ def input_user_data_repack(graph: Graph, input_user_shapes: [None, list, dict, n is_out_port = (direction == 'out') new_placeholder_id = get_new_placeholder_name(placeholder_id, is_out_port, port) _freeze_new_placeholder[placeholder_id].append( - {'direction' : direction, 'port' : port, 'name' : placeholder_name, 'id' : new_placeholder_id, 'value' : value}) + {'direction': direction, 'port': port, 'name': placeholder_name, 'id': new_placeholder_id, + 'value': value}) # input user shapes restructure if input_user_shapes is None: @@ -598,7 +600,8 @@ def input_user_data_repack(graph: Graph, input_user_shapes: [None, list, dict, n _input_shapes[node_id].append({'shape': shape, direction: port}) if _freeze_placeholder is not None: # here we give user an opportunity not to provide node names from --freeze_placeholder_with_value in --input - [_input_shapes[ph_id].append({'shape': None, 'port': None}) for ph_id in _freeze_placeholder if ph_id not in _input_shapes] + [_input_shapes[ph_id].append({'shape': None, 'port': None}) for ph_id in _freeze_placeholder + if ph_id not in _input_shapes] else: # np.ndarray is a shape. User provided only --input_shape key assert isinstance(input_user_shapes, np.ndarray) @@ -626,8 +629,8 @@ def input_user_data_repack(graph: Graph, input_user_shapes: [None, list, dict, n for node_id in _freeze_new_placeholder: new_phs = _freeze_new_placeholder[node_id] if node_id not in _input_shapes: - raise Error( - 'Shape is not specified for the placeholder with name {} through --input_shape option.'.format(new_phs[0]['name'])) + raise Error('Shape is not specified for the placeholder with name {} through --input_shape option.' + ''.format(new_phs[0]['name'])) _ins = _input_shapes[node_id] # list for new_ph in new_phs: name = new_ph['name'] @@ -638,8 +641,8 @@ def input_user_data_repack(graph: Graph, input_user_shapes: [None, list, dict, n if any([_in['shape'] is not None and direction in _in and _in[direction] == port for _in in _ins]): _freeze_placeholder[placeholder_id] = value else: - raise Error( - 'Shape is not specified for the placeholder with name {} through --input_shape option.'.format(name)) + raise Error('Shape is not specified for the placeholder with name {} through --input_shape option.' + ''.format(name)) return _input_shapes, _freeze_placeholder @@ -772,8 +775,8 @@ def set_is_input(graph: Graph, placeholders: list, is_input: bool): def check_input(graph: Graph, node_name: str): node = Node(graph, node_name) - if node['kind'] == 'op' and node['op'] == 'Parameter' and not len(graph.in_edges(node_name)) and not node[ - 'is_input']: + if node['kind'] == 'op' and node['op'] == 'Parameter' and not len(graph.in_edges(node_name)) and \ + not node['is_input']: raise Error("--input parameter was provided. Other inputs are needed for output computation. " "Provide more inputs or choose another place to cut the net. " + refer_to_faq_msg(27)) @@ -873,7 +876,7 @@ def add_input_op(graph: Graph, node_id: str, port: int = 0, data: bool = False, if data_type is None: data_type = np.float32 input_op = Parameter(graph, dict(shape=shape, data_type=data_type, initial_node_name=node_id, - name=get_new_placeholder_name(node_id, is_out_port, port))) + name=get_new_placeholder_name(node_id, is_out_port, port))) fw_name = Node(graph, node_id).soft_get('name') edge_attrs = {'in': port, 'out': 0, 'in_attrs': ['in'], 'out_attrs': ['out'], @@ -938,6 +941,7 @@ def add_input_ops_helper_before_infer_output_port(graph: Graph, port:int, node_i inputs.append(add_input_op(graph=graph, node_id=node_id, port=port, data=False, shape=shape, data_type=data_type, is_out_port=True)) + def add_input_ops_helper_after_infer_output_port(graph: Graph, smart_node: Node, port:int, node_id: str, inputs: list, edges_to_remove: list): out_node = smart_node.out_node(port) @@ -946,7 +950,7 @@ def add_input_ops_helper_after_infer_output_port(graph: Graph, smart_node: Node, raise Error('Shape for tensor "{}" is not defined. Can not proceed.' + refer_to_faq_msg(41), out_node.soft_get('name')) inputs.append(add_input_op(graph=graph, node_id=node_id, port=port, data=True, - shape=shape.copy(), data_type=out_node.soft_get('data_type', None), is_out_port=True)) + shape=shape.copy(), data_type=out_node.soft_get('data_type', None), is_out_port=True)) edges_to_remove.append((node_id, out_node.id)) @@ -982,6 +986,8 @@ def add_input_ops(graph: Graph, user_defined_inputs: dict, before_infer: bool): is_out_port = 'out' in port_and_shape_info # by default we assume input port or input node without port shape = port_and_shape_info['shape'] if 'shape' in port_and_shape_info else None + if shape is not None: + shape = shape_array([dim if dim >= 0 else dynamic_dimension_value for dim in shape]) data_type = port_and_shape_info['data_type'] if 'data_type' in port_and_shape_info else None smart_node = Node(graph, node_id) @@ -1137,7 +1143,8 @@ class CaffePythonFrontExtractorOp: def check_param(op_cls, attrs): for a in attrs: if a not in op_cls.supported_attrs(op_cls): - log.error('Parameter {} is not recognised, please check correctness.\n List of supported parameters is: {}'.format(a, op_cls.supported_attrs(op_cls)), extra={'is_warning':True}) + log.error('Parameter {} is not recognised, please check correctness.\n List of supported parameters ' + 'is: {}'.format(a, op_cls.supported_attrs(op_cls)), extra={'is_warning': True}) @classmethod def class_type(cls): diff --git a/model-optimizer/mo/front/mxnet/extractors/slice_axis.py b/model-optimizer/mo/front/mxnet/extractors/slice_axis.py index 5c79861c02b..7b0867b78ef 100644 --- a/model-optimizer/mo/front/mxnet/extractors/slice_axis.py +++ b/model-optimizer/mo/front/mxnet/extractors/slice_axis.py @@ -12,7 +12,7 @@ def slice_axis_ext(attrs): end = attrs.int("end", None) node_attrs = { - 'type': 'Crop', + 'op': 'Crop', 'axis': axis, 'offset': begin, 'dim': end, diff --git a/model-optimizer/mo/front/tf/extractors/fused_bn.py b/model-optimizer/mo/front/tf/extractors/fused_bn.py index 0d290ba2873..bedde50a4b2 100644 --- a/model-optimizer/mo/front/tf/extractors/fused_bn.py +++ b/model-optimizer/mo/front/tf/extractors/fused_bn.py @@ -5,13 +5,14 @@ import logging as log import numpy as np +from mo.front.common.partial_infer.utils import shape_array from mo.front.tf.extractors.utils import tf_dtype_extractor def tf_fused_bn_infer(node): output_shape = np.array(node.in_node(0).shape) for port, out_node in node.out_nodes().items(): - out_node.shape = output_shape + out_node.shape = shape_array(output_shape) def tf_fused_bn_extractor(pb): diff --git a/model-optimizer/mo/front/tf/extractors/pack.py b/model-optimizer/mo/front/tf/extractors/pack.py index 6b7fed47bb9..228338b07d4 100644 --- a/model-optimizer/mo/front/tf/extractors/pack.py +++ b/model-optimizer/mo/front/tf/extractors/pack.py @@ -1,13 +1,11 @@ # Copyright (C) 2018-2021 Intel Corporation # SPDX-License-Identifier: Apache-2.0 -from mo.front.common.partial_infer.concat import tf_pack_infer - def tf_pack_ext(pb): assert (pb.attr["N"].i == len(pb.input)) return { 'axis': pb.attr["axis"].i, 'N': pb.attr["N"].i, - 'infer': tf_pack_infer + 'infer': None } diff --git a/model-optimizer/mo/front/tf/extractors/utils.py b/model-optimizer/mo/front/tf/extractors/utils.py index c9d07083b38..7ec2ba89a85 100644 --- a/model-optimizer/mo/front/tf/extractors/utils.py +++ b/model-optimizer/mo/front/tf/extractors/utils.py @@ -5,13 +5,14 @@ import logging as log import numpy as np +from mo.front.common.partial_infer.utils import shape_array, dynamic_dimension_value from mo.front.tf.common import tf_data_type_decode from mo.utils.error import Error from mo.utils.utils import refer_to_faq_msg def tf_tensor_shape(pb): - return np.array([dim.size for dim in pb.dim], dtype=np.int64) + return shape_array([dim.size if dim.size >= 0 else dynamic_dimension_value for dim in pb.dim]) def tf_int_list(pb): diff --git a/model-optimizer/mo/graph/graph.py b/model-optimizer/mo/graph/graph.py index aa1bef5e3e9..c23e313f6c1 100644 --- a/model-optimizer/mo/graph/graph.py +++ b/model-optimizer/mo/graph/graph.py @@ -198,8 +198,6 @@ class Node: self.get_inputs(control_flow=control_flow)}) def in_nodes(self, control_flow: bool = False): - assert self.has('kind') # TODO: remove as it always exists - assert self.kind in ['op', 'data'] # TODO: remove as it always exists if self.kind == 'op': return dict_to_ordered_dict({x[1]['in']: Node(self.graph, x[0]) for x in self.get_inputs(control_flow=control_flow)}) diff --git a/model-optimizer/mo/graph/port.py b/model-optimizer/mo/graph/port.py index 80abb66684a..d59516b2170 100644 --- a/model-optimizer/mo/graph/port.py +++ b/model-optimizer/mo/graph/port.py @@ -4,9 +4,7 @@ import logging as log from copy import deepcopy -import numpy as np - -from mo.front.common.partial_infer.utils import int64_array +from mo.front.common.partial_infer.utils import int64_array, shape_array, strict_compare_tensors from mo.graph.connection import Connection from mo.utils.error import Error @@ -97,12 +95,12 @@ class Port: else: if self.type == 'in': assert self.node.in_node(self.idx, control_flow=self.control_flow).value is None - self.node.in_node(self.idx, control_flow=self.control_flow).shape = int64_array(shape) + self.node.in_node(self.idx, control_flow=self.control_flow).shape = shape_array(shape) else: data_node = self.node.out_node(self.idx, control_flow=self.control_flow) - assert data_node.value is None or \ - np.array_equal(data_node.soft_get('force_shape', data_node.shape), int64_array(shape)) - self.node.out_node(self.idx, control_flow=self.control_flow).shape = int64_array(shape) + assert data_node.value is None or self.node.has_and_set('override_output_shape') or \ + strict_compare_tensors(data_node.soft_get('force_shape', data_node.shape), shape_array(shape)) + self.node.out_node(self.idx, control_flow=self.control_flow).shape = shape_array(shape) def _get_value(self): if self.node.graph.stage == 'front': diff --git a/model-optimizer/mo/middle/passes/eliminate.py b/model-optimizer/mo/middle/passes/eliminate.py index e24fc4b444b..ba5e1b53daa 100644 --- a/model-optimizer/mo/middle/passes/eliminate.py +++ b/model-optimizer/mo/middle/passes/eliminate.py @@ -8,6 +8,7 @@ from collections import deque import networkx as nx import numpy as np +from mo.front.common.partial_infer.utils import is_fully_defined, compatible_shapes from mo.utils.error import Error from mo.utils.utils import deprecated_api @@ -107,7 +108,7 @@ def mark_const_producer_nodes(graph): graph.node[input]['is_const_producer'] = False graph.node[output]['is_const_producer'] = False - if not node.has('value') or node.value is None: + if not node.has('value') or node.value is None or not is_fully_defined(node.value): for input, _ in graph.in_edges(node.id): graph.node[input]['is_const_producer'] = False @@ -162,7 +163,9 @@ def shape_inference(graph): new_out_shapes = [port.data.get_shape() for port in node.out_ports().values() if not port.disconnected()] if not node.has_and_set('override_output_shape'): for shape1, shape2 in zip(old_out_shapes, new_out_shapes): - if shape1 is not None and not np.array_equal(shape1, shape2): + # do not use strict shapes comparison because after applying transformation the output shape may be + # specialized and some dynamic dimension become static + if shape1 is not None and not compatible_shapes(shape1, shape2): raise Error("After partial shape inference were found shape collision for node {} (old shape: " "{}, new shape: {})".format(node.name, shape1, shape2)) else: diff --git a/model-optimizer/mo/middle/passes/fusing/fuse_linear_seq.py b/model-optimizer/mo/middle/passes/fusing/fuse_linear_seq.py index 0522729705e..5e1ea374799 100644 --- a/model-optimizer/mo/middle/passes/fusing/fuse_linear_seq.py +++ b/model-optimizer/mo/middle/passes/fusing/fuse_linear_seq.py @@ -6,9 +6,9 @@ import logging as log import numpy as np from extensions.ops.elementwise import Mul, Add +from mo.front.common.partial_infer.utils import compatible_shapes from mo.graph.graph import Node, Graph -from mo.middle.passes.fusing.helpers import get_value_in_port, \ - get_tensor_in_port +from mo.middle.passes.fusing.helpers import get_value_in_port, get_tensor_in_port from mo.ops.const import Const @@ -25,7 +25,8 @@ def _fuse_linear_sequence(graph: Graph, start_node: Node): if len(destinations) != 1: break dst_node = destinations[0].node - if dst_node.soft_get('op') in ['Mul', 'Add'] and get_value_in_port(dst_node) is not None and dst_node.soft_get('can_be_fused') is True: + if dst_node.soft_get('op') in ['Mul', 'Add'] and get_value_in_port(dst_node) is not None and \ + dst_node.soft_get('can_be_fused') is True: fnodes.append(dst_node) else: break @@ -59,7 +60,7 @@ def _fuse_linear_sequence(graph: Graph, start_node: Node): if mul.shape != add.shape and len(mul.shape) == 1 and mul.shape[0] == 1: mul = np.array([mul[0] for x in range(add.shape[0])]) - assert (np.array_equal(get_tensor_in_port(fnodes[0]).data.get_shape(), fnodes[-1].out_port(0).data.get_shape())) + assert (compatible_shapes(get_tensor_in_port(fnodes[0]).data.get_shape(), fnodes[-1].out_port(0).data.get_shape())) mul_op = Mul(graph, dict(name='{}/Fused_Mul_'.format(first_mul_name or ''))) add_op = Add(graph, dict(name='{}/Fused_Add_'.format(first_add_name or ''))) @@ -128,7 +129,8 @@ def fuse_mul_add_sequence(graph: Graph): is_fused = False for node in graph.pseudo_topological_sort(): if node.id in graph: - if node.soft_get('op') in ['Mul', 'Add'] and get_value_in_port(node) is not None and node.soft_get('can_be_fused') is True: + if node.soft_get('op') in ['Mul', 'Add'] and get_value_in_port(node) is not None and \ + node.soft_get('can_be_fused') is True: is_fused |= _fuse_linear_sequence(graph, node) if not is_fused: - break \ No newline at end of file + break diff --git a/model-optimizer/mo/middle/passes/infer.py b/model-optimizer/mo/middle/passes/infer.py index bc6ff64acb4..8a411d7ce78 100644 --- a/model-optimizer/mo/middle/passes/infer.py +++ b/model-optimizer/mo/middle/passes/infer.py @@ -4,9 +4,8 @@ import logging as log import networkx as nx -import numpy as np -# TODO remove it +from mo.front.common.partial_infer.utils import dynamic_dimension from mo.graph.graph import Node, Graph from mo.graph.graph import dict_includes from mo.utils.error import Error @@ -19,12 +18,6 @@ def log_debug_dict(nodes_per_port: dict, direction_name: str): log.debug('{}[{}]: shape = {}, value = {}'.format(direction_name, port, node.soft_get('shape'), value)) -def is_fully_defined_shape(shape: np.ndarray): - if -1 in shape: - return False - return True - - def control_flow_infer(graph: Graph, node_name: str): """ Executes constant control flow. Propagates nodes executability @@ -139,16 +132,6 @@ def partial_infer(graph: Graph, start_node: str = None): if not out_node.has_valid('shape'): log.error('Shape is not defined for output {} of "{}".'.format(out_port, node_name)) not_all_output_shapes = True - elif not is_fully_defined_shape(out_node.shape): - log.error( - ('Shape {} is not fully defined for output {} of "{}". ' + - 'Use --input_shape with positive integers to override model input shapes.').format( - out_node.shape, - out_port, - node_name - ) - ) - not_all_output_shapes = True if not_all_output_shapes: raise Error('Not all output shapes were inferred or fully defined for node "{}". ' + @@ -218,7 +201,7 @@ def validate_batch_in_shape(shape, layer_name: str): shape: current shape of layer under validation layer_name: name of layer under validation """ - if len(shape) == 0 or shape[0] not in (-1, 0, 1): + if len(shape) == 0 or (shape[0] is not dynamic_dimension and shape[0] not in (-1, 0, 1)): raise Error(('The input layer {} has a shape {} defined in the model. \n\n' + 'When you use -b (--batch) option, Model Optimizer applies its value to the first ' + 'element of the shape if it is equal to -1, 0 or 1. Otherwise, this is the ambiguous ' + diff --git a/model-optimizer/mo/ops/broadcast.py b/model-optimizer/mo/ops/broadcast.py index 793d2b49102..7ef9fe004c7 100644 --- a/model-optimizer/mo/ops/broadcast.py +++ b/model-optimizer/mo/ops/broadcast.py @@ -1,6 +1,7 @@ # Copyright (C) 2018-2021 Intel Corporation # SPDX-License-Identifier: Apache-2.0 +from mo.front.common.partial_infer.utils import is_fully_defined from mo.graph.graph import Node, Graph from mo.graph.perm_inputs import PermuteInputs from mo.ops.op import Op @@ -23,8 +24,8 @@ class Broadcast(Op): def __init__(self, graph: Graph, attrs: dict): super().__init__(graph, { - 'type': __class__.op, - 'op': __class__.op, + 'type': self.op, + 'op': self.op, 'version': 'opset3', 'mode': 'numpy', 'in_ports_count': 3, @@ -33,7 +34,7 @@ class Broadcast(Op): {1: 'int64', 2: 'int64', }, - 'infer': __class__.infer, + 'infer': self.infer, }, attrs) def supported_attrs(self): @@ -51,7 +52,8 @@ class Broadcast(Op): PermuteInputs().set_input_permutation(node.in_node(1), node, 'output:0', 'shape') - if input_value is not None and not node.has_and_set('stop_value_propagation'): + if input_value is not None and not node.has_and_set('stop_value_propagation') and \ + is_fully_defined(target_shape): if node.mode == 'numpy': node.out_port(0).data.set_value(uni_directional_broadcasting(input_value, target_shape)) elif node.mode == 'bidirectional': @@ -76,7 +78,7 @@ class Broadcast(Op): 'is not supported. Node: `{}`'.format(node_name) PermuteInputs().set_input_permutation(node.in_node(2), node, 'output:0', 'axis') axes_mapping = node.in_port(2).data.get_value() - new_shape,_ = explicit_shape_broadcasting(input_shape, target_shape, axes_mapping) + new_shape, _ = explicit_shape_broadcasting(input_shape, target_shape, axes_mapping) node.out_port(0).data.set_shape(new_shape) else: raise Error('The node "{}" has unsupported mode "{}"'.format(node_name, node.mode)) diff --git a/model-optimizer/mo/ops/concat.py b/model-optimizer/mo/ops/concat.py index fe72efd6718..0e7f7f0ae57 100644 --- a/model-optimizer/mo/ops/concat.py +++ b/model-optimizer/mo/ops/concat.py @@ -11,8 +11,8 @@ class Concat(Op): def __init__(self, graph, attrs: dict): super().__init__(graph, { - 'type': __class__.op, - 'op': __class__.op, + 'type': self.op, + 'op': self.op, 'version': 'opset1', 'axis': 1, 'infer': concat_infer, diff --git a/model-optimizer/mo/ops/convolution.py b/model-optimizer/mo/ops/convolution.py index 3a7ff6cc288..b09fef7edc7 100644 --- a/model-optimizer/mo/ops/convolution.py +++ b/model-optimizer/mo/ops/convolution.py @@ -5,8 +5,8 @@ import logging as log import numpy as np -from mo.front.common.partial_infer.utils import int64_array, float_array, mark_input_bins, assign_dims_to_weights, \ - tf_window_op_pad_infer +from mo.front.common.partial_infer.utils import int64_array, mark_input_bins, assign_dims_to_weights, \ + tf_window_op_pad_infer, dynamic_dimension_value, shape_array from mo.front.onnx.extractors.utils import get_backend_pad from mo.graph.graph import Node, Graph from mo.graph.perm_inputs import PermuteInputs @@ -58,26 +58,26 @@ class Convolution(Op): @staticmethod def calc_convolution(input_spatial_shape, stride_spatial_shape, pad_spatial_shape, kernel_extent): - ''' Calculates output shape for Convolution. - Verified to be applicable for both Caffe and ONNX. - ''' + """ + Calculates output shape for Convolution. + Verified to be applicable for both Caffe and ONNX. + """ spatial_val_wo_stride = input_spatial_shape + pad_spatial_shape - kernel_extent if np.any(spatial_val_wo_stride < 0): raise Error("Data after padding has dimension less than window size. " + "Possible reason of error is incorrectly specified model input shape(s).") - float_spatial_val_wo_stride = float_array(spatial_val_wo_stride) - return float_spatial_val_wo_stride / stride_spatial_shape + 1 + return spatial_val_wo_stride / stride_spatial_shape + 1 @staticmethod def calc_deconvolution(node, input_spatial_shape, pad_spatial_shape, kernel_extent): - ''' Calculates output shape for Deconvolution. - Verified to be applicable for both Caffe and ONNX with explicitly defined pads. - If pads are not specified for ONNX operator, this function is not applicable. - ''' - shape = node.stride[node.spatial_dims] * (input_spatial_shape - 1) + kernel_extent - pad_spatial_shape - return shape + """ + Calculates output shape for Deconvolution. + Verified to be applicable for both Caffe and ONNX with explicitly defined pads. + If pads are not specified for ONNX operator, this function is not applicable. + """ + return node.stride[node.spatial_dims] * (input_spatial_shape - 1) + kernel_extent - pad_spatial_shape @staticmethod def infer(node: Node): @@ -89,9 +89,9 @@ class Convolution(Op): Args: node: graph convolution node """ - input_shape = node.in_node(0).shape + input_shape = node.in_port(0).data.get_shape() if input_shape is None: - return + raise Error('Input data shape is None for node {}'.format(node.soft_get('name', node.id))) # bias_term cannot be deduced earlier for frameworks that represent # convolution weights/biases as regular inputs; so the number of inputs @@ -116,10 +116,10 @@ class Convolution(Op): *[node.kernel_spatial[i] for i in range(len(node.kernel_spatial))]]) if node.type == 'Deconvolution': # layout for Deconvolution weights is IOHW kernel_shape[[0, 1]] = kernel_shape[[1, 0]] - #node.input_feature_channel, node.output_feature_channel = node.output_feature_channel, node.input_feature_channel if np.prod(kernel_shape) != np.prod(node.in_node(weights_index).value.shape): - log.error("Size of weights {} does not match kernel shape: {}\n".format(np.prod(node.in_node(weights_index).value.shape), kernel_shape) + + log.error("Size of weights {} does not match kernel shape: {}\n" + "".format(np.prod(node.in_node(weights_index).value.shape), kernel_shape) + " Possible reason is wrong channel number in input shape\n") raise Error("Cannot reshape weights to kernel shape") @@ -133,10 +133,12 @@ class Convolution(Op): # Calculate kernel_spatial_idx and spatial_dims if it is not specified # It is necessary for ONNX dut to convolution can be 1D/2D/3D if not node.has_valid('kernel_spatial_idx'): - node['kernel_spatial_idx'] = np.delete([x for x in range(len(kernel_shape))], (node.input_feature_channel, node.output_feature_channel)) + node['kernel_spatial_idx'] = np.delete([x for x in range(len(kernel_shape))], + (node.input_feature_channel, node.output_feature_channel)) if not node.has_valid('spatial_dims'): - node['spatial_dims'] = np.delete([x for x in range(len(input_shape))], (node.channel_dims[0], node.batch_dims[0])) + node['spatial_dims'] = np.delete([x for x in range(len(input_shape))], + (node.channel_dims[0], node.batch_dims[0])) node['kernel_spatial'] = kernel_shape[node.kernel_spatial_idx] @@ -192,7 +194,7 @@ class Convolution(Op): float_spatial = Convolution.calc_convolution(input_spatial_shape, stride_spatial_shape, pad_spatial_shape, kernel_extent) - node['output_spatial_shape'] = int64_array(float_spatial) + node['output_spatial_shape'] = shape_array(float_spatial) elif node.type == 'Deconvolution': # In case of given output_spatial_shape we calculate pads spatial if node.has_valid('output_spatial_shape'): @@ -210,19 +212,18 @@ class Convolution(Op): float_spatial = Convolution.calc_deconvolution(node, input_spatial_shape, pad_spatial_shape, kernel_extent) - node['output_spatial_shape'] = int64_array(float_spatial) + node['output_spatial_shape'] = shape_array(float_spatial) elif node.type == 'DeformableConvolution': # get the output spatial shape from the second input with offsets node['output_spatial_shape'] = int64_array([node.in_node(1).shape[2:4]]) else: assert 'Unsupported layer type "{}"'.format(node.type) - # For cases when group attribute wasn't set in extractor we should specify get_group attribute # this attribute should store lambda node: ... (check tf convolution extractor) if node.has_valid('get_group'): node['group'] = node.get_group(node) - output_shape = np.full_like(input_shape, -1, dtype=np.int64) + output_shape = shape_array([dynamic_dimension_value for _ in range(len(input_shape))]) output_shape[node.batch_dims] = input_shape[node.batch_dims] # pylint: disable=unsupported-assignment-operation output_shape[node.spatial_dims] = node.output_spatial_shape # pylint: disable=unsupported-assignment-operation @@ -233,8 +234,7 @@ class Convolution(Op): output_shape[node.channel_dims] = node.output # pylint: disable=unsupported-assignment-operation node['output_shape'] = output_shape - for n in node.out_nodes(): - node.out_node(n).shape = output_shape + node.out_port(0).data.set_shape(output_shape) # bin attribute is used for pre-processing, but it will be deleted in BlobNormalizer transformation # and the blobs (weights, biases) will be represented as inputs to the node diff --git a/model-optimizer/mo/ops/crop.py b/model-optimizer/mo/ops/crop.py index 1a9141df929..89bcca02f65 100644 --- a/model-optimizer/mo/ops/crop.py +++ b/model-optimizer/mo/ops/crop.py @@ -8,6 +8,7 @@ import numpy as np from mo.front.caffe.extractors.utils import get_canonical_axis_index from mo.graph.graph import Node, Graph from mo.ops.op import Op, PermuteAttrs +from mo.utils.error import Error class Crop(Op): @@ -15,9 +16,9 @@ class Crop(Op): def __init__(self, graph: Graph, attrs: dict): super().__init__(graph, { - 'type': __class__.op, - 'op': __class__.op, - 'infer': __class__.infer, + 'type': None, + 'op': self.op, + 'infer': self.infer, 'in_ports_count': 2, 'out_ports_count': 1, }, attrs) @@ -29,7 +30,8 @@ class Crop(Op): ('dim', lambda node: None if not node.has_valid('dim') else ','.join(map(str, node.dim))), - ('crop_begin', lambda node: None if not node.has_valid('crop_begin') else ','.join(map(str, node.crop_begin))), + ('crop_begin', lambda node: None if not node.has_valid('crop_begin') else ','.join(map(str, + node.crop_begin))), ('crop_end', lambda node: None if not node.has_valid('crop_end') else ','.join(map(str, node.crop_end))), ] @@ -56,65 +58,58 @@ class Crop(Op): @staticmethod def _one_input_infer(node: Node): - input_shape = np.array(node.in_node().shape) - + input_shape = node.in_port(0).data.get_shape() + node_name = node.soft_get('name', node.id) if input_shape is None: - log.error('input_shape is none for {} node'.format(node.name)) - return + raise Error('input_shape is none for {} node'.format(node_name)) if not node.has_valid('axis'): - log.error('axis attribute is missing for {} node. should be set in crop extractor'.format(node.name)) - return + raise Error('axis attribute is missing for {} node. should be set in crop extractor'.format(node_name)) - output_shape = input_shape + output_shape = input_shape.copy() if node.has_valid('dim'): if len(node.dim) != len(node.axis): - log.error('number of axis should match number of dim') - return + raise Error('Number of axis "{}" should match number of dim "{}" for node "{}"' + ''.format(node.axis, node.dim, node_name)) output_shape[node.axis] = node.dim elif node.has_valid('crop_begin') and node.has_valid('crop_end'): if len(node.crop_begin) != len(node.axis) or len(node.crop_end) != len(node.axis): - log.error('number of crop_begin/crop_end should match number of axis') - return + raise Error('number of crop_begin({})/crop_end({}) should match number of axis "{}" for node "{}"' + ''.format(node.crop_begin, node.crop_end, node.axis, node_name)) if type(node.axis) in [list, tuple]: for i in range(len(node.axis)): output_shape[node.axis[i]] = output_shape[node.axis[i]] - node.crop_begin[i] - node.crop_end[i] else: output_shape[node.axis] = output_shape[node.axis] - node.crop_begin - node.crop_end else: - log.error('Crop node {} should have either dim or crop_begin and crop_end attributes'.format(node.name)) - return + raise Error('Crop node {} should have either dim or crop_begin and crop_end attributes'.format(node_name)) - node.out_node().shape = np.array(output_shape) + node.out_port(0).data.set_shape(output_shape) PermuteAttrs.create_permute_attrs(node, attrs=[('axis', 'input:0')]) @staticmethod def _two_inputs_infer(node: Node): N = len(node.in_nodes()) + node_name = node.soft_get('name', node.id) - shapes = [node.in_node(i).shape for i in range(N)] + shapes = [node.in_port(i).data.get_shape() for i in range(N)] if any(s is None for s in shapes): - log.error('Not all input shapes were defined for {} node'.format(node.name)) - return + raise Error('Not all input shapes were defined for {} node'.format(node_name)) if not node.has_valid('axis'): - log.error('axis attribute is missing for {} node. should be set in crop extractor'.format(node.name)) - return + raise Error('axis attribute is missing for {} node. should be set in crop extractor'.format(node_name)) if not node.has_valid('offset'): - log.error('offset attribute is missing for {} node. should be set in crop extractor'.format(node.name)) - return + raise Error('offset attribute is missing for {} node. should be set in crop extractor'.format(node_name)) - input_shape = np.array(shapes[0]) + input_shape = shapes[0].copy() start_axis = get_canonical_axis_index(input_shape, node.axis) node.axis = start_axis - reference_shape = np.array(shapes[1]) + reference_shape = shapes[1].copy() if node.has_valid('axes'): - ''' - The axes parameter contain shape indexes for second input and - show which shape indexes we need to use for dim attribute. - ''' + # The axes parameter contain shape indexes for second input and show which shape indexes we need to use for + # dim attribute. input_dim = node.axes node.in_port(1).disconnect() else: @@ -138,8 +133,7 @@ class Crop(Op): crop_offset = node.offset[i - start_axis] if input_shape[i] - crop_offset < reference_shape[i]: - log.error('The crop for dimension is out of bounds in ' + node.node) - return + raise Error('The crop for dimension is out of bounds in node {}'.format(node_name)) dim.append(reference_shape[i]) ir_axis.append(i) @@ -149,9 +143,10 @@ class Crop(Op): node.axis = ir_axis node.offset = ir_offset node['dim'] = dim - node.out_node().shape = new_shape + node.out_port(0).data.set_shape(new_shape) - if node.in_node(0).has_valid('value') and not getattr(node.graph.graph['cmd_params'], 'enable_ssd_gluoncv', False): + if node.in_node(0).has_valid('value') and \ + not getattr(node.graph.graph['cmd_params'], 'enable_ssd_gluoncv', False): out_value = np.copy(node.in_node(0).value) slice_indexes = [] @@ -161,6 +156,6 @@ class Crop(Op): for axis in input_dim: slice_indexes[axis] = slice(0, new_shape[axis]) out_value = out_value[tuple(slice_indexes)] - node.out_node().value = out_value + node.out_port(0).data.set_value(out_value) PermuteAttrs.create_permute_attrs(node, attrs=[('axis', 'input:0')]) diff --git a/model-optimizer/mo/ops/deconvolution.py b/model-optimizer/mo/ops/deconvolution.py index ba080582d85..6f0255a514d 100644 --- a/model-optimizer/mo/ops/deconvolution.py +++ b/model-optimizer/mo/ops/deconvolution.py @@ -3,8 +3,8 @@ import numpy as np -from mo.front.common.partial_infer.utils import mark_input_bins, assign_dims_to_weights, tf_window_op_pad_infer -from mo.front.extractor import spatial_getter +from mo.front.common.partial_infer.utils import mark_input_bins, assign_dims_to_weights, tf_window_op_pad_infer, \ + shape_array, compatible_shapes from mo.front.onnx.extractors.utils import get_backend_pad from mo.graph.graph import Node, Graph from mo.graph.perm_inputs import PermuteInputs @@ -46,10 +46,9 @@ class Deconvolution(Op): They also deliver output shape that is interpreted here as input shape for convolution. We need to check that the real input shape and shape inferred by those utility functions match. """ - output_shape = np.array(node.in_node(2).value) - batch = np.array(node.in_node(0).shape)[0] - output_shape[0] = batch - kernel_shape = node.in_node(1).shape + output_shape = shape_array(node.in_node(2).value) + output_shape[0] = node.in_port(0).data.get_shape()[0] + kernel_shape = node.in_port(1).data.get_shape() node['kernel_shape'] = kernel_shape if output_shape is None or kernel_shape is None or node.spatial_dims is None or node.stride is None: return @@ -62,13 +61,13 @@ class Deconvolution(Op): node['dilation'] = np.full([len(output_shape)], 1, dtype=np.int64) spatial_dims = node.spatial_dims - output_spatial = np.array(output_shape[spatial_dims]) - stride_spatial = np.array(node.stride[spatial_dims]) - node['kernel_spatial'] = np.array(kernel_shape[node.kernel_spatial_idx]) + output_spatial = shape_array(output_shape[spatial_dims]) + stride_spatial = shape_array(node.stride[spatial_dims]) + node['kernel_spatial'] = shape_array(kernel_shape[node.kernel_spatial_idx]) node.pad_spatial_shape, input_spatial_for_check = tf_window_op_pad_infer( output_spatial, node.kernel_spatial, stride_spatial, node.auto_pad) - assert all(input_spatial_for_check == node.in_node(0).shape[spatial_dims]) + assert compatible_shapes(input_spatial_for_check, node.in_node(0).shape[spatial_dims]) pad = np.zeros((len(output_shape), 2), dtype=np.int64) pad[spatial_dims] = node.pad_spatial_shape @@ -76,7 +75,7 @@ class Deconvolution(Op): node.output = output_shape[node.channel_dims][0] node.output_shape = output_shape - node.out_node().shape = output_shape + node.out_port(0).data.set_shape(output_shape) mark_input_bins(node, ['weights'], 1) assign_dims_to_weights(node.in_node(1), node.kernel_spatial_idx, node.input_feature_channel, diff --git a/model-optimizer/mo/ops/eltwise.py b/model-optimizer/mo/ops/eltwise.py index ada8dd6a2f5..44937efcf68 100644 --- a/model-optimizer/mo/ops/eltwise.py +++ b/model-optimizer/mo/ops/eltwise.py @@ -15,23 +15,23 @@ class Eltwise(Op): operations = { 'sum': ('Add', lambda a, b: a + b), 'mul': ('Mul', lambda a, b: a * b), - 'max': ('Max', lambda a, b: np.maximum(a, b)), - 'pow': ('Pow', lambda a, b: np.power(a, b)), - 'less': ('Less', lambda a, b: a < b), - 'less_equal': ('LessEqual', lambda a, b: a <= b), - 'greater': ('Greater', lambda a, b: a > b), - 'greater_equal': ('GreaterEqual', lambda a, b: a >= b), - 'equal': ('Equal', lambda a, b: a == b), - 'floor_mod': ('FloorMod', lambda a, b: a % b), - 'not_equal': ('NotEqual', lambda a, b: a != b), + 'max': ('Max', lambda a, b: np.ma.maximum(a, b)), + 'pow': ('Pow', lambda a, b: np.ma.power(a, b)), + 'less': ('Less', lambda a, b: np.ma.less(a, b)), + 'less_equal': ('LessEqual', lambda a, b: np.ma.less_equal(a, b)), + 'greater': ('Greater', lambda a, b: np.ma.greater(a, b)), + 'greater_equal': ('GreaterEqual', lambda a, b: np.ma.greater_equal(a, b)), + 'equal': ('Equal', lambda a, b: np.ma.equal(a, b)), + 'floor_mod': ('FloorMod', lambda a, b: np.ma.fmod(a, b)), + 'not_equal': ('NotEqual', lambda a, b: np.ma.not_equal(a, b)), 'logical_or': ('LogicalOr', lambda a, b: bool(a) or bool(b)), 'logical_and': ('LogicalAnd', lambda a, b: bool(a) and bool(b)), 'logical_xor': ('LogicalXor', lambda a, b: bool(a) ^ bool(b)), - 'log': ('Log', lambda x: np.log(x)), + 'log': ('Log', lambda x: np.ma.log(x)), } super().__init__(graph, { - 'type': __class__.op, + 'type': self.op, 'op': operations[attrs['operation']][0], 'infer': lambda node: eltwise_infer(node, operations[node.operation][1]), 'in_ports_count': 2, diff --git a/model-optimizer/mo/ops/expand_dims.py b/model-optimizer/mo/ops/expand_dims.py index f1252bfc064..62ed4ee06f7 100644 --- a/model-optimizer/mo/ops/expand_dims.py +++ b/model-optimizer/mo/ops/expand_dims.py @@ -3,7 +3,7 @@ import numpy as np -from mo.front.common.partial_infer.utils import int64_array +from mo.front.common.partial_infer.utils import int64_array, is_fully_defined, shape_insert from mo.graph.graph import Node from mo.ops.op import Op from mo.utils.error import Error @@ -20,9 +20,9 @@ class ExpandDims(Op): def __init__(self, graph, attrs: dict): super().__init__(graph, { 'type': None, - 'op': __class__.op, + 'op': self.op, 'reinterp_shape': True, - 'infer': __class__.infer, + 'infer': self.infer, 'expand_axis': None, 'in_ports_count': 1, 'out_ports_count': 1, @@ -30,19 +30,20 @@ class ExpandDims(Op): @staticmethod def infer(node: Node): - input_node = node.in_nodes()[0] - output_node = node.out_node() - if input_node.shape is None: - return + node_name = node.soft_get('name', node.id) + input_shape = node.in_port(0).data.get_shape() + input_value = node.in_port(0).data.get_value() + if input_shape is None: + raise Error('Input shape for node "{}" is None'.format(node_name)) - assert len(node.in_nodes()) == 1, 'Wrong number of inputs to the layer {}'.format(node.soft_get('name')) + assert len(node.in_nodes()) == 1, 'Wrong number of inputs to the layer {}'.format(node_name) if not node.has_valid('expand_axis'): - raise Error('ExpandDims axis is not defined for node {}'.format(node.soft_get('name'))) + raise Error('ExpandDims axis is not defined for node {}'.format(node_name)) expand_axes = node.expand_axis if expand_axes is None: - raise Error('The "expand_axis" attribute is None for node "{}"'.format(node.soft_get('name'))) + raise Error('The "expand_axis" attribute is None for node "{}"'.format(node_name)) if isinstance(expand_axes, int): expand_axes = int64_array([expand_axes]) @@ -53,13 +54,14 @@ class ExpandDims(Op): # way not as insert operation for expand_axis in expand_axes: if expand_axis < 0: - expand_axis += len(input_node.shape) + 1 + expand_axis += len(input_shape) + 1 expand_axes = sorted(expand_axes) - + output_shape = input_shape.copy() for expand_axis in expand_axes: - output_node.shape = np.insert(input_node.shape, expand_axis, [1]) - # convert data type of the shape to int64 explicitly - output_node.shape = output_node.shape.astype(np.int64) - if input_node.value is not None: - output_node.value = input_node.value.reshape(output_node.shape) + output_shape = shape_insert(output_shape, expand_axis, 1) + + if input_value is not None and is_fully_defined(output_shape): + node.out_port(0).data.set_value(input_value.reshape(output_shape)) + else: + node.out_port(0).data.set_shape(output_shape) diff --git a/model-optimizer/mo/ops/memory.py b/model-optimizer/mo/ops/memory.py index cb90464af8c..c3b45f18642 100644 --- a/model-optimizer/mo/ops/memory.py +++ b/model-optimizer/mo/ops/memory.py @@ -2,7 +2,7 @@ # SPDX-License-Identifier: Apache-2.0 from mo.front.common.partial_infer.elemental import copy_shape_infer -from mo.front.common.partial_infer.utils import int64_array +from mo.front.common.partial_infer.utils import int64_array, shape_array from mo.graph.graph import Node, Graph from mo.middle.passes.convert_data_type import data_type_str_to_np from mo.ops.op import Op @@ -46,7 +46,7 @@ class Memory(Op): # And we can set the attribute 'shape' in extracting batch = 1 for out_node in node.out_nodes().values(): - out_node.shape = int64_array([batch, *node.shape[:]]) + out_node.shape = shape_array([batch, *node.shape[:]]) return else: raise Error('Model Optimizer is unable to calculate output shape of Memory node {}. ' + diff --git a/model-optimizer/mo/ops/op.py b/model-optimizer/mo/ops/op.py index 7af2448ea0e..423a50d6e13 100644 --- a/model-optimizer/mo/ops/op.py +++ b/model-optimizer/mo/ops/op.py @@ -8,7 +8,7 @@ from collections import namedtuple import networkx as nx import numpy as np -from mo.front.common.partial_infer.utils import int64_array +from mo.front.common.partial_infer.utils import int64_array, strict_compare_tensors from mo.front.extractor import add_attrs_props, update_ie_fields from mo.graph.graph import Node, Graph from mo.utils import class_registration @@ -198,9 +198,11 @@ class Op(object): for out_node in new_op_node.out_nodes().values(): out_node['nchw_layout'] = new_op_node.nchw_layout assert all(old_value is None for old_value in old_data_value) or all( - [np.array_equal(old_data_value[id], data_node.value) for id, data_node in enumerate(data_nodes)]) + [strict_compare_tensors(old_data_value[id], data_node.value) + for id, data_node in enumerate(data_nodes)]) assert all(old_shape is None for old_shape in old_data_shape) or all( - [np.array_equal(old_data_shape[id], data_node.shape) for id, data_node in enumerate(data_nodes)]), \ + [strict_compare_tensors(old_data_shape[id], data_node.shape) + for id, data_node in enumerate(data_nodes)]), \ "After re-inference of {} node, old and new shapes do not match. Old shapes: {}, new shapes: {}." \ "".format(new_op_node.soft_get('name'), [old_data_shape[id] for id in range(len(data_nodes))], [data_node.shape for data_node in data_nodes]) diff --git a/model-optimizer/mo/ops/pad.py b/model-optimizer/mo/ops/pad.py index 3e0810f7500..dc9cc92d5ad 100644 --- a/model-optimizer/mo/ops/pad.py +++ b/model-optimizer/mo/ops/pad.py @@ -3,6 +3,7 @@ import numpy as np +from mo.front.common.partial_infer.utils import is_fully_defined, shape_array from mo.graph.graph import Graph from mo.graph.perm_inputs import PermuteInputs from mo.ops.op import Op @@ -15,7 +16,7 @@ class Pad(Op): shape. The second and third inputs are 1D tensor with number of elements equal to input tensor rank. These inputs specify the begin and end paddings. - The forth input specifies the fill valuu for 'constant' mode and not used for other cases. + The forth input specifies the fill value for 'constant' mode and not used for other cases. """ op = 'Pad' @@ -50,6 +51,7 @@ class Pad(Op): assert len(node.in_nodes()) in [3, 4], "The node {} must have 3 or 4 inputs".format(pad_node_name) input_shape = node.in_port(0).data.get_shape() + input_value = node.in_port(0).data.get_value() pad_beg = node.in_port(1).data.get_value() pad_end = node.in_port(2).data.get_value() @@ -68,14 +70,17 @@ class Pad(Op): node.out_port(0).data.set_shape(input_shape + pad_beg + pad_end) - if node.in_port(0).data.get_value() is not None: + if input_value is not None and is_fully_defined(pad_beg) and is_fully_defined(pad_end): pads = np.insert(pad_end, np.arange(len(pad_end)), pad_beg) pads = np.reshape(pads, (len(pad_end), 2)) pad_val = 0 if len(node.in_nodes()) == 4: pad_val = node.in_port(3).data.get_value() if node.in_port(3).data is not None else 0 - node.out_port(0).data.set_value(np.pad(node.in_port(0).data.get_value(), pads, constant_values=pad_val, - mode='constant')) + if is_fully_defined(input_value): + node.out_port(0).data.set_value(np.pad(input_value, pads, constant_values=pad_val, mode='constant')) + else: + node.out_port(0).data.set_value(shape_array(np.pad(input_value, pads, constant_values=pad_val, + mode='constant'))) # pad values should be permuted during the NHWC->NCHW layout change PermuteInputs().set_input_permutation(node.in_node(1), node, 'input:0', 'shape') PermuteInputs().set_input_permutation(node.in_node(2), node, 'input:0', 'shape') diff --git a/model-optimizer/mo/ops/pooling.py b/model-optimizer/mo/ops/pooling.py index 02fa3af7738..4ae057c271a 100644 --- a/model-optimizer/mo/ops/pooling.py +++ b/model-optimizer/mo/ops/pooling.py @@ -3,7 +3,8 @@ import numpy as np -from mo.front.common.partial_infer.utils import tf_window_op_pad_infer, int64_array, float_array +from mo.front.common.partial_infer.utils import tf_window_op_pad_infer, int64_array, float_array, shape_array, \ + dynamic_dimension_value, dynamic_dimension from mo.front.onnx.extractors.utils import get_backend_pad from mo.graph.graph import Node, Graph from mo.ops.op import Op, PermuteAttrs @@ -128,7 +129,10 @@ class Pooling(Op): raise Error("Data after padding has dimension less than window size. " + "Possible reason of error is incorrectly specified model input shape(s).") - output_spatial_shape = int64_array(rounding(float_array(padded_spatial_shape) / stride_spatial)) + 1 + output_spatial_shape = shape_array([dynamic_dimension_value for _ in range(len(padded_spatial_shape))]) + for idx in range(len(padded_spatial_shape)): + if padded_spatial_shape[idx] is not dynamic_dimension and stride_spatial[idx] is not dynamic_dimension: + output_spatial_shape[idx] = int(rounding(padded_spatial_shape[idx] / stride_spatial[idx])) + 1 original_pads = np.array([i[1] for i in node.pad_spatial_shape]) @@ -141,7 +145,7 @@ class Pooling(Op): output_shape = input_shape.copy() output_shape[node.spatial_dims] = node.output_spatial_shape - node.out_node().shape = output_shape + node.out_port(0).data.set_shape(output_shape) # Add permute_attrs PermuteAttrs.create_permute_attrs(node, attrs=[('pad', 'input:0'), diff --git a/model-optimizer/mo/ops/reshape.py b/model-optimizer/mo/ops/reshape.py index 8a9b58cfef9..b64dd25abc8 100644 --- a/model-optimizer/mo/ops/reshape.py +++ b/model-optimizer/mo/ops/reshape.py @@ -3,6 +3,7 @@ import numpy as np +from mo.front.common.partial_infer.utils import dynamic_dimension, dynamic_dimension_value, is_fully_defined from mo.front.extractor import bool_to_str from mo.graph.graph import Node, Graph from mo.graph.perm_inputs import PermuteInputs @@ -53,12 +54,27 @@ class Reshape(Op): num_of_input_elements = np.prod(input_shape) num_of_output_elements = 1 for index, x in enumerate(new_shape): - if x == 0 and node.has_and_set('special_zero'): - num_of_output_elements *= input_shape[index] + if x is dynamic_dimension: + num_of_output_elements = dynamic_dimension_value + elif x == 0 and node.has_and_set('special_zero'): + if input_shape[index] is not dynamic_dimension: + num_of_output_elements *= input_shape[index] elif x != -1: num_of_output_elements *= x - undefined_dim = num_of_input_elements // num_of_output_elements + # input_shape = [dynamic, 5, 6], new_shape = [0, -1] => output_shape [dynamic, 30] + # marker that no dynamic input dimensions or all of them are copied with "0" magic value + all_dynamic_dimension_are_copied = True + if not is_fully_defined(input_shape): + for index, x in enumerate(input_shape): + if x is dynamic_dimension: + if index >= len(new_shape) or new_shape[index] != 0: + all_dynamic_dimension_are_copied = False + + undefined_dim = dynamic_dimension + if num_of_output_elements is not dynamic_dimension and all_dynamic_dimension_are_copied and \ + is_fully_defined(new_shape): + undefined_dim = num_of_input_elements // num_of_output_elements output_shape = [] for index, x in enumerate(new_shape): if x == 0 and node.has_and_set('special_zero'): @@ -68,13 +84,29 @@ class Reshape(Op): else: output_shape.append(x) - assert np.prod(input_shape) == np.prod(output_shape), \ - "Number of elements in input {} and output {} of reshape node {} mismatch" \ - "".format(input_shape, output_shape, name) + # even if the new_shape contains some dynamic values we can calculate the actual value by deducing it from the + # input shape if it is static: input_shape = [5, 3, 8], new_shape = [4, d] => output_shape = [4, 30] + if is_fully_defined(input_shape) and not is_fully_defined(new_shape): + dynamic_indices = np.argwhere([item is dynamic_dimension for item in new_shape]) + num_of_output_elements = 1 + if dynamic_indices.size == 1: + for index, x in enumerate(new_shape): + if x == 0 and node.has_and_set('special_zero'): + num_of_output_elements *= input_shape[index] + elif x is not dynamic_dimension and x != -1: + num_of_output_elements *= x + assert num_of_input_elements % num_of_output_elements == 0, \ + 'Incorrect number of output elements deduced for node {}: '.format(name) + output_shape[dynamic_indices[0][0]] = num_of_input_elements // num_of_output_elements + + assert not is_fully_defined(input_shape) or not is_fully_defined(output_shape) or \ + np.prod(input_shape) == np.prod(output_shape), \ + "Number of elements in input {} and output {} of reshape node {} mismatch" \ + "".format(input_shape, output_shape, name) PermuteInputs().set_input_permutation(node.in_node(1), node, 'output:0', 'shape') - if node.in_port(0).data.get_value() is not None: + if node.in_port(0).data.get_value() is not None and is_fully_defined(output_shape): node.out_port(0).data.set_value(node.in_port(0).data.get_value().reshape(output_shape)) else: node.out_port(0).data.set_shape(output_shape) diff --git a/model-optimizer/mo/ops/result.py b/model-optimizer/mo/ops/result.py index 5689023c469..d80b670fc09 100644 --- a/model-optimizer/mo/ops/result.py +++ b/model-optimizer/mo/ops/result.py @@ -14,8 +14,8 @@ class Result(Op): def __init__(self, graph: Graph, attrs: dict = None): super().__init__(graph, { - 'op': __class__.op, - 'type': __class__.op, + 'op': self.op, + 'type': self.op, 'version': 'opset1', 'infer': lambda x: None, 'value': None, diff --git a/model-optimizer/mo/ops/shape.py b/model-optimizer/mo/ops/shape.py index c68882326df..86d50df0a05 100644 --- a/model-optimizer/mo/ops/shape.py +++ b/model-optimizer/mo/ops/shape.py @@ -3,6 +3,7 @@ import numpy as np +from mo.front.common.partial_infer.utils import shape_array from mo.graph.graph import Graph from mo.middle.passes.convert_data_type import np_data_type_to_destination_type from mo.ops.op import Op @@ -58,7 +59,7 @@ class Shape(Op): if node.has_and_set('stop_value_propagation'): node.out_port(0).data.set_shape(input_shape.shape) else: - node.out_port(0).data.set_value(np.array(input_shape, dtype=node.output_type)) + node.out_port(0).data.set_value(shape_array(np.array(input_shape, dtype=node.output_type))) @staticmethod def type_infer(node): diff --git a/model-optimizer/mo/ops/slice.py b/model-optimizer/mo/ops/slice.py index b7762e836a0..da25d1dc2f0 100644 --- a/model-optimizer/mo/ops/slice.py +++ b/model-optimizer/mo/ops/slice.py @@ -3,7 +3,8 @@ import numpy as np -from mo.front.common.partial_infer.utils import get_shape_from_slice +from mo.front.common.partial_infer.utils import get_shape_from_slice, shape_array, dynamic_dimension_value, \ + dynamic_dimension, is_dynamic_slice from mo.graph.graph import Node, Graph from mo.ops.op import Op from mo.utils.error import Error @@ -121,30 +122,27 @@ class Slice(Op): starts = node.in_port(1).data.get_value() ends = node.in_port(2).data.get_value() - if starts is None or ends is None: - raise Error('The non-constant start/end values for Slice operation "{}" are not supported'.format(node.name)) + if node.is_in_port_connected(4): + steps = node.in_port(4).data.get_value() + else: + steps = np.ones(len(starts), dtype=np.int64) if node.is_in_port_connected(3): axes = node.in_port(3).data.get_value() - if axes is None: - raise Error('The non-constant axes values for Slice operation "{}" is not supported'.format(node.name)) else: axes = [x for x in range(len(starts))] - if node.is_in_port_connected(4): - steps = node.in_port(4).data.get_value() - if steps is None: - raise Error('The non-constant steps values for Slice operation "{}" is not supported'.format(node.name)) - else: - steps = np.ones(len(starts), dtype=np.int64) + if starts is None or ends is None or steps is None or axes is None: + node.out_port(0).data.set_shape(shape_array([dynamic_dimension_value] * len(input_shape))) + return slice_idx = [slice(0, in_shape, 1) for in_shape in input_shape] for i in range(len(axes)): # Ranged for output value for specified axis slice_idx[axes[i]] = slice(starts[i], ends[i], steps[i]) - if input_value is None: + if input_value is None or any(is_dynamic_slice(s) for s in slice_idx): output_shape = get_shape_from_slice(input_shape, slice_idx) - if np.any(output_shape <= 0): + if np.ma.any(output_shape <= 0): raise Error('Output shape: {} of node "{}" contains non-positive values'.format(output_shape, node.name)) node.out_port(0).data.set_shape(output_shape) else: diff --git a/model-optimizer/mo/ops/space_to_batch.py b/model-optimizer/mo/ops/space_to_batch.py index 9f8ed1acbd1..adcc4826d8b 100644 --- a/model-optimizer/mo/ops/space_to_batch.py +++ b/model-optimizer/mo/ops/space_to_batch.py @@ -3,7 +3,7 @@ import numpy as np -from mo.front.common.partial_infer.utils import int64_array +from mo.front.common.partial_infer.utils import is_fully_defined, dynamic_dimension from mo.graph.perm_inputs import PermuteInputs from mo.ops.op import Op @@ -19,7 +19,7 @@ class SpaceToBatch(Op): 'in_ports_count': 3, 'out_ports_count': 1, 'version': 'opset2', - 'infer': __class__.infer, + 'infer': self.infer, }, attrs) @staticmethod @@ -27,23 +27,25 @@ class SpaceToBatch(Op): """ https://www.tensorflow.org/api_docs/cc/class/tensorflow/ops/space-to-batch """ - input_shape = node.in_node(0).shape - if input_shape is None: - return - - if len(node.in_nodes()) != 4: - return + input_shape = node.in_port(0).data.get_shape() + node_name = node.soft_get('name', node.id) + assert len(node.in_nodes()) == 4, 'Some inputs are not connected for the operation SpaceToBatch with name {}' \ + ''.format(node_name) block_size = node.in_port(1).data.get_value() pads_begin = node.in_port(2).data.get_value() pads_end = node.in_port(3).data.get_value() - if block_size is None or pads_begin is None or pads_end is None: - return + assert block_size is not None and pads_begin is not None and pads_end is not None,\ + 'Some inputs are not defined for SpaceToBatch operation with name {}'.format(node_name) pads = pads_begin + input_shape + pads_end - node.out_node().shape = int64_array([input_shape[0] * np.prod(block_size), - *[int(x) for x in (pads[1:] / block_size[1:])]]) + if is_fully_defined(block_size): + block_elements_count = np.prod(block_size) + else: + block_elements_count = dynamic_dimension + node.out_port(0).data.set_shape([input_shape[0] * block_elements_count, + *[x for x in (pads[1:] // block_size[1:])]]) # block_shape, pads_begin, pads_end should be permuted during the NHWC->NCHW layout change PermuteInputs().set_input_permutation(node.in_node(1), node, 'input:0', 'shape') @@ -63,7 +65,7 @@ class BatchToSpace(Op): 'in_ports_count': 3, 'out_ports_count': 1, 'version': 'opset2', - 'infer': __class__.infer + 'infer': self.infer }, attrs) @staticmethod @@ -84,9 +86,13 @@ class BatchToSpace(Op): pads = block_size * input_shape sizes = pads[1:] - crops_begin[1:] - crops_end[1:] - batch = int(input_shape[0] / (np.prod(block_size))) + if is_fully_defined(block_size): + block_elements_count = np.prod(block_size) + else: + block_elements_count = dynamic_dimension + batch = input_shape[0] // block_elements_count - node.out_node().shape = int64_array([batch, *sizes]) + node.out_port(0).data.set_shape([batch, *sizes]) # block_shape, crops_begin, crops_end values should be permuted during the NHWC->NCHW layout change PermuteInputs().set_input_permutation(node.in_node(1), node, 'input:0', 'shape') diff --git a/model-optimizer/mo/ops/squeeze.py b/model-optimizer/mo/ops/squeeze.py index 0f4a5c65ea2..918592fd9a8 100644 --- a/model-optimizer/mo/ops/squeeze.py +++ b/model-optimizer/mo/ops/squeeze.py @@ -4,7 +4,7 @@ import numpy as np from mo.front.caffe.extractors.utils import get_canonical_axis_index -from mo.front.common.partial_infer.utils import int64_array +from mo.front.common.partial_infer.utils import int64_array, dynamic_dimension, shape_delete, is_fully_defined from mo.graph.graph import Node from mo.graph.perm_inputs import PermuteInputs from mo.ops.op import Op @@ -17,26 +17,27 @@ class Squeeze(Op): def __init__(self, graph, attrs: dict): super().__init__(graph, { - 'op': __class__.op, - 'type': __class__.op, + 'op': self.op, + 'type': self.op, 'version': 'opset1', 'squeeze_dims': None, 'reinterp_shape': True, 'keep_at_least_1d': 0, 'in_ports_count': 2, 'out_ports_count': 1, - 'infer': __class__.infer, + 'infer': self.infer, }, attrs) @staticmethod def infer(node: Node): real_squeeze_dims = int64_array([]) - input_shape = node.in_node().shape + input_shape = node.in_port(0).data.get_shape() + node_name = node.soft_get('name', node.id) if input_shape is None: - return + raise Error('Input shape is not defined for node {}'.format(node_name)) output_shape = input_shape.copy() - assert len(node.in_nodes()) == 2, 'The Squeeze node {} must have 2 inputs'.format(node.soft_get('name')) + assert len(node.in_nodes()) == 2, 'The Squeeze node {} must have 2 inputs'.format(node_name) # TODO remove the following 'if' statement when IE start support 0D tensors squeeze_dims = node.in_port(1).data.get_value() @@ -44,19 +45,20 @@ class Squeeze(Op): squeeze_dims = squeeze_dims.reshape([1]) for dim in squeeze_dims: - if output_shape[dim] == 1: - real_squeeze_dims = np.append(real_squeeze_dims, get_canonical_axis_index(output_shape, dim)) + if output_shape[dim] == 1 or output_shape[dim] is dynamic_dimension: + real_squeeze_dims = np.ma.append(real_squeeze_dims, get_canonical_axis_index(output_shape, dim)) else: - raise Error('Trying to squeeze dimension not equal to 1 for node "{}"'.format(node.soft_get('name'))) + raise Error('Trying to squeeze dimension not equal to 1 for node "{}"'.format(node_name)) # if squeeze_dims empty then all 1s should be removed (tf specification of Squeeze op) if squeeze_dims.size == 0: for i in range(output_shape.size): if output_shape[i] == 1: - real_squeeze_dims = np.append(real_squeeze_dims, get_canonical_axis_index(output_shape, i)) + real_squeeze_dims = np.ma.append(real_squeeze_dims, get_canonical_axis_index(output_shape, i)) - output_shape = np.delete(output_shape, real_squeeze_dims) - node.out_node().shape = output_shape + assert is_fully_defined(real_squeeze_dims), 'Squeeze dimension(s) is not defined for op "{}"'.format(node_name) + output_shape = shape_delete(output_shape, real_squeeze_dims) + node.out_port(0).data.set_shape(output_shape) # make dimensions positive to correctly translate from NHWC to NCHW layout if node.in_port(1).get_source().node.op == 'Const': diff --git a/model-optimizer/mo/ops/strided_slice.py b/model-optimizer/mo/ops/strided_slice.py index 52ab2337ff4..8958c466f55 100644 --- a/model-optimizer/mo/ops/strided_slice.py +++ b/model-optimizer/mo/ops/strided_slice.py @@ -5,10 +5,10 @@ from typing import List, Tuple import numpy as np -from mo.front.common.partial_infer.utils import get_shape_from_slice +from mo.front.common.partial_infer.utils import get_shape_from_slice, dynamic_dimension, dynamic_dimension_value, \ + is_dynamic_slice from mo.graph.graph import Node, Graph from mo.ops.op import Op -from mo.utils.error import Error from mo.utils.utils import array_to_str @@ -18,12 +18,12 @@ class StridedSlice(Op): def __init__(self, graph: Graph, attrs: dict): super().__init__(graph, { - 'type': __class__.op, + 'type': self.op, 'op': 'StridedSlice', 'version': 'opset1', 'in_ports_count': 4, 'out_ports_count': 1, - 'infer': __class__.infer + 'infer': self.infer }, attrs) for mask_name in StridedSlice.get_mask_names(): assert mask_name in attrs, 'Attribute {} of the StridedSlice node is not given.'.format(mask_name) @@ -44,15 +44,14 @@ class StridedSlice(Op): @staticmethod def infer(node: Node): - begin, end, strides = StridedSlice.validate_inputs_and_get_args(node) - - StridedSlice.align_mask_with_slice_rank(node, len(begin)) + StridedSlice.align_mask_with_slice_rank(node, node.in_port(1).data.get_shape()[0]) data_shape = node.in_port(0).data.get_shape() data_value = node.in_port(0).data.get_value() - slices = StridedSlice.get_slices(node, data_shape, begin, end, strides) + slices = StridedSlice.get_slices(node, data_shape) - if data_value is not None: + if data_value is not None and dynamic_dimension_value not in slices and \ + all(not is_dynamic_slice(s) for s in slices): node.out_port(0).data.set_value(data_value[tuple(slices)]) else: node.out_port(0).data.set_shape(get_shape_from_slice(data_shape, slices)) @@ -66,9 +65,14 @@ class StridedSlice(Op): # Therefore PermuteInputs will be set after StridedSliceNormalizer. @staticmethod - def get_slices(node: Node, data_shape: Tuple, begin: np.array, end: np.array, strides: np.array) -> List: + def get_slices(node: Node, data_shape: Tuple) -> List: input_rank = len(data_shape) - slice_rank = len(begin) + slice_rank = node.in_port(1).data.get_shape()[0] + begin = node.in_port(1).data.get_value() + end = node.in_port(2).data.get_value() + strides = node.in_port(3).data.get_value() if node.is_in_port_connected(3) else \ + np.ones([slice_rank], dtype=np.int64) + # from now slices are without ellipsis slices = [[]] * slice_rank in_idx = 0 # index along input tensor shapes, note that input_rank not necessary is equal to slice_rank @@ -76,48 +80,34 @@ class StridedSlice(Op): if node.new_axis_mask[i]: slices[i] = np.newaxis elif node.shrink_axis_mask[i]: - slices[i] = int(begin[i]) - if slices[i] < 0: # need for ConvertGroupedStridedSlice - slices[i] += int(data_shape[in_idx]) + if begin is not None and begin[i] is not dynamic_dimension: + slices[i] = int(begin[i]) + # the normalization is needed for the ConvertGroupedStridedSlice transformation + if slices[i] < 0 and data_shape[in_idx] is not dynamic_dimension: + slices[i] += int(data_shape[in_idx]) + else: + slices[i] = dynamic_dimension_value elif node.ellipsis_mask[i]: slices[i] = ... in_idx += input_rank - slice_rank + np.count_nonzero(node.new_axis_mask) else: - start, stop = begin[i], end[i] - if not node.begin_mask[i]: # if begin, and end are not specified take the whole range - start = None - if not node.end_mask[i]: - stop = None - slices[i] = slice(start, stop, strides[i]) + if begin is not None and end is not None and strides is not None: + start, stop = begin[i], end[i] + if not node.begin_mask[i]: # if begin, and end are not specified take the whole range + start = None + if not node.end_mask[i]: + stop = None + slices[i] = slice(start, stop, strides[i]) + else: + slices[i] = dynamic_dimension_value in_idx += 1 if not node.new_axis_mask[i] else 0 return slices @staticmethod def align_mask_with_slice_rank(node: Node, slice_rank: int): - # align masks sizes with slice_rank (not confuse with extending, mask_aligment != mask_extending) + # align masks sizes with slice_rank (not confuse with extending, mask_alignment != mask_extending) for mask_name in StridedSlice.get_mask_names(): num_insertations = slice_rank - len(node[mask_name]) val = 0 if mask_name not in ['begin_mask', 'end_mask'] else 1 # extend with ones only for begin and end node[mask_name] = np.append(node[mask_name], [val] * num_insertations).astype(int) - @staticmethod - def validate_inputs_and_get_args(node: Node) -> (np.ndarray, np.ndarray, np.ndarray): - node_name = node.soft_get('name', node.id) - begin = node.in_port(1).data.get_value() - end = node.in_port(2).data.get_value() - - if begin is None or end is None: - raise Error( - 'StridedSlice operation for node {} supports only constant begin and end inputs'.format(node_name)) - - if node.is_in_port_connected(3): - strides = node.in_port(3).data.get_value() - if strides is None: - raise Error( - 'StridedSlice operation for node {} supports only constant strides input'.format(node_name)) - else: - strides = np.ones_like(begin) - assert len(begin) == len(end) == len(strides), \ - 'begin, end, and strides of StridedSlice node {} must be of the same length. Got insted:' \ - 'begin = {}, end = {}, strides = {}'.format(node_name, begin, end, strides) - return begin, end, strides diff --git a/model-optimizer/mo/ops/tile.py b/model-optimizer/mo/ops/tile.py index 43d45a74ca0..81d15f7ab47 100644 --- a/model-optimizer/mo/ops/tile.py +++ b/model-optimizer/mo/ops/tile.py @@ -3,7 +3,8 @@ import numpy as np -from mo.front.common.partial_infer.utils import int64_array +from mo.front.common.partial_infer.utils import int64_array, dynamic_dimension_value, dynamic_dimension, \ + is_fully_defined, shape_array, shape_insert from mo.graph.graph import Node, Graph from mo.graph.perm_inputs import PermuteInputs from mo.ops.op import Op, PermuteAttrs @@ -41,12 +42,13 @@ class Tile(Op): # align ranks of the tile_array tensor and input shape node if shape.size < tile_array.size: - shape = np.insert(shape, 0, [1] * (tile_array.size - shape.size)) + shape = shape_insert(shape, 0, [1] * (tile_array.size - shape.size)) elif shape.size > tile_array.size: - tile_array = np.insert(tile_array, 0, [1] * (shape.size - tile_array.size)) + tile_array = shape_insert(tile_array, 0, [1] * (shape.size - tile_array.size)) - if node.in_port(0).data.get_value() is not None: - node.out_port(0).data.set_value(np.tile(node.in_port(0).data.get_value().reshape(shape), tile_array)) + input_value = node.in_port(0).data.get_value() + if input_value is not None and is_fully_defined(shape) and is_fully_defined(tile_array): + node.out_port(0).data.set_value(np.tile(input_value.reshape(shape), tile_array)) else: node.out_port(0).data.set_shape(shape * tile_array) diff --git a/model-optimizer/mo/ops/unsqueeze.py b/model-optimizer/mo/ops/unsqueeze.py index af1c9e3bb76..b5079058623 100644 --- a/model-optimizer/mo/ops/unsqueeze.py +++ b/model-optimizer/mo/ops/unsqueeze.py @@ -3,7 +3,7 @@ import numpy as np -from mo.front.common.partial_infer.utils import int64_array +from mo.front.common.partial_infer.utils import int64_array, shape_array, is_fully_defined, shape_insert from mo.graph.perm_inputs import PermuteInputs from mo.ops.op import Op from mo.utils.error import Error @@ -51,13 +51,13 @@ class Unsqueeze(Op): if node.in_port(1).get_source().node.op == 'Const': node.in_port(1).data.set_value(unsqueeze_dims) - output_shape = int64_array(input_shape.copy()) + output_shape = input_shape.copy() for dim in unsqueeze_dims: - output_shape = np.insert(output_shape, dim, 1) + output_shape = shape_insert(output_shape, dim, 1) - if input_value is not None: + if input_value is not None and is_fully_defined(output_shape): node.out_port(0).data.set_value(input_value.reshape(output_shape)) else: - node.out_port(0).data.set_shape(int64_array(output_shape)) + node.out_port(0).data.set_shape(output_shape) PermuteInputs().set_input_permutation(node.in_node(1), node, 'input:0', 'axis') diff --git a/model-optimizer/mo/utils/broadcasting.py b/model-optimizer/mo/utils/broadcasting.py index b876f4f97b4..ba725fcf749 100644 --- a/model-optimizer/mo/utils/broadcasting.py +++ b/model-optimizer/mo/utils/broadcasting.py @@ -2,12 +2,14 @@ # SPDX-License-Identifier: Apache-2.0 import logging as log + import numpy as np -from mo.front.common.partial_infer.utils import int64_array +from mo.front.common.partial_infer.utils import dynamic_dimension, shape_array, shape_insert, is_fully_defined, \ + dynamic_dimension_value -def make_equal_rank(shape_1: np.array, shape_2: np.array): +def make_equal_rank(shape_1: np.ndarray, shape_2: np.ndarray): """ Prepend shape with smaller length with 1. Return updates shapes :param shape_1: first shape @@ -15,10 +17,10 @@ def make_equal_rank(shape_1: np.array, shape_2: np.array): :return: tuple with updated shapes """ while len(shape_1) < len(shape_2): - shape_1 = np.insert(shape_1, 0, 1) + shape_1 = shape_insert(shape_1, 0, 1) while len(shape_2) < len(shape_1): - shape_2 = np.insert(shape_2, 0, 1) + shape_2 = shape_insert(shape_2, 0, 1) return shape_1, shape_2 @@ -39,13 +41,16 @@ def uni_directional_shape_broadcasting(input_shape: np.array, target_shape: np.a # prepend input shape with 1s input, target_shape = make_equal_rank(input, target_shape) - + result_shape = [] for left, right in zip(input, target_shape): - if left != right and left != 1: + if left != right and left != 1 and right is not dynamic_dimension: log.debug('The shape "{}" cannot be broadcasted to "{}"'.format(input_shape, target_shape)) return None - - return target_shape + if right is dynamic_dimension and left is not dynamic_dimension and left != 1: + result_shape.append(left) + else: + result_shape.append(right) + return shape_array(result_shape) def bi_directional_shape_broadcasting(input_shape_1: np.array, input_shape_2: np.array): @@ -58,20 +63,30 @@ def bi_directional_shape_broadcasting(input_shape_1: np.array, input_shape_2: np shape_1 = input_shape_1.copy() shape_2 = input_shape_2.copy() shape_1, shape_2 = make_equal_rank(shape_1, shape_2) + result = list() for left, right in zip(shape_1, shape_2): - if left != right and left != 1 and right != 1: + if left != right and left != 1 and right != 1 and left is not dynamic_dimension and \ + right is not dynamic_dimension: log.debug('The shape "{}" cannot be broadcasted to "{}"'.format(input_shape_1, input_shape_2)) return None + if left is not dynamic_dimension and right is not dynamic_dimension: + result.append(max(left, right)) + elif left is not dynamic_dimension and left != 1: + result.append(left) + elif right is not dynamic_dimension and right != 1: + result.append(right) + else: + result.append(dynamic_dimension_value) - return np.maximum(shape_1, shape_2) + return shape_array(result) def explicit_shape_broadcasting(input_shape: np.array, target_shape: np.array, axes_mapping: np.array) -> [np.array, np.array]: """ Explicit shape broadcasting of input tensor. Function only asserts that values are correct and normalizes axes. Resulting shape is equal to target_shape. - :param input_value: input value to broadcast + :param input_shape: input value to broadcast :param target_shape: target shape :param axes_mapping: a list of axis indices, each index maps an axis from the input_value to axis in the output :return: broadcasted shape and normalized axes @@ -94,10 +109,11 @@ def uni_directional_broadcasting(input_value: np.array, target_shape: np.array): :param target_shape: target shape :return: broadcasted value """ - assert uni_directional_shape_broadcasting(int64_array(input_value.shape), target_shape) is not None, \ + assert is_fully_defined(target_shape) + assert uni_directional_shape_broadcasting(shape_array(input_value.shape), target_shape) is not None, \ 'The tensor of shape "{}" cannot be uni-directionally broadcasted to shape "{}"'.format(input_value.shape, target_shape) - return np.broadcast_to(input_value, target_shape) + return input_value * np.ones(target_shape).astype(input_value.dtype) def bi_directional_broadcasting(input_value: np.array, second_shape: np.array): @@ -107,10 +123,11 @@ def bi_directional_broadcasting(input_value: np.array, second_shape: np.array): :param second_shape: second tensor shape :return: broadcasted value """ - assert bi_directional_shape_broadcasting(int64_array(input_value.shape), second_shape) is not None, \ - 'The tensor of shape "{}" cannot be bi-directionally broadcasted to shape "{}"'.format(input_value.shape, - second_shape) - return np.array(input_value * np.ones(second_shape), dtype=input_value.dtype) + output_shape = bi_directional_shape_broadcasting(shape_array(input_value.shape), second_shape) + assert output_shape is not None, 'The tensor of shape "{}" cannot be bi-directionally broadcasted to shape "{}"' \ + ''.format(input_value.shape, second_shape) + assert is_fully_defined(output_shape) + return input_value * np.ones(second_shape).astype(input_value.dtype) def explicit_broadcasting(input_value: np.array, target_shape: np.array, axes_mapping: np.array) -> np.array: diff --git a/model-optimizer/mo/utils/cli_parser.py b/model-optimizer/mo/utils/cli_parser.py index 3e89843ef54..bac0074c345 100644 --- a/model-optimizer/mo/utils/cli_parser.py +++ b/model-optimizer/mo/utils/cli_parser.py @@ -217,8 +217,8 @@ def get_common_cli_parser(parser: argparse.ArgumentParser = None): 'the order of dimensions depends on the framework input layout of the model. ' 'For example, [N,C,H,W] is used for Caffe* models and [N,H,W,C] for TensorFlow* ' 'models. Model Optimizer performs necessary transformations to convert the shape to ' - 'the layout required by Inference Engine (N,C,H,W). The shape should not contain ' - 'undefined dimensions (? or -1) and should fit the dimensions defined in the input ' + 'the layout required by Inference Engine (N,C,H,W). The shape could contain ' + 'undefined dimensions (-1) and should fit the dimensions defined in the input ' 'operation of the graph. If there are multiple inputs in the model, --input_shape ' 'should contain definition of shape for each input separated by a comma, for ' 'example: [1,3,227,227],[2,4] for a model with two inputs with 4D and 2D shapes. ' @@ -245,13 +245,13 @@ def get_common_cli_parser(parser: argparse.ArgumentParser = None): default='ERROR') common_group.add_argument('--input', help='Quoted list of comma-separated input nodes names with shapes, data types, ' - 'and values for freezing. The shape and value are specified as space-separated lists. ' - 'The data type of input node is specified in braces and can have one of the values: ' - 'f64 (float64), f32 (float32), f16 (float16), i64 (int64), i32 (int32), u8 (uint8), boolean. ' - 'For example, use the following format to set input port 0 ' - 'of the node `node_name1` with the shape [3 4] as an input node and ' - 'freeze output port 1 of the node `node_name2` with the value [20 15] of the int32 type ' - 'and shape [2]: "0:node_name1[3 4],node_name2:1[2]{i32}->[20 15]".') + 'and values for freezing. The shape and value are specified as space-separated ' + 'lists. The data type of input node is specified in braces and can have one of the ' + 'values: f64 (float64), f32 (float32), f16 (float16), i64 (int64), i32 (int32), u8 ' + '(uint8), boolean. For example, use the following format to set input port 0 of the ' + 'node `node_name1` with the shape [3 4] as an input node and freeze output port 1 ' + 'of the node `node_name2` with the value [20 15] of the int32 type and shape [2]: ' + '"0:node_name1[3 4],node_name2:1[2]{i32}->[20 15]".') common_group.add_argument('--output', help='The name of the output operation of the model. ' + 'For TensorFlow*, do not add :0 to this name.') diff --git a/model-optimizer/mo/utils/ir_engine/compare_graphs.py b/model-optimizer/mo/utils/ir_engine/compare_graphs.py index ecaaad4b3ea..e6d8d7fc4e5 100644 --- a/model-optimizer/mo/utils/ir_engine/compare_graphs.py +++ b/model-optimizer/mo/utils/ir_engine/compare_graphs.py @@ -9,8 +9,50 @@ import numpy as np from mo.graph.graph import Graph, Node -def compare_graphs(graph: Graph, graph_ref: Graph, last_node: str, last_node_ref=None, check_op_attrs=False): +def compare_node(node_ref, node, ref_attr_value, attr_value, attr, errors_list: list): from mo.utils.ir_engine.ir_engine import IREngine + + def err_format_string(): + return 'Current node "{}" with type "{}" and reference node "{}" with type "{}" have different attr "{}" : ' \ + '{} and {}'.format(node.id, node.soft_get('type', None), node_ref.id, node_ref.soft_get('type', None), + attr, attr_value, ref_attr_value) + + if type(ref_attr_value) in [np.ndarray, list]: + if not np.array_equal(attr_value, ref_attr_value): + errors_list.append(err_format_string()) + elif isinstance(ref_attr_value, tuple): + if len(ref_attr_value) != len(attr_value): + errors_list.append(err_format_string()) + else: + for ref_item, item in zip(ref_attr_value, attr_value): + compare_node(node_ref, node, ref_item, item, attr, errors_list) + elif isinstance(ref_attr_value, dict): + ref_keys = sorted(list(ref_attr_value.keys())) + keys = sorted(list(attr_value.keys())) + if ref_keys != keys: + errors_list.append(err_format_string()) + else: + for key in keys: + compare_node(node_ref, node, ref_attr_value[key], attr_value[key], key, errors_list) + elif isinstance(attr_value, Number): + eps = 5e-2 if node.has('precision') and node['precision'] == 'FP16' else 1e-4 + if abs(attr_value - ref_attr_value) > eps: + errors_list.append(err_format_string()) + elif isinstance(attr_value, IREngine): + resp, err_log = attr_value.compare(ref_attr_value) + if not resp: + errors_list.extend(err_log) + elif isinstance(attr_value, np.ma.masked_array): + if not np.ma.allequal(attr_value, ref_attr_value): + errors_list.append(err_format_string()) + elif isinstance(attr_value, np.ndarray): + if not np.array_equal(attr_value, ref_attr_value): + errors_list.append(err_format_string()) + elif attr_value != ref_attr_value: + errors_list.append(err_format_string()) + + +def compare_graphs(graph: Graph, graph_ref: Graph, last_node: str, last_node_ref=None, check_op_attrs=False): stderr = [] if last_node_ref is None: last_node_ref = last_node @@ -65,41 +107,23 @@ def compare_graphs(graph: Graph, graph_ref: Graph, last_node: str, last_node_ref cur_node_type = node.type if node.has_valid("type") else None ref_node_type = node_ref.type if node_ref.has_valid("type") else None for attr in graph_ref.node[node_ref.id]: - if graph_ref.node[node_ref.id][attr] is None or attr in ['name', 'id', '_in_ports', '_out_ports', - 'infer', 'IE', 'biases', 'weights', 'custom', 'offset', 'ir_data_attrs']: + if graph_ref.node[node_ref.id][attr] is None or attr in \ + ['name', 'id', '_in_ports', '_out_ports', 'infer', 'IE', 'biases', 'weights', 'custom', + 'offset', 'ir_data_attrs']: continue if attr not in graph.node[node.id]: - stderr.append('Current node "{}" with type {} has missing attribute {}'.format(node.id, cur_node_type, attr)) + stderr.append('Current node "{}" with type {} has missing attribute {}' + ''.format(node.id, cur_node_type, attr)) continue if attr == 'value': if not values_are_equal(node.value, node_ref.value): - stderr.append('Current node "{}" with type {} and reference node "{}" with type have different values ' - '\n{} \nand \n{}'.format(node.id, cur_node_type, node_ref.id, ref_node_type, node.value, node_ref.value)) + stderr.append('Current node "{}" with type {} and reference node "{}" with type have ' + 'different values \n{} \nand \n{}'.format( + node.id, cur_node_type, node_ref.id, ref_node_type, node.value, node_ref.value)) continue - - def err_format_string(): - return 'Current node "{}" with type {} and reference node "{}" with type {} have different attr "{}" : ' \ - '{} and {}'.format(node.id, cur_node_type, node_ref.id, ref_node_type, attr, - graph.node[node.id][attr], - graph_ref.node[node_ref.id][attr]) - - if type(graph_ref.node[node_ref.id][attr]) in [np.ndarray, list]: - if not np.array_equal(graph.node[node.id][attr], graph_ref.node[node_ref.id][attr]): - stderr.append(err_format_string()) - elif isinstance(graph.node[node.id][attr], Number): - eps = 5e-2 if node.has('precision') and node['precision'] == 'FP16' else 1e-4 - if abs(graph.node[node.id][attr] - graph_ref.node[node_ref.id][attr]) > eps: - stderr.append(err_format_string()) - elif isinstance(graph.node[node.id][attr], IREngine): - resp, err_log = graph.node[node.id][attr].compare(graph_ref.node[node_ref.id][attr]) - if not resp: - stderr.extend(err_log) - elif isinstance(graph.node[node.id][attr], np.ndarray): - if not np.array_equal(graph.node[node.id][attr], graph_ref.node[node_ref.id][attr]): - stderr.append(err_format_string()) - elif graph.node[node.id][attr] != graph_ref.node[node_ref.id][attr]: - stderr.append(err_format_string()) + compare_node(node_ref, node, graph_ref.node[node_ref.id][attr], graph.node[node.id][attr], attr, + stderr) else: if node_ref.has_valid('shape') and not node.has_valid('shape'): stderr.append('{} has None shape'.format(node.id)) diff --git a/model-optimizer/mo/utils/ir_engine/ir_engine.py b/model-optimizer/mo/utils/ir_engine/ir_engine.py index 3d534017828..ec3c1cd4015 100644 --- a/model-optimizer/mo/utils/ir_engine/ir_engine.py +++ b/model-optimizer/mo/utils/ir_engine/ir_engine.py @@ -14,6 +14,7 @@ from pathlib import Path import numpy as np +from mo.front.common.partial_infer.utils import dynamic_dimension_value, shape_array from mo.graph.graph import Node, Graph from mo.utils.ir_engine.compare_graphs import compare_graphs @@ -224,6 +225,8 @@ class IREngine(object): for dim in port: output_shape.append(int(dim.text)) + output_shape = shape_array([d if d != -1 else dynamic_dimension_value for d in output_shape]) + out_tensor_names = None if 'names' in port.attrib: out_tensor_names = port.attrib['names'] diff --git a/model-optimizer/mo/utils/ir_reader/extenders/parameter_extender.py b/model-optimizer/mo/utils/ir_reader/extenders/parameter_extender.py index 9f16198e086..d0d02ec5242 100644 --- a/model-optimizer/mo/utils/ir_reader/extenders/parameter_extender.py +++ b/model-optimizer/mo/utils/ir_reader/extenders/parameter_extender.py @@ -1,7 +1,7 @@ # Copyright (C) 2018-2021 Intel Corporation # SPDX-License-Identifier: Apache-2.0 -from mo.front.common.partial_infer.utils import int64_array +from mo.front.common.partial_infer.utils import int64_array, shape_array, dynamic_dimension_value from mo.middle.passes.convert_data_type import destination_type_to_np_data_type from mo.utils.graph import Node from mo.utils.ir_reader.extender import Extender @@ -18,3 +18,5 @@ class Parameter_extender(Extender): op.shape = int64_array([]) else: Extender.attr_to_list(op, 'shape') + if -1 in op.shape: + op.shape = shape_array([d if d != -1 else dynamic_dimension_value for d in op.shape]) diff --git a/model-optimizer/mo/utils/telemetry_utils.py b/model-optimizer/mo/utils/telemetry_utils.py index ce7a30d58c2..37b96cda969 100644 --- a/model-optimizer/mo/utils/telemetry_utils.py +++ b/model-optimizer/mo/utils/telemetry_utils.py @@ -1,11 +1,10 @@ # Copyright (C) 2018-2021 Intel Corporation # SPDX-License-Identifier: Apache-2.0 - +import numpy as np import argparse from collections import Counter -import numpy as np - +from mo.front.common.partial_infer.utils import is_fully_defined, unmask_shape, int64_array from mo.graph.graph import Graph from mo.middle.pattern_match import for_graph_and_each_sub_graph_recursively from mo.utils.cli_parser import get_params_with_paths_list @@ -53,8 +52,8 @@ def send_shapes_info(framework: str, graph: Graph): shape_str = "" is_partially_defined = "0" for shape in shapes: - shape_str += np.array2string(shape) + "," - if not all(shape > 0): + shape_str += np.array2string(int64_array(unmask_shape(shape))) + "," + if not is_fully_defined(shape): is_partially_defined = "1" message_str = "{fw:" + framework + ",shape:\"" + shape_str[:-1] + "\"}" t.send_event('mo', 'input_shapes', message_str) diff --git a/model-optimizer/mo/utils/utils.py b/model-optimizer/mo/utils/utils.py index 0c153f80ded..cc20f8b8ec0 100644 --- a/model-optimizer/mo/utils/utils.py +++ b/model-optimizer/mo/utils/utils.py @@ -10,6 +10,8 @@ from typing import Callable import numpy as np +from mo.front.common.partial_infer.utils import dynamic_dimension + def refer_to_faq_msg(question_num: int): return '\n For more information please refer to Model Optimizer FAQ, question #{0}. ' \ @@ -24,13 +26,12 @@ class NamedAttrsClass: def match_shapes(pattern: np.array, shape: np.array): - """ Check if shape matches shape pattern handling -1 and 0 in the pattern. """ - # Elements with values -1 and 0 in pattern are just ignored. - # Other elements should match. + """ Check if shape matches shape pattern handling undefined dimension and 0 in the pattern. """ + # Elements with value 0 and undefined values in pattern are just ignored. Other elements should match. if pattern.size != shape.size: return False - indices = [i for i, n in enumerate(pattern) if n not in [0, -1]] - return np.array_equal(pattern[indices], shape[indices]) + indices = [i for i, n in enumerate(pattern) if n != 0 and n is not dynamic_dimension] + return np.ma.allequal(pattern[indices], shape[indices]) def symm_match_shapes(shape1: np.array, shape2: np.array): diff --git a/model-optimizer/unit_tests/extensions/back/GatherTreeNormalizer_test.py b/model-optimizer/unit_tests/extensions/back/GatherTreeNormalizer_test.py new file mode 100644 index 00000000000..60fe1164ff4 --- /dev/null +++ b/model-optimizer/unit_tests/extensions/back/GatherTreeNormalizer_test.py @@ -0,0 +1,49 @@ +# Copyright (C) 2018-2021 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 + +import unittest + +import numpy as np + +from extensions.back.GatherNormalizer import GatherTreeNormalizer +from mo.front.common.partial_infer.utils import int64_array +from mo.middle.passes.eliminate import shape_inference +from mo.utils.ir_engine.compare_graphs import compare_graphs +from unit_tests.utils.graph import build_graph, regular_op_with_shaped_data, valued_const_with_data, result, connect + + +class GatherTreeNormalizerTests(unittest.TestCase): + def test_gather_tree_normalizer(self): + nodes = { + **regular_op_with_shaped_data('data_0', [100, 1, 10], {'type': 'Parameter'}), + **regular_op_with_shaped_data('data_1', [100, 1, 10], {'type': 'Parameter'}), + **regular_op_with_shaped_data('data_2', [1], {'type': 'Parameter'}), + **regular_op_with_shaped_data('gather_tree', [1], {'type': 'GatherTree'}), + **valued_const_with_data('const', np.array([2])), + **result('result'), + } + edges = [*connect('data_0', '0:gather_tree'), + *connect('data_1', '1:gather_tree'), + *connect('data_2', '2:gather_tree'), + *connect('const', '3:gather_tree'), + *connect('gather_tree', 'result'), + ] + ref_edges = [*connect('data_0', '0:gather_tree'), + *connect('data_1', '1:gather_tree'), + *connect('data_2', '2:gather_tree'), + *connect('const', '0:squeeze'), + *connect('squeeze_axis', '1:squeeze'), + *connect('squeeze', '3:gather_tree'), + *connect('gather_tree', 'result'),] + ref_nodes = nodes.copy() + ref_nodes.update({**valued_const_with_data('squeeze_axis', int64_array([0])), + **regular_op_with_shaped_data('squeeze', [], {'type': 'Squeeze'})}) + graph = build_graph(nodes, edges) + GatherTreeNormalizer().find_and_replace_pattern(graph) + # run shape inference to make sure that shape overriding happened + shape_inference(graph) + + ref_graph = build_graph(ref_nodes, ref_edges) + + (flag, resp) = compare_graphs(graph, ref_graph, 'result') + self.assertTrue(flag, resp) diff --git a/model-optimizer/unit_tests/extensions/back/compress_quantized_weights_test.py b/model-optimizer/unit_tests/extensions/back/compress_quantized_weights_test.py index 45d977beb55..2fd5eaa1c0a 100644 --- a/model-optimizer/unit_tests/extensions/back/compress_quantized_weights_test.py +++ b/model-optimizer/unit_tests/extensions/back/compress_quantized_weights_test.py @@ -259,10 +259,10 @@ class ZeroPointOptimizerTestClass(unittest.TestCase): nodes = lambda w, zp: { **valued_const_with_data('weights', np.array(w, dtype=np.int8)), **regular_op_with_shaped_data( - 'cast', len(w), {'type': 'Convert', 'op': 'Cast', 'infer': Cast.infer, 'dst_type': np.float32}), + 'cast', [len(w)], {'type': 'Convert', 'op': 'Cast', 'infer': Cast.infer, 'dst_type': np.float32}), **valued_const_with_data('zp', np.array(zp, dtype=np.float32)), **regular_op_with_shaped_data( - 'sub', len(w), + 'sub', [len(w)], {'type': 'Subtract', 'op': 'Sub', 'infer': lambda node: eltwise_infer(node, Sub.operation)}), **result() } @@ -293,10 +293,10 @@ class ZeroPointOptimizerTestClass(unittest.TestCase): nodes = lambda w, zp: { **valued_const_with_data('weights', np.array(w, dtype=np.int8)), **regular_op_with_shaped_data( - 'cast', len(w), {'type': 'Convert', 'op': 'Cast', 'infer': Cast.infer, 'dst_type': np.float32}), + 'cast', [len(w)], {'type': 'Convert', 'op': 'Cast', 'infer': Cast.infer, 'dst_type': np.float32}), **valued_const_with_data('zp', np.array(zp, dtype=np.float32)), **regular_op_with_shaped_data( - 'sub', len(w), + 'sub', [len(w)], {'type': 'Subtract', 'op': 'Sub', 'infer': lambda node: eltwise_infer(node, Sub.operation)}), **result() } diff --git a/model-optimizer/unit_tests/extensions/front/caffe/accum_ext_test.py b/model-optimizer/unit_tests/extensions/front/caffe/accum_ext_test.py deleted file mode 100644 index 603a1449f07..00000000000 --- a/model-optimizer/unit_tests/extensions/front/caffe/accum_ext_test.py +++ /dev/null @@ -1,55 +0,0 @@ -# Copyright (C) 2018-2021 Intel Corporation -# SPDX-License-Identifier: Apache-2.0 - -import unittest -from unittest.mock import patch - -from extensions.front.caffe.accum_ext import AccumFrontExtractor -from extensions.ops.accum import AccumOp -from mo.ops.op import Op -from unit_tests.utils.extractors import FakeMultiParam -from unit_tests.utils.graph import FakeNode - - -class FakeAccumProtoLayer: - def __init__(self, val): - self.accum_param = val - - -class TestAccumExt(unittest.TestCase): - @classmethod - def setUpClass(cls): - Op.registered_ops['Accum'] = AccumOp - - def test_accum_no_pb_no_ml(self): - self.assertRaises(AttributeError, AccumFrontExtractor.extract, None) - - @patch('extensions.front.caffe.accum_ext.collect_attributes') - def test_accum_ext(self, collect_attributes_mock): - params = { - 'top_height': 200, - 'top_width': 300, - 'size_divisible_by': 3, - 'have_reference': 'False', - } - collect_attributes_mock.return_value = { - **params, - 'have_reference': 0 - } - - fake_pl = FakeAccumProtoLayer(FakeMultiParam(params)) - fake_node = FakeNode(fake_pl, None) - - AccumFrontExtractor.extract(fake_node) - - exp_res = { - 'type': "Accum", - 'top_height': 200, - 'top_width': 300, - 'size_divisible_by': 3, - 'have_reference': 0, - 'infer': AccumOp.accum_infer - } - - for key in exp_res.keys(): - self.assertEqual(fake_node[key], exp_res[key]) diff --git a/model-optimizer/unit_tests/extensions/front/caffe/correlation_ext_test.py b/model-optimizer/unit_tests/extensions/front/caffe/correlation_ext_test.py deleted file mode 100644 index 577d9ba084a..00000000000 --- a/model-optimizer/unit_tests/extensions/front/caffe/correlation_ext_test.py +++ /dev/null @@ -1,64 +0,0 @@ -# Copyright (C) 2018-2021 Intel Corporation -# SPDX-License-Identifier: Apache-2.0 - -import unittest -from unittest.mock import patch - -from extensions.front.caffe.correlation_ext import CorrelationFrontExtractor -from extensions.ops.correlation import CorrelationOp -from mo.ops.op import Op -from unit_tests.utils.extractors import FakeMultiParam -from unit_tests.utils.graph import FakeNode - - -class FakeCorrProtoLayer: - def __init__(self, val): - self.correlation_param = val - - -class TestCorrelationExt(unittest.TestCase): - @classmethod - def setUpClass(cls): - Op.registered_ops['Correlation'] = CorrelationOp - - def test_da_no_pb_no_ml(self): - self.assertRaises(AttributeError, CorrelationFrontExtractor.extract, None) - - @patch('extensions.front.caffe.correlation_ext.merge_attrs') - def test_resample_ext_ideal_numbers(self, merge_attrs_mock): - params = { - 'pad': 20, - 'kernel_size': 1, - 'max_displacement': 20, - 'stride_1': 1, - 'stride_2': 2, - 'single_direction': 0, - 'do_abs': False, - 'correlation_type': 'caffe.CorrelationParameter.MULTIPLY' - } - merge_attrs_mock.return_value = { - **params, - 'test': 54, - 'test2': 'test3' - } - - fake_pl = FakeCorrProtoLayer(FakeMultiParam(params)) - fake_node = FakeNode(fake_pl, None) - - CorrelationFrontExtractor.extract(fake_node) - - exp_res = { - 'type': "Correlation", - 'pad': 20, - 'kernel_size': 1, - 'max_displacement': 20, - 'stride_1': 1, - 'stride_2': 2, - 'single_direction': 0, - 'do_abs': False, - 'correlation_type': 'caffe.CorrelationParameter.MULTIPLY', - 'infer': CorrelationOp.corr_infer - } - - for key in exp_res.keys(): - self.assertEqual(fake_node[key], exp_res[key]) diff --git a/model-optimizer/unit_tests/extensions/front/caffe/crop_ext_test.py b/model-optimizer/unit_tests/extensions/front/caffe/crop_ext_test.py index cc9407ab212..e1aead2f3cd 100644 --- a/model-optimizer/unit_tests/extensions/front/caffe/crop_ext_test.py +++ b/model-optimizer/unit_tests/extensions/front/caffe/crop_ext_test.py @@ -42,7 +42,7 @@ class TestCropExt(unittest.TestCase): CropFrontExtractor.extract(fake_node) exp_res = { - 'type': 'Crop', + 'op': 'Crop', 'axis': 0, 'offset': 0, 'dim': None, # set in infer diff --git a/model-optimizer/unit_tests/extensions/front/caffe/data_augmentation_ext_test.py b/model-optimizer/unit_tests/extensions/front/caffe/data_augmentation_ext_test.py deleted file mode 100644 index 0bbbf2cdb53..00000000000 --- a/model-optimizer/unit_tests/extensions/front/caffe/data_augmentation_ext_test.py +++ /dev/null @@ -1,81 +0,0 @@ -# Copyright (C) 2018-2021 Intel Corporation -# SPDX-License-Identifier: Apache-2.0 - -import unittest -from unittest.mock import patch - -import numpy as np - -from extensions.front.caffe.data_augmentation_ext import DataAugmentationFrontExtractor -from extensions.ops.data_augmentation import DataAugmentationOp -from mo.ops.op import Op -from unit_tests.utils.extractors import FakeMultiParam -from unit_tests.utils.graph import FakeNode - - -class FakeDAProtoLayer: - def __init__(self, val): - self.augmentation_param = val - - -class TestDA(unittest.TestCase): - @classmethod - def setUpClass(cls): - Op.registered_ops['DataAugmentation'] = DataAugmentationOp - - def test_da_no_pb_no_ml(self): - self.assertRaises(AttributeError, DataAugmentationFrontExtractor.extract, None) - - @patch('extensions.front.caffe.data_augmentation_ext.merge_attrs') - def test_da_ext_ideal_numbers(self, merge_attrs_mock): - params = { - 'crop_width': 0, - 'crop_height': 0, - 'write_augmented': "", - 'max_multiplier': 255.0, - 'augment_during_test': True, - 'recompute_mean': 0, - 'write_mean': "", - 'mean_per_pixel': False, - 'mean': 0, - 'mode': "add", - 'bottomwidth': 0, - 'bottomheight': 0, - 'num': 0, - 'chromatic_eigvec': [0.0] - - } - merge_attrs_mock.return_value = { - **params, - 'test': 54, - 'test2': 'test3' - } - fake_pl = FakeDAProtoLayer(FakeMultiParam(params)) - fake_node = FakeNode(fake_pl, None) - - DataAugmentationFrontExtractor.extract(fake_node) - exp_res = { - 'type': 'DataAugmentation', - 'op': 'DataAugmentation', - 'crop_width': 0, - 'crop_height': 0, - 'write_augmented': "", - 'max_multiplier': 255.0, - 'augment_during_test': 1, - 'recompute_mean': 0, - 'write_mean': "", - 'mean_per_pixel': 0, - 'mean': 0, - 'mode': "add", - 'bottomwidth': 0, - 'bottomheight': 0, - 'num': 0, - 'chromatic_eigvec': [0.0], - 'infer': DataAugmentationOp.data_augmentation_infer - } - - for key in exp_res.keys(): - if key in ('chromatic_eigvec',): - np.testing.assert_equal(exp_res[key], fake_node[key]) - else: - self.assertEqual(exp_res[key], fake_node[key]) diff --git a/model-optimizer/unit_tests/extensions/front/caffe/power_file_ext_test.py b/model-optimizer/unit_tests/extensions/front/caffe/power_file_ext_test.py deleted file mode 100644 index 1aebaebc020..00000000000 --- a/model-optimizer/unit_tests/extensions/front/caffe/power_file_ext_test.py +++ /dev/null @@ -1,51 +0,0 @@ -# Copyright (C) 2018-2021 Intel Corporation -# SPDX-License-Identifier: Apache-2.0 - -import unittest -from unittest.mock import patch - -from extensions.front.caffe.power_file_ext import PowerFileFrontExtractor -from extensions.ops.power_file import PowerFileOp -from mo.front.common.partial_infer.elemental import copy_shape_infer -from mo.ops.op import Op -from unit_tests.utils.extractors import FakeMultiParam -from unit_tests.utils.graph import FakeNode - - -class FakePowerFileProtoLayer: - def __init__(self, val): - self.power_file_param = val - - -class TestPowerFileExt(unittest.TestCase): - @classmethod - def setUpClass(cls): - Op.registered_ops['PowerFile'] = PowerFileOp - - def test_power_file_no_pb_no_ml(self): - self.assertRaises(AttributeError, PowerFileFrontExtractor.extract, None) - - @patch('extensions.front.caffe.power_file_ext.collect_attributes') - def test_mvn_ext_ideal_numbers(self, collect_attributes_mock): - params = { - 'normalize_variance': 'True', - 'across_channels': 'False', - 'eps': 1e-9 - } - collect_attributes_mock.return_value = { - 'shift_file': 'some_file_path' - } - - fake_pl = FakePowerFileProtoLayer(FakeMultiParam(params)) - fake_node = FakeNode(fake_pl, None) - - PowerFileFrontExtractor.extract(fake_node) - - exp_res = { - 'type': "PowerFile", - 'shift_file': 'some_file_path', - 'infer': copy_shape_infer - } - - for key in exp_res.keys(): - self.assertEqual(fake_node[key], exp_res[key]) diff --git a/model-optimizer/unit_tests/extensions/front/caffe/simplernms_ext_test.py b/model-optimizer/unit_tests/extensions/front/caffe/simplernms_ext_test.py deleted file mode 100644 index e716ee5fa7e..00000000000 --- a/model-optimizer/unit_tests/extensions/front/caffe/simplernms_ext_test.py +++ /dev/null @@ -1,61 +0,0 @@ -# Copyright (C) 2018-2021 Intel Corporation -# SPDX-License-Identifier: Apache-2.0 - -import unittest -from unittest.mock import patch - -from extensions.front.caffe.simplernms_ext import SimplerNMSFrontExtractor -from extensions.ops.simplernms import SimplerNMSOp -from mo.ops.op import Op -from unit_tests.utils.extractors import FakeMultiParam -from unit_tests.utils.graph import FakeNode - - -class FakeSimplerNMSProtoLayer: - def __init__(self, val): - self.simpler_nms_param = val - - -class TestSimplerNMSExt(unittest.TestCase): - @classmethod - def setUpClass(cls): - Op.registered_ops['SimplerNMS'] = SimplerNMSOp - - def test_simplernms_no_pb_no_ml(self): - self.assertRaises(AttributeError, SimplerNMSFrontExtractor.extract, None) - - @patch('extensions.front.caffe.simplernms_ext.merge_attrs') - def test_simplernms_ext_ideal_numbers(self, merge_attrs_mock): - params = { - 'cls_threshold': 0.5, - 'max_num_proposals': 300, - 'iou_threshold': 0.7, - 'min_bbox_size': 16, - 'feat_stride': 16, - 'pre_nms_topn': 6000, - 'post_nms_topn': 150, - 'scale': [1, 2, 3] - } - merge_attrs_mock.return_value = { - **params - } - - fake_pl = FakeSimplerNMSProtoLayer(FakeMultiParam(params)) - fake_node = FakeNode(fake_pl, None) - - SimplerNMSFrontExtractor.extract(fake_node) - - exp_res = { - 'cls_threshold': 0.5, - 'max_num_proposals': 300, - 'iou_threshold': 0.7, - 'min_bbox_size': 16, - 'feat_stride': 16, - 'pre_nms_topn': 6000, - 'post_nms_topn': 150, - 'scale': [1, 2, 3], - 'infer': SimplerNMSOp.simplernms_infer - } - - for key in exp_res.keys(): - self.assertEqual(fake_node[key], exp_res[key]) diff --git a/model-optimizer/unit_tests/extensions/front/caffe/spatial_transformer_ext_test.py b/model-optimizer/unit_tests/extensions/front/caffe/spatial_transformer_ext_test.py deleted file mode 100644 index 4e90bb317d6..00000000000 --- a/model-optimizer/unit_tests/extensions/front/caffe/spatial_transformer_ext_test.py +++ /dev/null @@ -1,68 +0,0 @@ -# Copyright (C) 2018-2021 Intel Corporation -# SPDX-License-Identifier: Apache-2.0 - -import unittest -from unittest.mock import patch - -from extensions.front.caffe.spatial_transformer_ext import SpatialTransformFrontExtractor -from extensions.ops.spatial_transformer import SpatialTransformOp -from mo.ops.op import Op -from unit_tests.utils.extractors import FakeMultiParam -from unit_tests.utils.graph import FakeNode - - -class FakeSpatialTransformProtoLayer: - def __init__(self, val): - self.st_param = val - - -class TestSpatialTransformExt(unittest.TestCase): - @classmethod - def setUpClass(cls): - Op.registered_ops['SpatialTransformer'] = SpatialTransformOp - - def test_st_no_pb_no_ml(self): - self.assertRaises(AttributeError, SpatialTransformFrontExtractor.extract, None) - - @patch('extensions.front.caffe.spatial_transformer_ext.merge_attrs') - def test_st_ext_ideal_numbers(self, merge_attrs_mock): - params = { - 'transform_type': "ffff", - 'sampler_type': "gggg", - 'output_H': 56, - 'output_W': 78, - 'to_compute_dU': True, - 'theta_1_1': 0.1, - 'theta_1_2': 0.2, - 'theta_1_3': 0.3, - 'theta_2_1': 0.4, - 'theta_2_2': 0.5, - 'theta_2_3': 0.6 - } - merge_attrs_mock.return_value = { - **params - } - - fake_pl = FakeSpatialTransformProtoLayer(FakeMultiParam(params)) - fake_node = FakeNode(fake_pl, None) - - SpatialTransformFrontExtractor.extract(fake_node) - - exp_res = { - 'type': "SpatialTransformer", - 'transform_type': "ffff", - 'sampler_type': "gggg", - 'output_H': 56, - 'output_W': 78, - 'to_compute_dU': 1, - 'theta_1_1': 0.1, - 'theta_1_2': 0.2, - 'theta_1_3': 0.3, - 'theta_2_1': 0.4, - 'theta_2_2': 0.5, - 'theta_2_3': 0.6, - 'infer': SpatialTransformOp.sp_infer - } - - for key in exp_res.keys(): - self.assertEqual(fake_node[key], exp_res[key]) diff --git a/model-optimizer/unit_tests/extensions/front/mxnet/crop_ext_test.py b/model-optimizer/unit_tests/extensions/front/mxnet/crop_ext_test.py deleted file mode 100644 index 725120444ff..00000000000 --- a/model-optimizer/unit_tests/extensions/front/mxnet/crop_ext_test.py +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright (C) 2018-2021 Intel Corporation -# SPDX-License-Identifier: Apache-2.0 - -import unittest - -from extensions.front.mxnet.crop_ext import CropFrontExtractor -from mo.ops.crop import Crop -from unit_tests.utils.extractors import PB - - -class TestCropExt(unittest.TestCase): - def test_crop_ext(self): - params = { - 'attrs': { - 'offset': '(5, 5)', - 'num_args': 2 - } - } - node = PB({'symbol_dict': params}) - CropFrontExtractor.extract(node) - - exp_res = { - 'axis': 2, - 'offset': [5, 5], - 'dim': None, - 'infer': Crop.infer, - 'type': 'Crop' - } - for key in exp_res.keys(): - self.assertEqual(node[key], exp_res[key]) diff --git a/model-optimizer/unit_tests/extensions/middle/ConvertGroupedStridedSlice_test.py b/model-optimizer/unit_tests/extensions/middle/ConvertGroupedStridedSlice_test.py index 71a957aff18..d3b6453c43a 100644 --- a/model-optimizer/unit_tests/extensions/middle/ConvertGroupedStridedSlice_test.py +++ b/model-optimizer/unit_tests/extensions/middle/ConvertGroupedStridedSlice_test.py @@ -7,7 +7,7 @@ import numpy as np from generator import generator, generate from extensions.middle.ConvertGroupedStridedSlice import ConvertGroupedStridedSlice -from mo.front.common.partial_infer.utils import int64_array +from mo.front.common.partial_infer.utils import int64_array, shape_array, dynamic_dimension_value from mo.graph.graph import Node from mo.utils.ir_engine.compare_graphs import compare_graphs from unit_tests.utils.graph import build_graph @@ -765,6 +765,47 @@ class ConvertGroupedStridedSliceTests(unittest.TestCase): (flag, resp) = compare_graphs(graph, graph_ref, 'concat_1_data', check_op_attrs=True) self.assertTrue(flag, resp) + # dynamic slice + def test_11(self): + graph = build_graph(nodes_attributes, + [('placeholder_1', 'placeholder_1_data'), + ('placeholder_1_data', 'sslice_1'), + ('sslice_1', 'sslice_1_data'), + ('placeholder_1_data', 'sslice_2'), + ('sslice_2', 'sslice_2_data'), + ('placeholder_1_data', 'sslice_3'), + ('sslice_3', 'sslice_3_data'), + ('sslice_1_data', 'concat_1'), + ('sslice_2_data', 'concat_1'), + ('sslice_3_data', 'concat_1'), + ('concat_1', 'concat_1_data'), + ('concat_1_data', 'op_output') + ], + {'placeholder_1_data': {'shape': np.array([1, 227, 227, 54])}, + + 'sslice_1': {'slices': np.array( + [slice(0, 1, 1), slice(0, 227, 1), slice(0, 227, 1), slice(19, 39, 1)])}, + 'sslice_1_data': {'shape': np.array([1, 227, 227, 20])}, + + 'sslice_2': {'slices': np.array( + [slice(0, 1, 1), slice(0, 227, 1), slice(0, 227, 1), slice(37, 54, 1)])}, + 'sslice_2_data': {'shape': np.array([1, 227, 227, 17])}, + + 'sslice_3': {'slices': [slice(0, 1, 1), slice(0, 227, 1), 12, slice(0, 19, 1)]}, + 'sslice_3_data': {'shape': shape_array([1, 227, dynamic_dimension_value, 19])}, + + 'concat_1_data': {'shape': shape_array([1, 227, dynamic_dimension_value, 54])}, + }) + graph.graph['layout'] = 'NHWC' + + graph_ref = graph.copy() + + pattern = ConvertGroupedStridedSlice() + pattern.find_and_replace_pattern(graph) + + (flag, resp) = compare_graphs(graph, graph_ref, 'concat_1_data', check_op_attrs=True) + self.assertTrue(flag, resp) + class AddReshapeAfterStridedSliceTests(unittest.TestCase): def test_ss_1_shrink_last(self): diff --git a/model-optimizer/unit_tests/extensions/middle/SequenceLenthToMask_test.py b/model-optimizer/unit_tests/extensions/middle/SequenceLenthToMask_test.py deleted file mode 100644 index 33ddeae4a12..00000000000 --- a/model-optimizer/unit_tests/extensions/middle/SequenceLenthToMask_test.py +++ /dev/null @@ -1,54 +0,0 @@ -# Copyright (C) 2018-2021 Intel Corporation -# SPDX-License-Identifier: Apache-2.0 - -import unittest - -import numpy as np - -from extensions.middle.SequenceLengthToMask import SequenceLengthToMask -from mo.front.common.partial_infer.utils import int64_array -from mo.utils.ir_engine.compare_graphs import compare_graphs -from unit_tests.utils.graph import build_graph - - -nodes_attributes = {'logits': {'shape': int64_array([5, 3, 30]), 'type': 'Parameter', 'kind': 'op', - 'op': 'Parameter'}, - 'logits_data': {'value': None, 'shape': int64_array([5, 3, 30]), 'kind': 'data'}, - 'seq_length': {'type': 'Const', 'kind': 'op', 'op': 'Const', 'value': int64_array([5, 2, 3])}, - 'seq_length_data': {'value': int64_array([5, 2, 3]), 'kind': 'data'}, - 'ctc_greedy_decoder': {'type': None, 'kind': 'op', 'op': 'CTCGreedyDecoder', - 'use_mask_format': True}, - 'ctc_greedy_decoder_data': {'value': None, 'shape': None, 'kind': 'data'}, - 'last': {'kind': 'op', 'op': 'Result'}, - - # new nodes - 'seq_mask': {'type': 'Const', 'kind': 'op', 'op': 'Const', - 'value': np.transpose(np.array([[1, 1, 1, 1, 1], - [1, 1, 0, 0, 0], - [1, 1, 1, 0, 0]], dtype=np.float))}, - 'seq_mask_data': {'value': None, 'kind': 'data'}, - 'new_ctc_greedy_decoder': {'type': None, 'kind': 'op', 'op': 'CTCGreedyDecoder'}, - } - -class ScaleInputTests(unittest.TestCase): - def test1(self): - graph = build_graph(nodes_attributes, - [('logits', 'logits_data'), - ('logits_data', 'ctc_greedy_decoder'), - ('seq_length', 'seq_length_data'), - ('seq_length_data', 'ctc_greedy_decoder'), - ('ctc_greedy_decoder', 'ctc_greedy_decoder_data'), - ('ctc_greedy_decoder_data', 'last')], - nodes_with_edges_only=True) - - graph_ref = build_graph(nodes_attributes, - [('logits', 'logits_data'), - ('logits_data', 'new_ctc_greedy_decoder'), - ('seq_mask', 'seq_mask_data'), - ('seq_mask_data', 'new_ctc_greedy_decoder'), - ('new_ctc_greedy_decoder', 'ctc_greedy_decoder_data'), - ('ctc_greedy_decoder_data', 'last')], - nodes_with_edges_only=True) - SequenceLengthToMask().find_and_replace_pattern(graph) - (flag, resp) = compare_graphs(graph, graph_ref, 'last') - self.assertTrue(flag, resp) diff --git a/model-optimizer/unit_tests/extensions/middle/quantize_fuses_test.py b/model-optimizer/unit_tests/extensions/middle/quantize_fuses_test.py index 3605cba6fa2..e7dff937f14 100644 --- a/model-optimizer/unit_tests/extensions/middle/quantize_fuses_test.py +++ b/model-optimizer/unit_tests/extensions/middle/quantize_fuses_test.py @@ -30,15 +30,15 @@ nodes = { 'mul_val_d': {'kind': 'data', 'shape': np.array([1]), 'value': np.array([5])}, 'mul': {'kind': 'op', 'op': 'Mul', 'infer': lambda node: eltwise_infer(node, lambda a, b: a * b)}, - 'mul_d': {'kind': 'data', 'shape': np.array([1, 3, 224, 224])}, + 'mul_d': {'kind': 'data', 'shape': np.array([1, 3, 224, 224]), 'value': None}, 'mul_1': {'kind': 'op', 'op': 'Mul', 'infer': lambda node: eltwise_infer(node, lambda a, b: a * b)}, - 'mul_1_d': {'kind': 'data', 'shape': np.array([1, 3, 224, 224])}, + 'mul_1_d': {'kind': 'data', 'shape': np.array([1, 3, 224, 224]), 'value': None}, 'mul_2': {'kind': 'op', 'op': 'Mul', 'infer': lambda node: eltwise_infer(node, lambda a, b: a * b)}, - 'mul_2_d': {'kind': 'data', 'shape': np.array([1, 3, 224, 224])}, + 'mul_2_d': {'kind': 'data', 'shape': np.array([1, 3, 224, 224]), 'value': None}, 'mul_3': {'kind': 'op', 'op': 'Mul', 'infer': lambda node: eltwise_infer(node, lambda a, b: a * b)}, - 'mul_3_d': {'kind': 'data', 'shape': np.array([1, 3, 224, 224])}, + 'mul_3_d': {'kind': 'data', 'shape': np.array([1, 3, 224, 224]), 'value': None}, 'mul_4': {'kind': 'op', 'op': 'Mul', 'infer': lambda node: eltwise_infer(node, lambda a, b: a * b)}, - 'mul_4_d': {'kind': 'data', 'shape': np.array([1, 3, 224, 224])}, + 'mul_4_d': {'kind': 'data', 'shape': np.array([1, 3, 224, 224]), 'value': None}, 'output': {'kind': 'op', 'op': 'Result'}, } diff --git a/model-optimizer/unit_tests/extensions/ops/If_test.py b/model-optimizer/unit_tests/extensions/ops/If_test.py index 5e757f5c9c1..82bca34da05 100644 --- a/model-optimizer/unit_tests/extensions/ops/If_test.py +++ b/model-optimizer/unit_tests/extensions/ops/If_test.py @@ -1,29 +1,35 @@ # Copyright (C) 2018-2021 Intel Corporation # SPDX-License-Identifier: Apache-2.0 -import numpy as np -import numpy.testing as npt import unittest +import numpy as np +import numpy.testing as npt +from generator import generate, generator + from extensions.ops.If import If -from mo.ops.shape import Shape from extensions.ops.elementwise import Add, Mul from extensions.ops.identity import Identity from extensions.ops.parameter import Parameter -from mo.front.common.partial_infer.concat import concat_infer -from mo.front.common.partial_infer.utils import int64_array -from mo.graph.graph import Node, Graph +from mo.front.common.partial_infer.utils import int64_array, shape_array, strict_compare_tensors, \ + dynamic_dimension_value +from mo.graph.graph import Node from mo.middle.passes.infer import partial_infer -from mo.ops.concat import Concat from mo.ops.eltwise import eltwise_infer -from mo.ops.result import Result +from mo.ops.shape import Shape from unit_tests.utils.graph import build_graph_with_edge_attrs, build_graph -from unit_tests.utils.graph import regular_op_with_empty_data, connect, const, result, valued_const_with_data, \ - regular_op, empty_data +from unit_tests.utils.graph import regular_op_with_empty_data, connect, result, valued_const_with_data, regular_op, \ + empty_data +@generator class TestIf(unittest.TestCase): - def test_simple_shape_inf(self): + @generate(*[ + (np.array([True], dtype=np.bool), shape_array([3]), shape_array([3])), + (np.array([False], dtype=np.bool), shape_array([3]), shape_array([2])), + (shape_array(dynamic_dimension_value), shape_array([3]), shape_array([dynamic_dimension_value])), + ]) + def test_simple_shape_inf(self, cond, output_port_0_shape, output_port_1_shape): then_graph_nodes = {**regular_op_with_empty_data('param_1', {'type': 'Parameter', 'kind': 'op', 'input_id': 1, 'shape': None, 'infer': Parameter.infer}), **regular_op_with_empty_data('param_2', {'type': 'Parameter', 'kind': 'op', 'input_id': 2, @@ -65,7 +71,7 @@ class TestIf(unittest.TestCase): then_graph = build_graph_with_edge_attrs(then_graph_nodes, then_graph_edges) else_graph = build_graph_with_edge_attrs(else_graph_nodes, else_graph_edges) external_graph_nodes = { - **valued_const_with_data('cond', np.array([True], dtype=np.bool)), + **valued_const_with_data('cond', cond), **valued_const_with_data('input_2', int64_array([3, 2, 1])), **valued_const_with_data('input_1', int64_array([1, 2, 3])), **valued_const_with_data('input_3', int64_array([8, 4])), @@ -87,10 +93,10 @@ class TestIf(unittest.TestCase): graph = build_graph(external_graph_nodes, external_graph_edges) graph.stage = 'middle' partial_infer(graph) - res_1 = Node(graph, 'res_1') - res_2 = Node(graph, 'res_2') - npt.assert_array_equal(res_1.in_port(0).data.get_shape(), int64_array([3])) - npt.assert_array_equal(res_2.in_port(0).data.get_shape(), int64_array([3])) + if_node = Node(graph, 'if') + self.assertTrue(strict_compare_tensors(if_node.out_port(0).data.get_shape(), output_port_0_shape)) + # shape of the "then" branch is [3] and shape of the "else" branch is [2], so the output shape is "[dynamic]" + self.assertTrue(strict_compare_tensors(if_node.out_port(1).data.get_shape(), output_port_1_shape)) def test_fake_results(self): then_graph_nodes = {**valued_const_with_data('fake_const', int64_array(0)), @@ -111,8 +117,8 @@ class TestIf(unittest.TestCase): then_graph = build_graph_with_edge_attrs(then_graph_nodes, then_graph_edges) else_graph = build_graph_with_edge_attrs(else_graph_nodes, else_graph_edges) external_graph_nodes = { - **valued_const_with_data('cond', np.array([True], dtype=np.bool)), - **valued_const_with_data('input_1', int64_array([[1, 2, 3], [3, 2, 3]])), + **valued_const_with_data('cond', shape_array([dynamic_dimension_value])), + **valued_const_with_data('input_1', int64_array([1, 2, 3, 3, 2, 3]).reshape((2, 3))), **regular_op_with_empty_data('if', {'kind': 'op', 'op': 'If', 'then_graph': then_graph, 'else_graph': else_graph, 'infer': If.infer}), **result('res_1')} @@ -123,5 +129,4 @@ class TestIf(unittest.TestCase): graph = build_graph(external_graph_nodes, external_graph_edges) graph.stage = 'middle' partial_infer(graph) - res_1 = Node(graph, 'res_1') - npt.assert_array_equal(res_1.in_port(0).data.get_shape(), int64_array([2,3])) + npt.assert_array_equal(Node(graph, 'if').out_port(0).data.get_shape(), int64_array([2, 3])) diff --git a/model-optimizer/unit_tests/extensions/ops/MatMul_test.py b/model-optimizer/unit_tests/extensions/ops/MatMul_test.py index 1706880eaf1..4612e388153 100644 --- a/model-optimizer/unit_tests/extensions/ops/MatMul_test.py +++ b/model-optimizer/unit_tests/extensions/ops/MatMul_test.py @@ -7,7 +7,7 @@ import numpy as np from generator import generator, generate from extensions.ops.MatMul import MatMul -from mo.front.common.partial_infer.utils import int64_array +from mo.front.common.partial_infer.utils import int64_array, shape_array, dynamic_dimension_value from mo.graph.graph import Node from unit_tests.utils.graph import build_graph_with_attrs @@ -34,25 +34,29 @@ class TestMatMul(unittest.TestCase): @generate(*[ ([1024], [1024, 1000], [1000], False, False), + ([dynamic_dimension_value], [1024, 1000], [1000], False, False), + ([1024], [dynamic_dimension_value, 1000], [1000], False, False), ([1024], [1024, 1000], [1000], True, False), ([1024], [1000, 1024], [1000], True, True), + ([dynamic_dimension_value], [dynamic_dimension_value, dynamic_dimension_value], [dynamic_dimension_value], True, + True), ([1, 1024], [1024, 1000], [1, 1000], False, False), ([1, 1024], [1000, 1024], [1, 1000], False, True), ([1024, 1000], [1000], [1024], False, False), ([1024, 1000], [1000], [1024], False, True), ([1000, 1024], [1000], [1024], True, True), + ([1000, dynamic_dimension_value], [1000], [dynamic_dimension_value], True, True), ([10, 1024], [1024, 1000], [10, 1000], False, False), ([5, 10, 1024], [1024, 1000], [5, 10, 1000], False, False), ([5, 10, 1024], [5, 1024, 1000], [5, 10, 1000], False, False), ([5, 10, 1024], [1, 1024, 1000], [5, 10, 1000], False, False), ([5, 10, 1024], [1, 1000, 1024], [5, 10, 1000], False, True), - ]) def test_positive_matmul_infer(self, A_shape, B_shape, C_shape, transpose_a, transpose_b): graph = build_graph_with_attrs(nodes_with_attrs=self.nodes, edges_with_attrs=self.edges, update_nodes_attributes=[ - ('A_d', {'shape': int64_array(A_shape)}), - ('B_d', {'shape': int64_array(B_shape)}), + ('A_d', {'shape': shape_array(A_shape)}), + ('B_d', {'shape': shape_array(B_shape)}), ('mat_mul', {'transpose_a': transpose_a, 'transpose_b': transpose_b}), ]) node = Node(graph, 'mat_mul') @@ -61,7 +65,7 @@ class TestMatMul(unittest.TestCase): msg = "MatMul infer failed for case: A_shape={}, B_shape={}, transpose_a={}, transpose_b={} " \ "expected_shape={}, actual_shape={}" - self.assertTrue(np.array_equal(graph.node['mat_mul_d']['shape'], int64_array(C_shape)), + self.assertTrue(np.array_equal(graph.node['mat_mul_d']['shape'], shape_array(C_shape)), msg.format(A_shape, B_shape, transpose_a, transpose_b, C_shape, graph.node['mat_mul_d']['shape'])) diff --git a/model-optimizer/unit_tests/extensions/ops/ReduceOps_test.py b/model-optimizer/unit_tests/extensions/ops/ReduceOps_test.py index 507b2cd584f..0f52d355820 100644 --- a/model-optimizer/unit_tests/extensions/ops/ReduceOps_test.py +++ b/model-optimizer/unit_tests/extensions/ops/ReduceOps_test.py @@ -7,7 +7,7 @@ import numpy as np from generator import generate, generator from extensions.ops.ReduceOps import reduce_infer -from mo.front.common.partial_infer.utils import int64_array +from mo.front.common.partial_infer.utils import int64_array, strict_compare_tensors, is_fully_defined from mo.graph.graph import Node from unit_tests.utils.graph import build_graph, regular_op_with_shaped_data, result, connect, valued_const_with_data @@ -54,3 +54,36 @@ class ReduceLpTest(unittest.TestCase): reduce_node.op = reduce_node.type = 'ReduceL' + str(p) reduce_infer(reduce_node) self.assertTrue(np.array_equal(reduce_node.out_port(0).data.get_value(), reduced)) + + @generate(*[ + ([3, 2, 2], [0], True, 1), + ([3, 2, 2], [2], False, 2), + ([3, 2, 2], [0, 2], False, 2), + ]) + def test_reduce_dynamic(self, shape, axes, keepdims, p): + false_mask = np.zeros(shape) + false_mask[0][1][1] = True + data = np.ma.masked_array(np.ones(shape), mask=false_mask) + assert not is_fully_defined(data) + reduced_tensor = np.sum(data, axis=tuple(axes), keepdims=keepdims) + # create an array of all masked elements which is the expected result of the reduce of the tensor with dynamic + # values + fully_undefined = np.ma.masked_array(reduced_tensor, mask=np.ones(reduced_tensor.shape)) + axis = int64_array(axes) + p = int64_array(p) + graph = build_graph(nodes_attributes, + [*connect('data', '0:reduce_lp'), + *connect('axis', '1:reduce_lp'), + *connect('reduce_lp', '0:identity'), + ('identity', 'identity_d', {'out': 0}), + ('identity_d', 'output') + ], + {'data_d': {'value': data, 'shape': data.shape}, + 'axis_d': {'value': axis, 'shape': axis.shape}, + 'reduce_lp': {'keep_dims': keepdims}}, + nodes_with_edges_only=True) + + reduce_node = Node(graph, 'reduce_lp') + reduce_node.op = reduce_node.type = 'ReduceL' + str(p) + reduce_infer(reduce_node) + self.assertTrue(strict_compare_tensors(reduce_node.out_port(0).data.get_value(), fully_undefined)) diff --git a/model-optimizer/unit_tests/extensions/ops/accum_test.py b/model-optimizer/unit_tests/extensions/ops/accum_test.py deleted file mode 100644 index 6b573d7ec9f..00000000000 --- a/model-optimizer/unit_tests/extensions/ops/accum_test.py +++ /dev/null @@ -1,119 +0,0 @@ -# Copyright (C) 2018-2021 Intel Corporation -# SPDX-License-Identifier: Apache-2.0 - -import unittest - -import numpy as np - -from extensions.ops.accum import AccumOp -from mo.graph.graph import Node -from unit_tests.utils.graph import build_graph - -wrong_attrs_graph = {'node_1': {'type': 'Identity', 'kind': 'op'}, - 'accum': {'type': 'Accum', 'kind': 'op'}, - 'node_3': {'type': 'Identity', 'kind': 'op'}, - 'op_output': { 'kind': 'op', 'op': 'Result'} - } - -nodes_attributes = {'node_1': {'type': 'Identity', 'kind': 'op'}, - 'node_2': {'type': 'Identity', 'kind': 'op'}, - 'accum': {'type': 'Accum', 'kind': 'op'}, - 'node_3': {'type': 'Identity', 'kind': 'op'}, - 'op_output': { 'kind': 'op', 'op': 'Result'} - } - - -class TestAccumOp(unittest.TestCase): - def test_accum_infer_assertion(self): - graph = build_graph(wrong_attrs_graph, - [('node_1', 'accum'), - ('accum', 'node_3'), - ('node_3', 'op_output') - ], - {'node_3': {'shape': None}, - 'node_1': {'shape': np.array([1, 3, 227, 227])}, - 'accum': { - 'top_height': 0, - 'top_width': 0, - 'size_divisible_by': 0, - 'have_reference': 1 - } - }) - - accum_node = Node(graph, 'accum') - self.assertRaises(AssertionError, AccumOp.accum_infer, accum_node) - - def test_accum_infer_have_reference(self): - graph = build_graph(nodes_attributes, - [('node_1', 'accum'), - ('node_2', 'accum'), - ('accum', 'node_3'), - ('node_3', 'op_output') - ], - {'node_3': {'shape': None}, - 'node_1': {'shape': np.array([1, 3, 227, 227])}, - 'node_2': {'shape': np.array([1, 3, 227, 227])}, - 'accum': { - 'top_height': 0, - 'top_width': 0, - 'size_divisible_by': 0, - 'have_reference': 1 - } - }) - - accum_node = Node(graph, 'accum') - AccumOp.accum_infer(accum_node) - exp_shape = np.array([1, 6, 227, 227]) - res_shape = graph.node['node_3']['shape'] - for i in range(0, len(exp_shape)): - self.assertEqual(exp_shape[i], res_shape[i]) - - def test_accum_infer(self): - graph = build_graph(nodes_attributes, - [('node_1', 'accum'), - ('node_2', 'accum'), - ('accum', 'node_3'), - ('node_3', 'op_output') - ], - {'node_3': {'shape': None}, - 'node_1': {'shape': np.array([1, 3, 227, 227])}, - 'node_2': {'shape': np.array([1, 3, 227, 227])}, - 'accum': { - 'top_height': 0, - 'top_width': 0, - 'size_divisible_by': 0, - 'have_reference': 0 - } - }) - - accum_node = Node(graph, 'accum') - AccumOp.accum_infer(accum_node) - exp_shape = np.array([1, 6, 227, 227]) - res_shape = graph.node['node_3']['shape'] - for i in range(0, len(exp_shape)): - self.assertEqual(exp_shape[i], res_shape[i]) - - def test_accum_infer_top_height_top_width(self): - graph = build_graph(nodes_attributes, - [('node_1', 'accum'), - ('node_2', 'accum'), - ('accum', 'node_3'), - ('node_3', 'op_output') - ], - {'node_3': {'shape': None}, - 'node_1': {'shape': np.array([1, 3, 227, 227])}, - 'node_2': {'shape': np.array([1, 3, 227, 227])}, - 'accum': { - 'top_height': 229, - 'top_width': 229, - 'size_divisible_by': 0, - 'have_reference': 0 - } - }) - - accum_node = Node(graph, 'accum') - AccumOp.accum_infer(accum_node) - exp_shape = np.array([1, 6, 229, 229]) - res_shape = graph.node['node_3']['shape'] - for i in range(0, len(exp_shape)): - self.assertEqual(exp_shape[i], res_shape[i]) diff --git a/model-optimizer/unit_tests/extensions/ops/correlation_test.py b/model-optimizer/unit_tests/extensions/ops/correlation_test.py deleted file mode 100644 index d2a60da82c6..00000000000 --- a/model-optimizer/unit_tests/extensions/ops/correlation_test.py +++ /dev/null @@ -1,48 +0,0 @@ -# Copyright (C) 2018-2021 Intel Corporation -# SPDX-License-Identifier: Apache-2.0 - -import unittest - -import numpy as np - -from extensions.ops.correlation import CorrelationOp -from mo.graph.graph import Node -from unit_tests.utils.graph import build_graph - -nodes_attributes = {'node_1': {'type': 'Identity', 'kind': 'op'}, - 'node_2': {'type': 'Identity', 'kind': 'op'}, - 'corr': {'type': 'Correlation', 'kind': 'op'}, - 'node_3': {'type': 'Identity', 'kind': 'op'}, - 'op_output': {'kind': 'op', 'op': 'Result'} - } - - -class TestConcatPartialInfer(unittest.TestCase): - def test_tf_concat_infer(self): - graph = build_graph(nodes_attributes, - [ - ('node_1', 'corr'), - ('node_2', 'corr'), - ('corr', 'node_3'), - ('node_3', 'op_output') - ], - { - 'node_3': {'shape': None}, - 'node_1': {'shape': np.array([1, 3, 227, 227])}, - 'node_2': {'shape': np.array([1, 3, 227, 227])}, - 'corr': {'pad': 20, - 'kernel_size': 1, - 'max_displacement': 20, - 'stride_1': 1, - 'stride_2': 2, - 'single_direction': 0, - 'do_abs': False, - 'correlation_type': 0} - }) - - corr_node = Node(graph, 'corr') - CorrelationOp.corr_infer(corr_node) - exp_shape = np.array([1, 441, 227, 227]) - res_shape = graph.node['node_3']['shape'] - for i in range(0, len(exp_shape)): - self.assertEqual(exp_shape[i], res_shape[i]) diff --git a/model-optimizer/unit_tests/extensions/ops/data_augmentation_test.py b/model-optimizer/unit_tests/extensions/ops/data_augmentation_test.py deleted file mode 100644 index 4d2fc8250bc..00000000000 --- a/model-optimizer/unit_tests/extensions/ops/data_augmentation_test.py +++ /dev/null @@ -1,52 +0,0 @@ -# Copyright (C) 2018-2021 Intel Corporation -# SPDX-License-Identifier: Apache-2.0 - -import unittest - -import numpy as np - -from extensions.ops.data_augmentation import DataAugmentationOp -from mo.graph.graph import Node -from unit_tests.utils.graph import build_graph - -nodes_attributes = { - 'node_1': {'type': 'Identity', 'kind': 'op'}, - 'da': {'type': 'DataAugmentation', 'kind': 'op'}, - 'node_3': {'type': 'Identity', 'kind': 'op'}, - 'op_output': { 'kind': 'op', 'op': 'Result'} -} - - -class TestConcatPartialInfer(unittest.TestCase): - def test_tf_concat_infer(self): - graph = build_graph(nodes_attributes, - [ - ('node_1', 'da'), - ('da', 'node_3'), - ('node_3', 'op_output') - ], - { - 'node_3': {'shape': None}, - 'node_1': {'shape': np.array([1, 3, 227, 227])}, - 'da': {'crop_width': 225, - 'crop_height': 225, - 'write_augmented': "", - 'max_multiplier': 255.0, - 'augment_during_test': True, - 'recompute_mean': 0, - 'write_mean': "", - 'mean_per_pixel': False, - 'mean': 0, - 'mode': "add", - 'bottomwidth': 0, - 'bottomheight': 0, - 'num': 0, - 'chromatic_eigvec': [0.0]} - }) - - da_node = Node(graph, 'da') - DataAugmentationOp.data_augmentation_infer(da_node) - exp_shape = np.array([1, 3, 225, 225]) - res_shape = graph.node['node_3']['shape'] - for i in range(0, len(exp_shape)): - self.assertEqual(exp_shape[i], res_shape[i]) diff --git a/model-optimizer/unit_tests/extensions/ops/gathernd_test.py b/model-optimizer/unit_tests/extensions/ops/gathernd_test.py index 2482a5b022b..4ad84bf5271 100644 --- a/model-optimizer/unit_tests/extensions/ops/gathernd_test.py +++ b/model-optimizer/unit_tests/extensions/ops/gathernd_test.py @@ -6,7 +6,7 @@ import unittest import numpy as np from extensions.ops.gathernd import GatherND -from mo.front.common.partial_infer.utils import int64_array +from mo.front.common.partial_infer.utils import int64_array, shape_array, dynamic_dimension_value, strict_compare_tensors from mo.graph.graph import Node from unit_tests.utils.graph import build_graph @@ -106,6 +106,10 @@ output8 = int64_array([[3, 8, 6], [36, 37, 37], [41, 48, 48]]) +# test data for partial infer: gather slices and batch_dims=2 +inputs9 = {'data_data': {'shape': shape_array([dynamic_dimension_value, 40, 4, 9]), 'value': None}, + 'indices_data': {'shape': shape_array([dynamic_dimension_value, 40, 3, 5, 1]), 'value': None}} + # invalid test case with incorrect rank for indices inputs_inv1 = {'data_data': {'shape': int64_array([10, 40]), 'value': None}, 'indices_data': {'shape': int64_array([5, 3, 4]), 'value': None}} @@ -118,6 +122,7 @@ inputs_inv2 = {'data_data': {'shape': int64_array([10, 40, 20]), 'value': None}, inputs_inv3 = {'data_data': {'shape': int64_array([10, 40, 20, 10, 2]), 'value': None}, 'indices_data': {'shape': int64_array([10, 40, 4]), 'value': None}} + class TestGatherNDUpdate(unittest.TestCase): def setUp(self): nodes_attributes['gathernd_node']['batch_dims'] = 0 @@ -165,6 +170,21 @@ class TestGatherNDUpdate(unittest.TestCase): self.assertTrue(np.array_equal(ref_output_shape, res_output_shape), 'values do not match expected: {} and given: {}'.format(ref_output_shape, res_output_shape)) + def test_partial_infer_gather_slice_batch_dims2_dynamic(self): + nodes_attributes['gathernd_node']['batch_dims'] = 2 + graph = build_graph(nodes_attributes, edges, inputs9) + gathernd_node = Node(graph, 'gathernd_node') + GatherND.infer(gathernd_node) + + # prepare reference results + ref_output_shape = shape_array([dynamic_dimension_value, 3, 5, 9]) + + # get the result + res_output_shape = graph.node['output']['shape'] + + self.assertTrue(strict_compare_tensors(ref_output_shape, res_output_shape), + 'values do not match expected: {} and given: {}'.format(ref_output_shape, res_output_shape)) + def test_infer4(self): graph = build_graph(nodes_attributes, edges, inputs4) gathernd_node = Node(graph, 'gathernd_node') diff --git a/model-optimizer/unit_tests/extensions/ops/merge_test.py b/model-optimizer/unit_tests/extensions/ops/merge_test.py index 73c33a57402..ab8fba09eae 100644 --- a/model-optimizer/unit_tests/extensions/ops/merge_test.py +++ b/model-optimizer/unit_tests/extensions/ops/merge_test.py @@ -34,7 +34,7 @@ class TestMerge(unittest.TestCase): graph_ref = build_graph_with_attrs(nodes_with_attrs=self.nodes, edges_with_attrs=self.edges, update_nodes_attributes=[('merge_output', {'shape': np.array([2, 2]), - 'value': np.ones((2,2))}), + 'value': np.ones((2, 2))}), ('merge', {'is_not_fully_inferred': False})]) tested_class = Merge(graph=graph, attrs={}) diff --git a/model-optimizer/unit_tests/extensions/ops/normalize_test.py b/model-optimizer/unit_tests/extensions/ops/normalize_test.py index d4868296b3d..db503fc4115 100644 --- a/model-optimizer/unit_tests/extensions/ops/normalize_test.py +++ b/model-optimizer/unit_tests/extensions/ops/normalize_test.py @@ -24,7 +24,7 @@ class TestNormalize(unittest.TestCase): ('node_3', 'op_output') ], {'node_3': {'shape': None}, - 'node_1': {'shape': np.array([1, 3, 227, 227])}, + 'node_1': {'shape': np.array([1, 3, 227, 227]), 'value': None}, 'norm': {} }) diff --git a/model-optimizer/unit_tests/extensions/ops/regionyolo_test.py b/model-optimizer/unit_tests/extensions/ops/regionyolo_test.py index 64409535dac..9f86121c453 100644 --- a/model-optimizer/unit_tests/extensions/ops/regionyolo_test.py +++ b/model-optimizer/unit_tests/extensions/ops/regionyolo_test.py @@ -7,6 +7,7 @@ import numpy as np from extensions.ops.regionyolo import RegionYoloOp from mo.front.common.extractors.utils import layout_attrs +from mo.front.common.partial_infer.utils import shape_array, dynamic_dimension_value, strict_compare_tensors from mo.graph.graph import Node from unit_tests.utils.graph import build_graph @@ -24,7 +25,7 @@ class TestRegionYOLOCaffe(unittest.TestCase): ('region', 'node_3'), ('node_3', 'op_output') ], - {'node_3': {'shape': None}, + {'node_3': {'shape': None, 'value': None}, 'node_1': {'shape': np.array([1, 3, 227, 227])}, 'region': {'axis': 1, 'end_axis': -1, 'do_softmax': 1, **layout_attrs()} }) @@ -42,7 +43,7 @@ class TestRegionYOLOCaffe(unittest.TestCase): ('region', 'node_3'), ('node_3', 'op_output') ], - {'node_3': {'shape': None}, + {'node_3': {'shape': None, 'value': None}, 'node_1': {'shape': np.array([1, 3, 227, 227])}, 'region': {'end_axis': 1, 'axis': 0, 'do_softmax': 1, **layout_attrs()} }) @@ -54,13 +55,30 @@ class TestRegionYOLOCaffe(unittest.TestCase): for i in range(0, len(exp_shape)): self.assertEqual(exp_shape[i], res_shape[i]) + def test_region_infer_dynamic_flatten(self): + graph = build_graph(nodes_attributes, + [('node_1', 'region'), + ('region', 'node_3'), + ('node_3', 'op_output') + ], + {'node_3': {'shape': None, 'value': None}, + 'node_1': {'shape': shape_array([1, dynamic_dimension_value, 227, 227])}, + 'region': {'end_axis': 1, 'axis': 0, 'do_softmax': 1, **layout_attrs()} + }) + graph.graph['layout'] = 'NCHW' + reorg_node = Node(graph, 'region') + RegionYoloOp.regionyolo_infer(reorg_node) + exp_shape = shape_array([dynamic_dimension_value, 227, 227]) + res_shape = graph.node['node_3']['shape'] + self.assertTrue(strict_compare_tensors(exp_shape, res_shape)) + def test_region_infer_flatten_again(self): graph = build_graph(nodes_attributes, [('node_1', 'region'), ('region', 'node_3'), ('node_3', 'op_output') ], - {'node_3': {'shape': None}, + {'node_3': {'shape': None, 'value': None}, 'node_1': {'shape': np.array([1, 3, 227, 227])}, 'region': {'end_axis': 2, 'axis': 0, 'do_softmax': 1, **layout_attrs()} }) @@ -78,7 +96,7 @@ class TestRegionYOLOCaffe(unittest.TestCase): ('region', 'node_3'), ('node_3', 'op_output') ], - {'node_3': {'shape': None}, + {'node_3': {'shape': None, 'value': None}, 'node_1': {'shape': np.array([1, 3, 227, 227])}, 'region': {'do_softmax': 0, 'end_axis': -1, 'axis': 1, 'classes': 80, 'coords': 4, 'mask': np.array([6, 7, 8]), **layout_attrs()} @@ -100,7 +118,7 @@ class TestRegionYOLOTF(unittest.TestCase): ('region', 'node_3'), ('node_3', 'op_output') ], - {'node_3': {'shape': None}, + {'node_3': {'shape': None, 'value': None}, 'node_1': {'shape': np.array([1, 227, 227, 3])}, 'region': {'axis': 1, 'end_axis': -1, 'do_softmax': 1, **layout_attrs()} }) @@ -118,7 +136,7 @@ class TestRegionYOLOTF(unittest.TestCase): ('region', 'node_3'), ('node_3', 'op_output') ], - {'node_3': {'shape': None}, + {'node_3': {'shape': None, 'value': None}, 'node_1': {'shape': np.array([1, 227, 227, 3])}, 'region': {'do_softmax': 0, 'end_axis': -1, 'axis': 1, 'classes': 80, 'coords': 4, 'mask': np.array([6, 7, 8]), **layout_attrs()} diff --git a/model-optimizer/unit_tests/extensions/ops/reorgyolo_test.py b/model-optimizer/unit_tests/extensions/ops/reorgyolo_test.py index 1a3f077dfa9..e1eef82e9f3 100644 --- a/model-optimizer/unit_tests/extensions/ops/reorgyolo_test.py +++ b/model-optimizer/unit_tests/extensions/ops/reorgyolo_test.py @@ -33,8 +33,8 @@ class TestReorgYOLO(unittest.TestCase): ('reorg', 'node_3'), ('node_3', 'op_output') ], - {'node_3': {'shape': None}, - 'node_1': {'shape': np.array([1, 3, 227, 227])}, + {'node_3': {'shape': None, 'value': None}, + 'node_1': {'shape': np.array([1, 3, 227, 227]), 'value': None}, 'reorg': {'stride': 2, **layout_attrs()} }) diff --git a/model-optimizer/unit_tests/extensions/ops/select_test.py b/model-optimizer/unit_tests/extensions/ops/select_test.py index fb12477f033..6c038cf6980 100644 --- a/model-optimizer/unit_tests/extensions/ops/select_test.py +++ b/model-optimizer/unit_tests/extensions/ops/select_test.py @@ -21,7 +21,7 @@ class TestSelect(unittest.TestCase): ('else_data', {'value': np.zeros((2, 2)), 'kind': 'data', 'executable': True, 'shape': np.array([2, 2])}), ('condition', {'value': None, 'kind': 'op'}), ('condition_data', {'value': None, 'kind': 'data', 'executable': True, 'shape': np.array([2, 2])}), - ('select', {'type': 'Select', 'kind': 'op', 'op': 'Select'}), + ('select', {'type': 'Select', 'kind': 'op', 'op': 'Select', 'infer': Select.infer}), ('select_output', {'value': None, 'kind': 'data', 'executable': True, 'shape': None}), ] edges = [ @@ -42,10 +42,8 @@ class TestSelect(unittest.TestCase): edges_with_attrs=self.edges, update_nodes_attributes=[('select_output', {'shape': np.array([2, 2])})]) - tested_class = Select(graph=graph, attrs={}) - node = Node(graph, 'select') - tested_class.infer(node) + node.infer(node) (flag, resp) = compare_graphs(graph, graph_ref, 'select_output', check_op_attrs=True) self.assertTrue(flag, resp) @@ -63,10 +61,8 @@ class TestSelect(unittest.TestCase): update_nodes_attributes=[('select_output', {'shape': np.array([2, 2]), 'value': np.ones((2, 2))})]) - tested_class = Select(graph=graph, attrs={}) - node = Node(graph, 'select') - tested_class.infer(node) + node.infer(node) (flag, resp) = compare_graphs(graph, graph_ref, 'select_output', check_op_attrs=True) self.assertTrue(flag, resp) @@ -84,22 +80,21 @@ class TestSelect(unittest.TestCase): update_nodes_attributes=[('select_output', {'shape': np.array([2, 2]), 'value': np.zeros((2, 2))})]) - tested_class = Select(graph=graph, attrs={}) - node = Node(graph, 'select') - tested_class.infer(node) + node.infer(node) (flag, resp) = compare_graphs(graph, graph_ref, 'select_output', check_op_attrs=True) self.assertTrue(flag, resp) def test_select_infer_assert_shapes(self): graph = build_graph_with_attrs(nodes_with_attrs=self.nodes, edges_with_attrs=self.edges, - update_nodes_attributes=[('else_data', {'shape': np.array([3, 3]), 'value':np.zeros((3, 3))})]) + update_nodes_attributes=[('else_data', {'shape': np.array([3, 3]), + 'value':np.zeros((3, 3))})]) tested_class = Select(graph=graph, attrs={}) node = Node(graph, 'select') - with self.assertRaisesRegex(AssertionError, "Input shape do not broadcast"): + with self.assertRaisesRegex(AssertionError, "Input shapes for node select are not broadcast-able"): tested_class.infer(node) @generate(*[ @@ -112,30 +107,18 @@ class TestSelect(unittest.TestCase): ]) def test_select_infer_condition_shapes_broadcast(self, else_data_shape, than_data_shape, select_output_shape): graph = build_graph_with_attrs(nodes_with_attrs=self.nodes, edges_with_attrs=self.edges, - update_nodes_attributes=[('else_data', {'shape': np.array(else_data_shape), - 'value': np.zeros(else_data_shape, dtype=np.float)}), - ('than_data', {'shape': np.array(than_data_shape), - 'value': np.zeros(than_data_shape, dtype=np.float)}), - ('select_output', {'shape': np.array(select_output_shape), - 'value': np.zeros(select_output_shape, dtype=np.float)}) - ]) - - # We should propagate shapes and values - graph_ref = build_graph_with_attrs(nodes_with_attrs=self.nodes, edges_with_attrs=self.edges, - update_nodes_attributes=[ - ('else_data', {'shape': np.array(else_data_shape), - 'value': np.zeros(else_data_shape, dtype=np.float)}), - ('than_data', {'shape': np.array(than_data_shape), - 'value': np.zeros(than_data_shape, dtype=np.float)}), - ('select_output', {'shape': np.array(select_output_shape), 'value': np.zeros(select_output_shape)})]) - - tested_class = Select(graph=graph, attrs={}) + update_nodes_attributes= + [('else_data', {'shape': np.array(else_data_shape), + 'value': np.zeros(else_data_shape, dtype=np.float)}), + ('than_data', {'shape': np.array(than_data_shape), + 'value': np.zeros(than_data_shape, dtype=np.float)}), + ('select_output', {'shape': None, 'value': None}) + ]) node = Node(graph, 'select') - tested_class.infer(node) + node.infer(node) - (flag, resp) = compare_graphs(graph, graph_ref, 'select_output', check_op_attrs=True) - self.assertTrue(flag, resp) + self.assertTrue(np.array_equal(graph.nodes['select_output']['shape'], np.array(select_output_shape))) @generate(*[ ([5, 6], [5, 6], [5, 6], [5, 6], lambda x: np.ones(x, dtype=np.float), @@ -171,8 +154,9 @@ class TestSelect(unittest.TestCase): lambda x: np.zeros(x, dtype=np.float), lambda x: np.ones(x, dtype=np.float), lambda x: np.ones(x, dtype=np.float)), ]) - def test_select_infer_condition_with_value(self, condition_shape, else_data_shape, than_data_shape, select_output_shape, - condition_value, else_value, than_value, output_value): + def test_select_infer_condition_with_value(self, condition_shape, else_data_shape, than_data_shape, + select_output_shape, condition_value, else_value, than_value, + output_value): """ Unit tests generator can sporadic throw exception if we try to run generator with call numpy array generation functions. @@ -194,21 +178,7 @@ class TestSelect(unittest.TestCase): 'value': None}) ]) - graph_ref = build_graph_with_attrs(nodes_with_attrs=self.nodes, edges_with_attrs=self.edges, - update_nodes_attributes=[ - ('condition_data', {'shape': np.array(condition_shape), - 'value': condition_value}), - ('else_data', {'shape': np.array(else_data_shape), - 'value': else_value}), - ('than_data', {'shape': np.array(than_data_shape), - 'value': than_value}), - ('select_output', {'shape': np.array(select_output_shape), - 'value': output_value})]) - node = Node(graph, 'select') - Select.infer(node) + node.infer(node) - if else_value is not None and than_value is not None: - (flag, resp) = compare_graphs(graph, graph_ref, 'select_output', check_op_attrs=True) - self.assertTrue(flag, resp) - self.assertTrue(np.array_equal(graph.nodes['select_output']['value'], graph_ref.nodes['select_output']['value'])) + self.assertTrue(np.array_equal(graph.nodes['select_output']['value'], output_value)) diff --git a/model-optimizer/unit_tests/extensions/ops/simplernms_test.py b/model-optimizer/unit_tests/extensions/ops/simplernms_test.py deleted file mode 100644 index 1301a7532cb..00000000000 --- a/model-optimizer/unit_tests/extensions/ops/simplernms_test.py +++ /dev/null @@ -1,49 +0,0 @@ -# Copyright (C) 2018-2021 Intel Corporation -# SPDX-License-Identifier: Apache-2.0 - -import unittest - -import numpy as np - -from extensions.ops.simplernms import SimplerNMSOp -from mo.graph.graph import Node -from unit_tests.utils.graph import build_graph - -nodes_attributes = {'SimplerNMS_1': {'type': 'SimplerNMS', 'kind': 'op'}, - 'node_1': {'type': 'Identity', 'kind': 'op'}, - 'op_output': { 'kind': 'op', 'op': 'Result'} - } - - -class TestSimplerNMSInfer(unittest.TestCase): - def test_simplernms_infer_ideal(self): - graph = build_graph(nodes_attributes, - [('SimplerNMS_1', 'node_1'), - ('node_1', 'op_output') - ], - {'node_1': {'shape': None}, - 'SimplerNMS_1': {'feat_stride': 16, 'post_nms_topn': 150, 'scale': [1, 2, 3]} - }) - - simplernms_node = Node(graph, 'SimplerNMS_1') - - SimplerNMSOp.simplernms_infer(simplernms_node) - exp_shape = np.array([150, 5]) - res_shape = graph.node['node_1']['shape'] - for i in range(0, len(exp_shape)): - self.assertEqual(exp_shape[i], res_shape[i]) - self.assertEqual(simplernms_node.scale, ['1', '2', '3']) - - def test_simplernms_infer_no_shape(self): - graph = build_graph(nodes_attributes, - [('SimplerNMS_1', 'node_1'), - ('node_1', 'op_output') - ], - {'node_1': {'shape': None}, - 'SimplerNMS_1': {'feat_stride': 12, 'post_nms_topn': 150, 'scale': [1, 2, 3]} - }) - - simplernms_node = Node(graph, 'SimplerNMS_1') - - SimplerNMSOp.simplernms_infer(simplernms_node) - self.assertIsNone(graph.node['node_1']['shape']) diff --git a/model-optimizer/unit_tests/extensions/ops/space_to_depth_test.py b/model-optimizer/unit_tests/extensions/ops/space_to_depth_test.py index db8da1268ff..6e238cb6631 100644 --- a/model-optimizer/unit_tests/extensions/ops/space_to_depth_test.py +++ b/model-optimizer/unit_tests/extensions/ops/space_to_depth_test.py @@ -2,8 +2,11 @@ # SPDX-License-Identifier: Apache-2.0 import unittest + import numpy as np + from extensions.ops.space_to_depth import SpaceToDepth +from mo.front.common.partial_infer.utils import dynamic_dimension_value, shape_array, strict_compare_tensors from mo.graph.graph import Node from mo.utils.error import Error from unit_tests.utils.graph import build_graph @@ -19,6 +22,7 @@ edges = [ ('StD', 'out_data_node') ] + class TestSpaceToDepthPartialInfer(unittest.TestCase): def test_tf_space_to_depth_infer_nhwc(self): graph = build_graph(nodes, edges) @@ -39,6 +43,16 @@ class TestSpaceToDepthPartialInfer(unittest.TestCase): res_shape = graph.node['out_data_node']['shape'] self.assertTrue(np.array_equal(exp_shape, res_shape)) + def test_tf_space_to_depth_infer_nchw_dynamic(self): + graph = build_graph(nodes, edges) + graph.graph['layout'] = 'NCHW' + graph.node['in_data_node']['shape'] = shape_array([1, 64, dynamic_dimension_value, 1152]) + std_node = Node(graph, 'StD') + SpaceToDepth.infer(std_node) + exp_shape = shape_array([1, 256, dynamic_dimension_value, 576]) + res_shape = graph.node['out_data_node']['shape'] + self.assertTrue(strict_compare_tensors(exp_shape, res_shape)) + def test_tf_space_to_depth_infer_shape_error(self): graph = build_graph(nodes, edges) graph.graph['layout'] = 'NHWC' diff --git a/model-optimizer/unit_tests/extensions/ops/sparse_fill_empty_rows_test.py b/model-optimizer/unit_tests/extensions/ops/sparse_fill_empty_rows_test.py index ea26404983e..bcff2075a93 100644 --- a/model-optimizer/unit_tests/extensions/ops/sparse_fill_empty_rows_test.py +++ b/model-optimizer/unit_tests/extensions/ops/sparse_fill_empty_rows_test.py @@ -18,6 +18,9 @@ nodes_attributes = {'input_indices': {'shape': None, 'value': None, 'kind': 'dat 'output_indices': {'shape': None, 'value': None, 'kind': 'data'}, 'output_values': {'shape': None, 'value': None, 'kind': 'data'}, 'empty_row_indicator': {'shape': None, 'value': None, 'kind': 'data'}, + 'result_indices': {'kind': 'op', 'op': 'Result'}, + 'result_values': {'kind': 'op', 'op': 'Result'}, + 'result_empty_row_indicator': {'kind': 'op', 'op': 'Result'}, } # graph 1 @@ -27,13 +30,18 @@ edges1 = [('input_indices', 'sparse_fill_empty_rows_node', {'in': 0}), ('default_value', 'sparse_fill_empty_rows_node', {'in': 3}), ('sparse_fill_empty_rows_node', 'output_indices', {'out': 0}), ('sparse_fill_empty_rows_node', 'output_values', {'out': 1}), - ('sparse_fill_empty_rows_node', 'empty_row_indicator', {'out': 2})] + ('sparse_fill_empty_rows_node', 'empty_row_indicator', {'out': 2}), + ('output_indices', 'result_indices', {'out': 0}), + ('output_values', 'result_values', {'out': 0}), + ('empty_row_indicator', 'result_empty_row_indicator', {'out': 0}), + ] inputs1 = {'input_indices': {'shape': int64_array([20, 2]), 'value': None}, 'input_values': {'shape': int64_array([20]), 'value': None}, 'dense_shape': {'shape': int64_array([2]), 'value': np.array([4, 5])}, 'default_value': {'shape': int64_array([]), 'value': None}} + class TestSparseFillEmptyRows(unittest.TestCase): def test_partial_infer(self): graph = build_graph(nodes_attributes, edges1, inputs1) @@ -66,7 +74,10 @@ class TestSparseFillEmptyRows(unittest.TestCase): ('dense_shape', 'sparse_fill_empty_rows_node', {'in': 2}), ('default_value', 'sparse_fill_empty_rows_node', {'in': 3}), ('sparse_fill_empty_rows_node', 'output_indices', {'out': 0}), - ('sparse_fill_empty_rows_node', 'empty_row_indicator', {'out': 2})] + ('sparse_fill_empty_rows_node', 'empty_row_indicator', {'out': 2}), + ('output_indices', 'result_indices', {'out': 0}), + ('empty_row_indicator', 'result_empty_row_indicator', {'out': 0}), + ] graph = build_graph(nodes_attributes, edges, inputs1) sparse_fill_empty_rows_node = Node(graph, 'sparse_fill_empty_rows_node') diff --git a/model-optimizer/unit_tests/extensions/ops/spatial_transformer_test.py b/model-optimizer/unit_tests/extensions/ops/spatial_transformer_test.py deleted file mode 100644 index 93b6f282163..00000000000 --- a/model-optimizer/unit_tests/extensions/ops/spatial_transformer_test.py +++ /dev/null @@ -1,63 +0,0 @@ -# Copyright (C) 2018-2021 Intel Corporation -# SPDX-License-Identifier: Apache-2.0 - -import unittest - -import numpy as np - -from extensions.ops.spatial_transformer import SpatialTransformOp -from mo.graph.graph import Node -from unit_tests.utils.graph import build_graph - -nodes_attributes = {'node_1': {'type': 'Identity', 'kind': 'op'}, - 'node_2': {'type': 'Identity', 'kind': 'op'}, - 'st': {'type': 'SpatialTransform', 'kind': 'op'}, - 'node_3': {'type': 'Identity', 'kind': 'op'}, - 'op_output': { 'kind': 'op', 'op': 'Result'} - } - - -class TestSpatialTransformInfer(unittest.TestCase): - def test_sp_transform_concat_infer(self): - graph = build_graph(nodes_attributes, - [ - ('node_1', 'st'), - ('node_2', 'st'), - ('st', 'node_3'), - ('node_3', 'op_output') - ], - { - 'node_3': {'shape': None}, - 'node_1': {'shape': np.array([1, 3, 227, 227])}, - 'node_2': {'shape': np.array([1, 3, 227, 227])}, - 'st': {} - }) - - st_node = Node(graph, 'st') - SpatialTransformOp.sp_infer(st_node) - exp_shape = np.array([1, 3, 227, 227]) - res_shape = graph.node['node_3']['shape'] - for i in range(0, len(exp_shape)): - self.assertEqual(exp_shape[i], res_shape[i]) - - def test_sp_transform_with_output_params_infer(self): - graph = build_graph(nodes_attributes, - [ - ('node_1', 'st'), - ('node_2', 'st'), - ('st', 'node_3'), - ('node_3', 'op_output') - ], - { - 'node_3': {'shape': None}, - 'node_1': {'shape': np.array([1, 3, 227, 227])}, - 'node_2': {'shape': np.array([1, 3, 227, 227])}, - 'st': {'output_H': 200, 'output_W': 15} - }) - - st_node = Node(graph, 'st') - SpatialTransformOp.sp_infer(st_node) - exp_shape = np.array([1, 3, 200, 15]) - res_shape = graph.node['node_3']['shape'] - for i in range(0, len(exp_shape)): - self.assertEqual(exp_shape[i], res_shape[i]) diff --git a/model-optimizer/unit_tests/extensions/ops/split_test.py b/model-optimizer/unit_tests/extensions/ops/split_test.py index 1a1accca1b5..08c6c6b5d93 100644 --- a/model-optimizer/unit_tests/extensions/ops/split_test.py +++ b/model-optimizer/unit_tests/extensions/ops/split_test.py @@ -6,7 +6,7 @@ import unittest import numpy as np from extensions.ops.split import AttributedSplit, AttributedVariadicSplit, VariadicSplit -from mo.front.common.partial_infer.utils import int64_array +from mo.front.common.partial_infer.utils import int64_array, shape_array, dynamic_dimension_value, strict_compare_tensors from mo.graph.graph import Node from mo.utils.ir_engine.compare_graphs import compare_graphs from unit_tests.utils.graph import build_graph @@ -71,6 +71,45 @@ class TestSplitOp(unittest.TestCase): (flag, resp) = compare_graphs(graph, graph_ref, 'split_input_data') self.assertTrue(flag, resp) + def test_split_dynamic_shape_infer(self): + # test configuration + input_shape = [2, dynamic_dimension_value] + input_value = None + axis = 1 + num_splits = 2 + output_shape = [2, dynamic_dimension_value] + output_value = [None, None] + + # action + graph = build_graph(self.nodes, self.edges, + { + 'split_input_data': {'shape': shape_array(input_shape), + 'value': input_value}, + 'split_op': {'axis': np.array(axis), 'num_splits': np.array(num_splits)}, + } + ) + + split_op = Node(graph, 'split_op') + AttributedSplit.infer(split_op) + + # reference + graph_ref = build_graph(self.nodes, self.edges, + { + 'split_input_data': {'shape': shape_array(input_shape), + 'value': input_value}, + 'split_op': {'axis': np.array(axis), 'num_splits': np.array(num_splits)}, + 'split_output_0_data': {'shape': shape_array(output_shape), + 'value': output_value[0]}, + 'split_output_1_data': {'shape': shape_array(output_shape), + 'value': output_value[1]}, + } + ) + + # check + (flag, resp) = compare_graphs(graph, graph_ref, 'split_input_data') + self.assertTrue(flag, resp) + self.assertTrue(strict_compare_tensors(Node(graph, 'split_output_0_data').shape, shape_array(output_shape))) + def test_split_value_infer(self): # test configuration input_shape = [2, 10] @@ -150,6 +189,23 @@ class TestAttributedVariadicSplitOp(unittest.TestCase): self.assertTrue(len(node.out_edges()) == 3) self.assertTrue(np.all(node.split_lengths == np.array([2, 13, 10]))) + def test_splitv_dynamic_input(self): + graph = build_graph(self.nodes, self.edges, + { + 'split_input_data': {'shape': shape_array([2, 12, dynamic_dimension_value, 30])}, + 'split_op': {'axis': np.array(2), 'split_lengths': np.array([2, 13, 10]), + 'out_ports_count': 4}, + } + ) + node = Node(graph, 'split_op') + for p in range(len(node.out_edges()), node.out_ports_count): + node.add_output_port(p) + + AttributedVariadicSplit.infer(node) + + self.assertTrue(len(node.out_edges()) == 3) + self.assertTrue(np.all(node.split_lengths == np.array([2, 13, 10]))) + def test_splitv_zero_not_last(self): graph = build_graph(self.nodes, self.edges, { diff --git a/model-optimizer/unit_tests/extensions/ops/switch_test.py b/model-optimizer/unit_tests/extensions/ops/switch_test.py index 68c196685f4..2279de07b57 100644 --- a/model-optimizer/unit_tests/extensions/ops/switch_test.py +++ b/model-optimizer/unit_tests/extensions/ops/switch_test.py @@ -17,15 +17,19 @@ class TestSwitch(unittest.TestCase): nodes = [ ('tensor', {'value': np.zeros((3, 3)), 'kind': 'data', 'executable': True, 'shape': np.array([3, 3])}), ('pred_id', {'value': True, 'kind': 'data', 'executable': True}), - ('switch', {'type': 'Switch', 'kind': 'op', 'op': 'Switch'}), - ('switch_data_0', {'value': None, 'kind': 'data', 'executable': True}), - ('switch_data_1', {'value': None, 'kind': 'data', 'executable': True}) + ('switch', {'type': 'Switch', 'kind': 'op', 'op': 'Switch', 'infer': Switch.infer}), + ('switch_data_0', {'value': None, 'kind': 'data', 'executable': True, 'shape': None}), + ('switch_data_1', {'value': None, 'kind': 'data', 'executable': True, 'shape': None}), + ('result_0', {'value': None, 'kind': 'op', 'executable': True, 'type': 'Result', 'op': 'Result'}), + ('result_1', {'value': None, 'kind': 'op', 'executable': True, 'type': 'Result', 'op': 'Result'}), ] edges = [ ('tensor', 'switch', {'in': 0}), ('pred_id', 'switch', {'in': 1}), ('switch', 'switch_data_0', {'out': 0}), - ('switch', 'switch_data_1', {'out': 1}) + ('switch', 'switch_data_1', {'out': 1}), + ('switch_data_0', 'result_0'), + ('switch_data_1', 'result_1'), ] graph = build_graph_with_attrs(nodes_with_attrs=nodes, edges_with_attrs=edges) @@ -33,14 +37,12 @@ class TestSwitch(unittest.TestCase): graph_ref = build_graph_with_attrs(nodes_with_attrs=nodes, edges_with_attrs=edges, update_nodes_attributes=[('switch_data_0', {'shape': np.array([3, 3]), - 'value': np.zeros((3,3))}), + 'value': np.zeros((3, 3))}), ('switch_data_1', {'shape': np.array([3, 3]), - 'value': np.zeros((3,3))})]) - - tested_class = Switch(graph=graph, attrs={}) + 'value': np.zeros((3, 3))})]) node = Node(graph, 'switch') - tested_class.infer(node) + node.infer(node) (flag, resp) = compare_graphs(graph, graph_ref, 'switch_data_0', check_op_attrs=True) self.assertTrue(flag, resp) @@ -49,15 +51,19 @@ class TestSwitch(unittest.TestCase): nodes = [ ('tensor', {'value': None, 'kind': 'data', 'executable': True, 'shape': np.array([1, 2, 1])}), ('pred_id', {'value': None, 'kind': 'data', 'executable': True}), - ('switch', {'type': 'Switch', 'kind': 'op', 'op': 'Switch'}), - ('switch_data_0', {'value': None, 'kind': 'data', 'executable': True}), - ('switch_data_1', {'value': None, 'kind': 'data', 'executable': True}) + ('switch', {'type': 'Switch', 'kind': 'op', 'op': 'Switch', 'infer': Switch.infer}), + ('switch_data_0', {'value': None, 'kind': 'data', 'executable': True, 'shape': None}), + ('switch_data_1', {'value': None, 'kind': 'data', 'executable': True, 'shape': None}), + ('result_0', {'value': None, 'kind': 'op', 'executable': True, 'type': 'Result', 'op': 'Result'}), + ('result_1', {'value': None, 'kind': 'op', 'executable': True, 'type': 'Result', 'op': 'Result'}), ] edges = [ ('tensor', 'switch', {'in': 0}), ('pred_id', 'switch', {'in': 1}), ('switch', 'switch_data_0', {'out': 0}), - ('switch', 'switch_data_1', {'out': 1}) + ('switch', 'switch_data_1', {'out': 1}), + ('switch_data_0', 'result_0'), + ('switch_data_1', 'result_1'), ] graph = build_graph_with_attrs(nodes_with_attrs=nodes, edges_with_attrs=edges) @@ -67,10 +73,8 @@ class TestSwitch(unittest.TestCase): update_nodes_attributes=[('switch_data_0', {'shape': np.array([1, 2, 1])}), ('switch_data_1', {'shape': np.array([1, 2, 1])})]) - tested_class = Switch(graph=graph, attrs={}) - node = Node(graph, 'switch') - tested_class.infer(node) + node.infer(node) (flag, resp) = compare_graphs(graph, graph_ref, 'switch_data_0', check_op_attrs=True) self.assertTrue(flag, resp) @@ -80,21 +84,24 @@ class TestSwitch(unittest.TestCase): nodes = { 'tensor': {'value': True, 'kind': 'data', 'executable': True}, 'pred_id': {'value': None, 'kind': 'data', 'executable': True}, - 'switch': {'type': 'Switch', 'kind': 'op', 'op': 'Switch'}, + 'switch': {'type': 'Switch', 'kind': 'op', 'op': 'Switch', 'control_flow_infer': Switch.control_flow_infer}, 'switch_data_0': {'value': None, 'kind': 'data', 'executable': True}, - 'switch_data_1': {'value': None, 'kind': 'data', 'executable': True} + 'switch_data_1': {'value': None, 'kind': 'data', 'executable': True}, + 'result_0': {'value': None, 'kind': 'op', 'executable': True, 'type': 'Result', 'op': 'Result'}, + 'result_1': {'value': None, 'kind': 'op', 'executable': True, 'type': 'Result', 'op': 'Result'}, } edges = [ ('tensor', 'switch', {'in': 0}), ('pred_id', 'switch', {'in': 1}), ('switch', 'switch_data_0', {'out': 0}), - ('switch', 'switch_data_1', {'out': 1}) + ('switch', 'switch_data_1', {'out': 1}), + ('switch_data_0', 'result_0', {'in': 0}), + ('switch_data_1', 'result_1', {'in': 0}), ] graph = build_graph_with_edge_attrs(nodes, edges) - tested_class = Switch(graph=graph, attrs={}) node = Node(graph, 'switch') - tested_class.control_flow_infer(node, True, me_mock) + node.control_flow_infer(node, True, me_mock) # In this case we should mark all ports as executable me_mock.assert_has_calls([call('switch_data_0', True), call('switch_data_1', True)], any_order=True) @@ -103,20 +110,23 @@ class TestSwitch(unittest.TestCase): nodes = { 'tensor': {'value': True, 'kind': 'data', 'executable': True}, 'pred_id': {'value': np.array(True), 'kind': 'data', 'executable': True}, - 'switch': {'type': 'Switch', 'kind': 'op', 'op': 'Switch'}, + 'switch': {'type': 'Switch', 'kind': 'op', 'op': 'Switch', 'control_flow_infer': Switch.control_flow_infer}, 'switch_data_0': {'value': None, 'kind': 'data', 'executable': True}, - 'switch_data_1': {'value': None, 'kind': 'data', 'executable': True} + 'switch_data_1': {'value': None, 'kind': 'data', 'executable': True}, + 'result_0': {'value': None, 'kind': 'op', 'executable': True, 'type': 'Result', 'op': 'Result'}, + 'result_1': {'value': None, 'kind': 'op', 'executable': True, 'type': 'Result', 'op': 'Result'}, } edges = [ ('tensor', 'switch', {'in': 0}), ('pred_id', 'switch', {'in': 1}), ('switch', 'switch_data_0', {'out': 0}), - ('switch', 'switch_data_1', {'out': 1}) + ('switch', 'switch_data_1', {'out': 1}), + ('switch_data_0', 'result_0', {'in': 0}), + ('switch_data_1', 'result_1', {'in': 0}), ] graph = build_graph_with_edge_attrs(nodes, edges) - tested_class = Switch(graph=graph, attrs={}) node = Node(graph, 'switch') - tested_class.control_flow_infer(node, True, me_mock) + node.control_flow_infer(node, True, me_mock) me_mock.assert_has_calls([call('switch_data_0', False), call('switch_data_1', True)], any_order=True) def test_switch_cf_false_both_ports(self): @@ -125,20 +135,23 @@ class TestSwitch(unittest.TestCase): nodes = { 'tensor': {'value': True, 'kind': 'data', 'executable': True}, 'pred_id': {'value': np.array(False), 'kind': 'data', 'executable': True}, - 'switch': {'type': 'Switch', 'kind': 'op', 'op': 'Switch'}, + 'switch': {'type': 'Switch', 'kind': 'op', 'op': 'Switch', 'control_flow_infer': Switch.control_flow_infer}, 'switch_data_0': {'value': None, 'kind': 'data', 'executable': True}, - 'switch_data_1': {'value': None, 'kind': 'data', 'executable': True} + 'switch_data_1': {'value': None, 'kind': 'data', 'executable': True}, + 'result_0': {'value': None, 'kind': 'op', 'executable': True, 'type': 'Result', 'op': 'Result'}, + 'result_1': {'value': None, 'kind': 'op', 'executable': True, 'type': 'Result', 'op': 'Result'}, } edges = [ ('tensor', 'switch', {'in': 0}), ('pred_id', 'switch', {'in': 1}), ('switch', 'switch_data_0', {'out': 0}), - ('switch', 'switch_data_1', {'out': 1}) + ('switch', 'switch_data_1', {'out': 1}), + ('switch_data_0', 'result_0', {'in': 0}), + ('switch_data_1', 'result_1', {'in': 0}), ] graph = build_graph_with_edge_attrs(nodes, edges) - tested_class = Switch(graph=graph, attrs={}) node = Node(graph, 'switch') - tested_class.control_flow_infer(node, True, me_mock) + node.control_flow_infer(node, True, me_mock) me_mock.assert_has_calls([call('switch_data_0', True), call('switch_data_1', False)], any_order=True) def test_switch_cf_true_one_exec_port(self): @@ -147,18 +160,19 @@ class TestSwitch(unittest.TestCase): nodes = { 'tensor': {'value': True, 'kind': 'data', 'executable': True}, 'pred_id': {'value': np.array(True), 'kind': 'data', 'executable': True}, - 'switch': {'type': 'Switch', 'kind': 'op', 'op': 'Switch'}, - 'switch_data_1': {'value': None, 'kind': 'data', 'executable': True} + 'switch': {'type': 'Switch', 'kind': 'op', 'op': 'Switch', 'control_flow_infer': Switch.control_flow_infer}, + 'switch_data_1': {'value': None, 'kind': 'data', 'executable': True}, + 'result_1': {'value': None, 'kind': 'op', 'executable': True, 'type': 'Result', 'op': 'Result'}, } edges = [ ('tensor', 'switch', {'in': 0}), ('pred_id', 'switch', {'in': 1}), - ('switch', 'switch_data_1', {'out': 1}) + ('switch', 'switch_data_1', {'out': 1}), + ('switch_data_1', 'result_1', {'in': 0}), ] graph = build_graph_with_edge_attrs(nodes, edges) - tested_class = Switch(graph=graph, attrs={}) node = Node(graph, 'switch') - tested_class.control_flow_infer(node, True, me_mock) + node.control_flow_infer(node, True, me_mock) me_mock.assert_has_calls([call('switch_data_1', True)], any_order=True) def test_switch_cf_false_one_exec_port(self): @@ -167,18 +181,19 @@ class TestSwitch(unittest.TestCase): nodes = { 'tensor': {'value': True, 'kind': 'data', 'executable': True}, 'pred_id': {'value': np.array(False), 'kind': 'data', 'executable': True}, - 'switch': {'type': 'Switch', 'kind': 'op', 'op': 'Switch'}, + 'switch': {'type': 'Switch', 'kind': 'op', 'op': 'Switch', 'control_flow_infer': Switch.control_flow_infer}, 'switch_data_0': {'value': None, 'kind': 'data', 'executable': True}, + 'result_0': {'value': None, 'kind': 'op', 'executable': True, 'type': 'Result', 'op': 'Result'}, } edges = [ ('tensor', 'switch', {'in': 0}), ('pred_id', 'switch', {'in': 1}), ('switch', 'switch_data_0', {'out': 0}), + ('switch_data_0', 'result_0', {'in': 0}), ] graph = build_graph_with_edge_attrs(nodes, edges) - tested_class = Switch(graph=graph, attrs={}) node = Node(graph, 'switch') - tested_class.control_flow_infer(node, True, me_mock) + node.control_flow_infer(node, True, me_mock) me_mock.assert_has_calls([call('switch_data_0', True)], any_order=True) def test_switch_cf_true_no_exec(self): @@ -187,18 +202,19 @@ class TestSwitch(unittest.TestCase): nodes = { 'tensor': {'value': True, 'kind': 'data', 'executable': True}, 'pred_id': {'value': np.array(True), 'kind': 'data', 'executable': True}, - 'switch': {'type': 'Switch', 'kind': 'op', 'op': 'Switch'}, - 'switch_data_0': {'value': None, 'kind': 'data', 'executable': True} + 'switch': {'type': 'Switch', 'kind': 'op', 'op': 'Switch', 'control_flow_infer': Switch.control_flow_infer}, + 'switch_data_0': {'value': None, 'kind': 'data', 'executable': True}, + 'result_0': {'value': None, 'kind': 'op', 'executable': True, 'type': 'Result', 'op': 'Result'}, } edges = [ ('tensor', 'switch', {'in': 0}), ('pred_id', 'switch', {'in': 1}), ('switch', 'switch_data_0', {'out': 0}), + ('switch_data_0', 'result_0', {'in': 0}), ] graph = build_graph_with_edge_attrs(nodes, edges) - tested_class = Switch(graph=graph, attrs={}) node = Node(graph, 'switch') - tested_class.control_flow_infer(node, True, me_mock) + node.control_flow_infer(node, True, me_mock) me_mock.assert_has_calls([call('switch_data_0', False)], any_order=True) def test_switch_cf_false_no_exec(self): @@ -207,16 +223,17 @@ class TestSwitch(unittest.TestCase): nodes = { 'tensor': {'value': True, 'kind': 'data', 'executable': True}, 'pred_id': {'value': np.array(False), 'kind': 'data', 'executable': True}, - 'switch': {'type': 'Switch', 'kind': 'op', 'op': 'Switch'}, - 'switch_data_1': {'value': None, 'kind': 'data', 'executable': True} + 'switch': {'type': 'Switch', 'kind': 'op', 'op': 'Switch', 'control_flow_infer': Switch.control_flow_infer}, + 'switch_data_1': {'value': None, 'kind': 'data', 'executable': True}, + 'result_1': {'value': None, 'kind': 'op', 'executable': True, 'type': 'Result', 'op': 'Result'}, } edges = [ ('tensor', 'switch', {'in': 0}), ('pred_id', 'switch', {'in': 1}), - ('switch', 'switch_data_1', {'out': 1}) + ('switch', 'switch_data_1', {'out': 1}), + ('switch_data_1', 'result_1', {'in': 0}), ] graph = build_graph_with_edge_attrs(nodes, edges) - tested_class = Switch(graph=graph, attrs={}) node = Node(graph, 'switch') - tested_class.control_flow_infer(node, True, me_mock) + node.control_flow_infer(node, True, me_mock) me_mock.assert_has_calls([call('switch_data_1', False)], any_order=True) diff --git a/model-optimizer/unit_tests/extensions/ops/upsample_test.py b/model-optimizer/unit_tests/extensions/ops/upsample_test.py index 2284463a7b5..d11ffde665f 100644 --- a/model-optimizer/unit_tests/extensions/ops/upsample_test.py +++ b/model-optimizer/unit_tests/extensions/ops/upsample_test.py @@ -7,6 +7,7 @@ import numpy as np from generator import generator, generate from extensions.ops.upsample import UpsampleOp +from mo.front.common.partial_infer.utils import shape_array, dynamic_dimension_value, strict_compare_tensors from mo.graph.graph import Node from unit_tests.utils.graph import build_graph @@ -20,9 +21,13 @@ nodes_attributes = {'node_1': {'type': 'Identity', 'kind': 'op'}, @generator class TestUpsampleOp(unittest.TestCase): @generate(*[ - (np.array([1., 1., 2., 2.]), np.array([1, 3, 227, 227]), np.array([1, 3, 454, 454], dtype=np.int64)), - (np.array([1., 1., 2.5, 1.5]), np.array([1, 5, 227, 227]), np.array([1, 5, 567, 340], dtype=np.int64)), - (np.array([1., 1., 1.3, 0.7]), np.array([1, 14, 1023, 713]), np.array([1, 14, 1329, 499], dtype=np.int64)), + (np.array([1., 1., 2., 2.]), shape_array([1, 3, 227, 227]), shape_array([1, 3, 454, 454])), + (np.array([1., 1., 2.5, 1.5]), shape_array([1, 5, 227, 227]), shape_array([1, 5, 567, 340])), + (np.array([1., 1., 1.3, 0.7]), shape_array([1, 14, 1023, 713]), shape_array([1, 14, 1329, 499])), + (np.array([1., 1., 1.3, 0.7]), shape_array([1, 14, dynamic_dimension_value, 713]), + shape_array([1, 14, dynamic_dimension_value, 499])), + (np.array([1., 1., 1.3, 0.7]), shape_array([1, 14, 1023, dynamic_dimension_value]), + shape_array([1, 14, 1329, dynamic_dimension_value])), ]) def test_upsample_with_scales_infer(self, scales, input_shape, expected_shape): graph = build_graph(nodes_attributes, @@ -30,7 +35,7 @@ class TestUpsampleOp(unittest.TestCase): ('upsample', 'node_3'), ('node_3', 'op_output') ], - {'node_3': {'shape': None}, + {'node_3': {'shape': None, 'value': None}, 'node_1': {'shape': input_shape}, 'upsample': {'mode': 'linear', 'height_scale': scales[2], @@ -41,13 +46,16 @@ class TestUpsampleOp(unittest.TestCase): upsample_node = Node(graph, 'upsample') UpsampleOp.upsample_infer(upsample_node) res_shape = graph.node['node_3']['shape'] - for i in range(0, len(expected_shape)): - self.assertEqual(expected_shape[i], res_shape[i]) + self.assertTrue(strict_compare_tensors(expected_shape, res_shape)) @generate(*[ - (np.array([1., 1., 2., 2.]), np.array([1, 3, 227, 227]), np.array([1, 3, 454, 454], dtype=np.int64)), - (np.array([1., 1., 2.5, 1.5]), np.array([1, 5, 227, 227]), np.array([1, 5, 567, 340], dtype=np.int64)), - (np.array([1., 1., 1.3, 0.7]), np.array([1, 14, 1023, 713]), np.array([1, 14, 1329, 499], dtype=np.int64)), + (np.array([1., 1., 2., 2.]), shape_array([1, 3, 227, 227]), shape_array([1, 3, 454, 454])), + (np.array([1., 1., 2.5, 1.5]), shape_array([1, 5, 227, 227]), shape_array([1, 5, 567, 340])), + (np.array([1., 1., 1.3, 0.7]), shape_array([1, 14, 1023, 713]), shape_array([1, 14, 1329, 499])), + (np.array([1., 1., 1.3, 0.7]), shape_array([1, 14, dynamic_dimension_value, 713]), + shape_array([1, 14, dynamic_dimension_value, 499])), + (np.array([1., 1., 1.3, 0.7]), shape_array([1, 14, 1023, dynamic_dimension_value]), + shape_array([1, 14, 1329, dynamic_dimension_value])), ]) def test_upsample_with_second_input_infer(self, scales, input_shape, expected_shape): nodes_attributes['scales'] = {'kind': 'data', 'value': scales} @@ -57,7 +65,7 @@ class TestUpsampleOp(unittest.TestCase): ('upsample', 'node_3'), ('node_3', 'op_output') ], - {'node_3': {'shape': None}, + {'node_3': {'shape': None, 'value': None}, 'node_1': {'shape': input_shape}, 'upsample': {'mode': 'linear', 'height_scale': None, @@ -68,5 +76,4 @@ class TestUpsampleOp(unittest.TestCase): upsample_node = Node(graph, 'upsample') UpsampleOp.upsample_infer(upsample_node) res_shape = graph.node['node_3']['shape'] - for i in range(0, len(expected_shape)): - self.assertEqual(expected_shape[i], res_shape[i]) + self.assertTrue(strict_compare_tensors(expected_shape, res_shape)) diff --git a/model-optimizer/unit_tests/mo/front/common/partial_infer/concat_test.py b/model-optimizer/unit_tests/mo/front/common/partial_infer/concat_test.py index a5a2fa0d78a..fa564bab909 100644 --- a/model-optimizer/unit_tests/mo/front/common/partial_infer/concat_test.py +++ b/model-optimizer/unit_tests/mo/front/common/partial_infer/concat_test.py @@ -4,79 +4,87 @@ import unittest import numpy as np +from generator import generate, generator from mo.front.common.partial_infer.concat import concat_infer +from mo.front.common.partial_infer.utils import shape_array, dynamic_dimension_value, strict_compare_tensors from mo.graph.graph import Node +from mo.utils.error import Error from unit_tests.utils.graph import build_graph nodes_attributes = {'node_1': {'kind': 'data', 'value': None}, 'node_2': {'kind': 'data', 'value': None}, 'concat': {'type': 'Concat', 'kind': 'op'}, 'node_3': {'kind': 'data'}, - 'op_output': { 'kind': 'op', 'op': 'Result'}, + 'op_output': {'kind': 'op', 'op': 'Result'}, } +@generator class TestConcatPartialInfer(unittest.TestCase): - def test_tf_concat_infer(self): + @generate(*[([1, 3, 227, 227], [1, 3, 220, 227], [1, 3, 447, 227], 2), + ([1, 3, 227, 227], [1, 3, 227, 220], [1, 3, 227, 447], -1), + ([1, 3, dynamic_dimension_value, 227], [1, dynamic_dimension_value, 227, 220], [1, 3, 227, 447], -1), + ([1, 3, 10, 227], [1, 3, 10, dynamic_dimension_value], [1, 3, 10, dynamic_dimension_value], -1), + ]) + def test_concat_infer(self, shape1, shape2, output_shape, axis): graph = build_graph(nodes_attributes, [('node_1', 'concat'), ('node_2', 'concat'), ('concat', 'node_3'), ('node_3', 'op_output') ], - {'node_3': {'shape': None}, - 'node_1': {'shape': np.array([1, 3, 227, 227])}, - 'node_2': {'shape': np.array([1, 3, 227, 227])}, - 'concat': {'axis': 2} + {'node_3': {'shape': None, 'value': None}, + 'node_1': {'shape': shape_array(shape1)}, + 'node_2': {'shape': shape_array(shape2)}, + 'concat': {'axis': axis} }) concat_node = Node(graph, 'concat') concat_infer(concat_node) - exp_shape = np.array([1, 3, 454, 227]) res_shape = graph.node['node_3']['shape'] - for i in range(0, len(exp_shape)): - self.assertEqual(exp_shape[i], res_shape[i]) + self.assertTrue(strict_compare_tensors(output_shape, res_shape)) - def test_tf_concat_infer_negative_axis(self): + @generate(*[(shape_array([1]), shape_array([4]), shape_array([1, 4]), 0), + (shape_array([dynamic_dimension_value]), shape_array([4]), + shape_array([dynamic_dimension_value, 4]), -1), + ]) + def test_concat_value_infer(self, value1, value2, output_value, axis): graph = build_graph(nodes_attributes, [('node_1', 'concat'), ('node_2', 'concat'), ('concat', 'node_3'), ('node_3', 'op_output') ], - {'node_3': {'shape': None}, - 'node_1': {'shape': np.array([1, 3, 227, 227])}, - 'node_2': {'shape': np.array([1, 3, 227, 227])}, - 'concat': {'axis': -1} + {'node_3': {'shape': output_value.shape, 'value': output_value}, + 'node_1': {'shape': value1.shape, 'value': value1}, + 'node_2': {'shape': value2.shape, 'value': value2}, + 'concat': {'axis': axis} }) concat_node = Node(graph, 'concat') concat_infer(concat_node) - exp_shape = np.array([1, 3, 227, 454]) - res_shape = graph.node['node_3']['shape'] - for i in range(0, len(exp_shape)): - self.assertEqual(exp_shape[i], res_shape[i]) + res_value = graph.node['node_3']['value'] + self.assertTrue(strict_compare_tensors(output_value, res_value)) - def test_tf_concat_infer_not_match(self): + def test_concat_infer_not_match(self): graph = build_graph(nodes_attributes, [('node_1', 'concat'), ('node_2', 'concat'), ('concat', 'node_3'), ('node_3', 'op_output') ], - {'node_3': {'shape': None}, + {'node_3': {'shape': None, 'value': None}, 'node_1': {'shape': np.array([1, 3, 227, 227])}, 'node_2': {'shape': np.array([1, 2, 227, 227])}, 'concat': {'axis': 2} }) concat_node = Node(graph, 'concat') - concat_infer(concat_node) - res_shape = graph.node['node_3']['shape'] - self.assertIsNone(res_shape) + with self.assertRaisesRegex(Error, "Concat input shapes do not match for node*"): + concat_infer(concat_node) - def test_tf_concat_infer_no_shape(self): + def test_concat_infer_no_shape(self): graph = build_graph(nodes_attributes, [('node_1', 'concat'), ('node_2', 'concat'), @@ -90,6 +98,5 @@ class TestConcatPartialInfer(unittest.TestCase): }) concat_node = Node(graph, 'concat') - concat_infer(concat_node) - res_shape = graph.node['node_3']['shape'] - self.assertIsNone(res_shape) + with self.assertRaisesRegex(Error, "One of the input shapes is not defined for node *"): + concat_infer(concat_node) diff --git a/model-optimizer/unit_tests/mo/front/common/partial_infer/crop_test.py b/model-optimizer/unit_tests/mo/front/common/partial_infer/crop_test.py index 00d43fa20aa..ca35d114d38 100644 --- a/model-optimizer/unit_tests/mo/front/common/partial_infer/crop_test.py +++ b/model-optimizer/unit_tests/mo/front/common/partial_infer/crop_test.py @@ -11,7 +11,7 @@ from unit_tests.utils.graph import build_graph nodes_attributes = {'node_1': {'value': None, 'kind': 'data'}, 'node_2': {'value': None, 'kind': 'data'}, - 'crop_1': {'type': 'Crop', 'kind': 'op'}, + 'crop_1': {'op': 'Crop', 'kind': 'op'}, 'node_3': {'value': None, 'kind': 'data'}, 'op_output': { 'kind': 'op', 'op': 'Result'} } diff --git a/model-optimizer/unit_tests/mo/front/common/partial_infer/eltwise_test.py b/model-optimizer/unit_tests/mo/front/common/partial_infer/eltwise_test.py index 8734433115f..4d65dd4f243 100644 --- a/model-optimizer/unit_tests/mo/front/common/partial_infer/eltwise_test.py +++ b/model-optimizer/unit_tests/mo/front/common/partial_infer/eltwise_test.py @@ -4,21 +4,44 @@ import unittest import numpy as np +from generator import generator, generate from mo.front.common.partial_infer.eltwise import eltwise_infer +from mo.front.common.partial_infer.utils import shape_array, dynamic_dimension_value, strict_compare_tensors from mo.graph.graph import Node +from mo.utils.error import Error from unit_tests.utils.graph import build_graph nodes_attributes = {'node_1': {'value': 2, 'kind': 'data'}, 'node_2': {'value': 3, 'kind': 'data'}, 'eltw_1': {'kind': 'op'}, 'node_3': {'value': None, 'kind': 'data'}, - 'op_output': { 'kind': 'op', 'op': 'Result'}, + 'op_output': {'kind': 'op', 'op': 'Result'}, } +@generator class TestEltwiseInfer(unittest.TestCase): - def test_eltwise_infer_max(self): + @generate(*[ + (np.array(2), [], np.array(3), [], lambda a, b: np.multiply(a, b), np.array(6), []), + (np.array(2), [], np.array(3), [], lambda a, b: np.maximum(a, b), np.array(3), []), + (np.array(2), [], np.array(3), [], lambda a, b: np.add(a, b), np.array(5), []), + (None, [1, 5], None, [1, 1], lambda a, b: np.add(a, b), None, [1, 5]), + (None, [dynamic_dimension_value, 3], None, [1, 1], lambda a, b: np.add(a, b), None, + [dynamic_dimension_value, 3]), + (None, [dynamic_dimension_value, 3], None, [1, dynamic_dimension_value], lambda a, b: np.add(a, b), None, + [dynamic_dimension_value, 3]), + (None, [4, 5, dynamic_dimension_value, 3], None, [1, dynamic_dimension_value], lambda a, b: np.add(a, b), None, + [4, 5, dynamic_dimension_value, 3]), + (None, [1, 10, 20, 30], None, [dynamic_dimension_value, 10, 20, 30], lambda a, b: np.add(a, b), None, + [dynamic_dimension_value, 10, 20, 30]), + # dynamic value propagation + (shape_array([dynamic_dimension_value, 5]), [2], np.array(3), [], lambda a, b: np.add(a, b), + shape_array([dynamic_dimension_value, 8]), [2]), + (shape_array([dynamic_dimension_value, 5]), [2], np.array([3, 7]), [], lambda a, b: np.add(a, b), + shape_array([dynamic_dimension_value, 12]), [2]), + ]) + def test_eltwise_infer(self, value1, shape1, value2, shape2, shape_infer, exp_value, exp_shape): graph = build_graph(nodes_attributes, [('node_1', 'eltw_1'), ('node_2', 'eltw_1'), @@ -26,72 +49,22 @@ class TestEltwiseInfer(unittest.TestCase): ('node_3', 'op_output') ], {'node_3': {'shape': None}, - 'node_1': {'shape': np.array([1, 3, 256, 256])}, - 'node_2': {'shape': np.array([1, 3, 256, 256])}, - 'eltw_1': {} + 'node_1': {'shape': shape_array(value1).shape if value1 is not None else shape_array(shape1), + 'value': value1}, + 'node_2': {'shape': shape_array(value2).shape if value2 is not None else shape_array(shape2), + 'value': value2} }) graph.graph['layout'] = 'NCHW' eltwise_node = Node(graph, 'eltw_1') - eltwise_infer(eltwise_node, lambda a, b: np.maximum(a, b)) - exp_shape = np.array([1, 3, 256, 256]) - exp_value = 3 + eltwise_infer(eltwise_node, shape_infer) res_shape = graph.node['node_3']['shape'] res_value = eltwise_node.out_node().value - for i in range(0, len(exp_shape)): - self.assertEqual(exp_shape[i], res_shape[i]) - - self.assertEqual(exp_value, res_value) - - def test_eltwise_infer_sum(self): - graph = build_graph(nodes_attributes, - [('node_1', 'eltw_1'), - ('node_2', 'eltw_1'), - ('eltw_1', 'node_3'), - ('node_3', 'op_output') - ], - {'node_3': {'shape': None}, - 'node_1': {'shape': np.array([1, 3, 256, 256])}, - 'node_2': {'shape': np.array([1, 3, 256, 256])} - }) - graph.graph['layout'] = 'NCHW' - eltwise_node = Node(graph, 'eltw_1') - - eltwise_infer(eltwise_node, lambda a, b: a + b) - exp_shape = np.array([1, 3, 256, 256]) - exp_value = 5 - res_shape = graph.node['node_3']['shape'] - res_value = eltwise_node.out_node().value - for i in range(0, len(exp_shape)): - self.assertEqual(exp_shape[i], res_shape[i]) - - self.assertEqual(exp_value, res_value) - - def test_eltwise_infer_mul(self): - graph = build_graph(nodes_attributes, - [('node_1', 'eltw_1'), - ('node_2', 'eltw_1'), - ('eltw_1', 'node_3'), - ('node_3', 'op_output') - ], - {'node_3': {'shape': None}, - 'node_1': {'shape': np.array([1, 3, 256, 256])}, - 'node_2': {'shape': np.array([1, 3, 256, 256])} - }) - graph.graph['layout'] = 'NCHW' - eltwise_node = Node(graph, 'eltw_1') - - eltwise_infer(eltwise_node, lambda a, b: a * b) - exp_shape = np.array([1, 3, 256, 256]) - exp_value = 6 - res_shape = graph.node['node_3']['shape'] - res_value = eltwise_node.out_node().value - for i in range(0, len(exp_shape)): - self.assertEqual(exp_shape[i], res_shape[i]) - - self.assertEqual(exp_value, res_value) + if exp_value is not None: + self.assertTrue(strict_compare_tensors(res_value, shape_array(exp_value))) + self.assertTrue(strict_compare_tensors(res_shape, shape_array(exp_shape))) def test_eltwise_infer_none_val(self): graph = build_graph(nodes_attributes, @@ -130,8 +103,5 @@ class TestEltwiseInfer(unittest.TestCase): graph.graph['layout'] = 'NCHW' eltwise_node = Node(graph, 'eltw_1') - eltwise_infer(eltwise_node) - exp_shape = np.array([1, 3, -1, -1]) - res_shape = graph.node['node_3']['shape'] - for i in range(0, len(exp_shape)): - self.assertEqual(exp_shape[i], res_shape[i]) + with self.assertRaisesRegex(Error, 'Input shapes mismatch*'): + eltwise_infer(eltwise_node) diff --git a/model-optimizer/unit_tests/mo/front/common/partial_infer/multi_box_detection_test.py b/model-optimizer/unit_tests/mo/front/common/partial_infer/multi_box_detection_test.py index fcaa9f6cdaf..1e73f840d39 100644 --- a/model-optimizer/unit_tests/mo/front/common/partial_infer/multi_box_detection_test.py +++ b/model-optimizer/unit_tests/mo/front/common/partial_infer/multi_box_detection_test.py @@ -6,7 +6,9 @@ import unittest import numpy as np from mo.front.common.partial_infer.multi_box_detection import multi_box_detection_infer +from mo.front.common.partial_infer.utils import shape_array, dynamic_dimension_value, strict_compare_tensors from mo.graph.graph import Node +from mo.utils.error import Error from unit_tests.utils.graph import build_graph nodes_attributes = {'node_1': {'value': None, 'kind': 'data'}, @@ -18,7 +20,7 @@ nodes_attributes = {'node_1': {'value': None, 'kind': 'data'}, class TestMultiBoxDetectionInfer(unittest.TestCase): - def test_prior_box_infer_ideal(self): + def test_do_infer_ideal(self): graph = build_graph(nodes_attributes, [('node_1', 'detection_output_1'), ('node_2', 'detection_output_1'), @@ -27,12 +29,12 @@ class TestMultiBoxDetectionInfer(unittest.TestCase): {'node_1': {'shape': np.array([1, 34928])}, 'node_2': {'shape': np.array([1, 183372])}, 'node_3': {'shape': np.array([1, 2, 34928])}, - 'detection_output_1': {"background_label_id": "0", "clip": "1", + 'detection_output_1': {"background_label_id": 0, "clip": 1, "code_type": "caffe.PriorBoxParameter.CENTER_SIZE", - "confidence_threshold": "0.01", "keep_top_k": "200", - "nms_threshold": "0.5", "num_classes": "21", - "share_location": "1", "top_k": "200", - "variance_encoded_in_target": "0"}, + "confidence_threshold": 0.01, "keep_top_k": 200, + "nms_threshold": 0.5, "num_classes": 21, + "share_location": 1, "top_k": 200, + "variance_encoded_in_target": 0}, 'node_4': {'shape': np.array([1, 1, 200, 7])}, }) @@ -45,18 +47,18 @@ class TestMultiBoxDetectionInfer(unittest.TestCase): for i in range(0, len(exp_shape)): self.assertEqual(exp_shape[i], res_shape[i]) - self.assertEqual(multi_box_detection_node.background_label_id, '0') - self.assertEqual(multi_box_detection_node.clip, '1') + self.assertEqual(multi_box_detection_node.background_label_id, 0) + self.assertEqual(multi_box_detection_node.clip, 1) self.assertEqual(multi_box_detection_node.code_type, 'caffe.PriorBoxParameter.CENTER_SIZE') - self.assertEqual(multi_box_detection_node.confidence_threshold, '0.01') - self.assertEqual(multi_box_detection_node.keep_top_k, '200') - self.assertEqual(multi_box_detection_node.nms_threshold, '0.5') + self.assertEqual(multi_box_detection_node.confidence_threshold, 0.01) + self.assertEqual(multi_box_detection_node.keep_top_k, 200) + self.assertEqual(multi_box_detection_node.nms_threshold, 0.5) self.assertEqual(multi_box_detection_node.num_classes, 21) - self.assertEqual(multi_box_detection_node.share_location, '1') - self.assertEqual(multi_box_detection_node.top_k, '200') - self.assertEqual(multi_box_detection_node.variance_encoded_in_target, '0') + self.assertEqual(multi_box_detection_node.share_location, 1) + self.assertEqual(multi_box_detection_node.top_k, 200) + self.assertEqual(multi_box_detection_node.variance_encoded_in_target, 0) - def test_prior_box_infer_without_top_k(self): + def test_do_infer_without_top_k(self): graph = build_graph(nodes_attributes, [('node_1', 'detection_output_1'), ('node_2', 'detection_output_1'), @@ -68,7 +70,7 @@ class TestMultiBoxDetectionInfer(unittest.TestCase): 'detection_output_1': {"background_label_id": "0", "clip": "1", "code_type": "caffe.PriorBoxParameter.CENTER_SIZE", "confidence_threshold": "0.01", "keep_top_k": -1, - "nms_threshold": "0.5", "num_classes": "21", + "nms_threshold": "0.5", "num_classes": 21, "share_location": "1", "top_k": -1, "variance_encoded_in_target": "0"}, 'node_4': {'shape': np.array([1, 1, 69856, 7])}, @@ -93,7 +95,43 @@ class TestMultiBoxDetectionInfer(unittest.TestCase): self.assertEqual(multi_box_detection_node.top_k, -1) self.assertEqual(multi_box_detection_node.variance_encoded_in_target, '0') - def test_prior_box_infer_raise_error(self): + def test_do_infer_without_top_k_dynamic_shape(self): + graph = build_graph(nodes_attributes, + [('node_1', 'detection_output_1'), + ('node_2', 'detection_output_1'), + ('node_3', 'detection_output_1'), + ('detection_output_1', 'node_4')], + {'node_1': {'shape': np.array([1, 34928])}, + 'node_2': {'shape': shape_array([dynamic_dimension_value, 183372])}, + 'node_3': {'shape': np.array([1, 2, 34928])}, + 'detection_output_1': {"background_label_id": "0", "clip": "1", + "code_type": "caffe.PriorBoxParameter.CENTER_SIZE", + "confidence_threshold": "0.01", "keep_top_k": -1, + "nms_threshold": "0.5", "num_classes": 21, + "share_location": "1", "top_k": -1, + "variance_encoded_in_target": "0"}, + 'node_4': {'shape': np.array([1, 1, 69856, 7])}, + }) + + multi_box_detection_node = Node(graph, 'detection_output_1') + + multi_box_detection_infer(multi_box_detection_node) + exp_shape = shape_array([1, 1, dynamic_dimension_value, 7]) + res_shape = graph.node['node_4']['shape'] + self.assertTrue(strict_compare_tensors(exp_shape, res_shape)) + + self.assertEqual(multi_box_detection_node.background_label_id, '0') + self.assertEqual(multi_box_detection_node.clip, '1') + self.assertEqual(multi_box_detection_node.code_type, 'caffe.PriorBoxParameter.CENTER_SIZE') + self.assertEqual(multi_box_detection_node.confidence_threshold, '0.01') + self.assertEqual(multi_box_detection_node.keep_top_k, 8732) + self.assertEqual(multi_box_detection_node.nms_threshold, '0.5') + self.assertEqual(multi_box_detection_node.num_classes, 21) + self.assertEqual(multi_box_detection_node.share_location, '1') + self.assertEqual(multi_box_detection_node.top_k, -1) + self.assertEqual(multi_box_detection_node.variance_encoded_in_target, '0') + + def test_do_infer_raise_error(self): graph = build_graph(nodes_attributes, [('node_1', 'detection_output_1'), ('node_2', 'detection_output_1'), @@ -105,7 +143,7 @@ class TestMultiBoxDetectionInfer(unittest.TestCase): 'detection_output_1': {"background_label_id": "0", "clip": "1", "code_type": "caffe.PriorBoxParameter.CENTER_SIZE", "confidence_threshold": "0.01", "keep_top_k": -1, - "nms_threshold": "0.5", "num_classes": "21", + "nms_threshold": "0.5", "num_classes": 21, "share_location": "1", "top_k": -1, "variance_encoded_in_target": 0}, 'node_4': {'shape': np.array([1, 1, 69856, 7])}, @@ -113,4 +151,5 @@ class TestMultiBoxDetectionInfer(unittest.TestCase): multi_box_detection_node = Node(graph, 'detection_output_1') - self.assertIsNone(multi_box_detection_infer(multi_box_detection_node)) + with self.assertRaisesRegex(Error, 'The "-2" dimension of the prior boxes must be 2 but it is "3" for node*'): + multi_box_detection_infer(multi_box_detection_node) diff --git a/model-optimizer/unit_tests/mo/front/common/partial_infer/utils_test.py b/model-optimizer/unit_tests/mo/front/common/partial_infer/utils_test.py new file mode 100644 index 00000000000..2f5c33f9c1c --- /dev/null +++ b/model-optimizer/unit_tests/mo/front/common/partial_infer/utils_test.py @@ -0,0 +1,131 @@ +# Copyright (C) 2018-2021 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 + +import unittest + +import numpy as np +from generator import generator, generate + +from mo.front.common.partial_infer.utils import int64_array, is_fully_defined, dynamic_dimension_value, \ + dynamic_dimension, shape_array, compatible_shapes, shape_delete, shape_insert, strict_compare_tensors +from mo.utils.error import Error + + +def gen_masked_array(array, masked_indices): + """ + Creates a masked array from the input array by masking specific elements. + + :param array: the input array + :param masked_indices: element indices to be masked + :return: the result masked array + """ + res = np.ma.masked_array(array) + for index in masked_indices: + res[index] = np.ma.masked + return res + + +@generator +class IsFullyDefinedTest(unittest.TestCase): + @generate(*[(None, False), + (int64_array([2, 3, 5, 7]), True), # int64 array with valid values + (np.array([2, 3, 5, 7]), True), # any numpy array with valid values + (np.array([2, dynamic_dimension_value]), True), # array with dynamic dimension value is fully defined! + (shape_array([2, dynamic_dimension_value, 5]), False), # masked array with at least one masked element + (shape_array([2, 4, 5]), True), # masked array with no masked elements is fully defined + (dynamic_dimension, False), # dynamic dimension is not fully defined + (dynamic_dimension_value, True), # dynamic dimension value is fully defined + ((dynamic_dimension_value, dynamic_dimension_value), True), # list with dynamic dimension values is + # fully defined + ((dynamic_dimension, 1), False), # tuple with dynamic dimension is not fully defined + ([dynamic_dimension, 1], False), # list with dynamic dimension is not fully defined + ]) + def test_is_fully_defined(self, data, result): + self.assertEqual(is_fully_defined(data), result) + + +@generator +class ShapeArrayTest(unittest.TestCase): + @generate(*[([1], shape_array([1]), True), + # if we provide a list with dynamic_dimension_value then it is converted to dynamic dimension + ([dynamic_dimension_value, 5], gen_masked_array([1, 5], [0]), True), + # if we provide a list with dynamic_dimension then the generated shape array still have it + ([7, dynamic_dimension], gen_masked_array([7, 1], [1]), True), + # negative test to make sure that np.ma.allequal works properly + ([2], gen_masked_array([1], []), False), + ]) + def test_shape_array(self, data, ref, result): + self.assertEqual(strict_compare_tensors(shape_array(data), ref), result) + + +@generator +class CompareShapesTest(unittest.TestCase): + @generate(*[(gen_masked_array([1, 2, 3], []), gen_masked_array([1, 2, 3], []), True), + (gen_masked_array([4, 2, 3], []), gen_masked_array([1, 2, 3], []), False), + (gen_masked_array([1, 2], []), gen_masked_array([1, 2, 3], []), False), + (gen_masked_array([1, 2, 3], []), gen_masked_array([1, 2], []), False), + (gen_masked_array([1, 2, 3], [1]), gen_masked_array([1, 5, 3], [1]), True), # [1, d, 3] vs [1, d, 3] + (gen_masked_array([1, 2, 3], [2]), gen_masked_array([1, 5, 3], [1]), True), # [1, 2, d] vs [1, d, 3] + (gen_masked_array([1, 2, 3], []), gen_masked_array([1, 5, 3], [1]), True), # [1, 2, 3] vs [1, d, 3] + (gen_masked_array([1, 2, 3], [0]), gen_masked_array([1, 5, 3], []), False), # [d, 2, 3] vs [1, 5, 3] + (np.array([1, 2, 3]), gen_masked_array([1, 5, 3], [1]), True), # [1, 2, 3] vs [1, d, 3] + (np.array([1, 2]), gen_masked_array([1, 5, 3], [1]), False), + (np.array([1, 2]), np.array([1, 2]), True), + (np.array([1, 2]), np.array([3, 2]), False), + ]) + def test_compare_shapes(self, input1, input2, result): + self.assertEqual(compatible_shapes(input1, input2), result) + + +@generator +class ShapeDeleteTest(unittest.TestCase): + @generate(*[(gen_masked_array([1, 2, 3], []), [], gen_masked_array([1, 2, 3], [])), + # [1, d, 3] -> [d, 3]. Indices input is a list + (gen_masked_array([1, 2, 3], [1]), [0], gen_masked_array([2, 3], [0])), + # [1, d, 3] -> [d, 3]. Indices input is a numpy array + (gen_masked_array([1, 2, 3], [1]), np.array([0]), gen_masked_array([2, 3], [0])), + # [1, d, 3] -> [d, 3]. Indices input is a masked array + (gen_masked_array([1, 2, 3], [1]), gen_masked_array([0], []), gen_masked_array([2, 3], [0])), + # [1, d, 3] -> [d, 3]. Indices input is a numpy array with scalar + (gen_masked_array([1, 2, 3], [1]), np.array(0), gen_masked_array([2, 3], [0])), + # [1, d, 3] -> [d, 3]. Indices input is an integer + (gen_masked_array([1, 2, 3], [1]), 0, gen_masked_array([2, 3], [0])), # [1, d, 3] -> [d, 3] + (gen_masked_array([1, 2, 3, 4], [1]), [0, 2], gen_masked_array([2, 4], [0])), # [1, d, 3, 4] -> [d, 4] + (gen_masked_array([1, 2, 3], [1]), [0, 2, 1], gen_masked_array([], [])), # [1, d, 3] -> [] + (gen_masked_array([1, 2, 3], [1]), [0, 2], gen_masked_array([2], [0])), # [1, d, 3] -> [d] + # [1, d, d, 4] -> [d, d] + (gen_masked_array([1, 2, 3, 4], [1, 2]), [3, 0], gen_masked_array([2, 3], [0, 1])), + (gen_masked_array([1, 2, 3, 4], [2]), 3, gen_masked_array([1, 2, 3], [2])), # [1, 2, d, 4] -> [1, 2, d] + ([1, 2, 3, 4], [1], [1, 3, 4]), # [1, 2, 3, 4] -> [1, 3, 4]. Input is a regular lists + (np.array([1, 2, 3, 4]), [1], [1, 3, 4]), # [1, 2, 3, 4] -> [1, 3, 4]. Input is a regular arrays + (np.array([1, 2, 3, 4]), [-1, -3], [1, 3]), # [1, 2, 3, 4] -> [1, 3]. Negative indices + (np.array([1, 2, 3, 4]), -2, [1, 2, 4]), # [1, 2, 3, 4] -> [1, 2, 4]. Negative index + ]) + def test_shape_delete(self, shape, indices, result): + self.assertTrue(strict_compare_tensors(shape_delete(shape, indices), result)) + + def test_shape_delete_raise_exception(self): + with self.assertRaisesRegex(Error, '.*Incorrect parameter type.*'): + shape_delete(gen_masked_array([1, 2, 3], []), {}) + + +@generator +class ShapeInsertTest(unittest.TestCase): + @generate(*[(gen_masked_array([1, 2, 3], []), 1, [5], gen_masked_array([1, 5, 2, 3], [])), + (gen_masked_array([1, 2, 3], [1]), 1, [5], gen_masked_array([1, 5, 2, 3], [2])), + (gen_masked_array([1, 2, 3], [1]), 1, [dynamic_dimension], gen_masked_array([1, 5, 2, 3], [1, 2])), + (gen_masked_array([1, 2, 3], [1]), 0, [dynamic_dimension], gen_masked_array([5, 1, 2, 3], [0, 2])), + (gen_masked_array([1, 2, 3], [1]), np.int64(0), [dynamic_dimension], + gen_masked_array([5, 1, 2, 3], [0, 2])), + (gen_masked_array([1, 2, 3], [1]), 3, [dynamic_dimension], gen_masked_array([1, 2, 3, 5], [1, 3])), + (gen_masked_array([1, 2, 3], [1]), 3, [dynamic_dimension, dynamic_dimension], + gen_masked_array([1, 2, 3, 5, 6], [1, 3, 4])), + (gen_masked_array([1], [0]), 0, [7, dynamic_dimension], gen_masked_array([7, 5, 2], [1, 2])), + ]) + def test_shape_insert(self, shape, pos, values, result): + self.assertTrue(strict_compare_tensors(shape_insert(shape, pos, values), result)) + + def test_shape_insert_raise_exception(self): + with self.assertRaisesRegex(Error, '.*Incorrect parameter type.*'): + shape_insert(gen_masked_array([1, 2, 3], []), 2, {}) + diff --git a/model-optimizer/unit_tests/mo/front/extractor_test.py b/model-optimizer/unit_tests/mo/front/extractor_test.py index 27e70db8178..1e547f1d851 100644 --- a/model-optimizer/unit_tests/mo/front/extractor_test.py +++ b/model-optimizer/unit_tests/mo/front/extractor_test.py @@ -6,6 +6,7 @@ import unittest import numpy as np from generator import generator, generate +from mo.front.common.partial_infer.utils import strict_compare_tensors from mo.front.extractor import input_user_data_repack, output_user_data_repack, update_ie_fields, add_input_op, \ get_node_id_with_ports from mo.front.extractor import spatial_attr_getter, add_input_ops, attr_getter, CaffePythonFrontExtractorOp, \ @@ -293,8 +294,8 @@ class TestInputAddition(unittest.TestCase): self.assertTrue(graph.node[new_input_2]['is_input']) self.assertTrue((new_input_1, 'node_1') in graph.edges()) self.assertTrue((new_input_2, 'node_4') in graph.edges()) - self.assertListEqual(shape_1, graph.node[new_input_1]['shape']) - self.assertListEqual(shape_2, graph.node[new_input_2]['shape']) + self.assertTrue(strict_compare_tensors(shape_1, graph.node[new_input_1]['shape'])) + self.assertTrue(strict_compare_tensors(shape_2, graph.node[new_input_2]['shape'])) def test_two_inputs_two_shapes_not_all_inputs(self): shape_1 = [1, 2, 3, 4] diff --git a/model-optimizer/unit_tests/mo/front/mxnet/extractors/slice_axis_test.py b/model-optimizer/unit_tests/mo/front/mxnet/extractors/slice_axis_test.py index ee91b638f19..fd147528e72 100644 --- a/model-optimizer/unit_tests/mo/front/mxnet/extractors/slice_axis_test.py +++ b/model-optimizer/unit_tests/mo/front/mxnet/extractors/slice_axis_test.py @@ -28,7 +28,7 @@ class TestMXNetSliceAxisExtractorOp(unittest.TestCase): }) exp_attrs = { - 'type': 'Crop', + 'op': 'Crop', 'axis': 0, 'offset': 10, 'dim': 25 diff --git a/model-optimizer/unit_tests/mo/middle/passes/fusing/resnet_optimization_test.py b/model-optimizer/unit_tests/mo/middle/passes/fusing/resnet_optimization_test.py index b7129db0b3a..b1176b43731 100644 --- a/model-optimizer/unit_tests/mo/middle/passes/fusing/resnet_optimization_test.py +++ b/model-optimizer/unit_tests/mo/middle/passes/fusing/resnet_optimization_test.py @@ -407,9 +407,6 @@ class ResnetOptimizationTests(unittest.TestCase): graph.graph['layout'] = 'NCHW' graph_ref.graph['layout'] = 'NCHW' - # dump_graph_for_graphviz(graph) - # dump_graph_for_graphviz(graph_ref) - stride_optimization(graph) (flag, resp) = compare_graphs(graph, graph_ref, 'conv_3_data', check_op_attrs=True) @@ -511,9 +508,6 @@ class ResnetOptimizationTests(unittest.TestCase): graph.graph['layout'] = 'NCHW' graph_ref.graph['layout'] = 'NCHW' - # dump_graph_for_graphviz(graph) - # dump_graph_for_graphviz(graph_ref) - stride_optimization(graph) (flag, resp) = compare_graphs(graph, graph_ref, 'conv_3_data', check_op_attrs=True) diff --git a/model-optimizer/unit_tests/mo/ops/convolution_test.py b/model-optimizer/unit_tests/mo/ops/convolution_test.py index 68a1d5f6bca..3ae1858d2dd 100644 --- a/model-optimizer/unit_tests/mo/ops/convolution_test.py +++ b/model-optimizer/unit_tests/mo/ops/convolution_test.py @@ -5,7 +5,7 @@ import unittest import numpy as np -from mo.front.common.partial_infer.utils import int64_array +from mo.front.common.partial_infer.utils import int64_array, shape_array, dynamic_dimension_value, strict_compare_tensors from mo.graph.graph import Node from mo.ops.convolution import Convolution from mo.utils.error import Error @@ -52,6 +52,36 @@ class TestConvolutionPartialInfer(unittest.TestCase): for i in range(0, len(exp_shape)): self.assertEqual(exp_shape[i], res_shape[i]) + def test_caffe_conv2d_dynamic_input_infer(self): + graph = build_graph(nodes_attributes, + [('conv_input', 'conv_node'), + ('conv_weights', 'conv_node'), + ('conv_node', 'conv_output'), + ('conv_output', 'op_output') + ], + {'conv_output': {'shape': None}, + 'conv_input': {'shape': shape_array([1, 3, dynamic_dimension_value, 227])}, + 'conv_weights': {'shape': np.array([64, 3, 3, 3]), + 'dim_attrs': ['spatial_dims', 'channel_dims', 'batch_dims', 'axis']}, + 'conv_node': {'pad_spatial_shape': np.array([[0, 0], [0, 0]]), + 'conv_pad': np.array([[0, 0], [0, 0], [0, 0], [0, 0]]), + 'dilation': np.array([1, 1, 1, 1]), 'bias_addable': True, 'bias_term': False, + 'output_spatial_shape': None, 'output_shape': None, + 'stride': np.array([1, 1, 1, 1]), 'group': 1, + 'kernel_spatial_idx': np.array([2, 3]), + 'input_feature_channel': 1, + 'output_feature_channel': 0, + 'output': 64, 'kernel_spatial': np.array([3, 3]), + 'spatial_dims': np.array([2, 3]), 'channel_dims': np.array([1]), + 'batch_dims': np.array([0])} + }) + + conv_node = Node(graph, 'conv_node') + Convolution.infer(conv_node) + exp_shape = shape_array([1, 64, dynamic_dimension_value, 225]) + res_shape = graph.node['conv_output']['shape'] + self.assertTrue(strict_compare_tensors(exp_shape, res_shape)) + def test_caffe_conv2d_infer_no_shape(self): graph = build_graph(nodes_attributes, [('conv_input', 'conv_node'), @@ -74,9 +104,8 @@ class TestConvolutionPartialInfer(unittest.TestCase): }) conv_node = Node(graph, 'conv_node') - Convolution.infer(conv_node) - res_shape = graph.node['conv_output']['shape'] - self.assertIsNone(res_shape) + with self.assertRaisesRegex(Error, "Input data shape is None for node.*"): + Convolution.infer(conv_node) def test_deconv_infer_ideal(self): graph = build_graph(nodes_attributes, @@ -117,6 +146,42 @@ class TestConvolutionPartialInfer(unittest.TestCase): for i in range(0, len(exp_shape)): self.assertEqual(exp_shape[i], res_shape[i]) + def test_deconv_dynamic_infer_ideal(self): + graph = build_graph(nodes_attributes, + [('conv_input', 'conv_node'), + ('conv_weights', 'conv_node'), + ('conv_node', 'conv_output'), + ('conv_output', 'op_output') + ], + {'conv_output': {'shape': None}, + 'conv_input': {'shape': shape_array([1, 21, dynamic_dimension_value, 16])}, + 'conv_weights': {'shape': np.array([1, 21, 4, 4]), + 'dim_attrs': ['spatial_dims', 'channel_dims', 'batch_dims', 'axis']}, + 'conv_node': {#'spatial_dims': np.array([2, 3]), 'batch_dims': np.array([0]), + 'channel_dims': np.array([1]), 'bias_addable': True, 'bias_term': False, + 'batch_dims': np.array([0]), + 'pad_spatial_shape': np.array([[0, 0], [0, 0]]), + 'kernel_spatial': np.array([4, 4]), 'output_spatial_shape': None, + 'kernel_spatial_idx': np.array([2, 3]), + 'input_feature_channel': 1, + 'output_feature_channel': 0, + 'output_padding': np.array([0, 0, 1, 1]), + 'type': 'Deconvolution', 'output': 21, 'dilation': np.array([1, 1, 1, 1]), + 'group': 1, 'stride': np.array([1, 1, 2, 2]), 'output_shape': None} + }) + + deconv_node = Node(graph, 'conv_node') + + Convolution.infer(deconv_node) + res_shape = deconv_node['output_shape'] + exp_shape = shape_array([1, 21, dynamic_dimension_value, 35]) + + self.assertTrue(strict_compare_tensors(exp_shape, res_shape)) + + # Check that after double infer shape and pad attrs do not changes + Convolution.infer(deconv_node) + + self.assertTrue(strict_compare_tensors(exp_shape, res_shape)) def test_deconv_infer_no_shape(self): graph = build_graph(nodes_attributes, @@ -141,9 +206,8 @@ class TestConvolutionPartialInfer(unittest.TestCase): }) deconv_node = Node(graph, 'conv_node') - Convolution.infer(deconv_node) - res_shape = deconv_node['output_shape'] - self.assertIsNone(res_shape) + with self.assertRaisesRegex(Error, "Input data shape is None for node.*"): + Convolution.infer(deconv_node) def test_conv_infer_set_default_attrs_nchw(self): graph = build_graph(nodes_attributes, diff --git a/model-optimizer/unit_tests/mo/ops/crop_test.py b/model-optimizer/unit_tests/mo/ops/crop_test.py index 8a7336ffe0e..fcc88d8e2ab 100644 --- a/model-optimizer/unit_tests/mo/ops/crop_test.py +++ b/model-optimizer/unit_tests/mo/ops/crop_test.py @@ -8,6 +8,7 @@ import numpy as np from mo.front.common.partial_infer.utils import int64_array from mo.graph.graph import Node from mo.ops.crop import Crop +from mo.utils.error import Error from unit_tests.utils.graph import build_graph @@ -15,7 +16,7 @@ class TestCropPartialInfer(unittest.TestCase): @staticmethod def _create_graph_type1(): nodes_attributes = {'crop_input': {'shape': None, 'value': None, 'kind': 'data'}, - 'crop_node': {'type': 'Crop', 'kind': 'op'}, + 'crop_node': {'op': 'Crop', 'kind': 'op'}, 'crop_output': {'shape': None, 'value': None, 'kind': 'data'} } return build_graph(nodes_attributes, @@ -33,7 +34,7 @@ class TestCropPartialInfer(unittest.TestCase): @staticmethod def _create_graph_type2(): nodes_attributes = {'crop_input': {'shape': None, 'value': None, 'kind': 'data'}, - 'crop_node': {'type': 'Crop', 'kind': 'op'}, + 'crop_node': {'op': 'Crop', 'kind': 'op'}, 'crop_output': {'shape': None, 'value': None, 'kind': 'data'} } return build_graph(nodes_attributes, @@ -49,7 +50,7 @@ class TestCropPartialInfer(unittest.TestCase): def _create_graph_type3(): nodes_attributes = {'crop_input': {'shape': None, 'value': None, 'kind': 'data'}, 'crop_input2': {'shape': None, 'value': None, 'kind': 'data'}, - 'crop_node': {'type': 'Crop', 'kind': 'op'}, + 'crop_node': {'op': 'Crop', 'kind': 'op'}, 'crop_output': {'shape': None, 'value': None, 'kind': 'data'} } return build_graph(nodes_attributes, @@ -80,8 +81,8 @@ class TestCropPartialInfer(unittest.TestCase): crop_node = Node(graph, 'crop_node') crop_node['axis'] = None - Crop.infer(crop_node) - self.assertIsNone(crop_node.out_node().shape) + with self.assertRaisesRegex(Error, "axis attribute is missing .*"): + Crop.infer(crop_node) def test_crop_type1_infer_neg2(self): graph = self._create_graph_type1() @@ -89,8 +90,8 @@ class TestCropPartialInfer(unittest.TestCase): crop_node = Node(graph, 'crop_node') crop_node['crop_begin'] = int64_array([1, 2, 3]) - Crop.infer(crop_node) - self.assertIsNone(crop_node.out_node().shape) + with self.assertRaisesRegex(Error, "number of crop_begin.*"): + Crop.infer(crop_node) def test_crop_type2_infer(self): graph = self._create_graph_type2() @@ -110,8 +111,8 @@ class TestCropPartialInfer(unittest.TestCase): crop_node = Node(graph, 'crop_node') crop_node['dim'] = int64_array([1, 2, 3]) - Crop.infer(crop_node) - self.assertIsNone(crop_node.out_node().shape) + with self.assertRaisesRegex(Error, "Number of axis.*"): + Crop.infer(crop_node) def test_crop_type2_infer_neg2(self): graph = self._create_graph_type2() @@ -120,8 +121,8 @@ class TestCropPartialInfer(unittest.TestCase): crop_node['dim'] = None crop_node['crop_begin'] = None - Crop.infer(crop_node) - self.assertIsNone(crop_node.out_node().shape) + with self.assertRaisesRegex(Error, "Crop node crop_node should have either.*"): + Crop.infer(crop_node) def test_crop_type3_infer(self): graph = self._create_graph_type3() @@ -142,8 +143,8 @@ class TestCropPartialInfer(unittest.TestCase): crop_input2 = Node(graph, 'crop_input2') crop_input2.shape = None - Crop.infer(crop_node) - self.assertIsNone(crop_node.out_node().shape) + with self.assertRaisesRegex(Error, "Not all input shapes were defined.*"): + Crop.infer(crop_node) def test_crop_type3_infer_neg2(self): graph = self._create_graph_type3() @@ -151,8 +152,8 @@ class TestCropPartialInfer(unittest.TestCase): crop_node = Node(graph, 'crop_node') crop_node['axis'] = None - Crop.infer(crop_node) - self.assertIsNone(crop_node.out_node().shape) + with self.assertRaisesRegex(Error, "axis attribute is missing for .*"): + Crop.infer(crop_node) def test_crop_type3_infer_neg3(self): graph = self._create_graph_type3() @@ -160,8 +161,8 @@ class TestCropPartialInfer(unittest.TestCase): crop_node = Node(graph, 'crop_node') crop_node['offset'] = None - Crop.infer(crop_node) - self.assertIsNone(crop_node.out_node().shape) + with self.assertRaisesRegex(Error, "offset attribute is missing.*"): + Crop.infer(crop_node) def test_crop_type3_infer_neg4(self): graph = self._create_graph_type3() @@ -170,5 +171,5 @@ class TestCropPartialInfer(unittest.TestCase): crop_input2 = Node(graph, 'crop_input2') crop_input2.shape = int64_array([1, 4, 423, 563]) - Crop.infer(crop_node) - self.assertIsNone(crop_node.out_node().shape) + with self.assertRaisesRegex(Error, "The crop for dimension is out of bounds.*"): + Crop.infer(crop_node) diff --git a/model-optimizer/unit_tests/mo/ops/expand_dims_test.py b/model-optimizer/unit_tests/mo/ops/expand_dims_test.py index b31620997d7..dc94a4fad5a 100644 --- a/model-optimizer/unit_tests/mo/ops/expand_dims_test.py +++ b/model-optimizer/unit_tests/mo/ops/expand_dims_test.py @@ -6,6 +6,7 @@ import unittest import numpy as np from generator import generator, generate +from mo.front.common.partial_infer.utils import shape_array, dynamic_dimension_value, strict_compare_tensors from mo.graph.graph import Node from mo.ops.expand_dims import ExpandDims from unit_tests.utils.graph import build_graph @@ -47,6 +48,27 @@ class ExpandDimsOp(unittest.TestCase): self.assertTrue(np.array_equal(expand_dims_node.out_node().shape, np.array(ref_out_shape))) +@generator +class ExpandDimsOpDynamicDims(unittest.TestCase): + @generate(*[(0, [1, 2, 3, dynamic_dimension_value, 224]), + (1, [2, 1, 3, dynamic_dimension_value, 224]), + (2, [2, 3, 1, dynamic_dimension_value, 224]), + (3, [2, 3, dynamic_dimension_value, 1, 224]), + (4, [2, 3, dynamic_dimension_value, 224, 1]), + ]) + def test_expand_dims_infer(self, axis, ref_out_shape): + graph = build_graph(nodes_attributes, + [('data_1', 'expand_dims'), + ('expand_dims', 'data_2')], + {'expand_dims': {'expand_axis': axis}}) + Node(graph, 'data_1').shape = shape_array([2, 3, dynamic_dimension_value, 224]) + expand_dims_node = Node(graph, 'expand_dims') + + ExpandDims.infer(expand_dims_node) + + self.assertTrue(strict_compare_tensors(expand_dims_node.out_node().shape, shape_array(ref_out_shape))) + + @generator class ExpandDimsOpValueInfer(unittest.TestCase): @generate(*[(0, [2, 3, 224, 224], [1, 2, 3, 224, 224]), diff --git a/model-optimizer/unit_tests/mo/ops/pad_test.py b/model-optimizer/unit_tests/mo/ops/pad_test.py index efef1d6beb7..e58e590ec68 100644 --- a/model-optimizer/unit_tests/mo/ops/pad_test.py +++ b/model-optimizer/unit_tests/mo/ops/pad_test.py @@ -5,6 +5,8 @@ import unittest import numpy as np +from mo.front.common.partial_infer.utils import shape_array, dynamic_dimension_value, dynamic_dimension, \ + strict_compare_tensors from mo.graph.graph import Node from mo.ops.pad import Pad, AttributedPad from unit_tests.utils.graph import build_graph @@ -14,7 +16,8 @@ class TestPadOps(unittest.TestCase): node_attrs = { 'data_in': { 'kind': 'data', - 'shape': np.array([1, 3, 100, 200]) + 'shape': np.array([1, 3, 100, 200]), + 'value': None, }, 'pads_begin': { 'kind': 'data', @@ -93,3 +96,26 @@ class TestPadOps(unittest.TestCase): self.assertTrue(np.array_equal(Node(graph, 'data_out').shape, np.array([1, 3, 100 + 1 + 3, 200 + 2 + 4]))) self.assertTrue(np.array_equal(Node(graph, 'data_out').value, ref_value)) + self.assertFalse(isinstance(Node(graph, 'data_out').value, np.ma.masked_array)) + + def test_two_inputs_dynamic_value_infer(self): + in_value = shape_array([dynamic_dimension_value, 3]).reshape((1, 1, 1, 2)) + graph = build_graph( + self.node_attrs, + self.edge_attrs + [('pads_begin', 'pad'), ('pads_end', 'pad')], + {'data_in': {'value': in_value, 'shape': in_value.shape}}, + nodes_with_edges_only=True, + ) + out_shape = (1, 1, 5, 8) + mask = np.zeros(out_shape, dtype=np.bool) + mask[0][0][1][2] = True + ref_value = np.ma.masked_array(np.zeros(out_shape, dtype=np.int64), mask=mask, dtype=np.int64) + ref_value[0][0][1][3] = 3 + + pad_node = Node(graph, 'pad') + Pad.infer(pad_node) + output_value = Node(graph, 'data_out').value + self.assertTrue(np.array_equal(Node(graph, 'data_out').shape, ref_value.shape)) + self.assertTrue(strict_compare_tensors(output_value, ref_value)) + self.assertTrue(isinstance(output_value, np.ma.masked_array)) + self.assertTrue(output_value[0][0][1][2] is dynamic_dimension) diff --git a/model-optimizer/unit_tests/mo/ops/pooling_test.py b/model-optimizer/unit_tests/mo/ops/pooling_test.py index ec378e5565a..a36b21396ca 100644 --- a/model-optimizer/unit_tests/mo/ops/pooling_test.py +++ b/model-optimizer/unit_tests/mo/ops/pooling_test.py @@ -5,6 +5,7 @@ import unittest import numpy as np +from mo.front.common.partial_infer.utils import shape_array, dynamic_dimension_value, strict_compare_tensors from mo.graph.graph import Node from mo.ops.pooling import Pooling from mo.utils.error import Error @@ -13,7 +14,7 @@ from unit_tests.utils.graph import build_graph nodes_attributes = {'node_1': {'value': None, 'kind': 'data'}, 'pool': {'type': 'Pooling', 'value': None, 'kind': 'op'}, 'node_2': {'value': None, 'kind': 'data'}, - 'op_output': { 'kind': 'op', 'op': 'Result'}, + 'op_output': {'kind': 'op', 'op': 'Result'}, } @@ -44,6 +45,32 @@ class TestPoolingPartialInfer(unittest.TestCase): for i in range(0, len(exp_shape)): self.assertEqual(exp_shape[i], res_shape[i]) + def test_pooling_dynamic_infer(self): + graph = build_graph(nodes_attributes, + [('node_1', 'pool'), + ('pool', 'node_2'), + ('node_2', 'op_output') + ], + {'node_2': {'shape': None}, + 'node_1': {'shape': shape_array([1, dynamic_dimension_value, dynamic_dimension_value, + 256])}, + 'pool': {'window': np.array([1, 1, 1, 1]), 'stride': np.array([1, 1, 2, 2]), + 'pad': np.array([[0, 0], [0, 0], [3, 3], [3, 3]]), + 'pad_spatial_shape': np.array([[3, 3], [3, 3]]), + 'pool_method': 'avg', 'exclude_pad': False, 'global_pool': False, + 'output_spatial_shape': None, 'output_shape': None, + 'kernel_spatial': np.array([3, 3]), 'spatial_dims': np.array([2, 3]), + 'channel_dims': np.array([1]), 'batch_dims': np.array([0]), + 'pooling_convention': 'full'} + }) + + pool_node = Node(graph, 'pool') + + Pooling.infer(pool_node) + exp_shape = shape_array([1, dynamic_dimension_value, dynamic_dimension_value, 131]) + res_shape = graph.node['node_2']['shape'] + self.assertTrue(strict_compare_tensors(exp_shape, res_shape)) + def test_pooling_infer_decrement_input_spatial(self): graph = build_graph(nodes_attributes, [('node_1', 'pool'), diff --git a/model-optimizer/unit_tests/mo/ops/reshape_test.py b/model-optimizer/unit_tests/mo/ops/reshape_test.py new file mode 100644 index 00000000000..57d15d39170 --- /dev/null +++ b/model-optimizer/unit_tests/mo/ops/reshape_test.py @@ -0,0 +1,93 @@ +# Copyright (C) 2018-2021 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 + +import unittest + +import numpy as np +from generator import generate, generator + +from mo.front.common.partial_infer.utils import shape_array, dynamic_dimension_value, strict_compare_tensors +from mo.graph.graph import Node +from mo.ops.reshape import Reshape +from unit_tests.utils.graph import build_graph + +nodes_attributes = { + 'input': { + 'kind': 'op', + 'op': 'Parameter', + 'shape': None, + 'value': None, + }, + 'data': { + 'kind': 'data', + 'shape': None, + 'value': None, + }, + 'output_shape': { + 'kind': 'op', + 'op': 'Const', + 'value': None, + 'shape': None, + }, + 'output_shape_data': { + 'kind': 'data', + 'shape': None, + 'value': None, + }, + 'reshape': { + 'op': 'Reshape', + 'kind': 'op', + 'special_zero': True, + }, + 'reshape_out': { + 'kind': 'data', + 'shape': None, + 'value': None, + } +} + + +@generator +class TestReshapeShapeInfer(unittest.TestCase): + @generate(*[ + (None, shape_array([1, 100, 4]), shape_array([-1, 25]), None, [16, 25]), + (None, shape_array([5, 100, 4]), shape_array([0, -1, 25]), None, [5, 16, 25]), + (None, shape_array([5, dynamic_dimension_value, 4]), shape_array([4, -1, 5]), None, + shape_array([4, dynamic_dimension_value, 5])), + (None, shape_array([5, dynamic_dimension_value, 4]), shape_array([4, dynamic_dimension_value, 5]), None, + shape_array([4, dynamic_dimension_value, 5])), + (None, shape_array([dynamic_dimension_value, 4, 5]), shape_array([0, -1]), None, + shape_array([dynamic_dimension_value, 20])), + (None, shape_array([dynamic_dimension_value, 4, 5]), shape_array([5, -1, dynamic_dimension_value]), + None, shape_array([5, dynamic_dimension_value, dynamic_dimension_value])), + (None, shape_array([dynamic_dimension_value, 1, 546]), shape_array([dynamic_dimension_value, -1, 91]), + None, shape_array([dynamic_dimension_value, dynamic_dimension_value, 91])), + (None, shape_array([5, dynamic_dimension_value, 8]), shape_array([4, -1]), + None, shape_array([4, dynamic_dimension_value])), + (None, shape_array([dynamic_dimension_value]), shape_array([5]), None, shape_array([5])), + (None, shape_array([dynamic_dimension_value]), shape_array([0]), None, shape_array([dynamic_dimension_value])), + (None, shape_array([dynamic_dimension_value]), shape_array([-1]), None, shape_array([dynamic_dimension_value])), + (None, shape_array([dynamic_dimension_value]), shape_array([dynamic_dimension_value]), None, + shape_array([dynamic_dimension_value])), + # even though the target shape is dynamic since all the inputs are static so we can calculate output + (None, shape_array([5, 3, 8]), shape_array([4, dynamic_dimension_value]), None, shape_array([4, 30])), + (None, shape_array([3, 14, 5]), shape_array([dynamic_dimension_value, 2, 0]), None, shape_array([21, 2, 5])), + (shape_array([1, 2, dynamic_dimension_value, 4, 5, 6]), shape_array([6]), shape_array([-1, 2]), + shape_array([1, 2, dynamic_dimension_value, 4, 5, 6]).reshape((3, 2)), shape_array([3, 2])), + ]) + def test_reshape_infer(self, input_value, input_shape, output_shape, ref_value, ref_shape): + graph = build_graph(nodes_attributes, + [('input', 'data'), + ('data', 'reshape'), + ('output_shape', 'output_shape_data'), + ('output_shape_data', 'reshape'), + ('reshape', 'reshape_out')], + {'data': {'shape': input_shape, 'value': input_value}, + 'output_shape': {'value': output_shape, 'shape': output_shape.shape}, + 'output_shape_data': {'value': output_shape, 'shape': output_shape.shape}, + }) + node = Node(graph, 'reshape') + Reshape.infer(node) + if ref_value is not None: + self.assertTrue(strict_compare_tensors(node.out_port(0).data.get_value(), shape_array(ref_value))) + self.assertTrue(strict_compare_tensors(node.out_port(0).data.get_shape(), shape_array(ref_shape))) diff --git a/model-optimizer/unit_tests/mo/ops/slice_test.py b/model-optimizer/unit_tests/mo/ops/slice_test.py index b56c9274196..9a2134c32a7 100644 --- a/model-optimizer/unit_tests/mo/ops/slice_test.py +++ b/model-optimizer/unit_tests/mo/ops/slice_test.py @@ -6,7 +6,7 @@ import unittest import numpy as np from generator import generator, generate -from mo.front.common.partial_infer.utils import int64_array +from mo.front.common.partial_infer.utils import int64_array, dynamic_dimension_value, shape_array, strict_compare_tensors from mo.graph.graph import Node from mo.ops.slice import Slice from mo.utils.error import Error @@ -18,43 +18,74 @@ from unit_tests.utils.graph import build_graph, valued_const_with_data, valued_d class TestSliceOp(unittest.TestCase): @generate(*[ # standard case - ([[4, 5, 6, 7], [2, 3, 5, 6], [5, 6, 8, 9], [5, 6, 8, 9]], [0, 1], [3, 2], [0, 1], [1, 1], [[5], [3], [6]]), + ([[4, 5, 6, 7], [2, 3, 5, 6], [5, 6, 8, 9], [5, 6, 8, 9]], [4, 4], [0, 1], [3, 2], [0, 1], [1, 1], + [[5], [3], [6]], [3, 1]), # negative bounds - ([[4, 5, 6, 7], [2, 3, 5, 6], [5, 6, 8, 9], [5, 6, 8, 9]], [0, 1], [3, -2], [0, 1], [1, 1], [[5], [3], [6]]), + ([[4, 5, 6, 7], [2, 3, 5, 6], [5, 6, 8, 9], [5, 6, 8, 9]], [4, 4], [0, 1], [3, -2], [0, 1], [1, 1], + [[5], [3], [6]], [3, 1]), # unusual order of axes - ([[4, 5, 6, 7], [2, 3, 5, 6], [5, 6, 8, 9], [5, 6, 8, 9]], [0, 1], [3, -2], [1, 0], [1, 1], [[2, 3, 5]]), - # when only input_shape is defined without values (one from buttom element is shape) - (None, [1, 2], [4, 3], [0, 1], [1, 1], [3, 1, 6], [4, 5, 6]), + ([[4, 5, 6, 7], [2, 3, 5, 6], [5, 6, 8, 9], [5, 6, 8, 9]], [4, 4], [0, 1], [3, -2], [1, 0], [1, 1], + [[2, 3, 5]], [1, 3]), + # when only input_shape is defined without values (one from bottom element is shape) + (None, [4, 5, 6], [1, 2], [4, 3], [0, 1], [1, 1], None, [3, 1, 6]), # boundary case - (None, [0, 2], [np.iinfo(np.int32).max, 3], [0, 1], [1, 1], [4, 1, 6], [4, 5, 6]), + (None, [4, 5, 6], [0, 2], [np.iinfo(np.int32).max, 3], [0, 1], [1, 1], None, [4, 1, 6]), # boundary case - (None, [np.iinfo(np.int32).min, 2], [3, 3], [0, 1], [1, 1], [3, 1, 6], [4, 5, 6]), + (None, [4, 5, 6], [np.iinfo(np.int32).min, 2], [3, 3], [0, 1], [1, 1], None, [3, 1, 6],), # 1D input - ([1, 3, 224, 224], [1], [2], [0], [1], [3]), + ([1, 3, 224, 224], [4], [1], [2], [0], [1], [3], [1]), # 1D input with negative starts - (None, [-1], [1], [0], [-1], [2], [4]), + (None, [4], [-1], [1], [0], [-1], None, [2]), # 1D input with negative ends - (None, [1], [-1], [0], [1], [2], [4]), + (None, [4], [1], [-1], [0], [1], None, [2]), # with rounding (e.g. take from 1st to 3rd with step 4 should give shape 1 not 0) - (None, [1], [3], [0], [4], [1], [4]), + (None, [4], [1], [3], [0], [4], None, [1]), # with rounding and negative steps (e.g. take from 1st to 3rd with step 4 should give shape 1 not 0) - (None, [7], [3], [0], [-7], [1], [10]), + (None, [10], [7], [3], [0], [-7], None, [1]), # reversing the sequence of elements - (None, [-1], [np.iinfo(np.int32).min], [0], [-1], [10], [10]), + (None, [10], [-1], [np.iinfo(np.int32).min], [0], [-1], None, [10]), + # dynamic dimensions cases + # starts are non-constant + ([[4, 5, 6, 7], [2, 3, 5, 6], [5, 6, 8, 9], [5, 6, 8, 9]], [4, 4], None, [3, 2], [0, 1], [1, 1], None, + [dynamic_dimension_value, dynamic_dimension_value]), + # ends are non-constant + ([[4, 5, 6, 7], [2, 3, 5, 6], [5, 6, 8, 9], [5, 6, 8, 9]], [4, 4], [0, 1], None, [0, 1], [1, 1], None, + [dynamic_dimension_value, dynamic_dimension_value]), + # axes are non-constant + ([[4, 5, 6, 7], [2, 3, 5, 6], [5, 6, 8, 9], [5, 6, 8, 9]], [4, 4], [0, 1], [3, -2], None, [1, 1], None, + [dynamic_dimension_value, dynamic_dimension_value]), + # steps are non-constant + ([[4, 5, 6, 7], [2, 3, 5, 6], [5, 6, 8, 9], [5, 6, 8, 9]], [4, 4], [0, 1], [3, -2], [0, 1], None, None, + [dynamic_dimension_value, dynamic_dimension_value]), ]) - def test_slice_infer(self, inp_value, starts, ends, axes, steps, expected, inp_shape=None): + def test_slice_infer(self, inp_value, inp_shape, starts, ends, axes, steps, expected_value, expected_shape): if inp_value is None: input_node = shaped_data('data_1', int64_array(inp_shape)) else: input_node = valued_data('data_1', int64_array(inp_value)) + if inp_value is not None and inp_shape is not None: + assert np.array_equal(np.array(inp_value).shape, inp_shape) + + def convert_args(val, name=''): + if val is not None: + return valued_const_with_data(name, int64_array(val)) + else: + return shaped_const_with_data(name, [0]) #fake shape + + starts = convert_args(starts, 'starts') + ends = convert_args(ends, 'ends') + axes = convert_args(axes, 'axes') + steps = convert_args(steps, 'steps') + if expected_shape is not None: + expected_shape = shape_array(expected_shape) nodes = { **input_node, **regular_op_with_empty_data('slice', {'op': 'Slice'}), - **valued_const_with_data('starts', int64_array(starts)), - **valued_const_with_data('ends', int64_array(ends)), - **valued_const_with_data('axes', int64_array(axes)), - **valued_const_with_data('steps', int64_array(steps)), + **starts, + **ends, + **axes, + **steps, } graph = build_graph(nodes, @@ -69,21 +100,12 @@ class TestSliceOp(unittest.TestCase): slice_node = Node(graph, 'slice') Slice.infer(slice_node) - if inp_value is not None: - self.assertTrue(np.array_equal(slice_node.out_node().value, expected)) - else: - self.assertTrue(np.array_equal(slice_node.out_node().shape, expected)) + if expected_value is not None: + self.assertTrue(strict_compare_tensors(slice_node.out_node().value, expected_value)) + self.assertTrue(strict_compare_tensors(slice_node.out_node().shape, expected_shape)) # negative tests @generate(*[ - # starts are non-constant - ([[4, 5, 6, 7], [2, 3, 5, 6], [5, 6, 8, 9], [5, 6, 8, 9]], None, [3, 2], [0, 1], [1, 1], [[5], [3], [6]]), - # ends are non-constant - ([[4, 5, 6, 7], [2, 3, 5, 6], [5, 6, 8, 9], [5, 6, 8, 9]], [0, 1], None, [0, 1], [1, 1], [[5], [3], [6]]), - # axes are non-constant - ([[4, 5, 6, 7], [2, 3, 5, 6], [5, 6, 8, 9], [5, 6, 8, 9]], [0, 1], [3, -2], None, [1, 1], [[5], [3], [6]]), - # steps are non-constant - ([[4, 5, 6, 7], [2, 3, 5, 6], [5, 6, 8, 9], [5, 6, 8, 9]], [0, 1], [3, -2], [0, 1], None, [[5], [3], [6]]), # 1D input with negative starts (None, [1], [-1], [0], [-2], [-6], [20]), # case when output shape has zero elements @@ -106,9 +128,10 @@ class TestSliceOp(unittest.TestCase): axes = convert_args(axes, 'axes') steps = convert_args(steps, 'steps') - nodes = { **input_node, - **regular_op_with_empty_data('slice', {'op': 'Slice'}), - **starts, **ends, **axes, **steps } + nodes = {**input_node, + **regular_op_with_empty_data('slice', {'op': 'Slice'}), + **starts, **ends, **axes, **steps + } graph = build_graph(nodes, [('data_1', 'slice'), diff --git a/model-optimizer/unit_tests/mo/ops/squeeze_test.py b/model-optimizer/unit_tests/mo/ops/squeeze_test.py index 440763e674c..bf4cc224ccb 100644 --- a/model-optimizer/unit_tests/mo/ops/squeeze_test.py +++ b/model-optimizer/unit_tests/mo/ops/squeeze_test.py @@ -4,9 +4,12 @@ import unittest import numpy as np +from generator import generate, generator +from mo.front.common.partial_infer.utils import shape_array, dynamic_dimension_value, strict_compare_tensors from mo.graph.graph import Node from mo.ops.squeeze import Squeeze +from mo.utils.error import Error from unit_tests.utils.graph import build_graph nodes_attributes = { @@ -38,33 +41,36 @@ nodes_attributes = { } +@generator class TestSqueezeInfer(unittest.TestCase): - def test_squeeze_squeeze_dims(self): + @generate(*[ + (None, shape_array([1, 2, 1, 4]), shape_array([2]), None, [1, 2, 4]), + # allow squeezing dynamic dimensions + (None, shape_array([1, 2, dynamic_dimension_value, 4]), shape_array([2]), None, [1, 2, 4]), + (None, shape_array([1, 2, 1, 4]), shape_array([]), None, [2, 4]), + (None, shape_array([1, dynamic_dimension_value, 1, 4]), shape_array([]), None, + shape_array([dynamic_dimension_value, 4])), + # do not allow squeeze dimensions not equal to 1 + (None, shape_array([1, 2, 1, 4]), shape_array([1]), None, None), + # do not allow squeeze input shape to be None + (None, None, shape_array([1]), None, None), + ]) + def test_squeeze_squeeze_dims(self, input_value, input_shape, squeeze_dims, ref_value, ref_shape): graph = build_graph(nodes_attributes, [('data', 'squeeze'), ('squeeze_dims', 'squeeze_dims_data'), ('squeeze_dims_data', 'squeeze'), ('squeeze', 'data_out')], - {'data': {'shape': np.array([1, 2, 1, 4])}, - 'squeeze_dims': {'value': np.array([2]), 'shape': np.array([1])}, - 'squeeze_dims_data': {'value': np.array([2]), 'shape': np.array([1])}, + {'data': {'shape': input_shape, 'value': input_value}, + 'squeeze_dims': {'value': squeeze_dims, 'shape': squeeze_dims.shape}, + 'squeeze_dims_data': {'value': squeeze_dims, 'shape': squeeze_dims.shape}, }) node = Node(graph, 'squeeze') - Squeeze.infer(node) - - self.assertTrue(np.all(node.out_port(0).data.get_shape() == [1, 2, 4])) - - def test_squeeze_empty_squeeze_dims(self): - graph = build_graph(nodes_attributes, - [('data', 'squeeze'), - ('squeeze_dims', 'squeeze_dims_data'), - ('squeeze_dims_data', 'squeeze'), - ('squeeze', 'data_out')], - {'data': {'shape': np.array([1, 2, 1, 4])}, - 'squeeze_dims': {'value': np.array([]), 'shape': np.array([1])}, - 'squeeze_dims_data': {'value': np.array([]), 'shape': np.array([1])}, - }) - node = Node(graph, 'squeeze') - Squeeze.infer(node) - - self.assertTrue(np.all(node.out_port(0).data.get_shape() == [2, 4])) + if ref_shape is None: # the test should fail + with self.assertRaises(Error): + Squeeze.infer(node) + else: + Squeeze.infer(node) + if ref_value is not None: + self.assertTrue(strict_compare_tensors(node.out_port(0).data.get_value(), ref_value)) + self.assertTrue(strict_compare_tensors(node.out_port(0).data.get_shape(), ref_shape)) diff --git a/model-optimizer/unit_tests/mo/ops/strided_slice_test.py b/model-optimizer/unit_tests/mo/ops/strided_slice_test.py index c61f30b5d7d..0aed2dcb5fd 100644 --- a/model-optimizer/unit_tests/mo/ops/strided_slice_test.py +++ b/model-optimizer/unit_tests/mo/ops/strided_slice_test.py @@ -2,10 +2,9 @@ # SPDX-License-Identifier: Apache-2.0 import unittest +from collections.abc import Iterable -import numpy.testing as npt - -from mo.front.common.partial_infer.utils import int64_array +from mo.front.common.partial_infer.utils import shape_array, dynamic_dimension_value, strict_compare_tensors from mo.graph.graph import Node from mo.ops.strided_slice import StridedSlice from unit_tests.utils.graph import build_graph, valued_const_with_data, result, regular_op_with_empty_data, \ @@ -17,9 +16,9 @@ class TestStridedSliceInfer(unittest.TestCase): def run_test(self, inp, is_shape, ref_res, begin, end, strides, begin_mask, end_mask, shrink_axis_mask, new_axis_mask, ellipsis_mask): if is_shape: - input_node = shaped_const_with_data('input', int64_array(inp)) + input_node = shaped_const_with_data('input', shape_array(inp)) else: - input_node = valued_const_with_data('input', int64_array(inp)) + input_node = valued_const_with_data('input', shape_array(inp)) nodes = { **input_node, @@ -27,9 +26,9 @@ class TestStridedSliceInfer(unittest.TestCase): {'op': 'StridedSlice', 'begin_mask': begin_mask, 'end_mask': end_mask, 'shrink_axis_mask': shrink_axis_mask, 'ellipsis_mask': ellipsis_mask, 'new_axis_mask': new_axis_mask}), - **valued_const_with_data('begin', int64_array(begin)), - **valued_const_with_data('end', int64_array(end)), - **valued_const_with_data('strides', int64_array(strides)), + **valued_const_with_data('begin', shape_array(begin)), + **valued_const_with_data('end', shape_array(end)), + **valued_const_with_data('strides', shape_array(strides)), **result('res'), } @@ -45,7 +44,10 @@ class TestStridedSliceInfer(unittest.TestCase): node = Node(graph, 'sslice') StridedSlice.infer(node) res = node.out_port(0).data.get_shape() if is_shape else node.out_port(0).data.get_value() - npt.assert_array_equal(res, ref_res) + if isinstance(ref_res, Iterable): + self.assertTrue(strict_compare_tensors(res, shape_array(ref_res))) + else: + self.assertEqual(res, ref_res) def test_slice_infer_value_1( self, # out = inp[:4:1] inp=(1, 34, 34, 62), ref_res=(1, 34, 34, 62), is_shape=False, @@ -278,6 +280,33 @@ class TestStridedSliceInfer(unittest.TestCase): self.run_test(inp, is_shape, ref_res, begin, end, strides, begin_mask, end_mask, shrink_axis_mask, new_axis_mask, ellipsis_mask) + def test_slice_infer_dynamic_shape_1( + self, # inp[0:3, 0:1, 0:5] + inp=(dynamic_dimension_value, 10, 10, 10), ref_res=(dynamic_dimension_value, 1, 5, 10), is_shape=True, + begin=(0, 0, 0), end=(3, 1, 5), strides=(1, 1, 1), begin_mask=(1, 1, 1), end_mask=(1, 1, 1), + shrink_axis_mask=(0,), new_axis_mask=(0,), ellipsis_mask=(0,) + ): + self.run_test(inp, is_shape, ref_res, begin, end, strides, + begin_mask, end_mask, shrink_axis_mask, new_axis_mask, ellipsis_mask) + + def test_slice_infer_dynamic_shape_2( + self, # inp[0:d, 0:1, 0:5] + inp=(10, 10, 10, 10), ref_res=(dynamic_dimension_value, 1, 5, 10), is_shape=True, + begin=(0, 0, 0), end=(dynamic_dimension_value, 1, 5), strides=(1, 1, 1), begin_mask=(1, 1, 1), + end_mask=(1, 1, 1), shrink_axis_mask=(0,), new_axis_mask=(0,), ellipsis_mask=(0,) + ): + self.run_test(inp, is_shape, ref_res, begin, end, strides, + begin_mask, end_mask, shrink_axis_mask, new_axis_mask, ellipsis_mask) + + def test_slice_infer_dynamic_shape_3( + self, # inp[1:34, 0, :, :d] + inp=(1, 35, 35, 3), ref_res=(1, 35, dynamic_dimension_value), is_shape=True, + begin=(0, 0, 0, 0), end=(1, 34, 0, dynamic_dimension_value), strides=(1, 1, 1, 1), begin_mask=(1, 1, 0, 0), + end_mask=(1, 0, 0, 1), shrink_axis_mask=(0, 1, 0, 0), new_axis_mask=(0, 0, 0, 0), ellipsis_mask=(0, 0, 0, 0) + ): + self.run_test(inp, is_shape, ref_res, begin, end, strides, + begin_mask, end_mask, shrink_axis_mask, new_axis_mask, ellipsis_mask) + def test_strided_slice_0( self, # inp_shape = (1, 100, 200, 3), out = inp[np.newaxis, ..., 0, :], out_shape=(1, 1, 100, 3) inp=(1, 100, 200, 3), ref_res=(1, 1, 100, 3), is_shape=True, diff --git a/model-optimizer/unit_tests/mo/ops/unsqueeze_test.py b/model-optimizer/unit_tests/mo/ops/unsqueeze_test.py index 2368ffa603f..fdc80d1bcbc 100644 --- a/model-optimizer/unit_tests/mo/ops/unsqueeze_test.py +++ b/model-optimizer/unit_tests/mo/ops/unsqueeze_test.py @@ -4,9 +4,9 @@ import unittest import numpy as np -from generator import generator +from generator import generator, generate -from mo.front.common.partial_infer.utils import int64_array +from mo.front.common.partial_infer.utils import int64_array, shape_array, dynamic_dimension_value, strict_compare_tensors from mo.graph.graph import Node from mo.ops.unsqueeze import Unsqueeze from mo.utils.ir_engine.compare_graphs import compare_graphs @@ -39,14 +39,23 @@ class TestUnsqueezeOp(unittest.TestCase): } } - def test_unsqueeze_infer(self): - unsq_dims = np.array([0, 4]) + @generate(*[(shape_array([1, 3, 64, 64]), int64_array([0, 4]), shape_array([1, 1, 3, 64, 1, 64]), + int64_array([0, 4]), None, None), + (shape_array([2, 3, 64, 64]), int64_array([-1]), shape_array([2, 3, 64, 64, 1]), int64_array([4]), None, + None), + (shape_array([2, 3, dynamic_dimension_value, 64]), int64_array([0]), + shape_array([1, 2, 3, dynamic_dimension_value, 64]), int64_array([0]), None, None), + (shape_array([1, 2]), int64_array([-1]), shape_array([1, 2, 1]), int64_array([2]), + shape_array([5, dynamic_dimension_value]).reshape((1, 2)), + shape_array([5, dynamic_dimension_value]).reshape((1, 2, 1))), + ]) + def test_unsqueeze_infer(self, input_shape, unsq_dims, output_shape, ref_uns_dims, input_value, output_value): graph = build_graph(self.nodes_attributes, [('data_1', 'unsq'), ('unsq_dims_const', 'unsq_dims'), ('unsq_dims', 'unsq'), ('unsq', 'data_2')], - {'data_1': {'shape': np.array([1, 3, 64, 64])}, + {'data_1': {'shape': input_shape, 'value': input_value}, 'unsq_dims': {'value': unsq_dims, 'shape': unsq_dims.shape}, 'unsq_dims_const': {'value': unsq_dims, 'shape': unsq_dims.shape}, }) @@ -56,39 +65,10 @@ class TestUnsqueezeOp(unittest.TestCase): ('unsq_dims_const', 'unsq_dims'), ('unsq_dims', 'unsq'), ('unsq', 'data_2')], - {'data_1': {'shape': np.array([1, 3, 64, 64])}, - 'unsq_dims': {'value': unsq_dims, 'shape': unsq_dims.shape}, - 'unsq_dims_const': {'value': unsq_dims, 'shape': unsq_dims.shape}, - 'data_2': {'shape': np.array([1, 1, 3, 64, 1, 64])}, - }) - - unsqueeze_node = Node(graph, 'unsq') - Unsqueeze.infer(unsqueeze_node) - - (flag, resp) = compare_graphs(graph, graph_ref, 'data_2') - self.assertTrue(flag, resp) - - def test_unsqueeze_infer_negative_indices(self): - unsq_dims = np.array([-1]) - graph = build_graph(self.nodes_attributes, - [('data_1', 'unsq'), - ('unsq_dims_const', 'unsq_dims'), - ('unsq_dims', 'unsq'), - ('unsq', 'data_2')], - {'data_1': {'shape': np.array([2, 3, 64, 64])}, - 'unsq_dims': {'value': unsq_dims, 'shape': unsq_dims.shape}, - 'unsq_dims_const': {'value': unsq_dims, 'shape': unsq_dims.shape}, - }) - - graph_ref = build_graph(self.nodes_attributes, - [('data_1', 'unsq'), - ('unsq_dims_const', 'unsq_dims'), - ('unsq_dims', 'unsq'), - ('unsq', 'data_2')], - {'data_1': {'shape': np.array([2, 3, 64, 64])}, - 'unsq_dims': {'value': int64_array([4]), 'shape': unsq_dims.shape}, - 'unsq_dims_const': {'value': int64_array([4]), 'shape': unsq_dims.shape}, - 'data_2': {'shape': np.array([2, 3, 64, 64, 1])}, + {'data_1': {'shape': input_shape, 'value': input_value}, + 'unsq_dims': {'value': ref_uns_dims, 'shape': ref_uns_dims.shape}, + 'unsq_dims_const': {'value': ref_uns_dims, 'shape': ref_uns_dims.shape}, + 'data_2': {'shape': output_shape, 'value': output_value}, }) unsqueeze_node = Node(graph, 'unsq') @@ -96,3 +76,6 @@ class TestUnsqueezeOp(unittest.TestCase): (flag, resp) = compare_graphs(graph, graph_ref, 'data_2') self.assertTrue(flag, resp) + self.assertTrue(strict_compare_tensors(Node(graph, 'data_2').shape, Node(graph_ref, 'data_2').shape)) + if Node(graph_ref, 'data_2').value is not None: + self.assertTrue(strict_compare_tensors(Node(graph, 'data_2').value, Node(graph_ref, 'data_2').value)) diff --git a/model-optimizer/unit_tests/mo/utils/broadcasting_test.py b/model-optimizer/unit_tests/mo/utils/broadcasting_test.py index 34000193f35..5b2cab3233d 100644 --- a/model-optimizer/unit_tests/mo/utils/broadcasting_test.py +++ b/model-optimizer/unit_tests/mo/utils/broadcasting_test.py @@ -6,8 +6,9 @@ import unittest import numpy as np from generator import generator, generate -from mo.front.common.partial_infer.utils import int64_array -from mo.utils.broadcasting import uni_directional_broadcasting, uni_directional_shape_broadcasting +from mo.front.common.partial_infer.utils import int64_array, dynamic_dimension_value, shape_array, strict_compare_tensors +from mo.utils.broadcasting import uni_directional_broadcasting, uni_directional_shape_broadcasting, \ + bi_directional_shape_broadcasting @generator @@ -28,7 +29,62 @@ class TestingBroadcasting(unittest.TestCase): input_value = np.array(np.random.rand(*input_shape)) if expected_shape is not None: expected_value = np.broadcast_to(input_value, int64_array(target_shape)) - self.assertTrue(np.array_equal(uni_directional_broadcasting(input_value, int64_array(target_shape)), expected_value)) + self.assertTrue(np.array_equal(uni_directional_broadcasting(input_value, int64_array(target_shape)), + expected_value)) else: with self.assertRaisesRegex(Exception, '.*cannot be uni-directionally broadcasted.*'): uni_directional_broadcasting(input_value, int64_array(target_shape)) + + @generate(*[([], [20, 30, 10], [20, 30, 10]), + ([1], [20, 30, 10], [20, 30, 10]), + ([1, 1, 10], [20, 30, 10], [20, 30, 10]), + ([20, 1, 10], [20, 30, 10], [20, 30, 10]), + ([20, 30, 10], [20, 30, 10], [20, 30, 10]), + ([20, 30, 10], [5, 7, 20, 30, 10], [5, 7, 20, 30, 10]), + ([1, 2], [20, 3, 10, 2], [20, 3, 10, 2]), + ([1, 1], [1], None), + ([5, 10], [1, 10], None), + ([10, 2], shape_array([dynamic_dimension_value, 3, 10, 2]), + shape_array([dynamic_dimension_value, 3, 10, 2])), + (shape_array([10, dynamic_dimension_value]), shape_array([dynamic_dimension_value, 3, 10, 2]), + shape_array([dynamic_dimension_value, 3, 10, 2])), + (shape_array([dynamic_dimension_value, 2]), shape_array([dynamic_dimension_value, 3, 10, 2]), + shape_array([dynamic_dimension_value, 3, 10, 2])), + (shape_array([dynamic_dimension_value]), shape_array([1]), shape_array([1])), + (shape_array([1]), shape_array([dynamic_dimension_value]), shape_array([dynamic_dimension_value])), + (shape_array([dynamic_dimension_value]), shape_array([6]), shape_array([6])), + (shape_array([6]), shape_array([dynamic_dimension_value]), shape_array([6])), + ]) + def test_uni_directional_shape_broadcasting(self, input_shape, target_shape, expected_shape): + result = uni_directional_shape_broadcasting(input_shape, target_shape) + if expected_shape is None: + self.assertIsNone(result) + else: + self.assertTrue(strict_compare_tensors(result, expected_shape)) + + @generate(*[([], [20, 30, 10], [20, 30, 10]), + ([1], [20, 30, 10], [20, 30, 10]), + ([1, 1, 10], [20, 30, 10], [20, 30, 10]), + ([20, 1, 10], [20, 30, 10], [20, 30, 10]), + ([20, 30, 10], [20, 30, 10], [20, 30, 10]), + ([20, 30, 10], [5, 7, 20, 30, 10], [5, 7, 20, 30, 10]), + ([1, 2], [20, 3, 10, 2], [20, 3, 10, 2]), + ([3, 2], [3], None), + ([5, 10], [1, 20], None), + ([10, 2], shape_array([dynamic_dimension_value, 3, 1, 2]), + shape_array([dynamic_dimension_value, 3, 10, 2])), + (shape_array([10, dynamic_dimension_value]), shape_array([dynamic_dimension_value, 3, 1, 2]), + shape_array([dynamic_dimension_value, 3, 10, 2])), + (shape_array([dynamic_dimension_value, 2]), shape_array([dynamic_dimension_value, 3, 10, 1]), + shape_array([dynamic_dimension_value, 3, 10, 2])), + (shape_array([dynamic_dimension_value]), shape_array([1]), shape_array([dynamic_dimension_value])), + (shape_array([1]), shape_array([dynamic_dimension_value]), shape_array([dynamic_dimension_value])), + (shape_array([dynamic_dimension_value]), shape_array([6]), shape_array([6])), + (shape_array([6]), shape_array([dynamic_dimension_value]), shape_array([6])), + ]) + def test_bi_directional_shape_broadcasting(self, input_shape, target_shape, expected_shape): + result = bi_directional_shape_broadcasting(input_shape, target_shape) + if expected_shape is None: + self.assertIsNone(result) + else: + self.assertTrue(strict_compare_tensors(result, expected_shape)) diff --git a/model-optimizer/unit_tests/mo/utils/ir_engine/ir_engine_test.py b/model-optimizer/unit_tests/mo/utils/ir_engine/ir_engine_test.py index 74f386a38fe..f27d9fe3109 100644 --- a/model-optimizer/unit_tests/mo/utils/ir_engine/ir_engine_test.py +++ b/model-optimizer/unit_tests/mo/utils/ir_engine/ir_engine_test.py @@ -7,8 +7,10 @@ import sys import unittest from unittest import mock +import numpy as np from generator import generator, generate +from mo.front.common.partial_infer.utils import shape_array, strict_compare_tensors from mo.graph.graph import Node from mo.utils.ir_engine.ir_engine import IREngine @@ -45,9 +47,10 @@ class TestFunction(unittest.TestCase): self.assertTrue(flag, 'Comparing false, test compare function failed') log.info('Test for function compare passed') - def test_comare_negative(self): + def test_compare_negative(self): # Reference data for test: - reference_msg = 'Current node "2" with type Const and reference node "2" with type Input have different attr "type" : Const and Input' + reference_msg = 'Current node "2" with type "Const" and reference node "2" with type "Input" have different ' \ + 'attr "type" : Const and Input' # Check function: flag, msg = self.IR.compare(self.IR_negative) self.assertFalse(flag, 'Comparing flag failed, test compare function failed') @@ -64,11 +67,11 @@ class TestFunction(unittest.TestCase): def test_get_inputs(self): # Reference data for test: - ref_input_dict = {'data': [1, 10, 16]} + ref_input_dict = {'data': shape_array([1, 10, 16])} # Check function: inputs_dict = self.IR.get_inputs() - # is_equal = compare_dictionaries(ref_input_dict, inputs_dict) - self.assertTrue(ref_input_dict == inputs_dict, 'Test on function get_inputs failed') + self.assertTrue(strict_compare_tensors(ref_input_dict['data'], inputs_dict['data']), + 'Test on function get_inputs failed') log.info('Test for function get_inputs passed') def test_eq_function(self): diff --git a/model-optimizer/unit_tests/mo/utils/telemetry_utils_test.py b/model-optimizer/unit_tests/mo/utils/telemetry_utils_test.py index 36d10d749f6..bfa692a0cf3 100644 --- a/model-optimizer/unit_tests/mo/utils/telemetry_utils_test.py +++ b/model-optimizer/unit_tests/mo/utils/telemetry_utils_test.py @@ -5,7 +5,7 @@ import unittest from collections import Counter from unittest.mock import Mock -from mo.front.common.partial_infer.utils import int64_array +from mo.front.common.partial_infer.utils import int64_array, shape_array, dynamic_dimension_value from mo.graph.graph import Graph, Node from mo.utils.telemetry_utils import send_op_names_info, send_shapes_info from unit_tests.utils.graph import build_graph, regular_op @@ -63,7 +63,8 @@ class TestTelemetryUtils(unittest.TestCase): '{partially_defined_shape:0,fw:framework}') def test_send_dynamic_shapes_case1(self): - graph = build_graph({**regular_op('placeholder1', {'shape': int64_array([-1, 3, 20, 20]), 'type': 'Parameter'}), + graph = build_graph({**regular_op('placeholder1', {'shape': shape_array([dynamic_dimension_value, 3, 20, 20]), + 'type': 'Parameter'}), **regular_op('mul', {'shape': int64_array([7, 8]), 'type': 'Multiply'})}, []) self.init_telemetry_mocks() @@ -76,13 +77,14 @@ class TestTelemetryUtils(unittest.TestCase): def test_send_dynamic_shapes_case2(self): graph = build_graph({**regular_op('placeholder1', {'shape': int64_array([2, 3, 20, 20]), 'type': 'Parameter'}), **regular_op('placeholder2', {'shape': int64_array([7, 4, 10]), 'type': 'Parameter'}), - **regular_op('placeholder3', {'shape': int64_array([5, 4, 0]), 'type': 'Parameter'}), + **regular_op('placeholder3', {'shape': shape_array([5, 4, dynamic_dimension_value]), + 'type': 'Parameter'}), **regular_op('mul', {'shape': int64_array([7, 8]), 'type': 'Multiply'})}, []) self.init_telemetry_mocks() send_shapes_info('framework', graph) tm.Telemetry.send_event.assert_any_call('mo', 'input_shapes', - '{fw:framework,shape:"[ 2 3 20 20],[ 7 4 10],[5 4 0]"}') + '{fw:framework,shape:"[ 2 3 20 20],[ 7 4 10],[ 5 4 -1]"}') tm.Telemetry.send_event.assert_any_call('mo', 'partially_defined_shape', '{partially_defined_shape:1,fw:framework}') diff --git a/model-optimizer/unit_tests/mo/utils/utils_test.py b/model-optimizer/unit_tests/mo/utils/utils_test.py index afc493adfc3..8ff211a2ece 100644 --- a/model-optimizer/unit_tests/mo/utils/utils_test.py +++ b/model-optimizer/unit_tests/mo/utils/utils_test.py @@ -3,27 +3,27 @@ import unittest -import numpy as np - +from mo.front.common.partial_infer.utils import shape_array, dynamic_dimension_value from mo.utils.utils import match_shapes class TestMatchShapes(unittest.TestCase): - def run_match_shapes(self, pattern: list, shape: list): - return match_shapes(np.array(pattern, dtype=np.int64), np.array(shape, dtype=np.int64)) + return match_shapes(shape_array(pattern), shape_array(shape)) def test_positive(self): self.assertTrue(self.run_match_shapes([], [])) - self.assertTrue(self.run_match_shapes([1,2,3], [1,2,3])) - self.assertTrue(self.run_match_shapes([-1,2,3], [1,2,3])) - self.assertTrue(self.run_match_shapes([1,-1,3], [1,2,3])) - self.assertTrue(self.run_match_shapes([-1,-1,-1], [1,2,3])) - self.assertTrue(self.run_match_shapes([-1], [2])) + self.assertTrue(self.run_match_shapes([1, 2, 3], [1, 2, 3])) + self.assertTrue(self.run_match_shapes([dynamic_dimension_value, 2, 3], [1, 2, 3])) + self.assertTrue(self.run_match_shapes([1, dynamic_dimension_value, 3], [1, 2, 3])) + self.assertTrue(self.run_match_shapes([dynamic_dimension_value, dynamic_dimension_value, + dynamic_dimension_value], [1, 2, 3])) + self.assertTrue(self.run_match_shapes([dynamic_dimension_value], [2])) def test_negative(self): - self.assertFalse(self.run_match_shapes([-1], [])) - self.assertFalse(self.run_match_shapes([-1], [1,2,3])) - self.assertFalse(self.run_match_shapes([-1,2,3], [1,3,3])) - self.assertFalse(self.run_match_shapes([1,-1,3], [2,2])) - self.assertFalse(self.run_match_shapes([-1, -1, -1], [2, 3, 4, 5])) + self.assertFalse(self.run_match_shapes([dynamic_dimension_value], [])) + self.assertFalse(self.run_match_shapes([dynamic_dimension_value], [1, 2, 3])) + self.assertFalse(self.run_match_shapes([dynamic_dimension_value, 2, 3], [1, 3, 3])) + self.assertFalse(self.run_match_shapes([1, dynamic_dimension_value, 3], [2, 2])) + self.assertFalse(self.run_match_shapes([dynamic_dimension_value, dynamic_dimension_value, + dynamic_dimension_value], [2, 3, 4, 5])) diff --git a/model-optimizer/unit_tests/utils/graph.py b/model-optimizer/unit_tests/utils/graph.py index 2d15ef523e6..4360e4c2844 100644 --- a/model-optimizer/unit_tests/utils/graph.py +++ b/model-optimizer/unit_tests/utils/graph.py @@ -7,7 +7,7 @@ from copy import deepcopy import networkx as nx from extensions.ops.parameter import Parameter -from mo.front.common.partial_infer.utils import int64_array +from mo.front.common.partial_infer.utils import int64_array, shape_array from mo.graph.graph import Node, Graph from mo.middle.pattern_match import all_edges_in_nodes from mo.ops.const import Const @@ -39,7 +39,7 @@ def check_and_update_ports(node, edges_data: list, in_port: bool = True): def build_graph_with_attrs(nodes_with_attrs: list, edges_with_attrs: list, new_nodes_with_attrs: list = [], new_edges_with_attrs: list = [], update_edge_attrs: dict = None, - update_nodes_attributes: dict = None, nodes_with_edges_only: bool = False, + update_nodes_attributes: list = None, nodes_with_edges_only: bool = False, add_nodes_from_edges: bool = False): """ Build the Graph with specific nodes and edges. Also update of edge and node parameters is supported. @@ -48,8 +48,9 @@ def build_graph_with_attrs(nodes_with_attrs: list, edges_with_attrs: list, new_n :param new_nodes_with_attrs: analogically nodes_with_attrs :param new_edges_with_attrs: analogically new_edges :param update_edge_attrs: optional dictionary like {('from_node', 'to_node', key): {edge_attrs}}. - :param update_nodes_attributes: optional dictionary which specifies nodes names and their attributes to be updated. The - key is a node name to update attribute and the value is a dictionary with attribute name and its value. + :param update_nodes_attributes: optional list of tuples which specifies nodes names and their attributes to be + updated. The first element is a node name to update attribute and the second element is a dictionary with attribute + name and its value. :param nodes_with_edges_only: add nodes which has at least one incoming or outcoming edge. :param add_nodes_from_edges: whether nodes that is not listed in all_nodes but are in all_edges is allowed. :return: generated graph. @@ -273,7 +274,7 @@ regular_op = lambda name, kwargs: {name: {'kind': 'op', 'type': 'NoType', **kwar valued_data = lambda name, value: {name: {'kind': 'data', 'value': value, 'shape': int64_array(value.shape) if value is not None else None}} shaped_data = lambda name, shape: {name: {'kind': 'data', 'value': None, - 'shape': int64_array(shape) if shape is not None else None}} + 'shape': shape_array(shape) if shape is not None else None}} empty_data = lambda name: valued_data(name, None) shaped_parameter = lambda name, shape, kwargs={}: {**regular_op(name, {'op': 'Parameter', 'type': 'Parameter', @@ -294,7 +295,7 @@ const = lambda name, value, kwargs={}: {name: {'kind': 'op', 'type': 'Const', 'o fake_const = lambda name, shape, kwargs={}: {name: {'kind': 'op', 'op': 'Const', 'type': 'Const', 'value': None, 'infer': Const.infer, **kwargs, - 'shape': int64_array(shape) if shape is not None else None}} + 'shape': shape_array(shape) if shape is not None else None}} shaped_const_with_data = lambda name, shape, kwargs={}: {**fake_const(name, shape, kwargs), **shaped_data(name + '_d', shape)} From 2e626f502d69c40c557b52bcb677582442ff9361 Mon Sep 17 00:00:00 2001 From: Ilya Churaev Date: Wed, 1 Sep 2021 15:25:36 +0300 Subject: [PATCH 72/76] Remove redundant header aftter PR #6969 (#7320) --- .../shared/include/behavior/infer_request.hpp | 656 ------------------ 1 file changed, 656 deletions(-) delete mode 100644 inference-engine/tests/functional/plugin/shared/include/behavior/infer_request.hpp diff --git a/inference-engine/tests/functional/plugin/shared/include/behavior/infer_request.hpp b/inference-engine/tests/functional/plugin/shared/include/behavior/infer_request.hpp deleted file mode 100644 index 66af6d6397c..00000000000 --- a/inference-engine/tests/functional/plugin/shared/include/behavior/infer_request.hpp +++ /dev/null @@ -1,656 +0,0 @@ -// Copyright (C) 2018-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#pragma once - -#include -#include -#include -#include -#include -#include -#include "ie_extension.h" -#include -#include "shared_test_classes/base/layer_test_utils.hpp" -#include "ngraph_functions/utils/ngraph_helpers.hpp" -#include "ngraph_functions/builders.hpp" -#include -#include -#include -#include -#include "common_test_utils/common_utils.hpp" -#include "functional_test_utils/plugin_cache.hpp" -#include "functional_test_utils/blob_utils.hpp" -#include "ngraph_functions/subgraph_builders.hpp" -#include "shared_test_classes/subgraph/basic_lstm.hpp" - -namespace BehaviorTestsDefinitions { -using InferRequestTests = BehaviorTestsUtils::BehaviorTestsBasic; - -// Setting empty config to LoadNetwork doesn't throw -TEST_P(InferRequestTests, SetEmptyConfig) { - // Skip test according to plugin specific disabledTestPatterns() (if any) - SKIP_IF_CURRENT_TEST_IS_DISABLED() - // Create CNNNetwork from ngrpah::Function - InferenceEngine::CNNNetwork cnnNet(function); - // Load CNNNetwork to target plugins - InferenceEngine::ExecutableNetwork execNet; - std::map config {}; - if (targetDevice.find(CommonTestUtils::DEVICE_AUTO) == std::string::npos && - targetDevice.find(CommonTestUtils::DEVICE_MULTI) == std::string::npos && - targetDevice.find(CommonTestUtils::DEVICE_HETERO) == std::string::npos) { - ASSERT_NO_THROW(ie->SetConfig(configuration, targetDevice)); - ASSERT_NO_THROW(execNet = ie->LoadNetwork(cnnNet, targetDevice, config)); - } else { - ASSERT_NO_THROW(ie->SetConfig(configuration, targetDevice)); - ASSERT_NO_THROW(execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration)); - } -} - -// Load correct network to Plugin to get executable network -TEST_P(InferRequestTests, canLoadCorrectNetworkToGetExecutable) { - // Skip test according to plugin specific disabledTestPatterns() (if any) - SKIP_IF_CURRENT_TEST_IS_DISABLED() - // Create CNNNetwork from ngrpah::Function - InferenceEngine::CNNNetwork cnnNet(function); - InferenceEngine::ExecutableNetwork execNet; - ASSERT_NO_THROW(execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration)); -} - -TEST_P(InferRequestTests, CanCreateTwoExeNetworks) { - // Skip test according to plugin specific disabledTestPatterns() (if any) - SKIP_IF_CURRENT_TEST_IS_DISABLED() - // Create CNNNetwork from ngrpah::Function - InferenceEngine::CNNNetwork cnnNet(function); - InferenceEngine::ExecutableNetwork execNet; - for (auto i = 0; i < 2; i++) { - ASSERT_NO_THROW(execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration)); - ASSERT_NE(nullptr, cnnNet.getFunction()); - } -} - -TEST_P(InferRequestTests, CanCreateInferRequest) { - // Skip test according to plugin specific disabledTestPatterns() (if any) - SKIP_IF_CURRENT_TEST_IS_DISABLED() - // Create CNNNetwork from ngrpah::Function - InferenceEngine::CNNNetwork cnnNet(function); - // Load CNNNetwork to target plugins - auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); - // Create InferRequest - InferenceEngine::InferRequest req; - ASSERT_NO_THROW(req = execNet.CreateInferRequest()); -} - -TEST_P(InferRequestTests, failToSetNullptrForInput) { - // Skip test according to plugin specific disabledTestPatterns() (if any) - SKIP_IF_CURRENT_TEST_IS_DISABLED() - // Create CNNNetwork from ngrpah::Function - InferenceEngine::CNNNetwork cnnNet(function); - // Load CNNNetwork to target plugins - auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); - // Create InferRequest - InferenceEngine::InferRequest req; - ASSERT_NO_THROW(req = execNet.CreateInferRequest()); - InferenceEngine::Blob::Ptr inputBlob = nullptr; - ASSERT_THROW(req.SetBlob(cnnNet.getInputsInfo().begin()->first, inputBlob), - InferenceEngine::Exception); -} - -TEST_P(InferRequestTests, failToSetEmptyInputBlob) { - // Skip test according to plugin specific disabledTestPatterns() (if any) - SKIP_IF_CURRENT_TEST_IS_DISABLED() - // Create CNNNetwork from ngrpah::Function - InferenceEngine::CNNNetwork cnnNet(function); - // Load CNNNetwork to target plugins - auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); - // Create InferRequest - InferenceEngine::InferRequest req; - ASSERT_NO_THROW(req = execNet.CreateInferRequest()); - InferenceEngine::Blob::Ptr blob; - ASSERT_THROW(req.SetBlob(cnnNet.getInputsInfo().begin()->first, blob), - InferenceEngine::Exception); -} - -TEST_P(InferRequestTests, failToSetEmptyOutputBlob) { - // Skip test according to plugin specific disabledTestPatterns() (if any) - SKIP_IF_CURRENT_TEST_IS_DISABLED() - // Create CNNNetwork from ngrpah::Function - InferenceEngine::CNNNetwork cnnNet(function); - // Load CNNNetwork to target plugins - auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); - // Create InferRequest - InferenceEngine::InferRequest req; - ASSERT_NO_THROW(req = execNet.CreateInferRequest()); - InferenceEngine::Blob::Ptr blob; - ASSERT_THROW(req.SetBlob(cnnNet.getOutputsInfo().begin()->first, blob), - InferenceEngine::Exception); -} - -TEST_P(InferRequestTests, failToSetNotAllocatedInput) { - // Skip test according to plugin specific disabledTestPatterns() (if any) - SKIP_IF_CURRENT_TEST_IS_DISABLED() - // Create CNNNetwork from ngrpah::Function - InferenceEngine::CNNNetwork cnnNet(function); - // Load CNNNetwork to target plugins - auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); - // Create InferRequest - InferenceEngine::InferRequest req; - ASSERT_NO_THROW(req = execNet.CreateInferRequest()); - InferenceEngine::Blob::Ptr blob = - FuncTestUtils::createAndFillBlob(cnnNet.getInputsInfo().begin()->second->getTensorDesc()); - ASSERT_NO_THROW(req.SetBlob(cnnNet.getInputsInfo().begin()->first, blob)); -} - -TEST_P(InferRequestTests, failToSetNotAllocatedOutput) { - // Skip test according to plugin specific disabledTestPatterns() (if any) - SKIP_IF_CURRENT_TEST_IS_DISABLED() - // Create CNNNetwork from ngrpah::Function - InferenceEngine::CNNNetwork cnnNet(function); - // Load CNNNetwork to target plugins - auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); - // Create InferRequest - InferenceEngine::InferRequest req; - ASSERT_NO_THROW(req = execNet.CreateInferRequest()); - InferenceEngine::Blob::Ptr blob = - FuncTestUtils::createAndFillBlob(cnnNet.getOutputsInfo().begin()->second->getTensorDesc()); - ASSERT_NO_THROW(req.SetBlob(cnnNet.getOutputsInfo().begin()->first, blob)); -} - -TEST_P(InferRequestTests, failToSetBlobWithIncorrectName) { - // Skip test according to plugin specific disabledTestPatterns() (if any) - SKIP_IF_CURRENT_TEST_IS_DISABLED() - // Create CNNNetwork from ngrpah::Function - InferenceEngine::CNNNetwork cnnNet(function); - // Load CNNNetwork to target plugins - auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); - // Create InferRequest - InferenceEngine::InferRequest req; - const char incorrect_input_name[] = "incorrect_input_name"; - ASSERT_NO_THROW(req = execNet.CreateInferRequest()); - InferenceEngine::Blob::Ptr blob = - FuncTestUtils::createAndFillBlob(cnnNet.getInputsInfo().begin()->second->getTensorDesc()); - blob->allocate(); - ASSERT_THROW(req.SetBlob(incorrect_input_name, blob), - InferenceEngine::Exception); -} - -TEST_P(InferRequestTests, failToSetInputWithIncorrectSizes) { - // Skip test according to plugin specific disabledTestPatterns() (if any) - SKIP_IF_CURRENT_TEST_IS_DISABLED() - // Create CNNNetwork from ngrpah::Function - InferenceEngine::CNNNetwork cnnNet(function); - // Load CNNNetwork to target plugins - auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); - // Create InferRequest - InferenceEngine::InferRequest req; - ASSERT_NO_THROW(req = execNet.CreateInferRequest()); - InferenceEngine::Blob::Ptr blob = - FuncTestUtils::createAndFillBlob(cnnNet.getInputsInfo().begin()->second->getTensorDesc()); - blob->allocate(); - blob->getTensorDesc().getDims()[0]*=2; - ASSERT_THROW(req.SetBlob(cnnNet.getInputsInfo().begin()->first, blob), - InferenceEngine::Exception); -} - -TEST_P(InferRequestTests, failToSetOutputWithIncorrectSizes) { - // Skip test according to plugin specific disabledTestPatterns() (if any) - SKIP_IF_CURRENT_TEST_IS_DISABLED() - // Create CNNNetwork from ngrpah::Function - InferenceEngine::CNNNetwork cnnNet(function); - // Load CNNNetwork to target plugins - auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); - // Create InferRequest - InferenceEngine::InferRequest req; - ASSERT_NO_THROW(req = execNet.CreateInferRequest()); - InferenceEngine::Blob::Ptr blob = - FuncTestUtils::createAndFillBlob(cnnNet.getOutputsInfo().begin()->second->getTensorDesc()); - blob->allocate(); - blob->getTensorDesc().getDims()[0]*=2; - ASSERT_THROW(req.SetBlob(cnnNet.getOutputsInfo().begin()->first, blob), - InferenceEngine::Exception); -} - -TEST_P(InferRequestTests, canInferWithoutSetAndGetInOut) { - // Skip test according to plugin specific disabledTestPatterns() (if any) - SKIP_IF_CURRENT_TEST_IS_DISABLED() - // Create CNNNetwork from ngrpah::Function - InferenceEngine::CNNNetwork cnnNet(function); - // Load CNNNetwork to target plugins - auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); - // Create InferRequest - InferenceEngine::InferRequest req; - ASSERT_NO_THROW(req = execNet.CreateInferRequest()); - ASSERT_NO_THROW(req.Infer()); -} - -TEST_P(InferRequestTests, canProcessDeallocatedInputBlobAfterGetBlob) { - // Skip test according to plugin specific disabledTestPatterns() (if any) - SKIP_IF_CURRENT_TEST_IS_DISABLED() - // Create CNNNetwork from ngrpah::Function - InferenceEngine::CNNNetwork cnnNet(function); - // Load CNNNetwork to target plugins - auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); - // Create InferRequest - InferenceEngine::InferRequest req; - InferenceEngine::Blob::Ptr blob; - ASSERT_NO_THROW(req = execNet.CreateInferRequest()); - ASSERT_NO_THROW(blob = req.GetBlob(cnnNet.getInputsInfo().begin()->first)); - ASSERT_NO_THROW(req.Infer()); -} - -TEST_P(InferRequestTests, canProcessDeallocatedInputBlobAfterGetBlobForAsync) { - // Skip test according to plugin specific disabledTestPatterns() (if any) - SKIP_IF_CURRENT_TEST_IS_DISABLED() - // Create CNNNetwork from ngrpah::Function - InferenceEngine::CNNNetwork cnnNet(function); - // Load CNNNetwork to target plugins - auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); - // Create InferRequest - InferenceEngine::InferRequest req; - InferenceEngine::Blob::Ptr blob; - ASSERT_NO_THROW(req = execNet.CreateInferRequest()); - ASSERT_NO_THROW(blob = req.GetBlob(cnnNet.getInputsInfo().begin()->first)); - ASSERT_NO_THROW(req.Infer()); - ASSERT_NO_THROW(req.StartAsync()); -} - -TEST_P(InferRequestTests, canProcessDeallocatedInputBlobAfterGetAndSetBlob) { - // Skip test according to plugin specific disabledTestPatterns() (if any) - SKIP_IF_CURRENT_TEST_IS_DISABLED() - // Create CNNNetwork from ngrpah::Function - InferenceEngine::CNNNetwork cnnNet(function); - // Load CNNNetwork to target plugins - auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); - // Create InferRequest - InferenceEngine::InferRequest req; - InferenceEngine::Blob::Ptr blob; - ASSERT_NO_THROW(req = execNet.CreateInferRequest()); - ASSERT_NO_THROW(blob = req.GetBlob(cnnNet.getInputsInfo().begin()->first)); - ASSERT_NO_THROW(req.SetBlob(cnnNet.getInputsInfo().begin()->first, blob)); - ASSERT_NO_THROW(req.Infer()); - ASSERT_NO_THROW(req.StartAsync()); -} - -TEST_P(InferRequestTests, canProcessDeallocatedInputBlobAfterSetBlob) { - // Skip test according to plugin specific disabledTestPatterns() (if any) - SKIP_IF_CURRENT_TEST_IS_DISABLED() - // Create CNNNetwork from ngrpah::Function - InferenceEngine::CNNNetwork cnnNet(function); - // Load CNNNetwork to target plugins - auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); - // Create InferRequest - InferenceEngine::InferRequest req; - InferenceEngine::Blob::Ptr blob = - FuncTestUtils::createAndFillBlob(cnnNet.getInputsInfo().begin()->second->getTensorDesc()); - ASSERT_NO_THROW(req = execNet.CreateInferRequest()); - blob->allocate(); - ASSERT_NO_THROW(req.SetBlob(cnnNet.getInputsInfo().begin()->first, blob)); - blob->deallocate(); - ASSERT_THROW(req.Infer(), InferenceEngine::Exception); -} - -TEST_P(InferRequestTests, canProcessDeallocatedOutputBlobAfterGetBlob) { - // Skip test according to plugin specific disabledTestPatterns() (if any) - SKIP_IF_CURRENT_TEST_IS_DISABLED() - // Create CNNNetwork from ngrpah::Function - InferenceEngine::CNNNetwork cnnNet(function); - // Load CNNNetwork to target plugins - auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); - // Create InferRequest - InferenceEngine::InferRequest req; - InferenceEngine::Blob::Ptr blob = - FuncTestUtils::createAndFillBlob(cnnNet.getOutputsInfo().begin()->second->getTensorDesc()); - ASSERT_NO_THROW(req = execNet.CreateInferRequest()); - blob->allocate(); - ASSERT_NO_THROW(req.SetBlob(cnnNet.getOutputsInfo().begin()->first, blob)); - blob->deallocate(); - ASSERT_THROW(req.Infer(), InferenceEngine::Exception); -} - -TEST_P(InferRequestTests, canProcessDeallocatedOutputBlobAfterGetBlobForAsync) { - // Skip test according to plugin specific disabledTestPatterns() (if any) - SKIP_IF_CURRENT_TEST_IS_DISABLED() - // Create CNNNetwork from ngrpah::Function - InferenceEngine::CNNNetwork cnnNet(function); - // Load CNNNetwork to target plugins - auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); - // Create InferRequest - InferenceEngine::InferRequest req; - InferenceEngine::Blob::Ptr blob = - FuncTestUtils::createAndFillBlob(cnnNet.getOutputsInfo().begin()->second->getTensorDesc()); - ASSERT_NO_THROW(req = execNet.CreateInferRequest()); - blob->allocate(); - ASSERT_NO_THROW(req.SetBlob(cnnNet.getOutputsInfo().begin()->first, blob)); - blob->deallocate(); - ASSERT_THROW(req.Infer(), InferenceEngine::Exception); - ASSERT_THROW({ req.StartAsync(); req.Wait(); }, InferenceEngine::Exception); -} - -TEST_P(InferRequestTests, canProcessDeallocatedOutputBlobAfterGetAndSetBlob) { - // Skip test according to plugin specific disabledTestPatterns() (if any) - SKIP_IF_CURRENT_TEST_IS_DISABLED() - // Create CNNNetwork from ngrpah::Function - InferenceEngine::CNNNetwork cnnNet(function); - // Load CNNNetwork to target plugins - auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); - // Create InferRequest - InferenceEngine::InferRequest req; - InferenceEngine::Blob::Ptr blob = - FuncTestUtils::createAndFillBlob(cnnNet.getOutputsInfo().begin()->second->getTensorDesc()); - ASSERT_NO_THROW(req = execNet.CreateInferRequest()); - blob->allocate(); - ASSERT_NO_THROW(blob = req.GetBlob(cnnNet.getOutputsInfo().begin()->first)); - ASSERT_NO_THROW(req.SetBlob(cnnNet.getOutputsInfo().begin()->first, blob)); - blob->deallocate(); - ASSERT_THROW(req.Infer(), InferenceEngine::Exception); -} - -TEST_P(InferRequestTests, canProcessDeallocatedOutputBlobAfterSetBlob) { - // Skip test according to plugin specific disabledTestPatterns() (if any) - SKIP_IF_CURRENT_TEST_IS_DISABLED() - // Create CNNNetwork from ngrpah::Function - InferenceEngine::CNNNetwork cnnNet(function); - // Load CNNNetwork to target plugins - auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); - // Create InferRequest - InferenceEngine::InferRequest req; - InferenceEngine::Blob::Ptr blob = - FuncTestUtils::createAndFillBlob(cnnNet.getOutputsInfo().begin()->second->getTensorDesc()); - ASSERT_NO_THROW(req = execNet.CreateInferRequest()); - blob->allocate(); - ASSERT_NO_THROW(req.SetBlob(cnnNet.getOutputsInfo().begin()->first, blob)); - blob->deallocate(); - ASSERT_THROW(req.Infer(), InferenceEngine::Exception); -} - -TEST_P(InferRequestTests, secondCallGetOutputDoNotReAllocateData) { - // Skip test according to plugin specific disabledTestPatterns() (if any) - SKIP_IF_CURRENT_TEST_IS_DISABLED() - // Create CNNNetwork from ngrpah::Function - InferenceEngine::CNNNetwork cnnNet(function); - // Load CNNNetwork to target plugins - auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); - // Create InferRequest - InferenceEngine::InferRequest req; - InferenceEngine::Blob::Ptr blob1; - InferenceEngine::Blob::Ptr blob2; - ASSERT_NO_THROW(req = execNet.CreateInferRequest()); - ASSERT_NO_THROW(blob1 = req.GetBlob(cnnNet.getInputsInfo().begin()->first)); - ASSERT_NO_THROW(blob2 = req.GetBlob(cnnNet.getInputsInfo().begin()->first)); - ASSERT_EQ(blob1.get(), blob2.get()); -} - -TEST_P(InferRequestTests, CorrectOneAsyncInferWithGetInOutWithInfWait) { - // Skip test according to plugin specific disabledTestPatterns() (if any) - SKIP_IF_CURRENT_TEST_IS_DISABLED() - // Create CNNNetwork from ngrpah::Function - InferenceEngine::CNNNetwork cnnNet(function); - // Load CNNNetwork to target plugins - auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); - // Create InferRequest - InferenceEngine::InferRequest req; - InferenceEngine::Blob::Ptr blob; - ASSERT_NO_THROW(req = execNet.CreateInferRequest()); - ASSERT_NO_THROW(blob = req.GetBlob(cnnNet.getInputsInfo().begin()->first)); - req.Infer(); - req.StartAsync(); - InferenceEngine::StatusCode sts; - sts = req.Wait(InferenceEngine::InferRequest::WaitMode::RESULT_READY); - ASSERT_EQ(InferenceEngine::StatusCode::OK, sts); - ASSERT_NO_THROW(blob = req.GetBlob(cnnNet.getOutputsInfo().begin()->first)); -} - -// Plugin correct infer request with allocating input and result BlobMaps inside plugin -TEST_P(InferRequestTests, canStartAsyncInferWithGetInOutWithStatusOnlyWait) { - // Skip test according to plugin specific disabledTestPatterns() (if any) - SKIP_IF_CURRENT_TEST_IS_DISABLED() - // Create CNNNetwork from ngrpah::Function - InferenceEngine::CNNNetwork cnnNet(function); - // Load CNNNetwork to target plugins - auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); - // Create InferRequest - InferenceEngine::InferRequest req; - InferenceEngine::Blob::Ptr blob = - FuncTestUtils::createAndFillBlob(cnnNet.getOutputsInfo().begin()->second->getTensorDesc()); - ASSERT_NO_THROW(req = execNet.CreateInferRequest()); - ASSERT_NO_THROW(blob = req.GetBlob(cnnNet.getInputsInfo().begin()->first)); - req.Infer(); - req.StartAsync(); - InferenceEngine::StatusCode sts; - sts = req.Wait(InferenceEngine::InferRequest::WaitMode::STATUS_ONLY); - ASSERT_TRUE(sts == InferenceEngine::StatusCode::OK || - sts == InferenceEngine::StatusCode::RESULT_NOT_READY); -} - -// Plugin correct infer request with allocating input and result BlobMaps inside plugin -TEST_P(InferRequestTests, FailedAsyncInferWithNegativeTimeForWait) { - // Skip test according to plugin specific disabledTestPatterns() (if any) - SKIP_IF_CURRENT_TEST_IS_DISABLED() - // Create CNNNetwork from ngrpah::Function - InferenceEngine::CNNNetwork cnnNet(function); - // Load CNNNetwork to target plugins - auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); - // Create InferRequest - InferenceEngine::InferRequest req; - InferenceEngine::Blob::Ptr blob = - FuncTestUtils::createAndFillBlob(cnnNet.getOutputsInfo().begin()->second->getTensorDesc()); - ASSERT_NO_THROW(req = execNet.CreateInferRequest()); - ASSERT_NO_THROW(blob = req.GetBlob(cnnNet.getInputsInfo().begin()->first)); - req.Infer(); - req.StartAsync(); - ASSERT_THROW(req.Wait(-2), InferenceEngine::Exception); -} - -TEST_P(InferRequestTests, canRun3SyncRequestsConsistentlyFromThreads) { - // Skip test according to plugin specific disabledTestPatterns() (if any) - SKIP_IF_CURRENT_TEST_IS_DISABLED() - // Create CNNNetwork from ngrpah::Function - InferenceEngine::CNNNetwork cnnNet(function); - // Load CNNNetwork to target plugins - auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); - // Create InferRequest - auto req1 = execNet.CreateInferRequest(); - auto req2 = execNet.CreateInferRequest(); - auto req3 = execNet.CreateInferRequest(); - - - auto f1 = std::async(std::launch::async, [&] { req1.Infer();}); - auto f2 = std::async(std::launch::async, [&] { req2.Infer();}); - auto f3 = std::async(std::launch::async, [&] { req3.Infer();}); - - ASSERT_NO_THROW(f1.get()); - ASSERT_NO_THROW(f2.get()); - ASSERT_NO_THROW(f3.get()); -} - -TEST_P(InferRequestTests, canRun3AsyncRequestsConsistentlyWithWait) { - // Skip test according to plugin specific disabledTestPatterns() (if any) - SKIP_IF_CURRENT_TEST_IS_DISABLED() - // Create CNNNetwork from ngrpah::Function - InferenceEngine::CNNNetwork cnnNet(function); - // Load CNNNetwork to target plugins - auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); - // Create InferRequest - auto req1 = execNet.CreateInferRequest(); - auto req2 = execNet.CreateInferRequest(); - auto req3 = execNet.CreateInferRequest(); - - req1.StartAsync(); - ASSERT_NO_THROW(req1.Wait(InferenceEngine::InferRequest::WaitMode::RESULT_READY)); - - req2.Infer(); - ASSERT_NO_THROW(req2.Wait(InferenceEngine::InferRequest::WaitMode::RESULT_READY)); - - req3.Infer(); - ASSERT_NO_THROW(req3.Wait(InferenceEngine::InferRequest::WaitMode::RESULT_READY)); -} - -TEST_P(InferRequestTests, canRun3AsyncRequestsConsistentlyFromThreadsWithoutWait) { - // Skip test according to plugin specific disabledTestPatterns() (if any) - SKIP_IF_CURRENT_TEST_IS_DISABLED() - // Create CNNNetwork from ngrpah::Function - InferenceEngine::CNNNetwork cnnNet(function); - // Load CNNNetwork to target plugins - auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); - // Create InferRequest - auto req1 = execNet.CreateInferRequest(); - auto req2 = execNet.CreateInferRequest(); - auto req3 = execNet.CreateInferRequest(); - InferenceEngine::ResponseDesc response1, response2, response3; - InferenceEngine::StatusCode sts1, sts2, sts3; - - req1.Infer(); - req2.Infer(); - req3.Infer(); - - std::thread t1([&] { req1.StartAsync(); sts1 = req1.Wait(InferenceEngine::InferRequest::WaitMode::RESULT_READY); }); - std::thread t2([&] { req2.StartAsync(); sts2 = req2.Wait(InferenceEngine::InferRequest::WaitMode::RESULT_READY); }); - std::thread t3([&] { req3.StartAsync(); sts3 = req3.Wait(InferenceEngine::InferRequest::WaitMode::RESULT_READY); }); - - t1.join(); - t2.join(); - t3.join(); - - ASSERT_EQ(static_cast(InferenceEngine::StatusCode::OK), sts1) << response1.msg; - ASSERT_EQ(static_cast(InferenceEngine::StatusCode::OK), sts2) << response2.msg; - ASSERT_EQ(static_cast(InferenceEngine::StatusCode::OK), sts3) << response3.msg; -} - -TEST_P(InferRequestTests, canWaitWithotStartAsync) { - // Skip test according to plugin specific disabledTestPatterns() (if any) - SKIP_IF_CURRENT_TEST_IS_DISABLED() - // Create CNNNetwork from ngrpah::Function - InferenceEngine::CNNNetwork cnnNet(function); - // Load CNNNetwork to target plugins - auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); - // Create InferRequest - auto req = execNet.CreateInferRequest(); - ASSERT_NO_THROW(req.Wait(InferenceEngine::InferRequest::WaitMode::RESULT_READY)); - ASSERT_NO_THROW(req.Wait(InferenceEngine::InferRequest::WaitMode::STATUS_ONLY)); - ASSERT_NO_THROW(req.Wait(1)); -} - -TEST_P(InferRequestTests, returnDeviceBusyOnSetBlobAfterAsyncInfer) { - // Skip test according to plugin specific disabledTestPatterns() (if any) - SKIP_IF_CURRENT_TEST_IS_DISABLED() - auto&& config = configuration; - auto itConfig = config.find(CONFIG_KEY(CPU_THROUGHPUT_STREAMS)); - if (itConfig != config.end()) { - if (itConfig->second != "CPU_THROUGHPUT_AUTO") { - if (std::stoi(itConfig->second) == 0) { - GTEST_SKIP() << "Not applicable with disabled streams"; - } - } - } - // Create CNNNetwork from ngrpah::Function - InferenceEngine::CNNNetwork cnnNet(function); - // Load CNNNetwork to target plugins - auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); - // Create InferRequest - auto req = execNet.CreateInferRequest(); - auto outputBlob = req.GetBlob(cnnNet.getInputsInfo().begin()->first); - InferenceEngine::ResponseDesc response; - - InferenceEngine::StatusCode sts; - sts = req.Wait(InferenceEngine::InferRequest::WaitMode::STATUS_ONLY); - ASSERT_EQ(InferenceEngine::StatusCode::INFER_NOT_STARTED, sts) << response.msg; - req.StartAsync(); - sts = req.Wait(InferenceEngine::InferRequest::WaitMode::RESULT_READY); - ASSERT_EQ(static_cast(InferenceEngine::StatusCode::OK), sts) << response.msg; - try { - req.SetBlob(cnnNet.getInputsInfo().begin()->first, outputBlob); - } - catch (const std::exception &e) { - std::cout << "Exception: " << e.what() << std::endl; - } - sts = req.Wait(InferenceEngine::InferRequest::WaitMode::STATUS_ONLY); - ASSERT_TRUE(sts == InferenceEngine::StatusCode::OK || - sts == InferenceEngine::StatusCode::RESULT_NOT_READY) << response.msg; -} - -TEST_P(InferRequestTests, returnDeviceBusyOnGetBlobAfterAsyncInfer) { - // Skip test according to plugin specific disabledTestPatterns() (if any) - SKIP_IF_CURRENT_TEST_IS_DISABLED() - // Create CNNNetwork from ngrpah::Function - InferenceEngine::CNNNetwork cnnNet(function); - // Load CNNNetwork to target plugins - auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); - // Create InferRequest - auto req = execNet.CreateInferRequest(); - auto outputBlob = req.GetBlob(cnnNet.getInputsInfo().begin()->first); - InferenceEngine::ResponseDesc response; - InferenceEngine::StatusCode sts; - req.StartAsync(); - sts = req.Wait(InferenceEngine::InferRequest::WaitMode::RESULT_READY); - ASSERT_EQ(static_cast(InferenceEngine::StatusCode::OK), sts) << response.msg; - try { - req.SetBlob(cnnNet.getInputsInfo().begin()->first, outputBlob); - } - catch (const std::exception &e) { - std::cout << "Exception" << e.what() << std::endl; - } -} - -TEST_P(InferRequestTests, returnDeviceBusyOnGetPerformanceCountAfterAsyncInfer) { - // Skip test according to plugin specific disabledTestPatterns() (if any) - SKIP_IF_CURRENT_TEST_IS_DISABLED() - // Create CNNNetwork from ngrpah::Function - InferenceEngine::CNNNetwork cnnNet(function); - // Load CNNNetwork to target plugins - auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); - // Create InferRequest - auto req = execNet.CreateInferRequest(); - auto outputBlob = req.GetBlob(cnnNet.getInputsInfo().begin()->first); - InferenceEngine::ResponseDesc response; - InferenceEngine::StatusCode sts; - req.StartAsync(); - sts = req.Wait(InferenceEngine::InferRequest::WaitMode::RESULT_READY); - ASSERT_EQ(static_cast(InferenceEngine::StatusCode::OK), sts) << response.msg; - - std::map perfMap; - - try { - perfMap = req.GetPerformanceCounts(); - } - catch (const std::exception &e) { - std::cout << "Exception" << e.what() << std::endl; - } -} - -class InferRequestTestsResultNotReady : public InferRequestTests { -}; - -TEST_P(InferRequestTestsResultNotReady, ReturnResultNotReadyFromWaitInAsyncModeForTooSmallTimeout) { - // Skip test according to plugin specific disabledTestPatterns() (if any) - SKIP_IF_CURRENT_TEST_IS_DISABLED() - // Create CNNNetwork from ngraph::Function - // return ngrpah::Function - // GetNetwork(3000, 380) make inference around 20ms on GNA SW - // so increases chances for getting RESULT_NOT_READY - function = SubgraphTestsDefinitions::Basic_LSTM_S::GetNetwork(300, 38); - InferenceEngine::CNNNetwork cnnNet(function); - // Load CNNNetwork to target plugins - auto execNet = ie->LoadNetwork(cnnNet, targetDevice, configuration); - // Create InferRequest - InferenceEngine::InferRequest req; - ASSERT_NO_THROW(req = execNet.CreateInferRequest()); - InferenceEngine::StatusCode sts = InferenceEngine::StatusCode::OK; - std::promise callbackTimeStamp; - auto callbackTimeStampFuture = callbackTimeStamp.get_future(); - // add a callback to the request and capture the timestamp - req.SetCompletionCallback([&]() { - callbackTimeStamp.set_value(std::chrono::system_clock::now()); - }); - req.StartAsync(); - ASSERT_NO_THROW(sts = req.Wait(InferenceEngine::InferRequest::WaitMode::STATUS_ONLY)); - // get timestamp taken AFTER return from the Wait(STATUS_ONLY) - const auto afterWaitTimeStamp = std::chrono::system_clock::now(); - // IF the callback timestamp is larger than the afterWaitTimeStamp - // then we should observe RESULT_NOT_READY - if (afterWaitTimeStamp < callbackTimeStampFuture.get()) { - ASSERT_TRUE(sts == InferenceEngine::StatusCode::RESULT_NOT_READY); - } - ASSERT_NO_THROW(req.Wait(InferenceEngine::InferRequest::WaitMode::RESULT_READY)); -} -} // namespace BehaviorTestsDefinitions From b3428b5312a2a6e2519cd5e43a3e267d175894e2 Mon Sep 17 00:00:00 2001 From: Victor Kuznetsov Date: Wed, 1 Sep 2021 18:06:39 +0300 Subject: [PATCH 73/76] update references for memcheck pre-commit (refs from 2021.4) (#7063) * update references for memcheck pre-commit (refs from 2021.4) * add distro==1.5.0 * merge master * upd only gpu refs * upd config memcheck --- .../desktop_references_config.xml | 73 +++++++++++-------- 1 file changed, 42 insertions(+), 31 deletions(-) diff --git a/tests/stress_tests/.automation/memcheck_tests/precommit_configs/desktop_references_config.xml b/tests/stress_tests/.automation/memcheck_tests/precommit_configs/desktop_references_config.xml index 87e2e36522b..fadaaabfcc5 100644 --- a/tests/stress_tests/.automation/memcheck_tests/precommit_configs/desktop_references_config.xml +++ b/tests/stress_tests/.automation/memcheck_tests/precommit_configs/desktop_references_config.xml @@ -3,54 +3,62 @@ - # values from {"commit_id": "2947789b3b18a724096abbd9a5c535ae3128ce05", "commit_date": "2021-07-12 23:30"} and *= 1.3 - - # values from {"commit_id": "2947789b3b18a724096abbd9a5c535ae3128ce05", "commit_date": "2021-07-12 23:30"} and *= 1.3 + # values from {"branch": "releases/2021/4", "commit_id": "96bc1b9bfb6140981e88bf09ee756b70f1723533", "commit_date": "2021-08-13 14:38"} and *= 1.3 # values from {"commit_id": "761e571042fa2b291d5954e523fffc1e2dfcafae", "commit_date": "2021-05-20 10:36"} and *= 1.3 - # values from {"commit_id": "2947789b3b18a724096abbd9a5c535ae3128ce05", "commit_date": "2021-07-12 23:30"} and *= 1.3 + # values from {"branch": "releases/2021/4", "commit_id": "96bc1b9bfb6140981e88bf09ee756b70f1723533", "commit_date": "2021-08-13 14:38"} and *= 1.3 + + # values from {"branch": "releases/2021/4", "commit_id": "96bc1b9bfb6140981e88bf09ee756b70f1723533", "commit_date": "2021-08-13 14:38"} and *= 1.3 + - # values from {"commit_id": "2947789b3b18a724096abbd9a5c535ae3128ce05", "commit_date": "2021-07-12 23:30"} and *= 1.3 - - # values from {"commit_id": "2947789b3b18a724096abbd9a5c535ae3128ce05", "commit_date": "2021-07-12 23:30"} and *= 1.3 + # values from {"branch": "releases/2021/4", "commit_id": "96bc1b9bfb6140981e88bf09ee756b70f1723533", "commit_date": "2021-08-13 14:38"} and *= 1.3 # values from {"commit_id": "761e571042fa2b291d5954e523fffc1e2dfcafae", "commit_date": "2021-05-20 10:36"} and *= 1.3 - # values from {"commit_id": "2947789b3b18a724096abbd9a5c535ae3128ce05", "commit_date": "2021-07-12 23:30"} and *= 1.3 + # values from {"branch": "releases/2021/4", "commit_id": "96bc1b9bfb6140981e88bf09ee756b70f1723533", "commit_date": "2021-08-13 14:38"} and *= 1.3 + + # values from {"branch": "releases/2021/4", "commit_id": "96bc1b9bfb6140981e88bf09ee756b70f1723533", "commit_date": "2021-08-13 14:38"} and *= 1.3 + - # values from {"commit_id": "2947789b3b18a724096abbd9a5c535ae3128ce05", "commit_date": "2021-07-12 23:30"} and *= 1.3 + # values from {"branch": "releases/2021/4", "commit_id": "96bc1b9bfb6140981e88bf09ee756b70f1723533", "commit_date": "2021-08-13 14:38"} and *= 1.3 + # values from {"branch": "releases/2021/4", "commit_id": "96bc1b9bfb6140981e88bf09ee756b70f1723533", "commit_date": "2021-08-13 14:38"} and *= 1.3 + # values from {"branch": "releases/2021/4", "commit_id": "96bc1b9bfb6140981e88bf09ee756b70f1723533", "commit_date": "2021-08-13 14:38"} and *= 1.3 - # values from {"commit_id": "2947789b3b18a724096abbd9a5c535ae3128ce05", "commit_date": "2021-07-12 23:30"} and *= 1.3 - # values from {"commit_id": "761e571042fa2b291d5954e523fffc1e2dfcafae", "commit_date": "2021-05-20 10:36"} and *= 1.3 - # values from {"commit_id": "2947789b3b18a724096abbd9a5c535ae3128ce05", "commit_date": "2021-07-12 23:30"} and *= 1.3 + # values from {"branch": "releases/2021/4", "commit_id": "96bc1b9bfb6140981e88bf09ee756b70f1723533", "commit_date": "2021-08-13 14:38"} and *= 1.3 + - # values from {"commit_id": "2947789b3b18a724096abbd9a5c535ae3128ce05", "commit_date": "2021-07-12 23:30"} and *= 1.3 + # values from {"branch": "releases/2021/4", "commit_id": "96bc1b9bfb6140981e88bf09ee756b70f1723533", "commit_date": "2021-08-13 14:38"} and *= 1.3 # values from {"commit_id": "761e571042fa2b291d5954e523fffc1e2dfcafae", "commit_date": "2021-05-20 10:36"} and *= 1.3 - # values from {"commit_id": "2947789b3b18a724096abbd9a5c535ae3128ce05", "commit_date": "2021-07-12 23:30"} and *= 1.3 + # values from {"branch": "releases/2021/4", "commit_id": "96bc1b9bfb6140981e88bf09ee756b70f1723533", "commit_date": "2021-08-13 14:38"} and *= 1.3 - # values from {"commit_id": "2947789b3b18a724096abbd9a5c535ae3128ce05", "commit_date": "2021-07-12 23:30"} and *= 1.3 + # values from {"branch": "releases/2021/4", "commit_id": "96bc1b9bfb6140981e88bf09ee756b70f1723533", "commit_date": "2021-08-13 14:38"} and *= 1.3 + # values from {"commit_id": "af63cb78ee5cbd66bac0d0980db61cb11b5d9995", "commit_date": "2021-03-03 15:44"} and *= 1.3 - # values from {"commit_id": "2947789b3b18a724096abbd9a5c535ae3128ce05", "commit_date": "2021-07-12 23:30"} and *= 1.3 - # values from {"commit_id": "af63cb78ee5cbd66bac0d0980db61cb11b5d9995", "commit_date": "2021-03-03 15:44"} and *= 1.3 - # values from {"commit_id": "2947789b3b18a724096abbd9a5c535ae3128ce05", "commit_date": "2021-07-12 23:30"} and *= 1.3 + # values from {"branch": "releases/2021/4", "commit_id": "96bc1b9bfb6140981e88bf09ee756b70f1723533", "commit_date": "2021-08-13 14:38"} and *= 1.3 # values from {"commit_id": "761e571042fa2b291d5954e523fffc1e2dfcafae", "commit_date": "2021-05-20 10:36"} and *= 1.3 - # values from {"commit_id": "2947789b3b18a724096abbd9a5c535ae3128ce05", "commit_date": "2021-07-12 23:30"} and *= 1.3 + # values from {"branch": "releases/2021/4", "commit_id": "96bc1b9bfb6140981e88bf09ee756b70f1723533", "commit_date": "2021-08-13 14:38"} and *= 1.3 + # values from {"commit_id": "af63cb78ee5cbd66bac0d0980db61cb11b5d9995", "commit_date": "2021-03-03 15:44"} and *= 1.3 + # values from {"branch": "releases/2021/4", "commit_id": "96bc1b9bfb6140981e88bf09ee756b70f1723533", "commit_date": "2021-08-13 14:38"} and *= 1.3 + # values from {"commit_id": "af63cb78ee5cbd66bac0d0980db61cb11b5d9995", "commit_date": "2021-03-03 15:44"} and *= 1.3 - # values from {"commit_id": "2947789b3b18a724096abbd9a5c535ae3128ce05", "commit_date": "2021-07-12 23:30"} and *= 1.3 - # values from {"commit_id": "af63cb78ee5cbd66bac0d0980db61cb11b5d9995", "commit_date": "2021-03-03 15:44"} and *= 1.3 - # values from {"commit_id": "2947789b3b18a724096abbd9a5c535ae3128ce05", "commit_date": "2021-07-12 23:30"} and *= 1.3 + # values from {"branch": "releases/2021/4", "commit_id": "96bc1b9bfb6140981e88bf09ee756b70f1723533", "commit_date": "2021-08-13 14:38"} and *= 1.3 # values from {"commit_id": "761e571042fa2b291d5954e523fffc1e2dfcafae", "commit_date": "2021-05-20 10:36"} and *= 1.3 - # values from {"commit_id": "2947789b3b18a724096abbd9a5c535ae3128ce05", "commit_date": "2021-07-12 23:30"} and *= 1.3 + # values from {"branch": "releases/2021/4", "commit_id": "96bc1b9bfb6140981e88bf09ee756b70f1723533", "commit_date": "2021-08-13 14:38"} and *= 1.3 + # values from {"commit_id": "af63cb78ee5cbd66bac0d0980db61cb11b5d9995", "commit_date": "2021-03-03 15:44"} and *= 1.3 + # values from {"branch": "releases/2021/4", "commit_id": "96bc1b9bfb6140981e88bf09ee756b70f1723533", "commit_date": "2021-08-13 14:38"} and *= 1.3 + # values from {"commit_id": "af63cb78ee5cbd66bac0d0980db61cb11b5d9995", "commit_date": "2021-03-03 15:44"} and *= 1.3 - # values from {"commit_id": "2947789b3b18a724096abbd9a5c535ae3128ce05", "commit_date": "2021-07-12 23:30"} and *= 1.3 + # values from {"branch": "releases/2021/4", "commit_id": "96bc1b9bfb6140981e88bf09ee756b70f1723533", "commit_date": "2021-08-13 14:38"} and *= 1.3 + # values from {"branch": "releases/2021/4", "commit_id": "96bc1b9bfb6140981e88bf09ee756b70f1723533", "commit_date": "2021-08-13 14:38"} and *= 1.3 + # values from {"branch": "releases/2021/4", "commit_id": "96bc1b9bfb6140981e88bf09ee756b70f1723533", "commit_date": "2021-08-13 14:38"} and *= 1.3 # values from {"commit_id": "af63cb78ee5cbd66bac0d0980db61cb11b5d9995", "commit_date": "2021-03-03 15:44"} and *= 1.3 - # values from {"commit_id": "2947789b3b18a724096abbd9a5c535ae3128ce05", "commit_date": "2021-07-12 23:30"} and *= 1.3 - # values from {"commit_id": "761e571042fa2b291d5954e523fffc1e2dfcafae", "commit_date": "2021-05-20 10:36"} and *= 1.3 - # values from {"commit_id": "2947789b3b18a724096abbd9a5c535ae3128ce05", "commit_date": "2021-07-12 23:30"} and *= 1.3 + # values from {"branch": "releases/2021/4", "commit_id": "96bc1b9bfb6140981e88bf09ee756b70f1723533", "commit_date": "2021-08-13 14:38"} and *= 1.3 + # values from {"commit_id": "af63cb78ee5cbd66bac0d0980db61cb11b5d9995", "commit_date": "2021-03-03 15:44"} and *= 1.3 - # values from {"commit_id": "2947789b3b18a724096abbd9a5c535ae3128ce05", "commit_date": "2021-07-12 23:30"} and *= 1.3 - # values from {"commit_id": "af63cb78ee5cbd66bac0d0980db61cb11b5d9995", "commit_date": "2021-03-03 15:44"} and *= 1.3 - # values from {"commit_id": "2947789b3b18a724096abbd9a5c535ae3128ce05", "commit_date": "2021-07-12 23:30"} and *= 1.3 + # values from {"branch": "releases/2021/4", "commit_id": "96bc1b9bfb6140981e88bf09ee756b70f1723533", "commit_date": "2021-08-13 14:38"} and *= 1.3 # values from {"commit_id": "761e571042fa2b291d5954e523fffc1e2dfcafae", "commit_date": "2021-05-20 10:36"} and *= 1.3 - # values from {"commit_id": "2947789b3b18a724096abbd9a5c535ae3128ce05", "commit_date": "2021-07-12 23:30"} and *= 1.3 + # values from {"branch": "releases/2021/4", "commit_id": "96bc1b9bfb6140981e88bf09ee756b70f1723533", "commit_date": "2021-08-13 14:38"} and *= 1.3 + # values from {"commit_id": "af63cb78ee5cbd66bac0d0980db61cb11b5d9995", "commit_date": "2021-03-03 15:44"} and *= 1.3 + # values from {"branch": "releases/2021/4", "commit_id": "96bc1b9bfb6140981e88bf09ee756b70f1723533", "commit_date": "2021-08-13 14:38"} and *= 1.3 + # values from {"commit_id": "30a30efbc44f3e74a0283acd0f9ccf2e7caf94b6", "commit_date": "2021-08-19 21:17"} and *= 1.3 # values from {"commit_id": "30a30efbc44f3e74a0283acd0f9ccf2e7caf94b6", "commit_date": "2021-08-19 21:17"} and *= 1.3 @@ -58,18 +66,21 @@ # values from {"commit_id": "30a30efbc44f3e74a0283acd0f9ccf2e7caf94b6", "commit_date": "2021-08-19 21:17"} and *= 1.3 # values from {"commit_id": "30a30efbc44f3e74a0283acd0f9ccf2e7caf94b6", "commit_date": "2021-08-19 21:17"} and *= 1.3 # values from {"commit_id": "30a30efbc44f3e74a0283acd0f9ccf2e7caf94b6", "commit_date": "2021-08-19 21:17"} and *= 1.3 + # values from {"commit_id": "30a30efbc44f3e74a0283acd0f9ccf2e7caf94b6", "commit_date": "2021-08-19 21:17"} and *= 1.3 # values from {"commit_id": "30a30efbc44f3e74a0283acd0f9ccf2e7caf94b6", "commit_date": "2021-08-19 21:17"} and *= 1.3 # values from {"commit_id": "30a30efbc44f3e74a0283acd0f9ccf2e7caf94b6", "commit_date": "2021-08-19 21:17"} and *= 1.3 # values from {"commit_id": "30a30efbc44f3e74a0283acd0f9ccf2e7caf94b6", "commit_date": "2021-08-19 21:17"} and *= 1.3 # values from {"commit_id": "30a30efbc44f3e74a0283acd0f9ccf2e7caf94b6", "commit_date": "2021-08-19 21:17"} and *= 1.3 # values from {"commit_id": "30a30efbc44f3e74a0283acd0f9ccf2e7caf94b6", "commit_date": "2021-08-19 21:17"} and *= 1.3 + # values from {"commit_id": "30a30efbc44f3e74a0283acd0f9ccf2e7caf94b6", "commit_date": "2021-08-19 21:17"} and *= 1.3 # values from {"commit_id": "30a30efbc44f3e74a0283acd0f9ccf2e7caf94b6", "commit_date": "2021-08-19 21:17"} and *= 1.3 # values from {"commit_id": "30a30efbc44f3e74a0283acd0f9ccf2e7caf94b6", "commit_date": "2021-08-19 21:17"} and *= 1.3 # values from {"commit_id": "30a30efbc44f3e74a0283acd0f9ccf2e7caf94b6", "commit_date": "2021-08-19 21:17"} and *= 1.3 # values from {"commit_id": "30a30efbc44f3e74a0283acd0f9ccf2e7caf94b6", "commit_date": "2021-08-19 21:17"} and *= 1.3 # values from {"commit_id": "30a30efbc44f3e74a0283acd0f9ccf2e7caf94b6", "commit_date": "2021-08-19 21:17"} and *= 1.3 + # values from {"commit_id": "30a30efbc44f3e74a0283acd0f9ccf2e7caf94b6", "commit_date": "2021-08-19 21:17"} and *= 1.3 # values from {"commit_id": "30a30efbc44f3e74a0283acd0f9ccf2e7caf94b6", "commit_date": "2021-08-19 21:17"} and *= 1.3 # values from {"commit_id": "30a30efbc44f3e74a0283acd0f9ccf2e7caf94b6", "commit_date": "2021-08-19 21:17"} and *= 1.3 From e07ac53300ea054bb7251eddf7a69c412fb0474c Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Wed, 1 Sep 2021 18:41:15 +0300 Subject: [PATCH 74/76] Removed speech demo (#7298) --- .ci/azure/linux_onnxruntime.yml | 1 - .ci/openvino-onnx/Dockerfile | 1 - cmake/dependencies.cmake | 41 --------------------------------- cmake/features.cmake | 2 -- inference-engine/CMakeLists.txt | 12 ---------- 5 files changed, 57 deletions(-) diff --git a/.ci/azure/linux_onnxruntime.yml b/.ci/azure/linux_onnxruntime.yml index 932fb76d5cc..dd9d8b44429 100644 --- a/.ci/azure/linux_onnxruntime.yml +++ b/.ci/azure/linux_onnxruntime.yml @@ -93,7 +93,6 @@ jobs: -DENABLE_CLDNN=OFF -DENABLE_PROFILING_ITT=OFF -DENABLE_SAMPLES=OFF - -DENABLE_SPEECH_DEMO=OFF -DNGRAPH_ONNX_FRONTEND_ENABLE=ON -DNGRAPH_DEBUG_ENABLE=OFF $(REPO_DIR) diff --git a/.ci/openvino-onnx/Dockerfile b/.ci/openvino-onnx/Dockerfile index 314ab2c1037..3a190c42769 100644 --- a/.ci/openvino-onnx/Dockerfile +++ b/.ci/openvino-onnx/Dockerfile @@ -65,7 +65,6 @@ RUN cmake .. \ -DENABLE_CLDNN=OFF \ -DENABLE_PROFILING_ITT=OFF \ -DENABLE_SAMPLES=OFF \ - -DENABLE_SPEECH_DEMO=OFF \ -DENABLE_PYTHON=ON \ -DPYTHON_EXECUTABLE=/usr/bin/python3 \ -DNGRAPH_ONNX_FRONTEND_ENABLE=ON \ diff --git a/cmake/dependencies.cmake b/cmake/dependencies.cmake index 82f98b4c515..046e9a83d57 100644 --- a/cmake/dependencies.cmake +++ b/cmake/dependencies.cmake @@ -298,44 +298,3 @@ if(ENABLE_GNA) update_deps_cache(GNA "${GNA}" "Path to GNA root folder") debug_message(STATUS "gna=" ${GNA}) endif() - -if(ENABLE_SPEECH_DEMO) - reset_deps_cache(SPEECH_LIBS_AND_DEMOS) - if(DEFINED ENV{THIRDPARTY_SERVER_PATH}) - set(IE_PATH_TO_DEPS "$ENV{THIRDPARTY_SERVER_PATH}") - elseif(DEFINED THIRDPARTY_SERVER_PATH) - set(IE_PATH_TO_DEPS "${THIRDPARTY_SERVER_PATH}") - else() - message(WARNING "Unable to locate Speech Demo") - endif() - if(DEFINED IE_PATH_TO_DEPS) - if(WIN32 AND X86_64) - RESOLVE_DEPENDENCY(SPEECH_LIBS_AND_DEMOS - ARCHIVE_WIN "speech_demo_1.0.0.780_windows.zip" - VERSION_REGEX ".*_([0-9]+.[0-9]+.[0-9]+.[0-9]+).*" - TARGET_PATH "${TEMP}/speech_demo_1.0.0.780" - SHA256 "957bd274a1f6dc1d83a46879c7ef3b3b06f17d11af85cc45c18919051d145abd") - debug_message(STATUS "speech_libs_and_demos=" ${SPEECH_LIBS_AND_DEMOS}) - elseif(LINUX AND X86_64) - if(LINUX_OS_NAME STREQUAL "CentOS 7" OR CMAKE_CXX_COMPILER_VERSION VERSION_LESS "4.9") - RESOLVE_DEPENDENCY(SPEECH_LIBS_AND_DEMOS - ARCHIVE_LIN "speech_demo_1.0.0.780_centos.tgz" - VERSION_REGEX ".*_([0-9]+.[0-9]+.[0-9]+.[0-9]+).*" - TARGET_PATH "${TEMP}/speech_demo_1.0.0.780" - SHA256 "6d8d1111d0e662fe71d71cd3debad2995f6fb6fe5df3b92196dae06ff7abdf44") - debug_message(STATUS "speech_libs_and_demos=" ${SPEECH_LIBS_AND_DEMOS}) - else() - RESOLVE_DEPENDENCY(SPEECH_LIBS_AND_DEMOS - ARCHIVE_LIN "speech_demo_1.0.0.780_linux.tgz" - VERSION_REGEX ".*_([0-9]+.[0-9]+.[0-9]+.[0-9]+).*" - TARGET_PATH "${TEMP}/speech_demo_1.0.0.780" - SHA256 "0ec6f1e47c00d781dc918af5d3055ab474ff47b9978dd6fe2add73e3339b0763") - debug_message(STATUS "speech_libs_and_demos=" ${SPEECH_LIBS_AND_DEMOS}) - endif() - else() - message(FATAL_ERROR "Speech Demo is not available on current platform") - endif() - unset(IE_PATH_TO_DEPS) - endif() - update_deps_cache(SPEECH_LIBS_AND_DEMOS "${SPEECH_LIBS_AND_DEMOS}" "Path to SPEECH_LIBS_AND_DEMOS root folder") -endif() diff --git a/cmake/features.cmake b/cmake/features.cmake index cf9fbebbe94..450b0d255cc 100644 --- a/cmake/features.cmake +++ b/cmake/features.cmake @@ -98,8 +98,6 @@ ie_dependent_option (ENABLE_FUNCTIONAL_TESTS "functional tests" ON "ENABLE_TESTS ie_dependent_option (ENABLE_SAMPLES "console samples are part of inference engine package" ON "NOT MINGW" OFF) -ie_dependent_option (ENABLE_SPEECH_DEMO "enable speech demo integration" ON "NOT APPLE;NOT ANDROID;X86_64" OFF) - ie_option (ENABLE_OPENCV "enables OpenCV" ON) ie_option (ENABLE_V7_SERIALIZE "enables serialization to IR v7" OFF) diff --git a/inference-engine/CMakeLists.txt b/inference-engine/CMakeLists.txt index 5f2fb047ce6..69a71eb55b5 100644 --- a/inference-engine/CMakeLists.txt +++ b/inference-engine/CMakeLists.txt @@ -80,15 +80,3 @@ install(DIRECTORY ie_bridges/c/samples/ install(FILES samples/CMakeLists.txt DESTINATION ${IE_CPACK_IE_DIR}/samples/c COMPONENT c_samples) - -# install speech demo files - -if(SPEECH_LIBS_AND_DEMOS) - ie_cpack_add_component(speech_demo_files) - - install(DIRECTORY ${TEMP}/deployment_tools - ${TEMP}/data_processing - DESTINATION . - USE_SOURCE_PERMISSIONS - COMPONENT speech_demo_files) -endif() From 28075fb7fcfe16f4e7205d3dc866394fa3dd4c71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Do=C5=82bniak?= Date: Wed, 1 Sep 2021 19:14:45 +0300 Subject: [PATCH 75/76] MaxPool 8 reference implementation (#7115) --- .../functional/op_reference/max_pool.cpp | 400 ++++++++++++++++++ ngraph/core/include/ngraph/shape.hpp | 15 + .../ngraph/runtime/reference/max_pool.hpp | 333 +++++++++++++++ .../runtime/interpreter/evaluates_map.cpp | 55 ++- .../runtime/interpreter/opset_int_tbl.hpp | 1 + 5 files changed, 792 insertions(+), 12 deletions(-) create mode 100644 docs/template_plugin/tests/functional/op_reference/max_pool.cpp diff --git a/docs/template_plugin/tests/functional/op_reference/max_pool.cpp b/docs/template_plugin/tests/functional/op_reference/max_pool.cpp new file mode 100644 index 00000000000..2cca7c50513 --- /dev/null +++ b/docs/template_plugin/tests/functional/op_reference/max_pool.cpp @@ -0,0 +1,400 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include + +#include +#include +#include +#include +#include + +#include "base_reference_test.hpp" + +using namespace ngraph; +using namespace reference_tests; +using namespace InferenceEngine; + +struct MaxPoolParams { + template + MaxPoolParams(const Shape& input_shape, + const element::Type& input_type, + const std::vector& input_data, + const std::vector& expected_values, + const element::Type& indices_type, + const std::vector& expected_indices, + const Strides& strides, + const Strides& dilations, + const Shape& pads_begin, + const Shape& pads_end, + const Shape& kernel, + const op::PadType pad_type = op::PadType::EXPLICIT, + const int64_t axis = 0) + : m_input_shape(input_shape), + m_input_type(input_type), + m_indices_type(indices_type), + m_input_data(CreateBlob(input_type, input_data)), + m_expected_values(CreateBlob(input_type, expected_values)), + m_expected_indices(CreateBlob(indices_type, expected_indices)), + m_strides(strides), + m_dilations(dilations), + m_pads_begin(pads_begin), + m_pads_end(pads_end), + m_kernel(kernel), + m_pad_type(pad_type), + m_axis(axis) {} + Shape m_input_shape; + element::Type m_input_type; + element::Type m_indices_type; + InferenceEngine::Blob::Ptr m_input_data; + InferenceEngine::Blob::Ptr m_expected_values; + InferenceEngine::Blob::Ptr m_expected_indices; + Strides m_strides; + Strides m_dilations; + Shape m_pads_begin; + Shape m_pads_end; + Shape m_kernel; + op::PadType m_pad_type; + int64_t m_axis; +}; + +class ReferenceMaxPoolLayerTest : public testing::TestWithParam, public CommonReferenceTest { +public: + void SetUp() override { + const auto params = GetParam(); + function = CreateFunction(params); + inputData = {params.m_input_data}; + refOutData = {params.m_expected_values, params.m_expected_indices}; + } + static std::string getTestCaseName(const testing::TestParamInfo& obj) { + const auto p = obj.param; + std::ostringstream result; + result << p.m_input_shape.size() - 2 << "D/"; + result << "input_shape=" << p.m_input_shape << ";"; + result << "input_type=" << p.m_input_type << ";"; + result << "indices_type=" << p.m_indices_type << ";"; + result << "strides=" << p.m_strides << ";"; + result << "dilations=" << p.m_dilations << ";"; + result << "pads_begin=" << p.m_pads_begin << ";"; + result << "pads_end=" << p.m_pads_end << ";"; + result << "kernel=" << p.m_kernel << ";"; + result << "pad_type=" << p.m_pad_type << ";"; + result << "axis=" << p.m_axis; + return result.str(); + } + +private: + static std::shared_ptr CreateFunction(const MaxPoolParams& params) { + const auto in = std::make_shared(params.m_input_type, params.m_input_shape); + const auto max_pool = std::make_shared(in, + params.m_strides, + params.m_dilations, + params.m_pads_begin, + params.m_pads_end, + params.m_kernel, + op::RoundingType::FLOOR, + params.m_pad_type, + params.m_indices_type, + params.m_axis); + return std::make_shared(max_pool, ParameterVector{in}); + } +}; + +TEST_P(ReferenceMaxPoolLayerTest, CompareWithHardcodedRefs) { + Exec(); +} + +INSTANTIATE_TEST_SUITE_P( + smoke_MaxPool_With_Hardcoded_Refs, + ReferenceMaxPoolLayerTest, + ::testing::Values( + MaxPoolParams(Shape{1, 1, 9}, + element::i32, + std::vector{1, 2, 3, 4, 5, 6, 7, 8, 9}, + std::vector{2, 3, 4, 5, 6, 7, 8, 9}, + element::i64, + std::vector{1, 2, 3, 4, 5, 6, 7, 8}, + Strides{1}, + Strides{1}, + Shape{}, + Shape{}, + Shape{2}), + MaxPoolParams(Shape{1, 1, 9}, + element::i32, + std::vector{1, 2, 3, 4, 5, 6, 7, 8, 9}, + std::vector{2, 4, 6, 8}, + element::i64, + std::vector{1, 3, 5, 7}, + Strides{2}, + Strides{1}, + Shape{}, + Shape{}, + Shape{2}), + MaxPoolParams(Shape{1, 1, 9}, + element::i32, + std::vector{1, 2, 3, 4, 5, 6, 7, 8, 9}, + std::vector{1, 3, 5, 7, 9}, + element::i64, + std::vector{0, 2, 4, 6, 8}, + Strides{2}, + Strides{1}, + Shape{}, + Shape{}, + Shape{2}, + op::PadType::SAME_LOWER), + MaxPoolParams(Shape{1, 1, 9}, + element::i32, + std::vector{1, 2, 3, 4, 5, 6, 7, 8, 9}, + std::vector{2, 4, 6, 8, 9}, + element::i64, + std::vector{1, 3, 5, 7, 8}, + Strides{2}, + Strides{1}, + Shape{}, + Shape{}, + Shape{2}, + op::PadType::SAME_UPPER), + MaxPoolParams(Shape{1, 1, 9}, + element::i32, + std::vector{1, 2, 3, 4, 5, 6, 7, 8, 9}, + std::vector{3, 5, 7, 9}, + element::i32, + std::vector{2, 4, 6, 8}, + Strides{2}, + Strides{2}, + Shape{}, + Shape{}, + Shape{2}), + MaxPoolParams(Shape{1, 2, 4}, + element::f32, + std::vector{1.0f, 2.0f, 3.0f, 4.0f, 0.0f, -3.14f, -2.71f, 5.0f}, + std::vector{3.0f, 4.0f, 0.0f, 5.0f}, + element::i32, + std::vector{2, 3, 4, 7}, + Strides{1}, + Strides{1}, + Shape{}, + Shape{}, + Shape{3}), + MaxPoolParams(Shape{1, 2, 4}, + element::f32, + std::vector{1.0f, 2.0f, 3.0f, 4.0f, 0.0f, -3.14f, -2.71f, 5.0f}, + std::vector{3.0f, 4.0f, 0.0f, 5.0f}, + element::i32, + std::vector{2, 3, 0, 3}, + Strides{1}, + Strides{1}, + Shape{}, + Shape{}, + Shape{3}, + op::PadType::EXPLICIT, + 2), + MaxPoolParams(Shape{1, 1, 9}, + element::i32, + std::vector{1, 9, 3, 8, 5, 2, 6, 4, 7}, + std::vector{1, 9, 6, 7}, + element::i32, + std::vector{0, 1, 6, 8}, + Strides{3}, + Strides{1}, + Shape{2}, + Shape{2}, + Shape{3}), + /*************************************************/ + /***************** 2D test cases *****************/ + /*************************************************/ + MaxPoolParams(Shape{1, 1, 3, 3}, + element::i32, + std::vector{3, 9, 10, 5, 7, 2, 18, 8, -2}, + std::vector{9, 10, 18, 8}, + element::i32, + std::vector{1, 2, 6, 7}, + Strides{1, 1}, + Strides{1, 1}, + Shape{}, + Shape{}, + Shape{2, 2}), + MaxPoolParams(Shape{1, 1, 4, 4}, // simple 4x4 input test + element::i32, + std::vector{8, -9, 1, -16, -14, 15, -17, 19, -13, 3, 10, 17, 16, -11, -15, 20}, + std::vector{15, 15, 19, 15, 15, 19, 16, 10, 20}, + element::i32, + std::vector{5, 5, 7, 5, 5, 7, 12, 10, 15}, + Strides{1, 1}, + Strides{1, 1}, + Shape{}, + Shape{}, + Shape{2, 2}), + MaxPoolParams(Shape{1, 1, 4, 4}, + element::i32, + std::vector{8, -9, 1, -16, -14, 15, -17, 19, -13, 3, 10, 17, 16, -11, -15, 20}, + std::vector{15, 19, 16, 20}, + element::i32, + std::vector{5, 7, 12, 15}, + Strides{2, 2}, // strides: 2x2 + Strides{1, 1}, + Shape{}, + Shape{}, + Shape{2, 2}), + MaxPoolParams(Shape{1, 1, 4, 4}, + element::i32, + std::vector{8, -9, 1, -16, -14, 15, -17, 19, -13, 3, 10, 17, 16, -11, -15, 20}, + std::vector{10, 17, 16, 20}, + element::i32, + std::vector{10, 11, 12, 15}, + Strides{1, 1}, + Strides{2, 2}, // dilations: 2x2 + Shape{}, + Shape{}, + Shape{2, 2}), + MaxPoolParams(Shape{1, 1, 4, 4}, + element::i32, + std::vector{8, -9, 1, -16, -14, 15, -17, 19, -13, 3, 10, 17, 16, -11, -15, 20}, + std::vector{15, 19, 16, 20}, + element::i32, + std::vector{5, 7, 12, 15}, + Strides{1, 1}, + Strides{1, 1}, + Shape{}, + Shape{}, + Shape{3, 3}), // kernel: 3x3 + MaxPoolParams(Shape{1, 1, 5, 5}, + element::i32, + std::vector{0, -2, 24, 13, 7, -5, -4, 4, 21, -18, 81, 20, -15, + 37, 23, 41, 18, 42, 8, 32, 9, 57, 58, 29, 3}, + std::vector{0, 21, 81, 37}, + element::i32, + std::vector{0, 8, 10, 13}, + Strides{2, 3}, // strides: 2x3 + Strides{1, 1}, + Shape{}, + Shape{}, + Shape{2, 2}), + MaxPoolParams(Shape{1, 1, 5, 5}, + element::i32, + std::vector{0, -2, 24, 13, 7, -5, -4, 4, 21, -18, 81, 20, -15, + 37, 23, 41, 18, 42, 8, 32, 9, 57, 58, 29, 3}, + std::vector{0, 24, 57, 58}, + element::i32, + std::vector{0, 2, 21, 22}, + Strides{3, 2}, // strides: 3x2 + Strides{1, 1}, + Shape{}, + Shape{}, + Shape{2, 2}), + MaxPoolParams(Shape{1, 1, 5, 5}, + element::i32, + std::vector{0, -2, 24, 13, 7, -5, -4, 4, 21, -18, 81, 20, -15, + 37, 23, 41, 18, 42, 8, 32, 9, 57, 58, 29, 3}, + std::vector{81, 24, 81, 58}, + element::i32, + std::vector{10, 2, 10, 22}, + Strides{2, 2}, // strides: 2x2 + Strides{2, 2}, // dilations: 2x2 + Shape{}, + Shape{}, + Shape{2, 2}), + MaxPoolParams(Shape{1, 1, 5, 5}, + element::i32, + std::vector{0, -2, 24, 13, 7, -5, -4, 4, 21, -18, 81, 20, -15, + 37, 23, 41, 18, 42, 8, 32, 9, 57, 58, 29, 3}, + std::vector{0, 24, 21, 81, 42, 37, 57, 58, 32}, + element::i32, + std::vector{0, 2, 8, 10, 17, 13, 21, 22, 19}, + Strides{2, 2}, // strides: 2x2 + Strides{1, 1}, + Shape{1, 1}, // pads_begin: 1x1 + Shape{1, 1}, // pads_end: 1x1 + Shape{3, 3}), + MaxPoolParams(Shape{1, 1, 5, 5}, + element::i32, + std::vector{0, -2, 24, 13, 7, -5, -4, 4, 21, -18, 81, 20, -15, + 37, 23, 41, 18, 42, 8, 32, 9, 57, 58, 29, 3}, + std::vector{81, 37, 81, 58, 58, 58}, + element::i32, + std::vector{10, 13, 10, 22, 22, 22}, + Strides{2, 2}, // strides: 2x2 + Strides{1, 1}, + Shape{}, + Shape{2, 1}, // pads_end: 2x1 + Shape{3, 3}), + MaxPoolParams(Shape{1, 2, 3, 3}, + element::i64, + std::vector{0, -2, 24, 13, 7, -5, -4, 4, 21, -18, 81, 20, -15, 37, 23, 41, 18, 42}, + std::vector{13, 24, 13, 21, 81, 81, 41, 42}, + element::i64, + std::vector{3, 2, 3, 8, 1, 1, 6, 8}, + Strides{1, 1}, + Strides{1, 1}, + Shape{}, + Shape{}, + Shape{2, 2}, + op::PadType::EXPLICIT, + 2), // axis: 2 + MaxPoolParams(Shape{1, 1, 2, 2}, + element::i32, + std::vector{1, 2, 3, 4}, + std::vector{1, 2, 3, 4}, + element::i32, + std::vector{0, 1, 2, 3}, + Strides{1, 1}, + Strides{1, 1}, + Shape{}, + Shape{}, + Shape{1, 1}), // kernel: 1x1 + /*************************************************/ + /***************** 3D test cases *****************/ + /*************************************************/ + MaxPoolParams(Shape{1, 1, 3, 3, 3}, + element::i32, + std::vector{0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 20, 30, 40, -20, + 60, 70, 80, 50, 50, 1, 2, 3, -15, -10, 50, 30, 81}, + std::vector{40, 60, 80, 80, 50, 60, 80, 81}, + element::i32, + std::vector{12, 14, 16, 16, 18, 14, 16, 26}, + Strides{1, 1, 1}, + Strides{1, 1, 1}, + Shape{}, + Shape{}, + Shape{2, 2, 2}), + MaxPoolParams(Shape{1, 1, 3, 3, 3}, + element::i32, + std::vector{0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 20, 30, 40, -20, + 60, 70, 80, 50, 50, 1, 2, 3, -15, -10, 50, 30, 81}, + std::vector{-20, -20, -20, -20, -20, -20, -20, -20}, + element::i32, + std::vector{13, 13, 13, 13, 13, 13, 13, 13}, + Strides{2, 2, 2}, + Strides{2, 2, 2}, + Shape{1, 1, 1}, + Shape{1, 1, 1}, + Shape{2, 2, 2}), + MaxPoolParams(Shape{1, 1, 3, 3, 3}, + element::i32, + std::vector{0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 20, 30, 40, -20, + 60, 70, 80, 50, 50, 1, 2, 3, -15, -10, 50, 30, 81}, + std::vector{8, 80, 81}, + element::i32, + std::vector{8, 16, 26}, + Strides{1, 1, 1}, + Strides{1, 1, 1}, + Shape{}, + Shape{}, + Shape{1, 3, 3}), + MaxPoolParams(Shape{1, 1, 3, 3, 3}, + element::i32, + std::vector{0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 20, 30, 40, -20, + 60, 70, 80, 50, 50, 1, 2, 3, -15, -10, 50, 30, 81}, + std::vector{4, 5, 7, 8, 40, 60, 80, 80, 50, 2, 50, 81}, + element::i32, + std::vector{4, 5, 7, 8, 3, 5, 7, 7, 0, 2, 6, 8}, + Strides{1, 1, 1}, + Strides{1, 1, 1}, + Shape{}, + Shape{}, + Shape{1, 2, 2}, + op::PadType::EXPLICIT, + 3)), + + ReferenceMaxPoolLayerTest::getTestCaseName); diff --git a/ngraph/core/include/ngraph/shape.hpp b/ngraph/core/include/ngraph/shape.hpp index ae3b25b261e..1a12974bd7a 100644 --- a/ngraph/core/include/ngraph/shape.hpp +++ b/ngraph/core/include/ngraph/shape.hpp @@ -5,6 +5,7 @@ #pragma once #include +#include #include #include "ngraph/attribute_adapter.hpp" @@ -45,6 +46,20 @@ size_t shape_size(const SHAPE_TYPE& shape) { return size; } +/// Number of elements in a subset of dimensions of a shape. +/// Returns a product of dimensions in a range [start_dim;end_dim) +template +size_t shape_size(ForwardIt start_dim, const ForwardIt end_dim) { + static_assert(std::is_arithmetic::value_type>::value, + "shape_size expects 2 forward iterators as inputs. value_type of those iterators has to be an " + "arithmetic type so that they can be used in multiplication operation."); + + return std::accumulate(start_dim, + end_dim, + typename std::iterator_traits::value_type{1}, + std::multiplies::value_type>()); +} + /// Row-major strides for a shape template std::vector row_major_strides(const SHAPE_TYPE& shape) { diff --git a/ngraph/core/reference/include/ngraph/runtime/reference/max_pool.hpp b/ngraph/core/reference/include/ngraph/runtime/reference/max_pool.hpp index e0729ee5e82..74c0261112b 100644 --- a/ngraph/core/reference/include/ngraph/runtime/reference/max_pool.hpp +++ b/ngraph/core/reference/include/ngraph/runtime/reference/max_pool.hpp @@ -110,6 +110,339 @@ void max_pool(const T* arg, } NGRAPH_SUPPRESS_DEPRECATED_END } + +namespace { +void validate_max_pool_kernel_params(const size_t dims, + const Shape& kernel, + const Strides& kernel_strides, + const Strides& kernel_dilations, + const Shape& pads_begin, + const Shape& pads_end) { + NGRAPH_CHECK(kernel.size() == dims && kernel_strides.size() == dims && kernel_dilations.size() == dims && + pads_begin.size() == dims && pads_end.size() == dims, + "One of the MaxPool params does not match the ", + dims, + "D implementation.\nkernel=", + kernel, + "\nkernel_strides=", + kernel_strides, + "\nkernel_dilations=", + kernel_dilations, + "\npads_begin=", + pads_begin, + "\npads_end=", + pads_end); +} + +/// \brief A helper struct representing spatial coordinates of a tensor element. It can use signed numbers as the +/// underlying type; this way it is possible to represent elements which belong to the padding area +/// (by using negative values). +/// +/// \note This struct can be used to represent a location of a pooling kernel in space (non-flattened version) +/// but at the same time it can represent pixel offsets in the filter itself (dilated or non-dilated) +template +struct Coord : public std::vector { + Coord(const Shape& pads_begin) { + std::vector::reserve(pads_begin.size()); + for (const auto axis_padding : pads_begin) { + std::vector::push_back(0 - axis_padding); + } + } + + Coord(std::initializer_list&& values) : std::vector{std::move(values)} {} +}; + +bool elem_in_padding_area(const Coord& kernel_position, + const Coord& kernel_offset, + const Shape& data_shape) { + for (size_t dim = 0; dim + 2 < data_shape.size(); ++dim) { + if (kernel_position[dim] + kernel_offset[dim] < 0 || + kernel_position[dim] + kernel_offset[dim] >= data_shape[dim + 2]) { + return true; + } + } + + return false; +} + +template +Coord next_kernel_position_2D(Coord kernel_position, + const Shape& kernel, + const Strides& kernel_strides, + const Strides& kernel_dilations, + const Shape& data_shape, + const Shape& pads_begin, + const Shape& pads_end) { + // move the kernel horizontally one stride to the right + kernel_position[1] += kernel_strides[1]; + + // if the top-right corner of the kernel is outside of the padding area, + // move it back to the left and one stride down + if (kernel_position[1] + (kernel[1] - 1) * kernel_dilations[1] >= data_shape[3] + pads_end[1]) { + kernel_position[1] = 0 - pads_begin[1]; + kernel_position[0] += kernel_strides[0]; + } + + return kernel_position; +} + +template +Coord next_kernel_position_3D(Coord kernel_position, + const Shape& kernel, + const Strides& kernel_strides, + const Strides& kernel_dilations, + const Shape& data_shape, + const Shape& pads_begin, + const Shape& pads_end) { + kernel_position[2] += kernel_strides[2]; + + if (kernel_position[2] + (kernel[2] - 1) * kernel_dilations[2] >= data_shape[4] + pads_end[2]) { + kernel_position[2] = 0 - pads_begin[2]; + kernel_position[1] += kernel_strides[1]; + if (kernel_position[1] + (kernel[1] - 1) * kernel_dilations[1] >= data_shape[3] + pads_end[1]) { + kernel_position[1] = 0 - pads_begin[1]; + kernel_position[0] += kernel_strides[0]; + } + } + + return kernel_position; +} + +namespace kernel { +template +void max_pool_1d(const Values_t* data, + Values_t* values, + Indices_t* indices, + const size_t data_elems, + const size_t out_elems, + const size_t kernel_size, + const size_t kernel_stride, + const size_t kernel_dilation, + const size_t pads_begin, + const size_t pads_end, + const size_t indices_offset) { + int kernel_position = 0 - pads_begin; + // select max elem and its index for each "placeholder" in the out buffer (pointed to by out_idx) + for (size_t out_idx = 0; out_idx < out_elems; ++out_idx) { + Values_t max_elem = std::numeric_limits::lowest(); + Indices_t max_elem_idx = Indices_t{0}; + for (size_t kernel_elem = 0; kernel_elem < kernel_size; ++kernel_elem) { + const size_t kernel_elem_offset = kernel_elem * kernel_dilation; + // don't process the padding elements + if (kernel_position + kernel_elem_offset >= 0 && kernel_position + kernel_elem_offset < data_elems && + data[kernel_position + kernel_elem_offset] > max_elem) { + max_elem = data[kernel_position + kernel_elem_offset]; + max_elem_idx = kernel_position + kernel_elem_offset; + } + } + values[out_idx] = max_elem; + indices[out_idx] = max_elem_idx + indices_offset; + kernel_position += kernel_stride; + } +} + +template +void max_pool_2d(const Values_t* data, + Values_t* values, + Indices_t* indices, + const Shape& data_shape, + const Shape& out_shape, + const Shape& kernel, + const Strides& kernel_strides, + const Strides& kernel_dilations, + const Shape& pads_begin, + const Shape& pads_end, + const size_t indices_offset) { + validate_max_pool_kernel_params(2, kernel, kernel_strides, kernel_dilations, pads_begin, pads_end); + + Coord kernel_position{pads_begin}; + + // select max elem and its index for each "placeholder" in the out buffer (pointed to by out_idx) + for (size_t out_idx = 0; out_idx < out_shape[2] * out_shape[3]; ++out_idx) { + Values_t max_elem = std::numeric_limits::lowest(); + Indices_t max_elem_idx = Indices_t{0}; + + // find the max element in the area covered by a current position of the kernel + for (size_t kernel_row = 0; kernel_row < kernel[0]; ++kernel_row) { + for (size_t kernel_col = 0; kernel_col < kernel[1]; ++kernel_col) { + // offset from the top-left corner of the kernel for a given row and col + const Coord kernel_offset{kernel_row * kernel_dilations[0], kernel_col * kernel_dilations[1]}; + + // ignore the elements in the padding area + if (!elem_in_padding_area(kernel_position, kernel_offset, data_shape)) { + // index of the flattened tensor element under the current row & column of the kernel + const size_t data_elem_index = + data_shape[2] * (kernel_offset[0] + kernel_position[0]) + kernel_offset[1] + kernel_position[1]; + + if (data[data_elem_index] > max_elem) { + max_elem = data[data_elem_index]; + max_elem_idx = data_elem_index; + } + } + } + } + + values[out_idx] = max_elem; + indices[out_idx] = max_elem_idx + indices_offset; + + kernel_position = next_kernel_position_2D(kernel_position, + kernel, + kernel_strides, + kernel_dilations, + data_shape, + pads_begin, + pads_end); + } +} + +template +void max_pool_3d(const Values_t* data, + Values_t* values, + Indices_t* indices, + const Shape& data_shape, + const Shape& out_shape, + const Shape& kernel, + const Strides& kernel_strides, + const Strides& kernel_dilations, + const Shape& pads_begin, + const Shape& pads_end, + const size_t indices_offset) { + validate_max_pool_kernel_params(3, kernel, kernel_strides, kernel_dilations, pads_begin, pads_end); + + Coord kernel_position{pads_begin}; + + const size_t out_elems = shape_size(std::begin(out_shape) + 2, std::end(out_shape)); + + // select max elem and its index for each "placeholder" in the out buffer (pointed to by out_idx) + for (size_t out_idx = 0; out_idx < out_elems; ++out_idx) { + Values_t max_elem = std::numeric_limits::lowest(); + Indices_t max_elem_idx = Indices_t{0}; + + for (size_t kernel_channel = 0; kernel_channel < kernel[0]; ++kernel_channel) { + for (size_t kernel_row = 0; kernel_row < kernel[1]; ++kernel_row) { + for (size_t kernel_col = 0; kernel_col < kernel[2]; ++kernel_col) { + // offset from the top-left corner of the kernel for a given row and col + const Coord kernel_offset{kernel_channel * kernel_dilations[0], + kernel_row * kernel_dilations[1], + kernel_col * kernel_dilations[2]}; + + // ignore the elements in the padding area + if (!elem_in_padding_area(kernel_position, kernel_offset, data_shape)) { + // index of the flattened tensor element under the current row & column of the kernel + const size_t data_elem_index = + data_shape[2] * data_shape[3] * (kernel_offset[0] + kernel_position[0]) + + data_shape[3] * (kernel_offset[1] + kernel_position[1]) + kernel_offset[2] + + kernel_position[2]; + + if (data[data_elem_index] > max_elem) { + max_elem = data[data_elem_index]; + max_elem_idx = data_elem_index; + } + } + } + } + } + values[out_idx] = max_elem; + indices[out_idx] = max_elem_idx + indices_offset; + + kernel_position = next_kernel_position_3D(kernel_position, + kernel, + kernel_strides, + kernel_dilations, + data_shape, + pads_begin, + pads_end); + } +} +} // namespace kernel +} // namespace + +template +void max_pool(const Values_t* data, + Values_t* values, + Indices_t* indices, + const Shape& data_shape, + const Shape& out_shape, + const Shape& kernel, + const Strides& strides, + const Strides& dilations, + const Shape& pads_begin, + const Shape& pads_end, + const int64_t axis = 0) { + const auto data_batch_elems = shape_size(std::begin(data_shape) + 1, std::end(data_shape)); + const auto data_channel_elems = shape_size(std::begin(data_shape) + 2, std::end(data_shape)); + + const auto out_batch_elems = shape_size(std::begin(out_shape) + 1, std::end(out_shape)); + const auto out_channel_elems = shape_size(std::begin(out_shape) + 2, std::end(out_shape)); + + for (size_t b = 0; b < data_shape[0]; ++b) { + const Indices_t batch_indices_offset = b * data_batch_elems; + + for (size_t c = 0; c < data_shape[1]; ++c) { + // calculate the buffer offsets for a given channel "c" then execute an appropriate + // kernel for each processed channel + const Values_t* data_channel_first_elem = data + b * data_batch_elems + c * data_channel_elems; + Values_t* out_channel_first_elem = values + b * out_batch_elems + c * out_channel_elems; + Indices_t* indices_channel_first_elem = indices + b * out_batch_elems + c * out_channel_elems; + const Indices_t channel_indices_offset = c * data_channel_elems; + // total offset of the flattened tensor indices for currently processed batch and channel + const Indices_t indices_offset = batch_indices_offset + channel_indices_offset; + + if (data_shape.size() == 3) { + kernel::max_pool_1d(data_channel_first_elem, + out_channel_first_elem, + indices_channel_first_elem, + data_shape[2], + out_shape[2], + kernel[0], + strides[0], + dilations[0], + pads_begin[0], + pads_end[0], + indices_offset); + } else if (data_shape.size() == 4) { + kernel::max_pool_2d(data_channel_first_elem, + out_channel_first_elem, + indices_channel_first_elem, + data_shape, + out_shape, + kernel, + strides, + dilations, + pads_begin, + pads_end, + indices_offset); + } else if (data_shape.size() == 5) { + kernel::max_pool_3d(data_channel_first_elem, + out_channel_first_elem, + indices_channel_first_elem, + data_shape, + out_shape, + kernel, + strides, + dilations, + pads_begin, + pads_end, + indices_offset); + } else { + NGRAPH_CHECK(false, + "Unsupported input shape ", + data_shape, + " passed to the MaxPool reference implementation. Supported shapes: 3D, 4D and 5D."); + } + } + } + + // adjust the calculated indices to the requested range (specified by the axis attribute) if needed + if (axis != 0) { + const Indices_t max_index = shape_size(std::begin(data_shape) + axis, std::end(data_shape)); + + const auto indices_number = shape_size(out_shape); + for (size_t i = 0; i < indices_number; ++i) { + indices[i] %= max_index; + } + } +} } // namespace reference } // namespace runtime } // namespace ngraph diff --git a/ngraph/test/runtime/interpreter/evaluates_map.cpp b/ngraph/test/runtime/interpreter/evaluates_map.cpp index a381faeaa6f..90adbe12457 100644 --- a/ngraph/test/runtime/interpreter/evaluates_map.cpp +++ b/ngraph/test/runtime/interpreter/evaluates_map.cpp @@ -51,6 +51,7 @@ #include #include #include +#include #include #include #include @@ -2945,6 +2946,47 @@ namespace return true; } + template + bool evaluate(const shared_ptr& op, + const HostTensorVector& outputs, + const HostTensorVector& inputs) + { + using T = typename element_type_traits::value_type; + if (op->get_index_element_type() == element::i32) + { + runtime::reference::max_pool(inputs[0]->get_data_ptr(), + outputs[0]->get_data_ptr(), + outputs[1]->get_data_ptr(), + inputs[0]->get_shape(), + outputs[0]->get_shape(), + op->get_kernel(), + op->get_strides(), + op->get_dilations(), + op->get_pads_begin(), + op->get_pads_end(), + op->get_axis()); + } + else if (op->get_index_element_type() == element::i64) + { + runtime::reference::max_pool(inputs[0]->get_data_ptr(), + outputs[0]->get_data_ptr(), + outputs[1]->get_data_ptr(), + inputs[0]->get_shape(), + outputs[0]->get_shape(), + op->get_kernel(), + op->get_strides(), + op->get_dilations(), + op->get_pads_begin(), + op->get_pads_end(), + op->get_axis()); + } + else + { + return false; + } + return true; + } + template bool evaluate_node(std::shared_ptr node, const HostTensorVector& outputs, @@ -2959,18 +3001,7 @@ namespace { element_type = node->get_input_element_type(0); } - for (size_t i = 1; i < node->outputs().size(); i++) - { - if ((ov::is_type(node) || - ov::is_type(node) || - ov::is_type(node) || - ov::is_type(node) || - ov::is_type(node)) && - i == 1) - { - continue; - } - } + switch (element_type) { case element::Type_t::boolean: diff --git a/ngraph/test/runtime/interpreter/opset_int_tbl.hpp b/ngraph/test/runtime/interpreter/opset_int_tbl.hpp index b24b8676961..7dea5e56ffc 100644 --- a/ngraph/test/runtime/interpreter/opset_int_tbl.hpp +++ b/ngraph/test/runtime/interpreter/opset_int_tbl.hpp @@ -101,4 +101,5 @@ NGRAPH_OP(AdaptiveAvgPool, ngraph::op::v8) NGRAPH_OP(AdaptiveMaxPool, ngraph::op::v8) NGRAPH_OP(Gather, op::v8) NGRAPH_OP(MatrixNms, op::v8) +NGRAPH_OP(MaxPool, op::v8) NGRAPH_OP(MulticlassNms, op::v8) From 07f7061f961f8bbbd05f05eb1b1d21c4dc443005 Mon Sep 17 00:00:00 2001 From: Andrei Kochin Date: Wed, 1 Sep 2021 19:59:17 +0300 Subject: [PATCH 76/76] CODEOWNERS: add template plugin maintainers (#5722) --- CODEOWNERS | 1 + 1 file changed, 1 insertion(+) diff --git a/CODEOWNERS b/CODEOWNERS index 165bc745563..92a821790ea 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -72,6 +72,7 @@ azure-pipelines.yml @openvinotoolkit/openvino-admins # Documentation /docs/ @openvinotoolkit/openvino-docs-maintainers +/docs/template_plugin/ @openvinotoolkit/openvino-ie-template-maintainers *.md @openvinotoolkit/openvino-docs-maintainers # Control 3d party dependencies