diff --git a/.ci/azure/windows.yml b/.ci/azure/windows.yml index c94153df5fbbe3..ecb5f96fc1697a 100644 --- a/.ci/azure/windows.yml +++ b/.ci/azure/windows.yml @@ -98,10 +98,6 @@ jobs: workingDirectory: $(BUILD_DIR) displayName: 'Build Win' - - script: echo Stop IncrediBuild_Agent && net stop IncrediBuild_Agent - displayName: Stop IncrediBuild - continueOnError: true - - script: dir $(REPO_DIR)\bin\ /s displayName: 'List files' @@ -204,4 +200,9 @@ jobs: #testRunTitle: 'Pre/Post-Commit' # Optional buildPlatform: 'x64' # Optional buildConfiguration: 'Windows' # Optional - #publishRunAttachments: true # Optional \ No newline at end of file + #publishRunAttachments: true # Optional + + - script: echo Stop IncrediBuild_Agent && net stop IncrediBuild_Agent + displayName: Stop IncrediBuild + continueOnError: true + enabled: false diff --git a/docs/IE_PLUGIN_DG/Doxyfile b/docs/IE_PLUGIN_DG/Doxyfile index 3d66d22b4a2000..e2c4baf4d79aa0 100644 --- a/docs/IE_PLUGIN_DG/Doxyfile +++ b/docs/IE_PLUGIN_DG/Doxyfile @@ -844,8 +844,7 @@ EXCLUDE_SYMLINKS = NO # Note that the wildcards are matched against the file with absolute path, so to # exclude all test directories for example use the pattern */test/* -EXCLUDE_PATTERNS = generic_ie.hpp \ - function_name.hpp \ +EXCLUDE_PATTERNS = function_name.hpp \ macro_overload.hpp # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names diff --git a/docs/doxygen/ie_plugin_api.config b/docs/doxygen/ie_plugin_api.config index 7f97edbaa27088..08a1381fbcd382 100644 --- a/docs/doxygen/ie_plugin_api.config +++ b/docs/doxygen/ie_plugin_api.config @@ -38,8 +38,6 @@ FILE_PATTERNS = *.c \ *.hpp \ *.md -EXCLUDE_PATTERNS = generic_ie.hpp - EXCLUDE_SYMBOLS = InferenceEngine::details TAGFILES = "@DOCS_BUILD_DIR@/ie_api.tag=.." \ diff --git a/inference-engine/include/ie_blob.h b/inference-engine/include/ie_blob.h index 234a13528ebdd1..30b9b6b978ad58 100644 --- a/inference-engine/include/ie_blob.h +++ b/inference-engine/include/ie_blob.h @@ -577,13 +577,14 @@ class TBlob : public MemoryBlob { /** *@brief Virtual destructor. */ -#ifdef __clang__ + +#if defined(__clang__) && !defined(__SYCL_COMPILER_VERSION) virtual ~TBlob(); #else virtual ~TBlob() { free(); } -#endif // __clang__ +#endif // __clang__ && !__SYCL_COMPILER_VERSION /** * @brief Gets the size of the given type. @@ -806,7 +807,7 @@ class TBlob : public MemoryBlob { } }; -#ifdef __clang__ +#if defined(__clang__) && !defined(__SYCL_COMPILER_VERSION) extern template class INFERENCE_ENGINE_API_CLASS(InferenceEngine::TBlob); extern template class INFERENCE_ENGINE_API_CLASS(InferenceEngine::TBlob); extern template class INFERENCE_ENGINE_API_CLASS(InferenceEngine::TBlob); @@ -819,7 +820,7 @@ extern template class INFERENCE_ENGINE_API_CLASS(InferenceEngine::TBlob); extern template class INFERENCE_ENGINE_API_CLASS(InferenceEngine::TBlob); extern template class INFERENCE_ENGINE_API_CLASS(InferenceEngine::TBlob); extern template class INFERENCE_ENGINE_API_CLASS(InferenceEngine::TBlob); -#endif // __clang__ +#endif // __clang__ && !__SYCL_COMPILER_VERSION /** * @brief Creates a blob with the given tensor descriptor. diff --git a/inference-engine/include/ie_parameter.hpp b/inference-engine/include/ie_parameter.hpp index d274edd083a203..e53cef2fb2cade 100644 --- a/inference-engine/include/ie_parameter.hpp +++ b/inference-engine/include/ie_parameter.hpp @@ -265,11 +265,11 @@ class INFERENCE_ENGINE_API_CLASS(Parameter) { struct HasOperatorEqual : CheckOperatorEqual::type {}; struct Any { -#ifdef __clang__ +#if defined(__clang__) && !defined(__SYCL_COMPILER_VERSION) virtual ~Any(); #else virtual ~Any() = default; -#endif +#endif // __clang__ && !__SYCL_COMPILER_VERSION virtual bool is(const std::type_info&) const = 0; virtual Any* copy() const = 0; virtual bool operator==(const Any& rhs) const = 0; @@ -326,7 +326,7 @@ class INFERENCE_ENGINE_API_CLASS(Parameter) { Any* ptr = nullptr; }; -#ifdef __clang__ +#if defined(__clang__) && !defined(__SYCL_COMPILER_VERSION) extern template struct INFERENCE_ENGINE_API_CLASS(InferenceEngine::Parameter::RealData); extern template struct INFERENCE_ENGINE_API_CLASS(InferenceEngine::Parameter::RealData); extern template struct INFERENCE_ENGINE_API_CLASS(InferenceEngine::Parameter::RealData); @@ -341,6 +341,6 @@ extern template struct INFERENCE_ENGINE_API_CLASS( InferenceEngine::Parameter::RealData>); extern template struct INFERENCE_ENGINE_API_CLASS( InferenceEngine::Parameter::RealData>); -#endif // __clang__ +#endif // __clang__ && !__SYCL_COMPILER_VERSION } // namespace InferenceEngine diff --git a/inference-engine/src/cldnn_engine/cldnn_engine.cpp b/inference-engine/src/cldnn_engine/cldnn_engine.cpp index 33db7d494c2c00..2a8a2acdd691e7 100644 --- a/inference-engine/src/cldnn_engine/cldnn_engine.cpp +++ b/inference-engine/src/cldnn_engine/cldnn_engine.cpp @@ -21,7 +21,6 @@ #include #include #include -#include #include #include @@ -137,8 +136,6 @@ InferenceEngine::CNNNetwork clDNNEngine::CloneAndTransformNetwork(const Inferenc if (clonedNetwork.getFunction()) { OV_ITT_SCOPED_TASK(itt::domains::CLDNNPlugin, "clDNNEngine::TransformNetwork"); auto nGraphFunc = clonedNetwork.getFunction(); - // Disable shape inference (WA for generic operations) - ngraph::op::GenericIE::DisableReshape noReshape(nGraphFunc); bool enableInt8; { diff --git a/inference-engine/src/cldnn_engine/cldnn_graph.cpp b/inference-engine/src/cldnn_engine/cldnn_graph.cpp index 340853cf44e5d0..dfa88e4a64b4e3 100644 --- a/inference-engine/src/cldnn_engine/cldnn_graph.cpp +++ b/inference-engine/src/cldnn_engine/cldnn_graph.cpp @@ -25,8 +25,8 @@ #include #include #include -#include "generic_ie.hpp" #include +#include #include "cldnn_itt.h" using namespace InferenceEngine; @@ -464,7 +464,6 @@ InferenceEngine::CNNNetwork CLDNNGraph::GetExecGraphInfoByPrimitivesInfo(std::ve create_ngraph_node(pi); } - ngraph::op::GenericIE::DisableReshape reshape(nodes); auto function = std::make_shared(results, params, "runtime_gpu_graph"); InferenceEngine::CNNNetwork net(function); return net; diff --git a/inference-engine/src/cldnn_engine/cldnn_primitives_list.hpp b/inference-engine/src/cldnn_engine/cldnn_primitives_list.hpp index c3fb7cad324eb0..7fa2f38ccf87e6 100644 --- a/inference-engine/src/cldnn_engine/cldnn_primitives_list.hpp +++ b/inference-engine/src/cldnn_engine/cldnn_primitives_list.hpp @@ -201,5 +201,8 @@ REGISTER_FACTORY(v5, Round); // REGISTER_FACTORY(v5, Loop); // REGISTER_FACTORY(v5, RNNSequence); +// ------------------------------ Supported v6 ops ------------------------------ // +REGISTER_FACTORY(v6, CTCGreedyDecoderSeqLen); + // --------------------------- Supported internal ops --------------------------- // REGISTER_FACTORY(internal, NonMaxSuppressionIEInternal); diff --git a/inference-engine/src/cldnn_engine/ops/ctc_greedy_decoder.cpp b/inference-engine/src/cldnn_engine/ops/ctc_greedy_decoder.cpp index db585aeb2e22ac..7a4398dd23c83f 100644 --- a/inference-engine/src/cldnn_engine/ops/ctc_greedy_decoder.cpp +++ b/inference-engine/src/cldnn_engine/ops/ctc_greedy_decoder.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020 Intel Corporation +// Copyright (C) 2020-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // @@ -6,27 +6,117 @@ #include "cldnn_common_utils.h" #include "ngraph/op/ctc_greedy_decoder.hpp" +#include "ngraph/op/ctc_greedy_decoder_seq_len.hpp" #include "api/ctc_greedy_decoder.hpp" +#include "api/reorder.hpp" +#include "api/mutable_data.hpp" + +#include "transformations/utils/utils.hpp" namespace CLDNNPlugin { -void CreateCTCGreedyDecoderOp(Program& p, const std::shared_ptr& op) { - p.ValidateInputs(op, {2}); +void CreateCommonCTCGreedyDecoderOp(Program& p, const std::shared_ptr& op, bool ctc_merge_repeated) { + p.ValidateInputs(op, {2, 3}); auto inputPrimitives = p.GetInputPrimitiveIDs(op); - std::string layerName = layer_type_name_ID(op); - auto primitive = cldnn::ctc_greedy_decoder(layerName, - inputPrimitives[0], - inputPrimitives[1], - op->get_ctc_merge_repeated(), - DataTypeFromPrecision(op->get_output_element_type(0)), - CldnnTensorFromIEDims(op->get_output_shape(0))); + std::vector reorderedInputs; + reorderedInputs.resize(inputPrimitives.size()); + + for (size_t portIndex = 0; portIndex < inputPrimitives.size(); portIndex++) { + auto inputDataType = DataTypeFromPrecision(op->get_input_element_type(portIndex)); + if (inputDataType == cldnn::data_types::i64) { + // clDNN primitive supports only i32 data type for 'sequence_length' and 'blank_index' inputs + // so we need additional reorder if it's provided as i64 + auto reorderPrimName = inputPrimitives[portIndex] + "_" + op->get_friendly_name() + Program::m_preProcessTag; + auto targetFormat = DefaultFormatForDims(op->get_input_shape(portIndex).size()); + auto preprocessPrim = cldnn::reorder(reorderPrimName, + inputPrimitives[portIndex], + targetFormat, + cldnn::data_types::i32); + p.AddPrimitive(preprocessPrim); + p.AddInnerPrimitiveToProfiler(reorderPrimName, layer_type_name_ID(op), op); + reorderedInputs[portIndex] = (reorderPrimName); + } else { + reorderedInputs[portIndex] = inputPrimitives[portIndex]; + } + } + + uint32_t blank_index = op->get_input_shape(0).back() - 1; + if (reorderedInputs.size() == 3) { + auto blank_index_node = std::dynamic_pointer_cast(op->get_input_node_shared_ptr(2)); + if (!blank_index_node) { + THROW_IE_EXCEPTION << "Unsupported blank_index node type in " << op->get_friendly_name() << " (" << op->get_type_name() << ")"; + } + float val; + if (ngraph::shape_size(blank_index_node->get_output_shape(0)) != 1 || !ngraph::op::util::get_single_value(blank_index_node, val)) { + THROW_IE_EXCEPTION << "Unsupported parameter size in " << op->get_friendly_name() << " (" << op->get_type_name() << ")"; + } + blank_index = static_cast(val); + reorderedInputs.pop_back(); + } + + std::size_t num_output = op->get_output_size(); + + std::vector shared_memory; + if (num_output == 2) { + auto mutable_precision = op->get_output_element_type(1); + if (mutable_precision == ngraph::element::i64) { + mutable_precision = ngraph::element::i32; + } + + cldnn::layout mutableLayout = cldnn::layout( + DataTypeFromPrecision(mutable_precision), + DefaultFormatForDims(op->get_output_shape(1).size()), + CldnnTensorFromIEDims(op->get_output_shape(1))); + + shared_memory.emplace_back(cldnn::memory::allocate(p.GetEngine(), mutableLayout)); + + cldnn::primitive_id ctc_gd_mutable_id_w = layer_type_name_ID(op) + "_md_write"; + auto ctc_gd_mutable_prim = cldnn::mutable_data(ctc_gd_mutable_id_w, shared_memory[0]); + p.primitivesToIRLayersMap[ctc_gd_mutable_id_w] = { op->get_friendly_name() }; + p.primitiveIDs[ctc_gd_mutable_id_w] = ctc_gd_mutable_id_w; + p.AddPrimitive(ctc_gd_mutable_prim); + reorderedInputs.push_back(ctc_gd_mutable_id_w); + } + + auto CTCGreedyDecoderLayerName = num_output == 2 ? layer_type_name_ID(op) + ".0" : layer_type_name_ID(op); + auto primitive = cldnn::ctc_greedy_decoder( + CTCGreedyDecoderLayerName, + reorderedInputs, + blank_index, + ctc_merge_repeated, + CldnnTensorFromIEDims(op->get_output_shape(0))); + + // clDNN primitive supports only i32 as output data type + primitive.output_data_type = DataTypeFromPrecision(ngraph::element::i32); + + if (num_output == 2) { + primitive.second_output = reorderedInputs.back(); + } p.AddPrimitive(primitive); - p.AddPrimitiveToProfiler(op); + + if (num_output == 2) { + cldnn::primitive_id ctc_gd_mutable_id_r = layer_type_name_ID(op) + ".1"; + auto ctc_gd_mutable_prim_r = cldnn::mutable_data(ctc_gd_mutable_id_r, { CTCGreedyDecoderLayerName }, shared_memory[0]); + p.primitivesToIRLayersMap[ctc_gd_mutable_id_r] = { op->get_friendly_name() }; + p.primitiveIDs[ctc_gd_mutable_id_r] = ctc_gd_mutable_id_r; + p.AddPrimitive(ctc_gd_mutable_prim_r); + } + + p.AddPrimitiveToProfiler(CTCGreedyDecoderLayerName, op); +} + +void CreateCTCGreedyDecoderOp(Program& p, const std::shared_ptr& op) { + CreateCommonCTCGreedyDecoderOp(p, op, op->get_ctc_merge_repeated()); +} + +void CreateCTCGreedyDecoderSeqLenOp(Program& p, const std::shared_ptr& op) { + CreateCommonCTCGreedyDecoderOp(p, op, op->get_merge_repeated()); } REGISTER_FACTORY_IMPL(v0, CTCGreedyDecoder); +REGISTER_FACTORY_IMPL(v6, CTCGreedyDecoderSeqLen); } // namespace CLDNNPlugin diff --git a/inference-engine/src/gna_plugin/gna_graph_compiler.cpp b/inference-engine/src/gna_plugin/gna_graph_compiler.cpp index 6eddc5575cc4ec..9fab04f8bed25e 100644 --- a/inference-engine/src/gna_plugin/gna_graph_compiler.cpp +++ b/inference-engine/src/gna_plugin/gna_graph_compiler.cpp @@ -1283,8 +1283,9 @@ void GNAGraphCompiler::AffinePrimitive(InferenceEngine::CNNLayerPtr layer, bool auto input_data = HasTo2DReshapeData(layer) ? Get2DReshapedData(inputs, 8) : inputs; auto in_dims = input_data->getDims(); - uint32_t num_rows_in = InferenceEngine::details::product(in_dims) / in_dims.front(); - uint32_t num_columns_in = in_dims.front(); + auto batch_size = (in_dims.size() == 1) ? 1 : in_dims.front(); + uint32_t num_rows_in = InferenceEngine::details::product(in_dims) / batch_size; + uint32_t num_columns_in = batch_size; uint32_t num_rows_out = isDiag ? num_rows_in : FROM_IR_DIM(outputs, 1); uint32_t num_padding = ALIGN(num_rows_in, 8) - num_rows_in; uint32_t num_padding_out = isDiag ? num_padding : 0; diff --git a/inference-engine/src/gna_plugin/gna_groups.hpp b/inference-engine/src/gna_plugin/gna_groups.hpp index 2635dc1b95cb8f..b2f3f106e708ea 100644 --- a/inference-engine/src/gna_plugin/gna_groups.hpp +++ b/inference-engine/src/gna_plugin/gna_groups.hpp @@ -31,7 +31,8 @@ inline InferenceEngine::DataPtr Get2DReshapedData(InferenceEngine::DataPtr input } } - InferenceEngine::SizeVector newDims(dims.size(), 1); + size_t newDimsSize = (dims.size() > 1) ? dims.size() : 2; + InferenceEngine::SizeVector newDims(newDimsSize, 1); newDims[0] = numColumnsIn; newDims[1] = numRowsIn; return std::make_shared(input->getName(), diff --git a/inference-engine/src/gna_plugin/gna_plugin.cpp b/inference-engine/src/gna_plugin/gna_plugin.cpp index c4e6b267e38a82..1236b695acfda6 100644 --- a/inference-engine/src/gna_plugin/gna_plugin.cpp +++ b/inference-engine/src/gna_plugin/gna_plugin.cpp @@ -40,7 +40,6 @@ #include #include "gna_graph_patterns.hpp" -#include #include #include #include @@ -682,8 +681,6 @@ void GNAPlugin::LoadNetwork(CNNNetwork & _network) { if (_network.getFunction()) { CNNNetwork clonedNetwork = InferenceEngine::cloneNetwork(_network); const auto& graph = clonedNetwork.getFunction(); - // Disable shape inference (WA for generic operations) - ngraph::op::GenericIE::DisableReshape noReshape(graph); ngraph::pass::Manager manager; manager.register_pass(); // WA: ConvertPriorBox must be executed before the 1st ConstantFolding pass @@ -1190,8 +1187,9 @@ uint32_t GNAPlugin::QueueInference(const InferenceEngine::BlobMap &inputs, Infer int inputNum = 0; for (auto &input : inputs) { auto inputLayout = input.second->getTensorDesc().getLayout(); - if (inputLayout != Layout::NC && inputLayout != Layout::CN && inputLayout != Layout::CHW && inputLayout != Layout::NCHW) { - THROW_GNA_EXCEPTION << "Expected input blob to have Layout::NC or Layout::CN, but was: " + if (inputLayout != Layout::C && inputLayout != Layout::NC && inputLayout != Layout::CN && + inputLayout != Layout::CHW && inputLayout != Layout::NCHW) { + THROW_GNA_EXCEPTION << "Expected input blob to have Layout::C, Layout::NC, Layout::CN, Layout::NCHW or Layout::CHW. But was: " << input.second->getTensorDesc().getLayout(); } @@ -1206,7 +1204,7 @@ uint32_t GNAPlugin::QueueInference(const InferenceEngine::BlobMap &inputs, Infer inputLayout = Layout::NC; } - auto is2D = input.second->getTensorDesc().getLayout() == Layout::NC || input.second->getTensorDesc().getLayout() == Layout::CN; + auto is1D = input.second->getTensorDesc().getLayout() == Layout::C; auto is3D = input.second->getTensorDesc().getLayout() == Layout::CHW; if (!inputsDesc->ptr_inputs_global_id.count(input.first)) { @@ -1232,9 +1230,9 @@ uint32_t GNAPlugin::QueueInference(const InferenceEngine::BlobMap &inputs, Infer } } - auto importedElements = is2D ? dims[dims.size() - 1] : dims[dims.size() - 1] * dims[dims.size() - 2] * dims[dims.size() - 3]; - auto importedFrames = is3D ? 1 : dims[0]; - auto targetGroups = is2D ? dims[dims.size() - 2] : dims[0]; // TODO: no proper support for groups yet + auto importedElements = is1D ? dims[0] : details::product(++std::begin(dims), std::end(dims)); + auto importedFrames = (is3D || is1D) ? 1 : dims[0]; + auto targetGroups = is1D ? 1 : dims[0]; // TODO: no proper support for groups yet auto importedElementSizeBytes = gnaFlags->sw_fp32 ? 4 : 2; auto importedBytes = importedElements * importedFrames * importedElementSizeBytes; @@ -1257,8 +1255,8 @@ uint32_t GNAPlugin::QueueInference(const InferenceEngine::BlobMap &inputs, Infer auto transpose_info = transpose_inputs_info.find(input.first); if (transpose_info != std::end(transpose_inputs_info)) { - size_t batchSize = dims[0]; - size_t elementsPerBatch = InferenceEngine::details::product(dims) / dims[0]; + size_t batchSize = (dims.size() > 1) ? dims[0] : 1; + size_t elementsPerBatch = (dims.size() > 1) ? InferenceEngine::details::product(dims) / dims[0] : dims[0]; size_t transposed_data_size = 0; for (const auto &part_transposition_info : transpose_info->second) { transposed_data_size += part_transposition_info.num_transpose_rows * part_transposition_info.num_transpose_columns; @@ -1345,87 +1343,85 @@ GnaWaitStatus GNAPlugin::WaitFor(uint32_t request_idx, int64_t millisTimeout) { for (auto && outputBlobIt : request) { auto & outputBlob = outputBlobIt.second; auto & outputDesc = outputsDesc[output_idx]; - if (outputBlob->getTensorDesc().getLayout() == Layout::NC || outputBlob->getTensorDesc().getLayout() == Layout::CN - || outputBlob->getTensorDesc().getLayout() == Layout::NCHW || outputBlob->getTensorDesc().getLayout() == Layout::CHW) { - auto dims = outputBlob->getTensorDesc().getDims(); - auto is2D = outputBlob->getTensorDesc().getLayout() == Layout::NC || outputBlob->getTensorDesc().getLayout() == Layout::CN; - auto is3D = outputBlob->getTensorDesc().getLayout() == Layout::CHW; - auto& exportOutputDims = outputBlob->getTensorDesc().getDims(); - auto batchSize = is3D ? 1 : exportOutputDims[0]; - auto elementsPerBatch = is2D ? exportOutputDims[exportOutputDims.size() - 1] - : exportOutputDims[exportOutputDims.size() - 1] - * exportOutputDims[exportOutputDims.size() - 2] - * exportOutputDims[exportOutputDims.size() - 3]; - - auto transpose_output_info = transpose_outputs_info.find(outputBlobIt.first); - if (transpose_output_info != std::end(transpose_outputs_info)) { - size_t transposed_data_size = 0; - for (const auto &part_transposition_info : transpose_output_info->second) { - transposed_data_size += part_transposition_info.num_transpose_rows * part_transposition_info.num_transpose_columns; - } - if (elementsPerBatch != transposed_data_size) { - THROW_GNA_EXCEPTION << "Transposed data size (" << transposed_data_size - << ") do not match output buffer length of " << elementsPerBatch; - } - TransposeTensorFromNCHWToNHWC(outputDesc.num_bytes_per_element, - batchSize, - elementsPerBatch, - reinterpret_cast(outputDesc.ptrs[request_idx]), - true, - transpose_output_info->second); + if (!outputBlob->getTensorDesc().getLayout() == Layout::C && !outputBlob->getTensorDesc().getLayout() == Layout::NC && + !outputBlob->getTensorDesc().getLayout() == Layout::CN && !outputBlob->getTensorDesc().getLayout() == Layout::NCHW && + !outputBlob->getTensorDesc().getLayout() == Layout::CHW) { + THROW_GNA_EXCEPTION << "Expected output blob to have Layout::C, Layout::NC, Layout::CN, Layout::NCHW or Layout::CHW. But was " + << outputBlob->getTensorDesc().getLayout(); + } + + auto dims = outputBlob->getTensorDesc().getDims(); + auto is1D = outputBlob->getTensorDesc().getLayout() == Layout::C; + auto is3D = outputBlob->getTensorDesc().getLayout() == Layout::CHW; + auto& exportOutputDims = outputBlob->getTensorDesc().getDims(); + auto batchSize = (is1D || is3D) ? 1 : exportOutputDims[0]; + auto elementsPerBatch = is1D ? exportOutputDims.front() : + details::product(++std::begin(exportOutputDims), std::end(exportOutputDims)); + + auto transpose_output_info = transpose_outputs_info.find(outputBlobIt.first); + if (transpose_output_info != std::end(transpose_outputs_info)) { + size_t transposed_data_size = 0; + for (const auto &part_transposition_info : transpose_output_info->second) { + transposed_data_size += part_transposition_info.num_transpose_rows * part_transposition_info.num_transpose_columns; + } + if (elementsPerBatch != transposed_data_size) { + THROW_GNA_EXCEPTION << "Transposed data size (" << transposed_data_size + << ") do not match output buffer length of " << elementsPerBatch; } + TransposeTensorFromNCHWToNHWC(outputDesc.num_bytes_per_element, + batchSize, + elementsPerBatch, + reinterpret_cast(outputDesc.ptrs[request_idx]), + true, + transpose_output_info->second); + } - ExportScores(outputBlob->buffer(), - outputDesc.ptrs[request_idx], - outputDesc.orientation, - batchSize, - batchSize, - elementsPerBatch, - elementsPerBatch, - elementsPerBatch, - outputDesc.num_bytes_per_element, - sizeof(float)); - - if (gnadevice) { + ExportScores(outputBlob->buffer(), + outputDesc.ptrs[request_idx], + outputDesc.orientation, + batchSize, + batchSize, + elementsPerBatch, + elementsPerBatch, + elementsPerBatch, + outputDesc.num_bytes_per_element, + sizeof(float)); + + if (gnadevice) { #ifdef PLOT - FILE* f = nullptr; - static int num_infers = 0; - { - f = fopen("ex_scores.txt", "w"); - } - num_infers++; - if (f) { - auto dims = outputBlob->getTensorDesc().getDims(); - for (int i = 0; i < dims[dims.size() - 2]; i++) { - for (int j = 0; j < dims[dims.size() - 1]; j++) { - fprintf(f, "%d ", outputBlob->cbuffer().as()[dims[dims.size() - 1] * i + j]); - } - fprintf(f, "\n"); + FILE* f = nullptr; + static int num_infers = 0; + { + f = fopen("ex_scores.txt", "w"); + } + num_infers++; + if (f) { + for (int i = 0; i < batchSize; i++) { + for (int j = 0; j < dims[dims.size() - 1]; j++) { + fprintf(f, "%d ", outputBlob->cbuffer().as()[dims[dims.size() - 1] * i + j]); } - fprintf(f, "\n\n"); + fprintf(f, "\n"); } + fprintf(f, "\n\n"); + } #endif - ConvertToFloat(outputBlob->buffer(), - outputBlob->buffer(), - elementsPerBatch, - batchSize, - outputDesc.scale_factor); + ConvertToFloat(outputBlob->buffer(), + outputBlob->buffer(), + elementsPerBatch, + batchSize, + outputDesc.scale_factor); #ifdef PLOT - if (f) { - auto dims = outputBlob->getTensorDesc().getDims(); - for (int i = 0; i < dims[dims.size() - 2]; i++) { - for (int j = 0; j < dims[dims.size() - 1]; j++) { - fprintf(f, "%.2f ", outputBlob->cbuffer().as()[dims[dims.size() - 1] * i + j]); - } - fprintf(f, "\n"); + if (f) { + auto dims = outputBlob->getTensorDesc().getDims(); + for (int i = 0; i < batchSize; i++) { + for (int j = 0; j < dims[dims.size() - 1]; j++) { + fprintf(f, "%.2f ", outputBlob->cbuffer().as()[dims[dims.size() - 1] * i + j]); } - fclose(f); + fprintf(f, "\n"); } -#endif + fclose(f); } - } else { - THROW_GNA_EXCEPTION << "Expected output blob to have Layout::NC, Layout::CN, Layout::NCHW or Layout::CHW. But was " - << outputBlob->getTensorDesc().getLayout(); +#endif } output_idx++; @@ -1455,11 +1451,22 @@ bool GNAPlugin::Infer(const InferenceEngine::BlobMap &input, InferenceEngine::Bl return Wait(QueueInference(input, result)); } +static InferenceEngine::Layout GetLayoutForDims(const InferenceEngine::SizeVector &dims) { + switch (dims.size()) { + case 1: return C; + case 2: return NC; + case 3: return CHW; + case 4: return NCHW; + default: + THROW_GNA_EXCEPTION << "Unsupported dimensions size in GNA: " << dims.size(); + } +} + Blob::Ptr GNAPlugin::GetOutputBlob(const std::string& name, InferenceEngine::Precision precision) { // need to have intermediate blob for interleave conversion InferenceEngine::Blob::Ptr outputBlob; auto outputDims = outputsDataMap[name]->getTensorDesc().getDims(); - outputBlob = make_blob_with_precision(TensorDesc(precision, outputDims, outputDims.size() == 2 ? NC : (outputDims.size() == 3 ? CHW : NCHW))); + outputBlob = make_blob_with_precision(TensorDesc(precision, outputDims, GetLayoutForDims(outputDims))); outputBlob->allocate(); return outputBlob; } @@ -1469,7 +1476,7 @@ Blob::Ptr GNAPlugin::GetInputBlob(const std::string& name, InferenceEngine::Prec // need to have intermediate blob for interleave conversion // TODO: NCHW format support is experimental = c++ MO did insert reshape, while TF mo - not auto inputDims = inputsDataMap[name]->getTensorDesc().getDims(); - inputBlob = make_blob_with_precision(TensorDesc(precision, inputDims, inputDims.size() == 2 ? NC : (inputDims.size() == 3 ? CHW : NCHW))); + inputBlob = make_blob_with_precision(TensorDesc(precision, inputDims, GetLayoutForDims(inputDims))); inputBlob->allocate(); return inputBlob; } diff --git a/inference-engine/src/inference_engine/cnn_network_ngraph_impl.cpp b/inference-engine/src/inference_engine/cnn_network_ngraph_impl.cpp index 774eed0dd2d35c..156b9ab3eccc72 100644 --- a/inference-engine/src/inference_engine/cnn_network_ngraph_impl.cpp +++ b/inference-engine/src/inference_engine/cnn_network_ngraph_impl.cpp @@ -32,7 +32,6 @@ #include "ie_ngraph_utils.hpp" #include "exec_graph_info.hpp" #include "ie_itt.hpp" -#include "generic_ie.hpp" using namespace std; using namespace InferenceEngine; @@ -44,7 +43,6 @@ static std::shared_ptr copyFunction(const std::shared_ptr CNNNetworkNGraphImpl::cloneFunction(bool const } void CNNNetworkNGraphImpl::reshape() { - // Disable reshape for generic nodes - ::ngraph::op::GenericIE::DisableReshape noReshape(_ngraph_function); reshape({}); } diff --git a/inference-engine/src/inference_engine/generic_ie.cpp b/inference-engine/src/inference_engine/generic_ie.cpp deleted file mode 100644 index b5155013fafb14..00000000000000 --- a/inference-engine/src/inference_engine/generic_ie.cpp +++ /dev/null @@ -1,115 +0,0 @@ -// Copyright (C) 2017-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#include "generic_ie.hpp" - -#include - -#include -#include -#include -#include -#include -#include - -#include "blob_factory.hpp" -#include -#include "ngraph/util.hpp" -#include "ngraph/graph_util.hpp" -#include "ngraph/validation_util.hpp" - -constexpr ::ngraph::NodeTypeInfo ngraph::op::GenericIE::type_info; - -void ngraph::op::GenericIE::addExtension(std::shared_ptr func, - const InferenceEngine::IShapeInferExtensionPtr& ext) { - NodeVector nodes; - - for (auto r : func->get_results()) - nodes.emplace_back(r); - for (auto s : func->get_sinks()) - nodes.emplace_back(s); - for (auto param : func->get_parameters()) - nodes.emplace_back(param); - - traverse_nodes(nodes, [&](std::shared_ptr op) { - if (auto generic = std::dynamic_pointer_cast(op)) { - generic->addExtension(ext); - } - if (auto ti = std::dynamic_pointer_cast(op)) { - addExtension(ti->get_body(), ext); - } - }); -} - -void ngraph::op::GenericIE::addExtension(const InferenceEngine::IShapeInferExtensionPtr& ext) { - extensions.emplace_back(ext); -} - -std::vector ngraph::op::GenericIE::getExtensions(std::shared_ptr func) { - for (auto& op : func->get_ops()) { - if (auto generic = std::dynamic_pointer_cast(op)) { - return generic->getExtensions(); - } - } - return {}; -} - -std::vector ngraph::op::GenericIE::getExtensions() { - return extensions; -} - -ngraph::op::GenericIE::GenericIE(const ngraph::OutputVector& inputs, - const std::map& params_, - const std::string type_, const std::vector& outputs_) - : Op(inputs), params(params_), outputs(outputs_), type(type_), initialized(0) { - constructor_validate_and_infer_types(); -} - -std::shared_ptr ngraph::op::GenericIE::clone_with_new_inputs(const ngraph::OutputVector& new_args) const { - auto genNode = std::make_shared(new_args, params, type, outputs); - genNode->extensions = extensions; - genNode->reshape = reshape; - return genNode; -} - -void ngraph::op::GenericIE::validate_and_infer_types() { - // This function returns precision based on existing precision and - // precision that was set in outputs vector - auto get_precision = [this](const size_t index) -> element::Type { - if (index >= get_output_size() || - get_output_element_type(index) == element::dynamic || - get_output_element_type(index) == element::undefined) { - return InferenceEngine::details::convertPrecision(outputs[index].precision); - } - return get_output_element_type(index); - }; - - // Extensions are not loaded when we create nGraph function - // First call: create node - if (initialized < 1) { - if (outputs.size()) - set_output_size(outputs.size()); - for (size_t output_index = 0; output_index < outputs.size(); output_index++) { - set_output_type(output_index, get_precision(output_index), Shape(outputs[output_index].dims)); - } - initialized++; - } else if (reshape) { - THROW_IE_EXCEPTION << "IShapeInferExtension wasn't registered for node " << get_friendly_name() - << " with type " << type; - } -} - -bool ngraph::op::GenericIE::visit_attributes(ngraph::AttributeVisitor& visitor) { - for (const auto& p : params) { - std::string name = p.first; - std::string value = p.second; - visitor.on_attribute(name, value); - } - // This is a way to pass type name to transformations::Serialize() without - // adding plugin_api dependency on transformation library - std::string name = "__generic_ie_type__"; - std::string value = getType(); - visitor.on_attribute(name, value); - return true; -} diff --git a/inference-engine/src/inference_engine/ie_rtti.cpp b/inference-engine/src/inference_engine/ie_rtti.cpp index a2e45d59fab47e..e32e69ff1881f5 100644 --- a/inference-engine/src/inference_engine/ie_rtti.cpp +++ b/inference-engine/src/inference_engine/ie_rtti.cpp @@ -81,7 +81,7 @@ Parameter::~Parameter() { clear(); } -#ifdef __clang__ +#if defined(__clang__) && !defined(__SYCL_COMPILER_VERSION) Parameter::Any::~Any() {} template struct InferenceEngine::Parameter::RealData; @@ -97,12 +97,12 @@ template struct InferenceEngine::Parameter::RealData> template struct InferenceEngine::Parameter::RealData>; template struct InferenceEngine::Parameter::RealData>; template struct InferenceEngine::Parameter::RealData; -#endif // __clang__ +#endif // __clang__ && !__SYCL_COMPILER_VERSION // // ie_blob.h // -#ifdef __clang__ +#if defined(__clang__) && !defined(__SYCL_COMPILER_VERSION) template TBlob::~TBlob() { free(); @@ -120,4 +120,4 @@ template class InferenceEngine::TBlob; template class InferenceEngine::TBlob; template class InferenceEngine::TBlob; template class InferenceEngine::TBlob; -#endif // __clang__ +#endif // __clang__ && !__SYCL_COMPILER_VERSION diff --git a/inference-engine/src/legacy_api/src/cnn_network_impl.cpp b/inference-engine/src/legacy_api/src/cnn_network_impl.cpp index 9ceb2101fd62f4..69ba2ea25d5945 100644 --- a/inference-engine/src/legacy_api/src/cnn_network_impl.cpp +++ b/inference-engine/src/legacy_api/src/cnn_network_impl.cpp @@ -17,7 +17,6 @@ #include #include -#include "generic_ie.hpp" #include "cnn_network_ngraph_impl.hpp" #include #include @@ -94,8 +93,6 @@ CNNNetworkImpl::CNNNetworkImpl(const ICNNNetwork & ngraphImpl) { IE_ASSERT(ngraphImplPtr != nullptr); IE_ASSERT(ngraphImplPtr->getFunction() != nullptr); auto graph = ngraph::clone_function(*ngraphImpl.getFunction()); - // Disable shape inference (WA for generic operations) - ::ngraph::op::GenericIE::DisableReshape noReshape(graph); ::ngraph::pass::Manager manager; manager.register_pass<::ngraph::pass::InitNodeInfo>(); diff --git a/inference-engine/src/legacy_api/src/convert_function_to_cnn_network.cpp b/inference-engine/src/legacy_api/src/convert_function_to_cnn_network.cpp index 676ba35e97e5cd..12d330a48f1cec 100644 --- a/inference-engine/src/legacy_api/src/convert_function_to_cnn_network.cpp +++ b/inference-engine/src/legacy_api/src/convert_function_to_cnn_network.cpp @@ -39,7 +39,6 @@ #include "legacy/ngraph_ops/rnn_sequence_ie.hpp" #include "legacy/ngraph_ops/lstm_sequence_ie.hpp" #include "legacy/ngraph_ops/gru_sequence_ie.hpp" -#include "generic_ie.hpp" #include "exec_graph_info.hpp" #include "caseless.hpp" @@ -1710,36 +1709,6 @@ InferenceEngine::details::CNNLayerCreator::CNNLayerCreator(const std::shared_ptr return res; }); - addSpecificCreator({"GenericIE"}, [](const std::shared_ptr<::ngraph::Node> &node, - const std::map ¶ms) -> CNNLayerPtr { - auto type = params.at("__generic_ie_type__"); - auto castedLayer = ngraph::as_type_ptr(node); - LayerParams attrs = {node->get_friendly_name(), type, details::convertPrecision(node->get_output_element_type(0))}; - auto res = std::make_shared(attrs); - if (type == "RNNCell") { - res = std::make_shared(attrs); - } - if (type == "GRUCell") { - res = std::make_shared(attrs); - } - - auto weightableLayer = std::dynamic_pointer_cast(res); - for (const auto& param : castedLayer->getParameters()) { - if (param.second.is()) { - res->blobs[param.first] = param.second.as(); - } else if (param.second.is()) { - res->blobs[param.first] = std::const_pointer_cast(param.second.as()); - } else if (param.second.is()) { - res->params[param.first] = param.second.as(); - } - if (weightableLayer && param.first == "weights") - weightableLayer->_weights = res->blobs[param.first]; - if (weightableLayer && param.first == "biases") - weightableLayer->_biases = res->blobs[param.first]; - } - return res; - }); - addSpecificCreator({"ShuffleChannels"}, [](const std::shared_ptr<::ngraph::Node>& node, const std::map& params) -> CNNLayerPtr { LayerParams attrs = {node->get_friendly_name(), "ShuffleChannels", details::convertPrecision(node->get_output_element_type(0))}; diff --git a/inference-engine/src/mkldnn_plugin/emitters/jit_bf16_emitters.hpp b/inference-engine/src/mkldnn_plugin/emitters/jit_bf16_emitters.hpp new file mode 100644 index 00000000000000..1c6aa581278e2c --- /dev/null +++ b/inference-engine/src/mkldnn_plugin/emitters/jit_bf16_emitters.hpp @@ -0,0 +1,73 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// +#pragma once + +#include "jit_emitter.hpp" + +namespace MKLDNNPlugin { + +class jit_emu_vcvtneps2bf16 : public jit_emitter { +public: + jit_emu_vcvtneps2bf16(mkldnn::impl::cpu::x64::jit_generator* host, mkldnn::impl::cpu::x64::cpu_isa_t host_isa, const MKLDNNNode* node, + InferenceEngine::Precision exec_prc = InferenceEngine::Precision::BF16) : jit_emitter(host, host_isa, node, exec_prc) { + prepare_table(); + }; + + size_t get_inputs_num() const override { return 1; }; + +private: + void emit_impl(const std::vector& in_vec_idxs, const std::vector& out_vec_idxs, + const std::vector& pool_vec_idxs, const std::vector& pool_gpr_idxs, + const emitter_context *emit_context) const override { + if (host_isa_ == mkldnn::impl::cpu::x64::cpu_isa_t::avx512_common) { + Xbyak::Zmm in = Xbyak::Zmm(in_vec_idxs[0]); + Xbyak::Ymm out = Xbyak::Ymm(out_vec_idxs[0]); + Xbyak::Zmm aux = Xbyak::Zmm(aux_vec_idxs[0]); + Xbyak::Zmm aux1 = Xbyak::Zmm(aux_vec_idxs[1]); + + h->uni_vpsrld(aux, in, 16); + h->vpandd(aux, aux, table_val("one")); + h->uni_vmovups(aux1, table_val("even")); + h->uni_vpaddd(aux, aux1, aux); + h->uni_vpaddd(aux, in, aux); + h->vfixupimmps(aux, in, table_val("selector"), 0); + h->vpsrad(aux, aux, 16); + h->vpmovdw(out, aux); + } else { + assert(!"unsupported isa"); + } + }; + + + inline int encode_fixup_selector(int input, int output) { + return ((output) << (4 * (input))); + } + + void register_table_entries() override { + enum { + fixup_input_code_qnan_ = 0, + fixup_input_code_snan_ = 1, + fixup_input_code_ninf_ = 4, + fixup_input_code_pinf_ = 5, + fixup_output_code_copy_input_ = 1, + fixup_output_code_qnan_input_ = 2, + }; + const int selector_int32 = + /* qnan input to qnan output (presenrving input bits 0..21) */ + encode_fixup_selector(fixup_input_code_snan_, fixup_output_code_qnan_input_) | + /* snan input to qnan output (presenrving input bits 0..21) */ + encode_fixup_selector(fixup_input_code_qnan_, fixup_output_code_qnan_input_) | + /* neg inf input copied to output */ + encode_fixup_selector(fixup_input_code_ninf_, fixup_output_code_copy_input_) | + /* pos inf input copied to output */ + encode_fixup_selector(fixup_input_code_pinf_, fixup_output_code_copy_input_); + push_arg_entry_of("one", 0x00000001, true); + push_arg_entry_of("even", 0x00007fff, true); + push_arg_entry_of("selector", selector_int32, true); + } + + size_t aux_vecs_count() const override { return 2; } +}; + +} // namespace MKLDNNPlugin { \ No newline at end of file diff --git a/inference-engine/src/mkldnn_plugin/nodes/jit_eltwise_emitters.cpp b/inference-engine/src/mkldnn_plugin/emitters/jit_eltwise_emitters.cpp similarity index 84% rename from inference-engine/src/mkldnn_plugin/nodes/jit_eltwise_emitters.cpp rename to inference-engine/src/mkldnn_plugin/emitters/jit_eltwise_emitters.cpp index 447c812f5ac191..aefca48ca3927b 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/jit_eltwise_emitters.cpp +++ b/inference-engine/src/mkldnn_plugin/emitters/jit_eltwise_emitters.cpp @@ -2,13 +2,11 @@ // SPDX-License-Identifier: Apache-2.0 // -#include "common/emitter.h" #include "jit_eltwise_emitters.hpp" -#include "mkldnn_eltwise_node.h" #include #include "legacy/ie_layers.h" - +#include using namespace InferenceEngine; using namespace mkldnn::impl::utils; @@ -19,14 +17,16 @@ using namespace Xbyak; namespace MKLDNNPlugin { /// ADD /// +jit_add_emitter::jit_add_emitter(jit_generator *host, cpu_isa_t host_isa, const std::shared_ptr& node, Precision exec_prc) +: jit_emitter(host, host_isa, node, exec_prc) {} jit_add_emitter::jit_add_emitter(jit_generator *host, cpu_isa_t host_isa, const MKLDNNNode* node, Precision exec_prc) : jit_emitter(host, host_isa, node, exec_prc) {} -size_t jit_add_emitter::get_inputs_num() { return 2; } +size_t jit_add_emitter::get_inputs_num() const { return 2; } void jit_add_emitter::emit_impl(const std::vector &in_vec_idxs, const std::vector &out_vec_idxs, const std::vector &pool_vec_idxs, const std::vector &pool_gpr_idxs, - const emitter_context *emit_context) { + const emitter_context *emit_context) const { if (host_isa_ == cpu::x64::sse41) { emit_isa(in_vec_idxs, out_vec_idxs); } else if (host_isa_ == cpu::x64::avx2) { @@ -54,14 +54,16 @@ void jit_add_emitter::emit_isa(const std::vector &in_vec_idxs, const std } /// MUL_ADD /// +jit_mul_add_emitter::jit_mul_add_emitter(jit_generator *host, cpu_isa_t host_isa, const std::shared_ptr& node, Precision exec_prc) +: jit_emitter(host, host_isa, node, exec_prc) {} jit_mul_add_emitter::jit_mul_add_emitter(jit_generator *host, cpu_isa_t host_isa, const MKLDNNNode* node, Precision exec_prc) : jit_emitter(host, host_isa, node, exec_prc) {} -size_t jit_mul_add_emitter::get_inputs_num() { return 3; } +size_t jit_mul_add_emitter::get_inputs_num() const { return 3; } void jit_mul_add_emitter::emit_impl(const std::vector &in_vec_idxs, const std::vector &out_vec_idxs, const std::vector &pool_vec_idxs, const std::vector &pool_gpr_idxs, - const emitter_context *emit_context) { + const emitter_context *emit_context) const { if (host_isa_ == cpu::x64::sse41) { emit_isa(in_vec_idxs, out_vec_idxs); } else if (host_isa_ == cpu::x64::avx2) { @@ -114,14 +116,16 @@ size_t jit_mul_add_emitter::aux_vecs_count() const { } /// SUB /// +jit_subtract_emitter::jit_subtract_emitter(jit_generator *host, cpu_isa_t host_isa, const std::shared_ptr& node, Precision exec_prc) +: jit_emitter(host, host_isa, node, exec_prc) {} jit_subtract_emitter::jit_subtract_emitter(jit_generator *host, cpu_isa_t host_isa, const MKLDNNNode* node, Precision exec_prc) : jit_emitter(host, host_isa, node, exec_prc) {} -size_t jit_subtract_emitter::get_inputs_num() { return 2; } +size_t jit_subtract_emitter::get_inputs_num() const { return 2; } void jit_subtract_emitter::emit_impl(const std::vector &in_vec_idxs, const std::vector &out_vec_idxs, const std::vector &pool_vec_idxs, const std::vector &pool_gpr_idxs, - const emitter_context *emit_context) { + const emitter_context *emit_context) const { if (host_isa_ == cpu::x64::sse41) { emit_isa(in_vec_idxs, out_vec_idxs); } else if (host_isa_ == cpu::x64::avx2) { @@ -150,14 +154,16 @@ void jit_subtract_emitter::emit_isa(const std::vector &in_vec_idxs, cons /// MULTIPLY /// +jit_multiply_emitter::jit_multiply_emitter(jit_generator *host, cpu_isa_t host_isa, const std::shared_ptr& node, Precision exec_prc) +: jit_emitter(host, host_isa, node, exec_prc) {} jit_multiply_emitter::jit_multiply_emitter(jit_generator *host, cpu_isa_t host_isa, const MKLDNNNode* node, Precision exec_prc) : jit_emitter(host, host_isa, node, exec_prc) {} -size_t jit_multiply_emitter::get_inputs_num() { return 2; } +size_t jit_multiply_emitter::get_inputs_num() const { return 2; } void jit_multiply_emitter::emit_impl(const std::vector &in_vec_idxs, const std::vector &out_vec_idxs, const std::vector &pool_vec_idxs, const std::vector &pool_gpr_idxs, - const emitter_context *emit_context) { + const emitter_context *emit_context) const { if (host_isa_ == cpu::x64::sse41) { emit_isa(in_vec_idxs, out_vec_idxs); } else if (host_isa_ == cpu::x64::avx2) { @@ -186,14 +192,16 @@ void jit_multiply_emitter::emit_isa(const std::vector &in_vec_idxs, cons /// DIVIDE /// +jit_divide_emitter::jit_divide_emitter(jit_generator *host, cpu_isa_t host_isa, const std::shared_ptr& node, Precision exec_prc) +: jit_emitter(host, host_isa, node, exec_prc) {} jit_divide_emitter::jit_divide_emitter(jit_generator *host, cpu_isa_t host_isa, const MKLDNNNode* node, Precision exec_prc) : jit_emitter(host, host_isa, node, exec_prc) {} -size_t jit_divide_emitter::get_inputs_num() { return 2; } +size_t jit_divide_emitter::get_inputs_num() const { return 2; } void jit_divide_emitter::emit_impl(const std::vector &in_vec_idxs, const std::vector &out_vec_idxs, const std::vector &pool_vec_idxs, const std::vector &pool_gpr_idxs, - const emitter_context *emit_context) { + const emitter_context *emit_context) const { if (host_isa_ == cpu::x64::sse41) { emit_isa(in_vec_idxs, out_vec_idxs); } else if (host_isa_ == cpu::x64::avx2) { @@ -251,14 +259,16 @@ size_t jit_divide_emitter::aux_vecs_count() const { } /// FLOOR_MOD /// +jit_floor_mod_emitter::jit_floor_mod_emitter(jit_generator *host, cpu_isa_t host_isa, const std::shared_ptr& node, Precision exec_prc) +: jit_emitter(host, host_isa, node, exec_prc) {} jit_floor_mod_emitter::jit_floor_mod_emitter(jit_generator *host, cpu_isa_t host_isa, const MKLDNNNode* node, Precision exec_prc) : jit_emitter(host, host_isa, node, exec_prc) {} -size_t jit_floor_mod_emitter::get_inputs_num() { return 2; } +size_t jit_floor_mod_emitter::get_inputs_num() const { return 2; } void jit_floor_mod_emitter::emit_impl(const std::vector &in_vec_idxs, const std::vector &out_vec_idxs, const std::vector &pool_vec_idxs, const std::vector &pool_gpr_idxs, - const emitter_context *emit_context) { + const emitter_context *emit_context) const { if (host_isa_ == cpu::x64::sse41) { emit_isa(in_vec_idxs, out_vec_idxs); } else if (host_isa_ == cpu::x64::avx2) { @@ -301,14 +311,16 @@ size_t jit_floor_mod_emitter::aux_vecs_count() const { } /// MOD /// +jit_mod_emitter::jit_mod_emitter(jit_generator *host, cpu_isa_t host_isa, const std::shared_ptr& node, Precision exec_prc) +: jit_emitter(host, host_isa, node, exec_prc) {} jit_mod_emitter::jit_mod_emitter(jit_generator *host, cpu_isa_t host_isa, const MKLDNNNode* node, Precision exec_prc) : jit_emitter(host, host_isa, node, exec_prc) {} -size_t jit_mod_emitter::get_inputs_num() { return 2; } +size_t jit_mod_emitter::get_inputs_num() const { return 2; } void jit_mod_emitter::emit_impl(const std::vector &in_vec_idxs, const std::vector &out_vec_idxs, const std::vector &pool_vec_idxs, const std::vector &pool_gpr_idxs, - const emitter_context *emit_context) { + const emitter_context *emit_context) const { if (host_isa_ == cpu::x64::sse41) { emit_isa(in_vec_idxs, out_vec_idxs); } else if (host_isa_ == cpu::x64::avx2) { @@ -351,14 +363,16 @@ size_t jit_mod_emitter::aux_vecs_count() const { } /// MAXIMUM /// +jit_maximum_emitter::jit_maximum_emitter(jit_generator *host, cpu_isa_t host_isa, const std::shared_ptr& node, Precision exec_prc) +: jit_emitter(host, host_isa, node, exec_prc) {} jit_maximum_emitter::jit_maximum_emitter(jit_generator *host, cpu_isa_t host_isa, const MKLDNNNode* node, Precision exec_prc) : jit_emitter(host, host_isa, node, exec_prc) {} -size_t jit_maximum_emitter::get_inputs_num() { return 2; } +size_t jit_maximum_emitter::get_inputs_num() const { return 2; } void jit_maximum_emitter::emit_impl(const std::vector &in_vec_idxs, const std::vector &out_vec_idxs, const std::vector &pool_vec_idxs, const std::vector &pool_gpr_idxs, - const emitter_context *emit_context) { + const emitter_context *emit_context) const { if (host_isa_ == cpu::x64::sse41) { emit_isa(in_vec_idxs, out_vec_idxs); } else if (host_isa_ == cpu::x64::avx2) { @@ -399,14 +413,16 @@ std::set jit_maximum_emitter::get_supported_precisio } /// MINIMUM /// +jit_minimum_emitter::jit_minimum_emitter(jit_generator *host, cpu_isa_t host_isa, const std::shared_ptr& node, Precision exec_prc) +: jit_emitter(host, host_isa, node, exec_prc) {} jit_minimum_emitter::jit_minimum_emitter(jit_generator *host, cpu_isa_t host_isa, const MKLDNNNode* node, Precision exec_prc) : jit_emitter(host, host_isa, node, exec_prc) {} -size_t jit_minimum_emitter::get_inputs_num() { return 2; } +size_t jit_minimum_emitter::get_inputs_num() const { return 2; } void jit_minimum_emitter::emit_impl(const std::vector &in_vec_idxs, const std::vector &out_vec_idxs, const std::vector &pool_vec_idxs, const std::vector &pool_gpr_idxs, - const emitter_context *emit_context) { + const emitter_context *emit_context) const { if (host_isa_ == cpu::x64::sse41) { emit_isa(in_vec_idxs, out_vec_idxs); } else if (host_isa_ == cpu::x64::avx2) { @@ -447,14 +463,17 @@ std::set jit_minimum_emitter::get_supported_precisio } /// SQUARED_DIFFERENCE /// +jit_squared_difference_emitter::jit_squared_difference_emitter( + jit_generator *host, cpu_isa_t host_isa, const std::shared_ptr& node, Precision exec_prc) +: jit_emitter(host, host_isa, node, exec_prc) {} jit_squared_difference_emitter::jit_squared_difference_emitter(jit_generator *host, cpu_isa_t host_isa, const MKLDNNNode* node, Precision exec_prc) : jit_emitter(host, host_isa, node, exec_prc) {} -size_t jit_squared_difference_emitter::get_inputs_num() { return 2; } +size_t jit_squared_difference_emitter::get_inputs_num() const { return 2; } void jit_squared_difference_emitter::emit_impl(const std::vector &in_vec_idxs, const std::vector &out_vec_idxs, const std::vector &pool_vec_idxs, const std::vector &pool_gpr_idxs, - const emitter_context *emit_context) { + const emitter_context *emit_context) const { if (host_isa_ == cpu::x64::sse41) { emit_isa(in_vec_idxs, out_vec_idxs); } else if (host_isa_ == cpu::x64::avx2) { @@ -486,14 +505,16 @@ void jit_squared_difference_emitter::emit_isa(const std::vector &in_vec_ /// POWER_DYNAMIC /// +jit_power_dynamic_emitter::jit_power_dynamic_emitter(jit_generator *host, cpu_isa_t host_isa, const std::shared_ptr& node, Precision exec_prc) +: jit_emitter(host, host_isa, node, exec_prc) {} jit_power_dynamic_emitter::jit_power_dynamic_emitter(jit_generator *host, cpu_isa_t host_isa, const MKLDNNNode* node, Precision exec_prc) : jit_emitter(host, host_isa, node, exec_prc) {} -size_t jit_power_dynamic_emitter::get_inputs_num() { return 2; } +size_t jit_power_dynamic_emitter::get_inputs_num() const { return 2; } void jit_power_dynamic_emitter::emit_impl(const std::vector &in_vec_idxs, const std::vector &out_vec_idxs, const std::vector &pool_vec_idxs, const std::vector &pool_gpr_idxs, - const emitter_context *emit_context) { + const emitter_context *emit_context) const { if (host_isa_ == cpu::x64::sse41) { emit_isa(in_vec_idxs, out_vec_idxs); } else if (host_isa_ == cpu::x64::avx2) { @@ -593,16 +614,20 @@ void jit_power_dynamic_emitter::emit_isa(const std::vector &in_vec_idxs, /// EQUAL /// +jit_equal_emitter::jit_equal_emitter(jit_generator *host, cpu_isa_t host_isa, const std::shared_ptr& node, Precision exec_prc) +: jit_emitter(host, host_isa, node, exec_prc) { + prepare_table(); +} jit_equal_emitter::jit_equal_emitter(jit_generator *host, cpu_isa_t host_isa, const MKLDNNNode* node, Precision exec_prc) : jit_emitter(host, host_isa, node, exec_prc) { prepare_table(); } -size_t jit_equal_emitter::get_inputs_num() { return 2; } +size_t jit_equal_emitter::get_inputs_num() const { return 2; } void jit_equal_emitter::emit_impl(const std::vector &in_vec_idxs, const std::vector &out_vec_idxs, const std::vector &pool_vec_idxs, const std::vector &pool_gpr_idxs, - const emitter_context *emit_context) { + const emitter_context *emit_context) const { if (host_isa_ == cpu::x64::sse41) { emit_isa(in_vec_idxs, out_vec_idxs); } else if (host_isa_ == cpu::x64::avx2) { @@ -650,16 +675,20 @@ size_t jit_equal_emitter::aux_vecs_count() const { } /// NOT_EQUAL /// +jit_not_equal_emitter::jit_not_equal_emitter(jit_generator *host, cpu_isa_t host_isa, const std::shared_ptr& node, Precision exec_prc) +: jit_emitter(host, host_isa, node, exec_prc) { + prepare_table(); +} jit_not_equal_emitter::jit_not_equal_emitter(jit_generator *host, cpu_isa_t host_isa, const MKLDNNNode* node, Precision exec_prc) : jit_emitter(host, host_isa, node, exec_prc) { prepare_table(); } -size_t jit_not_equal_emitter::get_inputs_num() { return 2; } +size_t jit_not_equal_emitter::get_inputs_num() const { return 2; } void jit_not_equal_emitter::emit_impl(const std::vector &in_vec_idxs, const std::vector &out_vec_idxs, const std::vector &pool_vec_idxs, const std::vector &pool_gpr_idxs, - const emitter_context *emit_context) { + const emitter_context *emit_context) const { if (host_isa_ == cpu::x64::sse41) { emit_isa(in_vec_idxs, out_vec_idxs); } else if (host_isa_ == cpu::x64::avx2) { @@ -707,16 +736,20 @@ size_t jit_not_equal_emitter::aux_vecs_count() const { } /// GREATER /// +jit_greater_emitter::jit_greater_emitter(jit_generator *host, cpu_isa_t host_isa, const std::shared_ptr& node, Precision exec_prc) +: jit_emitter(host, host_isa, node, exec_prc) { + prepare_table(); +} jit_greater_emitter::jit_greater_emitter(jit_generator *host, cpu_isa_t host_isa, const MKLDNNNode* node, Precision exec_prc) : jit_emitter(host, host_isa, node, exec_prc) { prepare_table(); } -size_t jit_greater_emitter::get_inputs_num() { return 2; } +size_t jit_greater_emitter::get_inputs_num() const { return 2; } void jit_greater_emitter::emit_impl(const std::vector &in_vec_idxs, const std::vector &out_vec_idxs, const std::vector &pool_vec_idxs, const std::vector &pool_gpr_idxs, - const emitter_context *emit_context) { + const emitter_context *emit_context) const { if (host_isa_ == cpu::x64::sse41) { emit_isa(in_vec_idxs, out_vec_idxs); } else if (host_isa_ == cpu::x64::avx2) { @@ -764,16 +797,20 @@ size_t jit_greater_emitter::aux_vecs_count() const { } /// GREATER_EQUAL /// +jit_greater_equal_emitter::jit_greater_equal_emitter(jit_generator *host, cpu_isa_t host_isa, const std::shared_ptr& node, Precision exec_prc) +: jit_emitter(host, host_isa, node, exec_prc) { + prepare_table(); +} jit_greater_equal_emitter::jit_greater_equal_emitter(jit_generator *host, cpu_isa_t host_isa, const MKLDNNNode* node, Precision exec_prc) : jit_emitter(host, host_isa, node, exec_prc) { prepare_table(); } -size_t jit_greater_equal_emitter::get_inputs_num() { return 2; } +size_t jit_greater_equal_emitter::get_inputs_num() const { return 2; } void jit_greater_equal_emitter::emit_impl(const std::vector &in_vec_idxs, const std::vector &out_vec_idxs, const std::vector &pool_vec_idxs, const std::vector &pool_gpr_idxs, - const emitter_context *emit_context) { + const emitter_context *emit_context) const { if (host_isa_ == cpu::x64::sse41) { emit_isa(in_vec_idxs, out_vec_idxs); } else if (host_isa_ == cpu::x64::avx2) { @@ -821,16 +858,20 @@ size_t jit_greater_equal_emitter::aux_vecs_count() const { } /// LESS /// +jit_less_emitter::jit_less_emitter(jit_generator *host, cpu_isa_t host_isa, const std::shared_ptr& node, Precision exec_prc) +: jit_emitter(host, host_isa, node, exec_prc) { + prepare_table(); +} jit_less_emitter::jit_less_emitter(jit_generator *host, cpu_isa_t host_isa, const MKLDNNNode* node, Precision exec_prc) : jit_emitter(host, host_isa, node, exec_prc) { prepare_table(); } -size_t jit_less_emitter::get_inputs_num() { return 2; } +size_t jit_less_emitter::get_inputs_num() const { return 2; } void jit_less_emitter::emit_impl(const std::vector &in_vec_idxs, const std::vector &out_vec_idxs, const std::vector &pool_vec_idxs, const std::vector &pool_gpr_idxs, - const emitter_context *emit_context) { + const emitter_context *emit_context) const { if (host_isa_ == cpu::x64::sse41) { emit_isa(in_vec_idxs, out_vec_idxs); } else if (host_isa_ == cpu::x64::avx2) { @@ -878,16 +919,20 @@ size_t jit_less_emitter::aux_vecs_count() const { } /// LESS_EQUAL /// +jit_less_equal_emitter::jit_less_equal_emitter(jit_generator *host, cpu_isa_t host_isa, const std::shared_ptr& node, Precision exec_prc) +: jit_emitter(host, host_isa, node, exec_prc) { + prepare_table(); +} jit_less_equal_emitter::jit_less_equal_emitter(jit_generator *host, cpu_isa_t host_isa, const MKLDNNNode* node, Precision exec_prc) : jit_emitter(host, host_isa, node, exec_prc) { prepare_table(); } -size_t jit_less_equal_emitter::get_inputs_num() { return 2; } +size_t jit_less_equal_emitter::get_inputs_num() const { return 2; } void jit_less_equal_emitter::emit_impl(const std::vector &in_vec_idxs, const std::vector &out_vec_idxs, const std::vector &pool_vec_idxs, const std::vector &pool_gpr_idxs, - const emitter_context *emit_context) { + const emitter_context *emit_context) const { if (host_isa_ == cpu::x64::sse41) { emit_isa(in_vec_idxs, out_vec_idxs); } else if (host_isa_ == cpu::x64::avx2) { @@ -936,16 +981,20 @@ size_t jit_less_equal_emitter::aux_vecs_count() const { } /// LOGICAL_AND /// +jit_logical_and_emitter::jit_logical_and_emitter(jit_generator *host, cpu_isa_t host_isa, const std::shared_ptr& node, Precision exec_prc) +: jit_emitter(host, host_isa, node, exec_prc) { + prepare_table(); +} jit_logical_and_emitter::jit_logical_and_emitter(jit_generator *host, cpu_isa_t host_isa, const MKLDNNNode* node, Precision exec_prc) : jit_emitter(host, host_isa, node, exec_prc) { prepare_table(); } -size_t jit_logical_and_emitter::get_inputs_num() { return 2; } +size_t jit_logical_and_emitter::get_inputs_num() const { return 2; } void jit_logical_and_emitter::emit_impl(const std::vector &in_vec_idxs, const std::vector &out_vec_idxs, const std::vector &pool_vec_idxs, const std::vector &pool_gpr_idxs, - const emitter_context *emit_context) { + const emitter_context *emit_context) const { if (host_isa_ == cpu::x64::sse41) { emit_isa(in_vec_idxs, out_vec_idxs); } else if (host_isa_ == cpu::x64::avx2) { @@ -1014,16 +1063,20 @@ size_t jit_logical_and_emitter::aux_vecs_count() const { /// LOGICAL_OR /// +jit_logical_or_emitter::jit_logical_or_emitter(jit_generator *host, cpu_isa_t host_isa, const std::shared_ptr& node, Precision exec_prc) +: jit_emitter(host, host_isa, node, exec_prc) { + prepare_table(); +} jit_logical_or_emitter::jit_logical_or_emitter(jit_generator *host, cpu_isa_t host_isa, const MKLDNNNode* node, Precision exec_prc) : jit_emitter(host, host_isa, node, exec_prc) { prepare_table(); } -size_t jit_logical_or_emitter::get_inputs_num() { return 2; } +size_t jit_logical_or_emitter::get_inputs_num() const { return 2; } void jit_logical_or_emitter::emit_impl(const std::vector &in_vec_idxs, const std::vector &out_vec_idxs, const std::vector &pool_vec_idxs, const std::vector &pool_gpr_idxs, - const emitter_context *emit_context) { + const emitter_context *emit_context) const { if (host_isa_ == cpu::x64::sse41) { emit_isa(in_vec_idxs, out_vec_idxs); } else if (host_isa_ == cpu::x64::avx2) { @@ -1091,16 +1144,20 @@ size_t jit_logical_or_emitter::aux_vecs_count() const { } /// LOGICAL_XOR /// +jit_logical_xor_emitter::jit_logical_xor_emitter(jit_generator *host, cpu_isa_t host_isa, const std::shared_ptr& node, Precision exec_prc) +: jit_emitter(host, host_isa, node, exec_prc) { + prepare_table(); +} jit_logical_xor_emitter::jit_logical_xor_emitter(jit_generator *host, cpu_isa_t host_isa, const MKLDNNNode* node, Precision exec_prc) : jit_emitter(host, host_isa, node, exec_prc) { prepare_table(); } -size_t jit_logical_xor_emitter::get_inputs_num() { return 2; } +size_t jit_logical_xor_emitter::get_inputs_num() const { return 2; } void jit_logical_xor_emitter::emit_impl(const std::vector &in_vec_idxs, const std::vector &out_vec_idxs, const std::vector &pool_vec_idxs, const std::vector &pool_gpr_idxs, - const emitter_context *emit_context) { + const emitter_context *emit_context) const { if (host_isa_ == cpu::x64::sse41) { emit_isa(in_vec_idxs, out_vec_idxs); } else if (host_isa_ == cpu::x64::avx2) { @@ -1168,16 +1225,20 @@ size_t jit_logical_xor_emitter::aux_vecs_count() const { } /// LOGICAL_NOT /// +jit_logical_not_emitter::jit_logical_not_emitter(jit_generator *host, cpu_isa_t host_isa, const std::shared_ptr& node, Precision exec_prc) +: jit_emitter(host, host_isa, node, exec_prc) { + prepare_table(); +} jit_logical_not_emitter::jit_logical_not_emitter(jit_generator *host, cpu_isa_t host_isa, const MKLDNNNode* node, Precision exec_prc) : jit_emitter(host, host_isa, node, exec_prc) { prepare_table(); } -size_t jit_logical_not_emitter::get_inputs_num() { return 1; } +size_t jit_logical_not_emitter::get_inputs_num() const { return 1; } void jit_logical_not_emitter::emit_impl(const std::vector &in_vec_idxs, const std::vector &out_vec_idxs, const std::vector &pool_vec_idxs, const std::vector &pool_gpr_idxs, - const emitter_context *emit_context) { + const emitter_context *emit_context) const { if (host_isa_ == cpu::x64::sse41) { emit_isa(in_vec_idxs, out_vec_idxs); } else if (host_isa_ == cpu::x64::avx2) { @@ -1224,16 +1285,44 @@ size_t jit_logical_not_emitter::aux_vecs_count() const { } /// POWER_STATIC /// +jit_power_static_emitter::jit_power_static_emitter(jit_generator *host, cpu_isa_t host_isa, const std::shared_ptr& node, Precision exec_prc) +: jit_emitter(host, host_isa, node, exec_prc) { + auto parent = node->input(1).get_source_output().get_node_shared_ptr(); + if (!std::dynamic_pointer_cast(parent)) { + throw ngraph::ngraph_error("unsupported non constant power"); + } + + if (!(node->input(1).get_shape() == ngraph::Shape() || ngraph::shape_size(node->input(1).get_shape()) == 1)) { + throw ngraph::ngraph_error("unsupported non scalar power"); + } + power = ngraph::as_type_ptr(parent)->get_data_ptr()[0]; + scale = 1.f; + shift = 0.f; + push_arg_entry_of("power", float2int(power), true); + push_arg_entry_of("scale", 0x3f800000, true); + push_arg_entry_of("shift", 0x00000000, true); + push_arg_entry_of("one", 0x3f800000, true); + + prepare_table(); +} jit_power_static_emitter::jit_power_static_emitter(jit_generator *host, cpu_isa_t host_isa, const MKLDNNNode* node, Precision exec_prc) : jit_emitter(host, host_isa, node, exec_prc) { + auto *powerLayer = dynamic_cast(node->getCnnLayer().get()); + if (powerLayer == nullptr) + THROW_IE_EXCEPTION << "Cannot convert power layer."; + + power = powerLayer->power; + scale = powerLayer->scale; + shift = powerLayer->offset; + prepare_table(); } -size_t jit_power_static_emitter::get_inputs_num() { return 1; } +size_t jit_power_static_emitter::get_inputs_num() const { return 1; } void jit_power_static_emitter::emit_impl(const std::vector &in_vec_idxs, const std::vector &out_vec_idxs, const std::vector &pool_vec_idxs, const std::vector &pool_gpr_idxs, - const emitter_context *emit_context) { + const emitter_context *emit_context) const { if (host_isa_ == cpu::x64::sse41) { emit_isa(in_vec_idxs, out_vec_idxs); } else if (host_isa_ == cpu::x64::avx2) { @@ -1252,14 +1341,6 @@ void jit_power_static_emitter::emit_isa(const std::vector &in_vec_idxs, Vmm vmm_dst = Vmm(out_vec_idxs[0]); Vmm vmm_aux0 = Vmm(aux_vec_idxs[0]); - auto *powerLayer = dynamic_cast(n->getCnnLayer().get()); - if (powerLayer == nullptr) - THROW_IE_EXCEPTION << "Cannot convert power layer."; - - float power = powerLayer->power; - float scale = powerLayer->scale; - float shift = powerLayer->offset; - Xmm xmm0 = Xmm(0), xmm1 = Xmm(1); if (scale != 1.f || shift != 0.f) { @@ -1394,17 +1475,9 @@ void jit_power_static_emitter::emit_isa(const std::vector &in_vec_idxs, } void jit_power_static_emitter::register_table_entries() { - auto *powerLayer = dynamic_cast(n->getCnnLayer().get()); - if (powerLayer == nullptr) - THROW_IE_EXCEPTION << "Cannot convert power layer."; - - float power_ = powerLayer->power; - float scale_ = powerLayer->scale; - float shift_ = powerLayer->offset; - - push_arg_entry_of("power", float2int(power_), true); - push_arg_entry_of("scale", float2int(scale_), true); - push_arg_entry_of("shift", float2int(shift_), true); + push_arg_entry_of("power", float2int(power), true); + push_arg_entry_of("scale", float2int(scale), true); + push_arg_entry_of("shift", float2int(shift), true); push_arg_entry_of("one", float2int(1.f), true); } @@ -1413,16 +1486,19 @@ size_t jit_power_static_emitter::aux_vecs_count() const { } /// PRELU /// +jit_prelu_emitter::jit_prelu_emitter(jit_generator *host, cpu_isa_t host_isa, const std::shared_ptr& node, Precision exec_prc) +: jit_emitter(host, host_isa, node, exec_prc) { + prepare_table(); +} jit_prelu_emitter::jit_prelu_emitter(jit_generator *host, cpu_isa_t host_isa, const MKLDNNNode* node, Precision exec_prc) : jit_emitter(host, host_isa, node, exec_prc) { prepare_table(); } - -size_t jit_prelu_emitter::get_inputs_num() { return 2; } +size_t jit_prelu_emitter::get_inputs_num() const { return 2; } void jit_prelu_emitter::emit_impl(const std::vector &in_vec_idxs, const std::vector &out_vec_idxs, const std::vector &pool_vec_idxs, const std::vector &pool_gpr_idxs, - const emitter_context *emit_context) { + const emitter_context *emit_context) const { if (host_isa_ == cpu::x64::sse41) { emit_isa(in_vec_idxs, out_vec_idxs); } else if (host_isa_ == cpu::x64::avx2) { @@ -1469,4 +1545,64 @@ size_t jit_prelu_emitter::aux_vecs_count() const { return 2; } +/// SQRT /// +jit_sqrt_emitter::jit_sqrt_emitter(jit_generator *host, cpu_isa_t host_isa, const std::shared_ptr& node, Precision exec_prc) +: jit_emitter(host, host_isa, node, exec_prc) {} +jit_sqrt_emitter::jit_sqrt_emitter(jit_generator *host, cpu_isa_t host_isa, const MKLDNNNode* node, Precision exec_prc) +: jit_emitter(host, host_isa, node, exec_prc) {} + +size_t jit_sqrt_emitter::get_inputs_num() const { return 1; } + +void jit_sqrt_emitter::emit_impl(const std::vector &in_vec_idxs, const std::vector &out_vec_idxs, + const std::vector &pool_vec_idxs, const std::vector &pool_gpr_idxs, + const emitter_context *emit_context) const { + if (host_isa_ == cpu::x64::sse41) { + emit_isa(in_vec_idxs, out_vec_idxs); + } else if (host_isa_ == cpu::x64::avx2) { + emit_isa(in_vec_idxs, out_vec_idxs); + } else if (host_isa_ == cpu::x64::avx512_common) { + emit_isa(in_vec_idxs, out_vec_idxs); + } else { + assert(!"unsupported isa"); + } +} + +template +void jit_sqrt_emitter::emit_isa(const std::vector &in_vec_idxs, const std::vector &out_vec_idxs) const { + using Vmm = typename conditional3::type; + Vmm vmm_src0 = Vmm(in_vec_idxs[0]); + Vmm vmm_dst = Vmm(out_vec_idxs[0]); + + h->uni_vsqrtps(vmm_dst, vmm_src0); +} + +/// Negate /// +jit_negative_emitter::jit_negative_emitter(jit_generator *host, cpu_isa_t host_isa, const std::shared_ptr& node, Precision exec_prc) +: jit_emitter(host, host_isa, node, exec_prc) {} + +size_t jit_negative_emitter::get_inputs_num() const { return 1; } + +void jit_negative_emitter::emit_impl(const std::vector &in_vec_idxs, const std::vector &out_vec_idxs, + const std::vector &pool_vec_idxs, const std::vector &pool_gpr_idxs, + const emitter_context *emit_context) const { + if (host_isa_ == cpu::x64::sse41) { + emit_isa(in_vec_idxs, out_vec_idxs); + } else if (host_isa_ == cpu::x64::avx2) { + emit_isa(in_vec_idxs, out_vec_idxs); + } else if (host_isa_ == cpu::x64::avx512_common) { + emit_isa(in_vec_idxs, out_vec_idxs); + } else { + assert(!"unsupported isa"); + } +} + +template +void jit_negative_emitter::emit_isa(const std::vector &in_vec_idxs, const std::vector &out_vec_idxs) const { + using Vmm = typename conditional3::type; + Vmm vmm_src = Vmm(in_vec_idxs[0]); + Vmm vmm_dst = Vmm(out_vec_idxs[0]); + h->uni_vpxor(vmm_dst, vmm_dst, vmm_dst); + h->uni_vsubps(vmm_dst, vmm_dst, vmm_src); +} + } // namespace MKLDNNPlugin diff --git a/inference-engine/src/mkldnn_plugin/nodes/jit_eltwise_emitters.hpp b/inference-engine/src/mkldnn_plugin/emitters/jit_eltwise_emitters.hpp similarity index 62% rename from inference-engine/src/mkldnn_plugin/nodes/jit_eltwise_emitters.hpp rename to inference-engine/src/mkldnn_plugin/emitters/jit_eltwise_emitters.hpp index fb8d2e16fb1480..0fe92fa50180ad 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/jit_eltwise_emitters.hpp +++ b/inference-engine/src/mkldnn_plugin/emitters/jit_eltwise_emitters.hpp @@ -4,8 +4,8 @@ #pragma once -#include "common/emitter.h" #include +#include "jit_emitter.hpp" #include "mkldnn_node.h" namespace MKLDNNPlugin { @@ -14,13 +14,15 @@ class jit_add_emitter : public jit_emitter { public: jit_add_emitter(mkldnn::impl::cpu::x64::jit_generator *host, mkldnn::impl::cpu::x64::cpu_isa_t host_isa, const MKLDNNNode* node, InferenceEngine::Precision exec_prc = InferenceEngine::Precision::FP32); + jit_add_emitter(mkldnn::impl::cpu::x64::jit_generator *host, mkldnn::impl::cpu::x64::cpu_isa_t host_isa, const std::shared_ptr& n, + InferenceEngine::Precision exec_prc = InferenceEngine::Precision::FP32); - size_t get_inputs_num() override; + size_t get_inputs_num() const override; private: void emit_impl(const std::vector &in_vec_idxs, const std::vector &out_vec_idxs, const std::vector &pool_vec_idxs, const std::vector &pool_gpr_idxs, - const emitter_context *emit_context) override; + const emitter_context *emit_context) const override; template void emit_isa(const std::vector &in_vec_idxs, const std::vector &out_vec_idxs) const; @@ -30,13 +32,15 @@ class jit_mul_add_emitter : public jit_emitter { public: jit_mul_add_emitter(mkldnn::impl::cpu::x64::jit_generator *host, mkldnn::impl::cpu::x64::cpu_isa_t host_isa, const MKLDNNNode* node, InferenceEngine::Precision exec_prc = InferenceEngine::Precision::FP32); + jit_mul_add_emitter(mkldnn::impl::cpu::x64::jit_generator *host, mkldnn::impl::cpu::x64::cpu_isa_t host_isa, const std::shared_ptr& n, + InferenceEngine::Precision exec_prc = InferenceEngine::Precision::FP32); - size_t get_inputs_num() override; + size_t get_inputs_num() const override; private: void emit_impl(const std::vector &in_vec_idxs, const std::vector &out_vec_idxs, const std::vector &pool_vec_idxs, const std::vector &pool_gpr_idxs, - const emitter_context *emit_context) override; + const emitter_context *emit_context) const override; template void emit_isa(const std::vector &in_vec_idxs, const std::vector &out_vec_idxs) const; @@ -49,13 +53,15 @@ class jit_subtract_emitter : public jit_emitter { public: jit_subtract_emitter(mkldnn::impl::cpu::x64::jit_generator *host, mkldnn::impl::cpu::x64::cpu_isa_t host_isa, const MKLDNNNode* node, InferenceEngine::Precision exec_prc = InferenceEngine::Precision::FP32); + jit_subtract_emitter(mkldnn::impl::cpu::x64::jit_generator *host, mkldnn::impl::cpu::x64::cpu_isa_t host_isa, const std::shared_ptr& n, + InferenceEngine::Precision exec_prc = InferenceEngine::Precision::FP32); - size_t get_inputs_num() override; + size_t get_inputs_num() const override; private: void emit_impl(const std::vector &in_vec_idxs, const std::vector &out_vec_idxs, const std::vector &pool_vec_idxs, const std::vector &pool_gpr_idxs, - const emitter_context *emit_context) override; + const emitter_context *emit_context) const override; template void emit_isa(const std::vector &in_vec_idxs, const std::vector &out_vec_idxs) const; @@ -66,13 +72,15 @@ class jit_multiply_emitter : public jit_emitter { public: jit_multiply_emitter(mkldnn::impl::cpu::x64::jit_generator *host, mkldnn::impl::cpu::x64::cpu_isa_t host_isa, const MKLDNNNode* node, InferenceEngine::Precision exec_prc = InferenceEngine::Precision::FP32); + jit_multiply_emitter(mkldnn::impl::cpu::x64::jit_generator *host, mkldnn::impl::cpu::x64::cpu_isa_t host_isa, const std::shared_ptr& n, + InferenceEngine::Precision exec_prc = InferenceEngine::Precision::FP32); - size_t get_inputs_num() override; + size_t get_inputs_num() const override; private: void emit_impl(const std::vector &in_vec_idxs, const std::vector &out_vec_idxs, const std::vector &pool_vec_idxs, const std::vector &pool_gpr_idxs, - const emitter_context *emit_context) override; + const emitter_context *emit_context) const override; template void emit_isa(const std::vector &in_vec_idxs, const std::vector &out_vec_idxs) const; @@ -83,14 +91,16 @@ class jit_divide_emitter : public jit_emitter { public: jit_divide_emitter(mkldnn::impl::cpu::x64::jit_generator *host, mkldnn::impl::cpu::x64::cpu_isa_t host_isa, const MKLDNNNode* node, InferenceEngine::Precision exec_prc = InferenceEngine::Precision::FP32); + jit_divide_emitter(mkldnn::impl::cpu::x64::jit_generator *host, mkldnn::impl::cpu::x64::cpu_isa_t host_isa, const std::shared_ptr& n, + InferenceEngine::Precision exec_prc = InferenceEngine::Precision::FP32); - size_t get_inputs_num() override; + size_t get_inputs_num() const override; static std::set get_supported_precisions(); private: void emit_impl(const std::vector &in_vec_idxs, const std::vector &out_vec_idxs, const std::vector &pool_vec_idxs, const std::vector &pool_gpr_idxs, - const emitter_context *emit_context) override; + const emitter_context *emit_context) const override; template void emit_isa(const std::vector &in_vec_idxs, const std::vector &out_vec_idxs) const; @@ -102,13 +112,15 @@ class jit_floor_mod_emitter : public jit_emitter { public: jit_floor_mod_emitter(mkldnn::impl::cpu::x64::jit_generator *host, mkldnn::impl::cpu::x64::cpu_isa_t host_isa, const MKLDNNNode* node, InferenceEngine::Precision exec_prc = InferenceEngine::Precision::FP32); + jit_floor_mod_emitter(mkldnn::impl::cpu::x64::jit_generator *host, mkldnn::impl::cpu::x64::cpu_isa_t host_isa, const std::shared_ptr& n, + InferenceEngine::Precision exec_prc = InferenceEngine::Precision::FP32); - size_t get_inputs_num() override; + size_t get_inputs_num() const override; private: void emit_impl(const std::vector &in_vec_idxs, const std::vector &out_vec_idxs, const std::vector &pool_vec_idxs, const std::vector &pool_gpr_idxs, - const emitter_context *emit_context) override; + const emitter_context *emit_context) const override; template void emit_isa(const std::vector &in_vec_idxs, const std::vector &out_vec_idxs) const; @@ -120,13 +132,15 @@ class jit_mod_emitter : public jit_emitter { public: jit_mod_emitter(mkldnn::impl::cpu::x64::jit_generator *host, mkldnn::impl::cpu::x64::cpu_isa_t host_isa, const MKLDNNNode* node, InferenceEngine::Precision exec_prc = InferenceEngine::Precision::FP32); + jit_mod_emitter(mkldnn::impl::cpu::x64::jit_generator *host, mkldnn::impl::cpu::x64::cpu_isa_t host_isa, const std::shared_ptr& n, + InferenceEngine::Precision exec_prc = InferenceEngine::Precision::FP32); - size_t get_inputs_num() override; + size_t get_inputs_num() const override; private: void emit_impl(const std::vector &in_vec_idxs, const std::vector &out_vec_idxs, const std::vector &pool_vec_idxs, const std::vector &pool_gpr_idxs, - const emitter_context *emit_context) override; + const emitter_context *emit_context) const override; template void emit_isa(const std::vector &in_vec_idxs, const std::vector &out_vec_idxs) const; @@ -138,14 +152,16 @@ class jit_maximum_emitter : public jit_emitter { public: jit_maximum_emitter(mkldnn::impl::cpu::x64::jit_generator *host, mkldnn::impl::cpu::x64::cpu_isa_t host_isa, const MKLDNNNode* node, InferenceEngine::Precision exec_prc = InferenceEngine::Precision::FP32); + jit_maximum_emitter(mkldnn::impl::cpu::x64::jit_generator *host, mkldnn::impl::cpu::x64::cpu_isa_t host_isa, const std::shared_ptr& n, + InferenceEngine::Precision exec_prc = InferenceEngine::Precision::FP32); - size_t get_inputs_num() override; + size_t get_inputs_num() const override; static std::set get_supported_precisions(); private: void emit_impl(const std::vector &in_vec_idxs, const std::vector &out_vec_idxs, const std::vector &pool_vec_idxs, const std::vector &pool_gpr_idxs, - const emitter_context *emit_context) override; + const emitter_context *emit_context) const override; template void emit_isa(const std::vector &in_vec_idxs, const std::vector &out_vec_idxs) const; @@ -156,14 +172,16 @@ class jit_minimum_emitter : public jit_emitter { public: jit_minimum_emitter(mkldnn::impl::cpu::x64::jit_generator *host, mkldnn::impl::cpu::x64::cpu_isa_t host_isa, const MKLDNNNode* node, InferenceEngine::Precision exec_prc = InferenceEngine::Precision::FP32); + jit_minimum_emitter(mkldnn::impl::cpu::x64::jit_generator *host, mkldnn::impl::cpu::x64::cpu_isa_t host_isa, const std::shared_ptr& n, + InferenceEngine::Precision exec_prc = InferenceEngine::Precision::FP32); - size_t get_inputs_num() override; + size_t get_inputs_num() const override; static std::set get_supported_precisions(); private: void emit_impl(const std::vector &in_vec_idxs, const std::vector &out_vec_idxs, const std::vector &pool_vec_idxs, const std::vector &pool_gpr_idxs, - const emitter_context *emit_context) override; + const emitter_context *emit_context) const override; template void emit_isa(const std::vector &in_vec_idxs, const std::vector &out_vec_idxs) const; @@ -174,13 +192,15 @@ class jit_squared_difference_emitter : public jit_emitter { public: jit_squared_difference_emitter(mkldnn::impl::cpu::x64::jit_generator *host, mkldnn::impl::cpu::x64::cpu_isa_t host_isa, const MKLDNNNode* node, InferenceEngine::Precision exec_prc = InferenceEngine::Precision::FP32); + jit_squared_difference_emitter(mkldnn::impl::cpu::x64::jit_generator *host, mkldnn::impl::cpu::x64::cpu_isa_t host_isa, const std::shared_ptr& n, + InferenceEngine::Precision exec_prc = InferenceEngine::Precision::FP32); - size_t get_inputs_num() override; + size_t get_inputs_num() const override; private: void emit_impl(const std::vector &in_vec_idxs, const std::vector &out_vec_idxs, const std::vector &pool_vec_idxs, const std::vector &pool_gpr_idxs, - const emitter_context *emit_context) override; + const emitter_context *emit_context) const override; template void emit_isa(const std::vector &in_vec_idxs, const std::vector &out_vec_idxs) const; @@ -191,13 +211,15 @@ class jit_power_dynamic_emitter : public jit_emitter { public: jit_power_dynamic_emitter(mkldnn::impl::cpu::x64::jit_generator *host, mkldnn::impl::cpu::x64::cpu_isa_t host_isa, const MKLDNNNode* node, InferenceEngine::Precision exec_prc = InferenceEngine::Precision::FP32); + jit_power_dynamic_emitter(mkldnn::impl::cpu::x64::jit_generator *host, mkldnn::impl::cpu::x64::cpu_isa_t host_isa, const std::shared_ptr& n, + InferenceEngine::Precision exec_prc = InferenceEngine::Precision::FP32); - size_t get_inputs_num() override; + size_t get_inputs_num() const override; private: void emit_impl(const std::vector &in_vec_idxs, const std::vector &out_vec_idxs, const std::vector &pool_vec_idxs, const std::vector &pool_gpr_idxs, - const emitter_context *emit_context) override; + const emitter_context *emit_context) const override; template void emit_isa(const std::vector &in_vec_idxs, const std::vector &out_vec_idxs) const; @@ -208,13 +230,15 @@ class jit_equal_emitter : public jit_emitter { public: jit_equal_emitter(mkldnn::impl::cpu::x64::jit_generator *host, mkldnn::impl::cpu::x64::cpu_isa_t host_isa, const MKLDNNNode* node, InferenceEngine::Precision exec_prc = InferenceEngine::Precision::FP32); + jit_equal_emitter(mkldnn::impl::cpu::x64::jit_generator *host, mkldnn::impl::cpu::x64::cpu_isa_t host_isa, const std::shared_ptr& n, + InferenceEngine::Precision exec_prc = InferenceEngine::Precision::FP32); - size_t get_inputs_num() override; + size_t get_inputs_num() const override; private: void emit_impl(const std::vector &in_vec_idxs, const std::vector &out_vec_idxs, const std::vector &pool_vec_idxs, const std::vector &pool_gpr_idxs, - const emitter_context *emit_context) override; + const emitter_context *emit_context) const override; template void emit_isa(const std::vector &in_vec_idxs, const std::vector &out_vec_idxs) const; @@ -228,13 +252,15 @@ class jit_not_equal_emitter : public jit_emitter { public: jit_not_equal_emitter(mkldnn::impl::cpu::x64::jit_generator *host, mkldnn::impl::cpu::x64::cpu_isa_t host_isa, const MKLDNNNode* node, InferenceEngine::Precision exec_prc = InferenceEngine::Precision::FP32); + jit_not_equal_emitter(mkldnn::impl::cpu::x64::jit_generator *host, mkldnn::impl::cpu::x64::cpu_isa_t host_isa, const std::shared_ptr& n, + InferenceEngine::Precision exec_prc = InferenceEngine::Precision::FP32); - size_t get_inputs_num() override; + size_t get_inputs_num() const override; private: void emit_impl(const std::vector &in_vec_idxs, const std::vector &out_vec_idxs, const std::vector &pool_vec_idxs, const std::vector &pool_gpr_idxs, - const emitter_context *emit_context) override; + const emitter_context *emit_context) const override; template void emit_isa(const std::vector &in_vec_idxs, const std::vector &out_vec_idxs) const; @@ -248,13 +274,15 @@ class jit_greater_emitter : public jit_emitter { public: jit_greater_emitter(mkldnn::impl::cpu::x64::jit_generator *host, mkldnn::impl::cpu::x64::cpu_isa_t host_isa, const MKLDNNNode* node, InferenceEngine::Precision exec_prc = InferenceEngine::Precision::FP32); + jit_greater_emitter(mkldnn::impl::cpu::x64::jit_generator *host, mkldnn::impl::cpu::x64::cpu_isa_t host_isa, const std::shared_ptr& n, + InferenceEngine::Precision exec_prc = InferenceEngine::Precision::FP32); - size_t get_inputs_num() override; + size_t get_inputs_num() const override; private: void emit_impl(const std::vector &in_vec_idxs, const std::vector &out_vec_idxs, const std::vector &pool_vec_idxs, const std::vector &pool_gpr_idxs, - const emitter_context *emit_context) override; + const emitter_context *emit_context) const override; template void emit_isa(const std::vector &in_vec_idxs, const std::vector &out_vec_idxs) const; @@ -268,13 +296,15 @@ class jit_greater_equal_emitter : public jit_emitter { public: jit_greater_equal_emitter(mkldnn::impl::cpu::x64::jit_generator *host, mkldnn::impl::cpu::x64::cpu_isa_t host_isa, const MKLDNNNode* node, InferenceEngine::Precision exec_prc = InferenceEngine::Precision::FP32); + jit_greater_equal_emitter(mkldnn::impl::cpu::x64::jit_generator *host, mkldnn::impl::cpu::x64::cpu_isa_t host_isa, const std::shared_ptr& n, + InferenceEngine::Precision exec_prc = InferenceEngine::Precision::FP32); - size_t get_inputs_num() override; + size_t get_inputs_num() const override; private: void emit_impl(const std::vector &in_vec_idxs, const std::vector &out_vec_idxs, const std::vector &pool_vec_idxs, const std::vector &pool_gpr_idxs, - const emitter_context *emit_context) override; + const emitter_context *emit_context) const override; template void emit_isa(const std::vector &in_vec_idxs, const std::vector &out_vec_idxs) const; @@ -288,13 +318,15 @@ class jit_less_emitter : public jit_emitter { public: jit_less_emitter(mkldnn::impl::cpu::x64::jit_generator *host, mkldnn::impl::cpu::x64::cpu_isa_t host_isa, const MKLDNNNode* node, InferenceEngine::Precision exec_prc = InferenceEngine::Precision::FP32); + jit_less_emitter(mkldnn::impl::cpu::x64::jit_generator *host, mkldnn::impl::cpu::x64::cpu_isa_t host_isa, const std::shared_ptr& n, + InferenceEngine::Precision exec_prc = InferenceEngine::Precision::FP32); - size_t get_inputs_num() override; + size_t get_inputs_num() const override; private: void emit_impl(const std::vector &in_vec_idxs, const std::vector &out_vec_idxs, const std::vector &pool_vec_idxs, const std::vector &pool_gpr_idxs, - const emitter_context *emit_context) override; + const emitter_context *emit_context) const override; template void emit_isa(const std::vector &in_vec_idxs, const std::vector &out_vec_idxs) const; @@ -309,12 +341,15 @@ class jit_less_equal_emitter : public jit_emitter { jit_less_equal_emitter(mkldnn::impl::cpu::x64::jit_generator *host, mkldnn::impl::cpu::x64::cpu_isa_t host_isa, const MKLDNNNode* node, InferenceEngine::Precision exec_prc = InferenceEngine::Precision::FP32); - size_t get_inputs_num() override; + jit_less_equal_emitter(mkldnn::impl::cpu::x64::jit_generator *host, mkldnn::impl::cpu::x64::cpu_isa_t host_isa, const std::shared_ptr& n, + InferenceEngine::Precision exec_prc = InferenceEngine::Precision::FP32); + + size_t get_inputs_num() const override; private: void emit_impl(const std::vector &in_vec_idxs, const std::vector &out_vec_idxs, const std::vector &pool_vec_idxs, const std::vector &pool_gpr_idxs, - const emitter_context *emit_context) override; + const emitter_context *emit_context) const override; template void emit_isa(const std::vector &in_vec_idxs, const std::vector &out_vec_idxs) const; @@ -328,13 +363,15 @@ class jit_logical_and_emitter : public jit_emitter { public: jit_logical_and_emitter(mkldnn::impl::cpu::x64::jit_generator *host, mkldnn::impl::cpu::x64::cpu_isa_t host_isa, const MKLDNNNode* node, InferenceEngine::Precision exec_prc = InferenceEngine::Precision::FP32); + jit_logical_and_emitter(mkldnn::impl::cpu::x64::jit_generator *host, mkldnn::impl::cpu::x64::cpu_isa_t host_isa, const std::shared_ptr& n, + InferenceEngine::Precision exec_prc = InferenceEngine::Precision::FP32); - size_t get_inputs_num() override; + size_t get_inputs_num() const override; private: void emit_impl(const std::vector &in_vec_idxs, const std::vector &out_vec_idxs, const std::vector &pool_vec_idxs, const std::vector &pool_gpr_idxs, - const emitter_context *emit_context) override; + const emitter_context *emit_context) const override; template void emit_isa(const std::vector &in_vec_idxs, const std::vector &out_vec_idxs) const; @@ -348,13 +385,15 @@ class jit_logical_or_emitter : public jit_emitter { public: jit_logical_or_emitter(mkldnn::impl::cpu::x64::jit_generator *host, mkldnn::impl::cpu::x64::cpu_isa_t host_isa, const MKLDNNNode* node, InferenceEngine::Precision exec_prc = InferenceEngine::Precision::FP32); + jit_logical_or_emitter(mkldnn::impl::cpu::x64::jit_generator *host, mkldnn::impl::cpu::x64::cpu_isa_t host_isa, const std::shared_ptr& n, + InferenceEngine::Precision exec_prc = InferenceEngine::Precision::FP32); - size_t get_inputs_num() override; + size_t get_inputs_num() const override; private: void emit_impl(const std::vector &in_vec_idxs, const std::vector &out_vec_idxs, const std::vector &pool_vec_idxs, const std::vector &pool_gpr_idxs, - const emitter_context *emit_context) override; + const emitter_context *emit_context) const override; template void emit_isa(const std::vector &in_vec_idxs, const std::vector &out_vec_idxs) const; @@ -368,13 +407,15 @@ class jit_logical_xor_emitter : public jit_emitter { public: jit_logical_xor_emitter(mkldnn::impl::cpu::x64::jit_generator *host, mkldnn::impl::cpu::x64::cpu_isa_t host_isa, const MKLDNNNode* node, InferenceEngine::Precision exec_prc = InferenceEngine::Precision::FP32); + jit_logical_xor_emitter(mkldnn::impl::cpu::x64::jit_generator *host, mkldnn::impl::cpu::x64::cpu_isa_t host_isa, const std::shared_ptr& n, + InferenceEngine::Precision exec_prc = InferenceEngine::Precision::FP32); - size_t get_inputs_num() override; + size_t get_inputs_num() const override; private: void emit_impl(const std::vector &in_vec_idxs, const std::vector &out_vec_idxs, const std::vector &pool_vec_idxs, const std::vector &pool_gpr_idxs, - const emitter_context *emit_context) override; + const emitter_context *emit_context) const override; template void emit_isa(const std::vector &in_vec_idxs, const std::vector &out_vec_idxs) const; @@ -387,13 +428,15 @@ class jit_logical_not_emitter : public jit_emitter { public: jit_logical_not_emitter(mkldnn::impl::cpu::x64::jit_generator *host, mkldnn::impl::cpu::x64::cpu_isa_t host_isa, const MKLDNNNode* node, InferenceEngine::Precision exec_prc = InferenceEngine::Precision::FP32); + jit_logical_not_emitter(mkldnn::impl::cpu::x64::jit_generator *host, mkldnn::impl::cpu::x64::cpu_isa_t host_isa, const std::shared_ptr& n, + InferenceEngine::Precision exec_prc = InferenceEngine::Precision::FP32); - size_t get_inputs_num() override; + size_t get_inputs_num() const override; private: void emit_impl(const std::vector &in_vec_idxs, const std::vector &out_vec_idxs, const std::vector &pool_vec_idxs, const std::vector &pool_gpr_idxs, - const emitter_context *emit_context) override; + const emitter_context *emit_context) const override; template void emit_isa(const std::vector &in_vec_idxs, const std::vector &out_vec_idxs) const; @@ -405,33 +448,41 @@ class jit_logical_not_emitter : public jit_emitter { class jit_power_static_emitter : public jit_emitter { public: jit_power_static_emitter(mkldnn::impl::cpu::x64::jit_generator *host, mkldnn::impl::cpu::x64::cpu_isa_t host_isa, const MKLDNNNode* node, + InferenceEngine::Precision exec_prc = InferenceEngine::Precision::FP32); + jit_power_static_emitter(mkldnn::impl::cpu::x64::jit_generator *host, mkldnn::impl::cpu::x64::cpu_isa_t host_isa, const std::shared_ptr& n, InferenceEngine::Precision exec_prc = InferenceEngine::Precision::FP32); - size_t get_inputs_num() override; + size_t get_inputs_num() const override; private: void emit_impl(const std::vector &in_vec_idxs, const std::vector &out_vec_idxs, const std::vector &pool_vec_idxs, const std::vector &pool_gpr_idxs, - const emitter_context *emit_context) override; + const emitter_context *emit_context) const override; template void emit_isa(const std::vector &in_vec_idxs, const std::vector &out_vec_idxs) const; void register_table_entries() override; size_t aux_vecs_count() const override; + + float power; + float scale; + float shift; }; class jit_prelu_emitter : public jit_emitter { public: jit_prelu_emitter(mkldnn::impl::cpu::x64::jit_generator *host, mkldnn::impl::cpu::x64::cpu_isa_t host_isa, const MKLDNNNode* node, InferenceEngine::Precision exec_prc = InferenceEngine::Precision::FP32); + jit_prelu_emitter(mkldnn::impl::cpu::x64::jit_generator *host, mkldnn::impl::cpu::x64::cpu_isa_t host_isa, const std::shared_ptr& n, + InferenceEngine::Precision exec_prc = InferenceEngine::Precision::FP32); - size_t get_inputs_num() override; + size_t get_inputs_num() const override; private: void emit_impl(const std::vector &in_vec_idxs, const std::vector &out_vec_idxs, const std::vector &pool_vec_idxs, const std::vector &pool_gpr_idxs, - const emitter_context *emit_context) override; + const emitter_context *emit_context) const override; template void emit_isa(const std::vector &in_vec_idxs, const std::vector &out_vec_idxs) const; @@ -439,4 +490,38 @@ class jit_prelu_emitter : public jit_emitter { size_t aux_vecs_count() const override; }; +class jit_sqrt_emitter : public jit_emitter { +public: + jit_sqrt_emitter(mkldnn::impl::cpu::x64::jit_generator *host, mkldnn::impl::cpu::x64::cpu_isa_t host_isa, const MKLDNNNode* node, + InferenceEngine::Precision exec_prc = InferenceEngine::Precision::FP32); + jit_sqrt_emitter(mkldnn::impl::cpu::x64::jit_generator *host, mkldnn::impl::cpu::x64::cpu_isa_t host_isa, const std::shared_ptr& n, + InferenceEngine::Precision exec_prc = InferenceEngine::Precision::FP32); + + size_t get_inputs_num() const override; + +private: + void emit_impl(const std::vector &in_vec_idxs, const std::vector &out_vec_idxs, + const std::vector &pool_vec_idxs, const std::vector &pool_gpr_idxs, + const emitter_context *emit_context) const override; + + template + void emit_isa(const std::vector &in_vec_idxs, const std::vector &out_vec_idxs) const; +}; + +class jit_negative_emitter : public jit_emitter { +public: + jit_negative_emitter(mkldnn::impl::cpu::x64::jit_generator *host, mkldnn::impl::cpu::x64::cpu_isa_t host_isa, const std::shared_ptr& n, + InferenceEngine::Precision exec_prc = InferenceEngine::Precision::FP32); + + size_t get_inputs_num() const override; + +private: + void emit_impl(const std::vector& in, const std::vector& out, + const std::vector& pool, const std::vector& gpr, + const MKLDNNPlugin::emitter_context *emit_context) const override; + + template + void emit_isa(const std::vector &in_vec_idxs, const std::vector &out_vec_idxs) const; +}; + } // namespace MKLDNNPlugin diff --git a/inference-engine/src/mkldnn_plugin/nodes/common/emitter.cpp b/inference-engine/src/mkldnn_plugin/emitters/jit_emitter.cpp similarity index 91% rename from inference-engine/src/mkldnn_plugin/nodes/common/emitter.cpp rename to inference-engine/src/mkldnn_plugin/emitters/jit_emitter.cpp index 1aa4744b249bdf..2b3bedb1fe16a9 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/common/emitter.cpp +++ b/inference-engine/src/mkldnn_plugin/emitters/jit_emitter.cpp @@ -2,10 +2,8 @@ // SPDX-License-Identifier: Apache-2.0 // -#include "emitter.h" - +#include "jit_emitter.hpp" #include "utils/general_utils.h" - #include using namespace mkldnn::impl::cpu; @@ -57,7 +55,7 @@ std::set jit_emitter::get_supported_precisions() { } void jit_emitter::emitter_preamble(const std::vector &in_idxs, const std::vector &out_idxs, - const std::vector &pool_vec_idxs, const std::vector &pool_gpr_idxs) { + const std::vector &pool_vec_idxs, const std::vector &pool_gpr_idxs) const { using namespace Xbyak::util; bool is_vec_input = (in_out_type_ == emitter_in_out_map::vec_to_vec) || (in_out_type_ == emitter_in_out_map::vec_to_gpr); bool is_vec_output = (in_out_type_ == emitter_in_out_map::vec_to_vec) || (in_out_type_ == emitter_in_out_map::gpr_to_vec); @@ -148,7 +146,8 @@ void jit_emitter::emitter_preamble(const std::vector &in_idxs, const std load_table_addr(); } -void jit_emitter::emitter_postamble() { + +void jit_emitter::emitter_postamble() const { using namespace Xbyak::util; for (size_t i = 0; i < preserved_vec_idxs.size(); ++i) @@ -167,9 +166,9 @@ void jit_emitter::emitter_postamble() { aux_gpr_idxs.clear(); } -void jit_emitter::emit_table() { +void jit_emitter::emit_data() const { h->align(64); - h->L(l_table); + h->L(*l_table.get()); // Assumption: entries can be inserted with dd, so they should be 4 bytes. assert(sizeof(table_entry_val_t) == 4); @@ -198,8 +197,8 @@ void jit_emitter::prepare_table() { } } -void jit_emitter::emit(const std::vector &in_idxs, const std::vector &out_idxs, - const std::vector &pool_vec_idxs, const std::vector &pool_gpr_idxs) { +void jit_emitter::emit_code(const std::vector &in_idxs, const std::vector &out_idxs, + const std::vector &pool_vec_idxs, const std::vector &pool_gpr_idxs) const { emitter_preamble(in_idxs, out_idxs, pool_vec_idxs, pool_gpr_idxs); emit_impl(in_idxs, out_idxs, pool_vec_idxs, pool_gpr_idxs, nullptr); @@ -207,9 +206,9 @@ void jit_emitter::emit(const std::vector &in_idxs, const std::vector &in_idxs, const std::vector &out_idxs, - const std::shared_ptr &emit_context, - const std::vector &pool_vec_idxs, const std::vector &pool_gpr_idxs) { +void jit_emitter::emit_code(const std::vector &in_idxs, const std::vector &out_idxs, + const std::shared_ptr &emit_context, + const std::vector &pool_vec_idxs, const std::vector &pool_gpr_idxs) { emitter_preamble(in_idxs, out_idxs, pool_vec_idxs, pool_gpr_idxs); emit_impl(in_idxs, out_idxs, pool_vec_idxs, pool_gpr_idxs, emit_context.get()); diff --git a/inference-engine/src/mkldnn_plugin/nodes/common/emitter.h b/inference-engine/src/mkldnn_plugin/emitters/jit_emitter.hpp similarity index 73% rename from inference-engine/src/mkldnn_plugin/nodes/common/emitter.h rename to inference-engine/src/mkldnn_plugin/emitters/jit_emitter.hpp index 5f6428c2fa50a6..dd7fce5a570c0b 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/common/emitter.h +++ b/inference-engine/src/mkldnn_plugin/emitters/jit_emitter.hpp @@ -6,6 +6,7 @@ #include #include + #include "mkldnn_node.h" #include @@ -25,20 +26,26 @@ struct emitter_context { class jit_emitter { public: - jit_emitter(mkldnn::impl::cpu::x64::jit_generator* host, mkldnn::impl::cpu::x64::cpu_isa_t host_isa, const MKLDNNNode* node, + jit_emitter(dnnl::impl::cpu::x64::jit_generator* host, dnnl::impl::cpu::x64::cpu_isa_t host_isa, const MKLDNNNode* node, InferenceEngine::Precision exec_prc = InferenceEngine::Precision::FP32, emitter_in_out_map in_out_type = emitter_in_out_map::vec_to_vec) - : h(host), host_isa_(host_isa), n(node), exec_prc_(exec_prc), in_out_type_(in_out_type) { + : h(host), host_isa_(host_isa), exec_prc_(exec_prc), in_out_type_(in_out_type), l_table (new Xbyak::Label()) { k_mask = Xbyak::Opmask(1); // FIXME: in general case we need preserve k_mask state as well } - virtual void emit(const std::vector &in_idxs, const std::vector &out_idxs, - const std::vector &pool_vec_idxs = {}, const std::vector &pool_gpr_idxs = {}); + jit_emitter(dnnl::impl::cpu::x64::jit_generator* host, dnnl::impl::cpu::x64::cpu_isa_t host_isa, const std::shared_ptr& n, + InferenceEngine::Precision exec_prc = InferenceEngine::Precision::FP32, emitter_in_out_map in_out_type = emitter_in_out_map::vec_to_vec) + : h(host), host_isa_(host_isa), exec_prc_(exec_prc), in_out_type_(in_out_type), l_table (new Xbyak::Label()) { + k_mask = Xbyak::Opmask(1); // FIXME: in general case we need preserve k_mask state as well + } + + virtual void emit_code(const std::vector &in_idxs, const std::vector &out_idxs, + const std::vector &pool_vec_idxs = {}, const std::vector &pool_gpr_idxs = {}) const; + virtual void emit_data() const; - virtual void emit(const std::vector &in_idxs, const std::vector &out_idxs, + virtual void emit_code(const std::vector &in_idxs, const std::vector &out_idxs, const std::shared_ptr &emit_context, const std::vector &pool_vec_idxs = {}, const std::vector &pool_gpr_idxs = {}); - virtual void emit_table(); - virtual size_t get_inputs_num() = 0; + virtual size_t get_inputs_num() const = 0; virtual size_t aux_vecs_count() const; static std::set get_supported_precisions(); @@ -48,17 +55,15 @@ class jit_emitter { size_t get_max_vecs_count() const; size_t get_vec_length() const; - const MKLDNNNode* n; mkldnn::impl::cpu::x64::jit_generator* h; mkldnn::impl::cpu::x64::cpu_isa_t host_isa_; InferenceEngine::Precision exec_prc_; - Xbyak::Opmask k_mask; virtual void prepare_table(); virtual void register_table_entries() {} - void load_table_addr() { h->mov(p_table, l_table); } + void load_table_addr() const { h->mov(p_table, *l_table.get()); } // we accept only 32bit hexadecimal table values to avoid any rounding using table_entry_val_t = uint32_t; @@ -75,8 +80,8 @@ class jit_emitter { table_entry_bcast_t bcast; }; - Xbyak::Reg64 p_table; - Xbyak::Label l_table; + mutable Xbyak::Reg64 p_table; + mutable std::shared_ptr l_table; enum { _cmp_eq_oq = mkldnn::impl::cpu::x64::jit_generator::_cmp_eq_oq, @@ -89,16 +94,16 @@ class jit_emitter { virtual void emit_impl(const std::vector &in_idxs, const std::vector &out_idxs, const std::vector &pool_vec_idxs, const std::vector &pool_gpr_idxs, - const emitter_context *emit_context) = 0; + const emitter_context *emit_context) const = 0; virtual void emitter_preamble(const std::vector &in_idxs, const std::vector &out_idxs, - const std::vector &pool_vec_idxs, const std::vector &pool_gpr_idxs); - virtual void emitter_postamble(); + const std::vector &pool_vec_idxs, const std::vector &pool_gpr_idxs) const; + virtual void emitter_postamble() const; emitter_in_out_map in_out_type_; - std::vector aux_vec_idxs; - std::vector aux_gpr_idxs; + mutable std::vector aux_vec_idxs; + mutable std::vector aux_gpr_idxs; static constexpr int k_mask_size = 8; @@ -126,8 +131,8 @@ class jit_emitter { } private: - std::vector preserved_vec_idxs; - std::vector preserved_gpr_idxs; + mutable std::vector preserved_vec_idxs; + mutable std::vector preserved_gpr_idxs; void push_vec(const Xbyak::Address &addr, size_t vec_idx) const; void pop_vec(size_t vec_idx, const Xbyak::Address &addr) const; diff --git a/inference-engine/src/mkldnn_plugin/nodes/common/jit_load_store_emitters.cpp b/inference-engine/src/mkldnn_plugin/emitters/jit_load_store_emitters.cpp similarity index 88% rename from inference-engine/src/mkldnn_plugin/nodes/common/jit_load_store_emitters.cpp rename to inference-engine/src/mkldnn_plugin/emitters/jit_load_store_emitters.cpp index 75850b92b79eea..dc267ac9866b07 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/common/jit_load_store_emitters.cpp +++ b/inference-engine/src/mkldnn_plugin/emitters/jit_load_store_emitters.cpp @@ -2,8 +2,8 @@ // SPDX-License-Identifier: Apache-2.0 // -#include "emitter.h" -#include "jit_load_store_emitters.h" +#include "jit_emitter.hpp" +#include "jit_load_store_emitters.hpp" #include "legacy/ie_layers.h" #include #include "utils/bfloat16.hpp" @@ -21,12 +21,12 @@ namespace MKLDNNPlugin { /// LOAD /// jit_load_emitter::jit_load_emitter(jit_generator *host, cpu_isa_t host_isa, const MKLDNNNode* node, Precision exec_prc, emitter_in_out_map in_out_type) -: jit_emitter(host, host_isa, node, exec_prc, in_out_type) { +: jit_emitter(host, host_isa, node, exec_prc, in_out_type), name(node ? node->getName() : "unknown") { prepare_table(); v_len_elt = get_vec_length() / exec_prc.size(); } -size_t jit_load_emitter::get_inputs_num() { return 1; } +size_t jit_load_emitter::get_inputs_num() const { return 1; } // 0 for temp reg for mask load, 1 for table address size_t jit_load_emitter::aux_gprs_count() const { @@ -35,10 +35,10 @@ size_t jit_load_emitter::aux_gprs_count() const { void jit_load_emitter::emit_impl(const std::vector &in_idxs, const std::vector &out_idxs, const std::vector &pool_vec_idxs, const std::vector &pool_gpr_idxs, - const emitter_context *emit_context) { + const emitter_context *emit_context) const { const auto* load_emitter_context = dynamic_cast(emit_context); if (load_emitter_context == nullptr) { - THROW_IE_EXCEPTION << "Load emitter in " << n->getName() << " does not get load emmiter context."; + THROW_IE_EXCEPTION << "Load emitter in " << name << " does not get load emmiter context."; } if (host_isa_ == cpu::x64::sse41) { @@ -51,7 +51,7 @@ void jit_load_emitter::emit_impl(const std::vector &in_idxs, const std:: emit_isa(Reg64(in_idxs[0]), load_emitter_context->offset_byte_, load_emitter_context->src_prc_, static_cast(out_idxs[0]), load_emitter_context->dst_prc_, load_emitter_context->load_num_, load_emitter_context->is_fill_, load_emitter_context->fill_value_); } else { - THROW_IE_EXCEPTION << "Load emitter in " << n->getName() << " is performed on unsupported isa(at least x64::sse41)."; + THROW_IE_EXCEPTION << "Load emitter in " << name << " is performed on unsupported isa(at least x64::sse41)."; } } @@ -60,10 +60,10 @@ void jit_load_emitter::emit_isa(const Xbyak::Reg64 ®_src, int offset_byte, In const int out_vec_idx, InferenceEngine::Precision dst_prc, int load_num, bool is_fill, std::string fill_value) const { bool matched_prc = (dst_prc == src_prc) || (dst_prc == Precision::FP32) || (dst_prc == Precision::I32); if (!matched_prc) { - THROW_IE_EXCEPTION << "Load emitter in " << n->getName() << " only support output precision of FP32 or I32 or the same precision as input."; + THROW_IE_EXCEPTION << "Load emitter in " << name << " only support output precision of FP32 or I32 or the same precision as input."; } if (load_num > (get_vec_length() / dst_prc.size())) { - THROW_IE_EXCEPTION << "Load emitter in " << n->getName() << " have unexpected number of elements to load."; + THROW_IE_EXCEPTION << "Load emitter in " << name << " have unexpected number of elements to load."; } using Vmm = typename conditional3::type; @@ -94,7 +94,7 @@ void jit_load_emitter::emit_isa(const Xbyak::Reg64 ®_src, int offset_byte, In load_words_to_dword_extension(Vmm(out_vec_idx), reg_src, offset_byte, true, false, load_num * src_prc.size(), is_fill, fill_value); break; default: - THROW_IE_EXCEPTION << "Load emitter in " << n->getName() << " has unsupported src precision to load."; + THROW_IE_EXCEPTION << "Load emitter in " << name << " has unsupported src precision to load."; } } @@ -140,12 +140,12 @@ void jit_load_emitter::load_bytes(const Vmm &vmm, const Xbyak::Reg64 ®, int o // Ensure data fits completely inside the Xmm/Ymm/Zmm register if (load_size < 0 || load_size > 64) - THROW_IE_EXCEPTION << "Load emitter in " << n->getName() << " has unexpected number of values to load in load_byte."; + THROW_IE_EXCEPTION << "Load emitter in " << name << " has unexpected number of values to load in load_byte."; // check if proper number bytes fit inside the Xmm/Ymm register if (is_ymm && load_size > 32) - THROW_IE_EXCEPTION << "Load emitter in " << n->getName() << " has unexpected number of values to load to ymm in load_byte."; + THROW_IE_EXCEPTION << "Load emitter in " << name << " has unexpected number of values to load to ymm in load_byte."; if (is_xmm && load_size > 16) - THROW_IE_EXCEPTION << "Load emitter in " << n->getName() << " has unexpected number of values to load to xmm in load_byte."; + THROW_IE_EXCEPTION << "Load emitter in " << name << " has unexpected number of values to load to xmm in load_byte."; auto xmm = Xbyak::Xmm(vmm.getIdx()); auto ymm = Xbyak::Ymm(vmm.getIdx()); @@ -239,7 +239,7 @@ void jit_load_emitter::load_bytes(const Vmm &vmm, const Xbyak::Reg64 ®, int o break; case 16: break; default: - THROW_IE_EXCEPTION << "Load emitter in " << n->getName() << " has unexpected number of values to load in load_byte."; + THROW_IE_EXCEPTION << "Load emitter in " << name<< " has unexpected number of values to load in load_byte."; } if (has_xmm_block) { @@ -295,11 +295,11 @@ void jit_load_emitter::load_bytes_to_dword_extension(const Vmm &vmm, const Xbyak // For Ymm register, load capacity is halved (32 * load_size <= 256) // For Xmm register, load capacity is halved further (32 * load_size <= 128) if (load_size < 0 || load_size > 16) - THROW_IE_EXCEPTION << "Load emitter in " << n->getName() << " has unexpected number of values to load in load_bytes_to_dword_extension."; + THROW_IE_EXCEPTION << "Load emitter in " << name << " has unexpected number of values to load in load_bytes_to_dword_extension."; if (is_ymm && load_size > 8) - THROW_IE_EXCEPTION << "Load emitter in " << n->getName() << " has unexpected number of values to load to ymm in load_bytes_to_dword_extension."; + THROW_IE_EXCEPTION << "Load emitter in " << name << " has unexpected number of values to load to ymm in load_bytes_to_dword_extension."; if (is_xmm && load_size > 4) - THROW_IE_EXCEPTION << "Load emitter in " << n->getName() << " has unexpected number of values to load to xmm in load_bytes_to_dword_extension."; + THROW_IE_EXCEPTION << "Load emitter in " << name << " has unexpected number of values to load to xmm in load_bytes_to_dword_extension."; // For load_size == 4/8/16, do load/extension in one go if (load_size == 16) { @@ -380,11 +380,11 @@ void jit_load_emitter::load_words_to_dword_extension(const Vmm &vmm, const Xbyak // For Ymm register, load capacity is halved (16/2(num) * 32 <= 128) // For Xmm register, load capacity is halved again (8/2(num) * 32 <= 128) if (load_size < 0 || load_size > 32) - THROW_IE_EXCEPTION << "Load emitter in " << n->getName() << " has unexpected number of values to load in load_words_to_dword_extension."; + THROW_IE_EXCEPTION << "Load emitter in " << name << " has unexpected number of values to load in load_words_to_dword_extension."; if (is_ymm && load_size > 16) - THROW_IE_EXCEPTION << "Load emitter in " << n->getName() << " has unexpected number of values to load to ymm in load_words_to_dword_extension."; + THROW_IE_EXCEPTION << "Load emitter in " << name << " has unexpected number of values to load to ymm in load_words_to_dword_extension."; if (is_xmm && load_size > 8) - THROW_IE_EXCEPTION << "Load emitter in " << n->getName() << " has unexpected number of values to load to xmm in load_words_to_dword_extension."; + THROW_IE_EXCEPTION << "Load emitter in " << name << " has unexpected number of values to load to xmm in load_words_to_dword_extension."; auto xmm = Xbyak::Xmm(vmm.getIdx()); auto ymm = Xbyak::Ymm(vmm.getIdx()); @@ -491,7 +491,7 @@ void jit_load_emitter::register_table_entries() { /// STORE /// jit_store_emitter::jit_store_emitter(jit_generator *host, cpu_isa_t host_isa, const MKLDNNNode* node, Precision exec_prc, emitter_in_out_map in_out_type) -: jit_emitter(host, host_isa, node, exec_prc, in_out_type) { +: jit_emitter(host, host_isa, node, exec_prc, in_out_type), name(node ? node->getName() : "unknown") { v_len_elt = get_vec_length() / exec_prc.size(); if (!mayiuse(cpu::x64::avx512_core_bf16) && mayiuse(cpu::x64::avx512_core)) { emu_vcvtneps2bf16.reset(new jit_emu_vcvtneps2bf16(host, host_isa, nullptr)); @@ -508,14 +508,14 @@ size_t jit_store_emitter::aux_vecs_count() const { return 1; } -size_t jit_store_emitter::get_inputs_num() { return 1; } +size_t jit_store_emitter::get_inputs_num() const { return 1; } void jit_store_emitter::emit_impl(const std::vector &in_idxs, const std::vector &out_idxs, const std::vector &pool_vec_idxs, const std::vector &pool_gpr_idxs, - const emitter_context *emit_context) { + const emitter_context *emit_context) const { const auto* store_emitter_context = dynamic_cast(emit_context); if (store_emitter_context == nullptr) { - THROW_IE_EXCEPTION << "Store emitter in " << n->getName() << " does not get store emmiter context."; + THROW_IE_EXCEPTION << "Store emitter in " << name << " does not get store emmiter context."; } if (host_isa_ == cpu::x64::sse41) { emit_isa(static_cast(in_idxs[0]), store_emitter_context->src_prc_, Reg64(out_idxs[0]), @@ -527,7 +527,7 @@ void jit_store_emitter::emit_impl(const std::vector &in_idxs, const std: emit_isa(static_cast(in_idxs[0]), store_emitter_context->src_prc_, Reg64(out_idxs[0]), store_emitter_context->offset_byte_, store_emitter_context->dst_prc_, store_emitter_context->store_num_); } else { - THROW_IE_EXCEPTION << "Store emitter in " << n->getName() << " is performed on unsupported isa(at least x64::sse41)."; + THROW_IE_EXCEPTION << "Store emitter in " << name << " is performed on unsupported isa(at least x64::sse41)."; } } @@ -536,12 +536,12 @@ template const Xbyak::Reg64 ®_dst, int offset_byte, InferenceEngine::Precision dst_prc, int store_num) const { bool matched_prc = (src_prc == dst_prc) || (src_prc == Precision::FP32) || (src_prc == Precision::I32); if (!matched_prc) { - THROW_IE_EXCEPTION << "Store emitter in " << n->getName() << " only support input precision of FP32 or I32 or the same precision as output."; + THROW_IE_EXCEPTION << "Store emitter in " << name << " only support input precision of FP32 or I32 or the same precision as output."; } if ((src_prc == Precision::FP32) || (src_prc == Precision::I32)) { if ((isa == cpu::x64::sse41 && store_num > 4) || (isa == cpu::x64::avx2 && store_num > 8) || (isa == cpu::x64::avx512_common && store_num > 16) || store_num < 0) { - THROW_IE_EXCEPTION << "Store emitter in " << n->getName() << " has unexpected number of values to store."; + THROW_IE_EXCEPTION << "Store emitter in " << name << " has unexpected number of values to store."; } } @@ -586,7 +586,7 @@ template store_dword_to_word_extension(Vmm(in_vec_idx), reg_dst, offset_byte, true, false, store_num); break; default: - THROW_IE_EXCEPTION << "Store emitter in " << n->getName() << " has unsupported dst precision to store."; + THROW_IE_EXCEPTION << "Store emitter in " << name << " has unsupported dst precision to store."; } } } @@ -618,11 +618,11 @@ template // Ensure data fits completely inside the Xmm/Ymm/Zmm register if (store_size < 0 || store_size > 64) - THROW_IE_EXCEPTION << "Store emitter in " << n->getName() << " has unexpected number of values to store in store_bytes."; + THROW_IE_EXCEPTION << "Store emitter in " << name << " has unexpected number of values to store in store_bytes."; if (is_ymm && store_size > 32) - THROW_IE_EXCEPTION << "Store emitter in " << n->getName() << " has unexpected number of values to store to ymm in store_bytes."; + THROW_IE_EXCEPTION << "Store emitter in " << name << " has unexpected number of values to store to ymm in store_bytes."; if (is_xmm && store_size > 16) - THROW_IE_EXCEPTION << "Store emitter in " << n->getName() << " has unexpected number of values to store to xmm in store_bytes."; + THROW_IE_EXCEPTION << "Store emitter in " << name << " has unexpected number of values to store to xmm in store_bytes."; auto xmm = Xbyak::Xmm(vmm.getIdx()); auto ymm = Xbyak::Ymm(vmm.getIdx()); @@ -718,14 +718,14 @@ template break; case 16: break; default: - THROW_IE_EXCEPTION << "Store emitter in " << n->getName() << " has unexpected number of values to store in store_bytes."; + THROW_IE_EXCEPTION << "Store emitter in " << name << " has unexpected number of values to store in store_bytes."; } } } } /** -* store_dword_to_byte_extension is the utility function to +* store_dword_to_byte_extension is the utility function to * 1. convert store_num (0 <= store_num <= 16) dwords in the Xmm/Ymm/Zmm to store_num bytes with singed or unsinged saturation. * 2. store the packed byte into the memory referenced by ptr[reg + offset] address. */ @@ -743,11 +743,11 @@ template // At most 8 dwords can fit inside the Ymm register // At most 4 dwords can fit inside the Xmm register if (store_num < 0 || store_num > 16) - THROW_IE_EXCEPTION << "Store emitter in " << n->getName() << " has unexpected number of values to store in store_dword_to_byte_extension."; + THROW_IE_EXCEPTION << "Store emitter in " << name << " has unexpected number of values to store in store_dword_to_byte_extension."; if (is_ymm && store_num > 8) - THROW_IE_EXCEPTION << "Store emitter in " << n->getName() << " has unexpected number of values to store to ymm in store_dword_to_byte_extension."; + THROW_IE_EXCEPTION << "Store emitter in " << name << " has unexpected number of values to store to ymm in store_dword_to_byte_extension."; if (is_xmm && store_num > 4) - THROW_IE_EXCEPTION << "Store emitter in " << n->getName() << " has unexpected number of values to store to xmm in store_dword_to_byte_extension."; + THROW_IE_EXCEPTION << "Store emitter in " << name << " has unexpected number of values to store to xmm in store_dword_to_byte_extension."; auto ymm = Xbyak::Ymm(vmm.getIdx()); @@ -816,11 +816,11 @@ template // At most 4 dwords can fit inside the Xmm register // At most 8 dwords can fit inside the Ymm register if (store_num < 0 || store_num > 16) - THROW_IE_EXCEPTION << "Store emitter in " << n->getName() << " has unexpected number of values to store in store_dword_to_word_extension."; + THROW_IE_EXCEPTION << "Store emitter in " << name << " has unexpected number of values to store in store_dword_to_word_extension."; if (is_ymm && store_num > 8) - THROW_IE_EXCEPTION << "Store emitter in " << n->getName() << " has unexpected number of values to store to ymm in store_dword_to_word_extension."; + THROW_IE_EXCEPTION << "Store emitter in " << name << " has unexpected number of values to store to ymm in store_dword_to_word_extension."; if (is_xmm && store_num > 4) - THROW_IE_EXCEPTION << "Store emitter in " << n->getName() << " has unexpected number of values to store to xmm in store_dword_to_word_extension."; + THROW_IE_EXCEPTION << "Store emitter in " << name << " has unexpected number of values to store to xmm in store_dword_to_word_extension."; auto ymm = Xbyak::Ymm(vmm.getIdx()); auto zmm = Xbyak::Zmm(vmm.getIdx()); @@ -829,7 +829,7 @@ template if (mayiuse(cpu::x64::avx512_core_bf16)) { h->vcvtneps2bf16(ymm, zmm); } else { - emu_vcvtneps2bf16->emit({static_cast(vmm.getIdx())}, {static_cast(ymm.getIdx())}); + emu_vcvtneps2bf16->emit_code({static_cast(vmm.getIdx())}, {static_cast(ymm.getIdx())}); } if (store_num == 16) { h->vmovdqu16(ptr[reg + offset], ymm); diff --git a/inference-engine/src/mkldnn_plugin/nodes/common/jit_load_store_emitters.h b/inference-engine/src/mkldnn_plugin/emitters/jit_load_store_emitters.hpp similarity index 94% rename from inference-engine/src/mkldnn_plugin/nodes/common/jit_load_store_emitters.h rename to inference-engine/src/mkldnn_plugin/emitters/jit_load_store_emitters.hpp index 332d54903e5b99..0f434c2406e3ad 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/common/jit_load_store_emitters.h +++ b/inference-engine/src/mkldnn_plugin/emitters/jit_load_store_emitters.hpp @@ -4,10 +4,10 @@ #pragma once -#include "emitter.h" +#include "jit_emitter.hpp" #include #include "mkldnn_node.h" -#include "utils/bfloat16.hpp" +#include "jit_bf16_emitters.hpp" using namespace mkldnn::impl; using namespace mkldnn::impl::cpu::x64; @@ -66,9 +66,9 @@ class jit_load_emitter : public jit_emitter { */ void emit_impl(const std::vector &in_idxs, const std::vector &out_idxs, const std::vector &pool_vec_idxs, const std::vector &pool_gpr_idxs, - const emitter_context *emit_context) override; + const emitter_context *emit_context) const override; - size_t get_inputs_num() override; + size_t get_inputs_num() const override; private: template @@ -94,6 +94,7 @@ class jit_load_emitter : public jit_emitter { size_t aux_gprs_count() const override; + std::string name; int v_len_elt; // 4/8/16 }; @@ -119,9 +120,9 @@ class jit_store_emitter : public jit_emitter { */ void emit_impl(const std::vector &in_idxs, const std::vector &out_idxs, const std::vector &pool_vec_idxs, const std::vector &pool_gpr_idxs, - const emitter_context *emit_context) override; + const emitter_context *emit_context) const override; - size_t get_inputs_num() override; + size_t get_inputs_num() const override; std::shared_ptr get_emu_vcvtneps2bf16() const { return emu_vcvtneps2bf16; @@ -144,6 +145,7 @@ class jit_store_emitter : public jit_emitter { size_t aux_gprs_count() const override; size_t aux_vecs_count() const override; + std::string name; int v_len_elt; // 4/8/16 std::shared_ptr emu_vcvtneps2bf16; }; diff --git a/inference-engine/src/mkldnn_plugin/nodes/jit_mkldnn_emitters.cpp b/inference-engine/src/mkldnn_plugin/emitters/jit_mkldnn_emitters.cpp similarity index 61% rename from inference-engine/src/mkldnn_plugin/nodes/jit_mkldnn_emitters.cpp rename to inference-engine/src/mkldnn_plugin/emitters/jit_mkldnn_emitters.cpp index 84132993e026e6..6264be3bf42872 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/jit_mkldnn_emitters.cpp +++ b/inference-engine/src/mkldnn_plugin/emitters/jit_mkldnn_emitters.cpp @@ -2,10 +2,8 @@ // SPDX-License-Identifier: Apache-2.0 // -#include "common/emitter.h" #include "jit_mkldnn_emitters.hpp" -#include "mkldnn_eltwise_node.h" -#include "legacy/ie_layers.h" +#include "nodes/mkldnn_eltwise_node.h" using namespace mkldnn::impl::utils; using namespace mkldnn::impl; @@ -14,30 +12,45 @@ using namespace Xbyak; namespace MKLDNNPlugin { +jit_mkldnn_emitter::jit_mkldnn_emitter(jit_generator *host, cpu_isa_t host_isa, const std::shared_ptr& node, InferenceEngine::Precision exec_prc) + : jit_emitter(host, host_isa, node, exec_prc) { + + kind = mkldnn_eltwise_tanh; + alpha = 0.f; + beta = 0.f; + + set_injector(); +} + jit_mkldnn_emitter::jit_mkldnn_emitter(jit_generator *host, cpu_isa_t host_isa, const MKLDNNNode* node, InferenceEngine::Precision exec_prc) : jit_emitter(host, host_isa, node, exec_prc) { - auto& eltwiseNode = dynamic_cast(*n); + auto eltwiseNode = dynamic_cast(node); + kind = static_cast(eltwiseNode->getAlgorithm()); + alpha = eltwiseNode->getAlpha(); + beta = eltwiseNode->getBeta(); - auto alg = static_cast(eltwiseNode.getAlgorithm()); + set_injector(); +} +void jit_mkldnn_emitter::set_injector() { if (host_isa_ == cpu::x64::sse41) { eltwise_injector_sse42 = std::make_shared>( - host, alg, eltwiseNode.getAlpha(), eltwiseNode.getBeta(), 1); + h, kind, alpha, beta, 1); } else if (host_isa_ == cpu::x64::avx2) { eltwise_injector_avx2 = std::make_shared>( - host, alg, eltwiseNode.getAlpha(), eltwiseNode.getBeta(), 1); + h, kind, alpha, beta, 1); } else if (host_isa_ == cpu::x64::avx512_common) { eltwise_injector_avx512_common = std::make_shared>( - host, alg, eltwiseNode.getAlpha(), eltwiseNode.getBeta(), 1); + h, kind, alpha, beta, 1); } else { assert(!"unsupported isa"); } } -size_t jit_mkldnn_emitter::get_inputs_num() { return 1; } +size_t jit_mkldnn_emitter::get_inputs_num() const { return 1; } -void jit_mkldnn_emitter::emit(const std::vector &in_vec_idxs, const std::vector &out_vec_idxs, - const std::vector &pool_vec_idxs, const std::vector &pool_gpr_idxs) { +void jit_mkldnn_emitter::emit_code(const std::vector &in_vec_idxs, const std::vector &out_vec_idxs, + const std::vector &pool_vec_idxs, const std::vector &pool_gpr_idxs) const { if (host_isa_ == cpu::x64::sse41) { if (out_vec_idxs[0] != in_vec_idxs[0]) h->uni_vmovups(Xmm(out_vec_idxs[0]), Xmm(in_vec_idxs[0])); @@ -55,7 +68,7 @@ void jit_mkldnn_emitter::emit(const std::vector &in_vec_idxs, const std: } } -void jit_mkldnn_emitter::emit_table() { +void jit_mkldnn_emitter::emit_data() const { if (host_isa_ == cpu::x64::sse41) { eltwise_injector_sse42->prepare_table(); } else if (host_isa_ == cpu::x64::avx2) { @@ -67,5 +80,8 @@ void jit_mkldnn_emitter::emit_table() { } } +jit_mkldnn_aux_emitter::jit_mkldnn_aux_emitter(jit_generator *host, cpu_isa_t host_isa, const MKLDNNNode* node, InferenceEngine::Precision exec_prc) + : jit_mkldnn_emitter(host, host_isa, node, exec_prc) { +} } // namespace MKLDNNPlugin diff --git a/inference-engine/src/mkldnn_plugin/nodes/jit_mkldnn_emitters.hpp b/inference-engine/src/mkldnn_plugin/emitters/jit_mkldnn_emitters.hpp similarity index 52% rename from inference-engine/src/mkldnn_plugin/nodes/jit_mkldnn_emitters.hpp rename to inference-engine/src/mkldnn_plugin/emitters/jit_mkldnn_emitters.hpp index dd3bd9daa3c148..1dfc9b5f4cf420 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/jit_mkldnn_emitters.hpp +++ b/inference-engine/src/mkldnn_plugin/emitters/jit_mkldnn_emitters.hpp @@ -4,34 +4,51 @@ #pragma once -#include "common/emitter.h" #include -#include "mkldnn_node.h" #include +#include "jit_emitter.hpp" +#include "mkldnn_node.h" + namespace MKLDNNPlugin { class jit_mkldnn_emitter : public jit_emitter { public: - jit_mkldnn_emitter(mkldnn::impl::cpu::x64::jit_generator *host, mkldnn::impl::cpu::x64::cpu_isa_t host_isa, const MKLDNNNode* node, - InferenceEngine::Precision exec_prc = InferenceEngine::Precision::FP32); + void emit_code(const std::vector &in_vec_idxs, const std::vector &out_vec_idxs, + const std::vector &pool_vec_idxs, const std::vector &pool_gpr_idxs) const override; - size_t get_inputs_num() override; - - void emit(const std::vector &in_vec_idxs, const std::vector &out_vec_idxs, - const std::vector &pool_vec_idxs = {}, const std::vector &pool_gpr_idxs = {}) override; - - void emit_table() override; + void emit_data() const override; void emit_impl(const std::vector &in_idxs, const std::vector &out_idxs, const std::vector &pool_vec_idxs, const std::vector &pool_gpr_idxs, - const emitter_context *emit_context = nullptr) override {}; + const emitter_context *emit_context = nullptr) const override {}; +protected: + jit_mkldnn_emitter(mkldnn::impl::cpu::x64::jit_generator *host, mkldnn::impl::cpu::x64::cpu_isa_t host_isa, const MKLDNNNode* node, + InferenceEngine::Precision exec_prc = InferenceEngine::Precision::FP32); + jit_mkldnn_emitter(mkldnn::impl::cpu::x64::jit_generator *host, mkldnn::impl::cpu::x64::cpu_isa_t host_isa, const std::shared_ptr& n, + InferenceEngine::Precision exec_prc = InferenceEngine::Precision::FP32); + void set_injector(); -private: + mkldnn_alg_kind_t kind {mkldnn_alg_kind_undef}; + float alpha {0.f}; + float beta {0.f}; + +protected: std::shared_ptr> eltwise_injector_sse42; std::shared_ptr> eltwise_injector_avx2; std::shared_ptr> eltwise_injector_avx512_common; + +private: + size_t get_inputs_num() const override; +}; + +class jit_mkldnn_aux_emitter : public jit_mkldnn_emitter { +public: + jit_mkldnn_aux_emitter(mkldnn::impl::cpu::x64::jit_generator *host, mkldnn::impl::cpu::x64::cpu_isa_t host_isa, const MKLDNNNode* node, + InferenceEngine::Precision exec_prc = InferenceEngine::Precision::FP32); + +private: }; -} // namespace MKLDNNPlugin +} // namespace MKLDNNPlugin \ No newline at end of file diff --git a/inference-engine/src/mkldnn_plugin/mkldnn_graph_dumper.cpp b/inference-engine/src/mkldnn_plugin/mkldnn_graph_dumper.cpp index 543893930d191a..c22512cd97240c 100644 --- a/inference-engine/src/mkldnn_plugin/mkldnn_graph_dumper.cpp +++ b/inference-engine/src/mkldnn_plugin/mkldnn_graph_dumper.cpp @@ -8,8 +8,8 @@ #include #include "exec_graph_info.hpp" #include "mkldnn_debug.h" -#include "generic_ie.hpp" #include +#include "ngraph/ngraph.hpp" #include #include @@ -136,7 +136,6 @@ InferenceEngine::CNNNetwork dump_graph_as_ie_ngraph_net(const MKLDNNGraph &graph holder->add_control_dependency(node); } - ngraph::op::GenericIE::DisableReshape reshape(nodes); auto function = std::make_shared(results, params, graph._name); InferenceEngine::CNNNetwork net(function); return net; diff --git a/inference-engine/src/mkldnn_plugin/mkldnn_plugin.cpp b/inference-engine/src/mkldnn_plugin/mkldnn_plugin.cpp index 880b91b9bcca4c..9036d68abbaa8b 100644 --- a/inference-engine/src/mkldnn_plugin/mkldnn_plugin.cpp +++ b/inference-engine/src/mkldnn_plugin/mkldnn_plugin.cpp @@ -15,7 +15,6 @@ #include #include #include -#include #include #include #include @@ -107,8 +106,6 @@ Engine::~Engine() { static void Transformation(CNNNetwork& clonedNetwork, const Config& conf) { auto nGraphFunc = clonedNetwork.getFunction(); - // Disable shape inference (WA for generic operations) - ngraph::op::GenericIE::DisableReshape noReshape(nGraphFunc); ngraph::pass::Manager manager; manager.register_pass(); diff --git a/inference-engine/src/mkldnn_plugin/nodes/common/softmax.cpp b/inference-engine/src/mkldnn_plugin/nodes/common/softmax.cpp index 3358215c5d262a..3bb1e83e4b23b7 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/common/softmax.cpp +++ b/inference-engine/src/mkldnn_plugin/nodes/common/softmax.cpp @@ -9,6 +9,7 @@ #include #include // TODO: just to replace mkldnn->dnnl via macros #include "utils/bfloat16.hpp" +#include "emitters/jit_bf16_emitters.hpp" #include #include @@ -162,7 +163,7 @@ struct jit_uni_softmax_kernel_f32 : public jit_uni_softmax_kernel, public jit_ge this->postamble(); if (!mayiuse(avx512_core_bf16) && mayiuse(avx512_core)) - emu_vcvtneps2bf16->emit_table(); + emu_vcvtneps2bf16->emit_data(); exp_injector->prepare_table(); } @@ -218,7 +219,7 @@ struct jit_uni_softmax_kernel_f32 : public jit_uni_softmax_kernel, public jit_ge if (mayiuse(avx512_core_bf16)) vcvtneps2bf16(ymm_dst, vmm_dst); else - emu_vcvtneps2bf16->emit({static_cast(vmm_dst.getIdx())}, {static_cast(ymm_dst.getIdx())}); + emu_vcvtneps2bf16->emit_code({static_cast(vmm_dst.getIdx())}, {static_cast(ymm_dst.getIdx())}); vmovdqu16(op, ymm_dst); break; default: 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 438a0161dc3440..320309738b7ae9 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_eltwise_node.cpp +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_eltwise_node.cpp @@ -15,9 +15,11 @@ #include "mkldnn_extension_utils.h" #include "mkldnn_quantize_node.h" #include "mkldnn_pooling_node.h" -#include "common/emitter.h" -#include "jit_eltwise_emitters.hpp" -#include "jit_mkldnn_emitters.hpp" + +#include "emitters/jit_emitter.hpp" +#include "emitters/jit_eltwise_emitters.hpp" +#include "emitters/jit_mkldnn_emitters.hpp" +#include "emitters/jit_bf16_emitters.hpp" #include #include @@ -293,11 +295,11 @@ struct jit_uni_eltwise_generic : public MKLDNNPlugin::jit_uni_eltwise_kernel, pu this->postamble(); if (!mayiuse(avx512_core_bf16) && mayiuse(avx512_core)) - emu_vcvtneps2bf16->emit_table(); + emu_vcvtneps2bf16->emit_data(); - eltwise_emitter->emit_table(); + eltwise_emitter->emit_data(); for (int i = 0; i < post_op_emitters.size(); i++) { - post_op_emitters[i]->emit_table(); + post_op_emitters[i]->emit_data(); } } @@ -363,25 +365,25 @@ struct jit_uni_eltwise_generic : public MKLDNNPlugin::jit_uni_eltwise_kernel, pu std::set precisions; OV_SWITCH(MKLDNNPlugin, SupportedPrecisions, precisions, eltwiseNode.getOpType(), - OV_CASE(Relu, jit_mkldnn_emitter), - OV_CASE(Gelu, jit_mkldnn_emitter), - OV_CASE(Elu, jit_mkldnn_emitter), - OV_CASE(Tanh, jit_mkldnn_emitter), - OV_CASE(Logistic, jit_mkldnn_emitter), - OV_CASE(Square, jit_mkldnn_emitter), - OV_CASE(Abs, jit_mkldnn_emitter), - OV_CASE(Sqrt, jit_mkldnn_emitter), - OV_CASE(Linear, jit_mkldnn_emitter), - OV_CASE(BoundedRelu, jit_mkldnn_emitter), - OV_CASE(SoftRelu, jit_mkldnn_emitter), - OV_CASE(Relu6, jit_mkldnn_emitter), - OV_CASE(Exp, jit_mkldnn_emitter), - OV_CASE(Clamp, jit_mkldnn_emitter), - OV_CASE(Swish, jit_mkldnn_emitter), - OV_CASE(Hswish, jit_mkldnn_emitter), - OV_CASE(Mish, jit_mkldnn_emitter), - OV_CASE(Hsigmoid, jit_mkldnn_emitter), - OV_CASE(Round, jit_mkldnn_emitter), + OV_CASE(Relu, jit_mkldnn_aux_emitter), + OV_CASE(Gelu, jit_mkldnn_aux_emitter), + OV_CASE(Elu, jit_mkldnn_aux_emitter), + OV_CASE(Tanh, jit_mkldnn_aux_emitter), + OV_CASE(Logistic, jit_mkldnn_aux_emitter), + OV_CASE(Square, jit_mkldnn_aux_emitter), + OV_CASE(Abs, jit_mkldnn_aux_emitter), + OV_CASE(Sqrt, jit_mkldnn_aux_emitter), + OV_CASE(Linear, jit_mkldnn_aux_emitter), + OV_CASE(BoundedRelu, jit_mkldnn_aux_emitter), + OV_CASE(SoftRelu, jit_mkldnn_aux_emitter), + OV_CASE(Relu6, jit_mkldnn_aux_emitter), + OV_CASE(Exp, jit_mkldnn_aux_emitter), + OV_CASE(Clamp, jit_mkldnn_aux_emitter), + OV_CASE(Swish, jit_mkldnn_aux_emitter), + OV_CASE(Hswish, jit_mkldnn_aux_emitter), + OV_CASE(Mish, jit_mkldnn_aux_emitter), + OV_CASE(Hsigmoid, jit_mkldnn_aux_emitter), + OV_CASE(Round, jit_mkldnn_aux_emitter), OV_CASE(Add, jit_add_emitter), OV_CASE(MulAdd, jit_mul_add_emitter), OV_CASE(Subtract, jit_subtract_emitter), @@ -413,37 +415,36 @@ struct jit_uni_eltwise_generic : public MKLDNNPlugin::jit_uni_eltwise_kernel, pu } std::shared_ptr create_eltwise_emitter(MKLDNNNode& node, Precision exec_prec) { - auto& eltwiseNode = dynamic_cast(node); - const MKLDNNNode * eltwiseNodePtr = dynamic_cast(&node); + const auto& eltwiseNode = dynamic_cast(node); EltwiseEmitterContext ctx = { nullptr, this, isa, - eltwiseNodePtr, + &node, exec_prec }; OV_SWITCH(MKLDNNPlugin, EltwiseEmitter, ctx, eltwiseNode.getOpType(), - OV_CASE(Relu, jit_mkldnn_emitter), - OV_CASE(Gelu, jit_mkldnn_emitter), - OV_CASE(Elu, jit_mkldnn_emitter), - OV_CASE(Tanh, jit_mkldnn_emitter), - OV_CASE(Logistic, jit_mkldnn_emitter), - OV_CASE(Square, jit_mkldnn_emitter), - OV_CASE(Abs, jit_mkldnn_emitter), - OV_CASE(Sqrt, jit_mkldnn_emitter), - OV_CASE(Linear, jit_mkldnn_emitter), - OV_CASE(BoundedRelu, jit_mkldnn_emitter), - OV_CASE(SoftRelu, jit_mkldnn_emitter), - OV_CASE(Relu6, jit_mkldnn_emitter), - OV_CASE(Exp, jit_mkldnn_emitter), - OV_CASE(Clamp, jit_mkldnn_emitter), - OV_CASE(Swish, jit_mkldnn_emitter), - OV_CASE(Hswish, jit_mkldnn_emitter), - OV_CASE(Mish, jit_mkldnn_emitter), - OV_CASE(Hsigmoid, jit_mkldnn_emitter), - OV_CASE(Round, jit_mkldnn_emitter), + OV_CASE(Relu, jit_mkldnn_aux_emitter), + OV_CASE(Gelu, jit_mkldnn_aux_emitter), + OV_CASE(Elu, jit_mkldnn_aux_emitter), + OV_CASE(Tanh, jit_mkldnn_aux_emitter), + OV_CASE(Logistic, jit_mkldnn_aux_emitter), + OV_CASE(Square, jit_mkldnn_aux_emitter), + OV_CASE(Abs, jit_mkldnn_aux_emitter), + OV_CASE(Sqrt, jit_mkldnn_aux_emitter), + OV_CASE(Linear, jit_mkldnn_aux_emitter), + OV_CASE(BoundedRelu, jit_mkldnn_aux_emitter), + OV_CASE(SoftRelu, jit_mkldnn_aux_emitter), + OV_CASE(Relu6, jit_mkldnn_aux_emitter), + OV_CASE(Exp, jit_mkldnn_aux_emitter), + OV_CASE(Clamp, jit_mkldnn_aux_emitter), + OV_CASE(Swish, jit_mkldnn_aux_emitter), + OV_CASE(Hswish, jit_mkldnn_aux_emitter), + OV_CASE(Mish, jit_mkldnn_aux_emitter), + OV_CASE(Hsigmoid, jit_mkldnn_aux_emitter), + OV_CASE(Round, jit_mkldnn_aux_emitter), OV_CASE(Add, jit_add_emitter), OV_CASE(MulAdd, jit_mul_add_emitter), OV_CASE(Subtract, jit_subtract_emitter), @@ -485,7 +486,7 @@ struct jit_uni_eltwise_generic : public MKLDNNPlugin::jit_uni_eltwise_kernel, pu std::vector out_idxs; out_idxs.push_back(vmm_dst.getIdx()); - eltwise_emitter->emit(in_idxs, out_idxs, aux_idxs); + eltwise_emitter->emit_code(in_idxs, out_idxs, aux_idxs); } inline void apply_post_ops(bool is_scalar, int offset = 0) { @@ -505,7 +506,7 @@ struct jit_uni_eltwise_generic : public MKLDNNPlugin::jit_uni_eltwise_kernel, pu std::vector out_idxs; out_idxs.push_back(vmm_dst.getIdx()); - post_op_emitters[eltwise_post_op_idx]->emit(in_idxs, out_idxs, aux_idxs); + post_op_emitters[eltwise_post_op_idx]->emit_code(in_idxs, out_idxs, aux_idxs); eltwise_post_op_idx++; } else { @@ -647,7 +648,7 @@ struct jit_uni_eltwise_generic : public MKLDNNPlugin::jit_uni_eltwise_kernel, pu if (mayiuse(avx512_core_bf16)) vcvtneps2bf16(ymm_dst, vmm_dst); else - emu_vcvtneps2bf16->emit({static_cast(vmm_dst.getIdx())}, {static_cast(ymm_dst.getIdx())}); + emu_vcvtneps2bf16->emit_code({static_cast(vmm_dst.getIdx())}, {static_cast(ymm_dst.getIdx())}); vmovdqu16(op, ymm_dst); break; case Precision::I16: diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_interpolate_node.cpp b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_interpolate_node.cpp index b9dec20c50eb2c..a211c288d1f699 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_interpolate_node.cpp +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_interpolate_node.cpp @@ -23,6 +23,7 @@ #include #include "common/cpu_memcpy.h" #include "utils/bfloat16.hpp" +#include "emitters/jit_bf16_emitters.hpp" using namespace mkldnn; using namespace MKLDNNPlugin; @@ -148,7 +149,7 @@ struct jit_uni_interpolate_kernel_f32 : public jit_uni_interpolate_kernel, publi this->postamble(); if (!mayiuse(avx512_core_bf16) && mayiuse(avx512_core)) - emu_vcvtneps2bf16->emit_table(); + emu_vcvtneps2bf16->emit_data(); for (auto& inj : eltwise_injectors) inj->prepare_table(); @@ -1483,7 +1484,7 @@ struct jit_uni_interpolate_kernel_f32 : public jit_uni_interpolate_kernel, publi if (mayiuse(avx512_core_bf16)) vcvtneps2bf16(ymm_dst, vmm_dst); else - emu_vcvtneps2bf16->emit({static_cast(vmm_dst.getIdx())}, {static_cast(ymm_dst.getIdx())}); + emu_vcvtneps2bf16->emit_code({static_cast(vmm_dst.getIdx())}, {static_cast(ymm_dst.getIdx())}); vmovdqu16(op, ymm_dst); } } diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_mvn_node.cpp b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_mvn_node.cpp index dd4179b2d22c09..5200b1386e5839 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_mvn_node.cpp +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_mvn_node.cpp @@ -16,7 +16,8 @@ #include #include "ie_parallel.hpp" #include -#include "common/jit_load_store_emitters.h" +#include "emitters/jit_load_store_emitters.hpp" +#include "emitters/jit_bf16_emitters.hpp" #include #include @@ -200,7 +201,7 @@ struct jit_uni_mvn_mean_variance_kernel_f32 : public jit_uni_mvn_mean_variance_k this->postamble(); - load_emitter->emit_table(); + load_emitter->emit_data(); } private: @@ -241,7 +242,7 @@ struct jit_uni_mvn_mean_variance_kernel_f32 : public jit_uni_mvn_mean_variance_k inline void worker_full_size() { Precision dst_prc = isFloatCompatible(jcp_.src_prc) ? Precision::FP32 : Precision::I32; - load_emitter->emit({static_cast(reg_src.getIdx())}, {static_cast(vmm_val.getIdx())}, + load_emitter->emit_code({static_cast(reg_src.getIdx())}, {static_cast(vmm_val.getIdx())}, std::make_shared(jcp_.src_prc, dst_prc, step), {}, {load_pool_gpr_idxs}); @@ -263,7 +264,7 @@ struct jit_uni_mvn_mean_variance_kernel_f32 : public jit_uni_mvn_mean_variance_k inline void worker_tail_blk() { Precision dst_prc = isFloatCompatible(jcp_.src_prc) ? Precision::FP32 : Precision::I32; - load_emitter->emit({static_cast(reg_src.getIdx())}, {static_cast(vmm_val.getIdx())}, + load_emitter->emit_code({static_cast(reg_src.getIdx())}, {static_cast(vmm_val.getIdx())}, std::make_shared(jcp_.src_prc, dst_prc, tail_num), {}, {load_pool_gpr_idxs}); @@ -307,7 +308,7 @@ struct jit_uni_mvn_mean_variance_kernel_f32 : public jit_uni_mvn_mean_variance_k inline void worker_tail_planar() { Precision dst_prc = isFloatCompatible(jcp_.src_prc) ? Precision::FP32 : Precision::I32; - load_emitter->emit({static_cast(reg_src.getIdx())}, {static_cast(vmm_val.getIdx())}, + load_emitter->emit_code({static_cast(reg_src.getIdx())}, {static_cast(vmm_val.getIdx())}, std::make_shared(jcp_.src_prc, dst_prc, tail_num, true, "zero"), {}, {load_pool_gpr_idxs}); @@ -478,9 +479,9 @@ struct jit_uni_mvn_kernel_f32 : public jit_uni_mvn_kernel, public jit_generator this->postamble(); - load_emitter->emit_table(); + load_emitter->emit_data(); if (!mayiuse(avx512_core_bf16) && mayiuse(avx512_core) && store_emitter != nullptr && store_emitter->get_emu_vcvtneps2bf16() != nullptr) - store_emitter->get_emu_vcvtneps2bf16()->emit_table(); + store_emitter->get_emu_vcvtneps2bf16()->emit_data(); for (auto& inj : eltwise_injectors) inj->prepare_table(); @@ -531,7 +532,7 @@ struct jit_uni_mvn_kernel_f32 : public jit_uni_mvn_kernel, public jit_generator inline void worker_mvn(bool is_tail) { int elt_num = is_tail ? tail_num : step; - load_emitter->emit({static_cast(reg_src.getIdx())}, {static_cast(vmm_val.getIdx())}, + load_emitter->emit_code({static_cast(reg_src.getIdx())}, {static_cast(vmm_val.getIdx())}, std::make_shared(jcp_.src_prc, Precision::FP32, elt_num), {}, {load_pool_gpr_idxs}); @@ -541,7 +542,7 @@ struct jit_uni_mvn_kernel_f32 : public jit_uni_mvn_kernel, public jit_generator apply_post_ops(jcp_.dst_prc, jcp_.planar_layout); - store_emitter->emit({static_cast(vmm_val.getIdx())}, {static_cast(reg_dst.getIdx())}, + store_emitter->emit_code({static_cast(vmm_val.getIdx())}, {static_cast(reg_dst.getIdx())}, std::make_shared(Precision::FP32, jcp_.dst_prc, elt_num), {store_pool_vec_idxs}, {store_pool_gpr_idxs}); } diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_normalize_node.cpp b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_normalize_node.cpp index 66132ae81bc794..b193716bf4d10b 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_normalize_node.cpp +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_normalize_node.cpp @@ -10,6 +10,7 @@ #include "mkldnn_quantize_node.h" #include "mkldnn_eltwise_node.h" #include "utils/bfloat16.hpp" +#include "emitters/jit_bf16_emitters.hpp" #include "mkldnn_extension_utils.h" #include #include @@ -207,7 +208,7 @@ struct jit_uni_normalize_kernel_f32 : public jit_uni_normalize_kernel, public ji this->postamble(); if (!mayiuse(avx512_core_bf16) && mayiuse(avx512_core)) - emu_vcvtneps2bf16->emit_table(); + emu_vcvtneps2bf16->emit_data(); for (auto& inj : eltwise_injectors) inj->prepare_table(); } @@ -603,7 +604,7 @@ struct jit_uni_normalize_kernel_f32 : public jit_uni_normalize_kernel, public ji if (mayiuse(avx512_core_bf16)) vcvtneps2bf16(ymm_dst, vmm_dst); else - emu_vcvtneps2bf16->emit({static_cast(vmm_dst.getIdx())}, {static_cast(ymm_dst.getIdx())}); + emu_vcvtneps2bf16->emit_code({static_cast(vmm_dst.getIdx())}, {static_cast(ymm_dst.getIdx())}); vmovdqu16(op, ymm_dst); } else if (dst_dt == memory::data_type::u8) { uni_vcvtps2dq(vmm_dst, vmm_dst); diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_reduce_node.cpp b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_reduce_node.cpp index 19740905c3e7dc..9b5b73d62792f0 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_reduce_node.cpp +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_reduce_node.cpp @@ -13,6 +13,7 @@ #include #include #include "utils/bfloat16.hpp" +#include "emitters/jit_bf16_emitters.hpp" #include "ie_parallel.hpp" #include @@ -115,7 +116,7 @@ struct jit_uni_reduce_kernel_f32 : public jit_uni_reduce_kernel, public jit_gene this->postamble(); if (!mayiuse(avx512_core_bf16) && mayiuse(avx512_core)) - emu_vcvtneps2bf16->emit_table(); + emu_vcvtneps2bf16->emit_data(); if (jcp_.reduce_mode == Reduce::And || jcp_.reduce_mode == Reduce::L1 || jcp_.reduce_mode == Reduce::Max || jcp_.reduce_mode == Reduce::Min || jcp_.reduce_mode == Reduce::Prod || jcp_.reduce_mode == Reduce::Or) { @@ -622,7 +623,7 @@ struct jit_uni_reduce_kernel_f32 : public jit_uni_reduce_kernel, public jit_gene if (mayiuse(avx512_core_bf16)) vcvtneps2bf16(ymm_dst, vmm_dst); else - emu_vcvtneps2bf16->emit({static_cast(vmm_dst.getIdx())}, {static_cast(ymm_dst.getIdx())}); + emu_vcvtneps2bf16->emit_code({static_cast(vmm_dst.getIdx())}, {static_cast(ymm_dst.getIdx())}); vmovdqu16(op, ymm_dst); break; case memory::data_type::s8: @@ -851,7 +852,7 @@ struct jit_uni_reduce_post_kernel_f32 : public jit_uni_reduce_post_kernel, publi this->postamble(); if (!mayiuse(avx512_core_bf16) && mayiuse(avx512_core)) - emu_vcvtneps2bf16->emit_table(); + emu_vcvtneps2bf16->emit_data(); if (jcp_.reduce_mode == Reduce::LogSum || jcp_.reduce_mode == Reduce::LogSumExp) { log_injector->prepare_table(); @@ -1096,7 +1097,7 @@ struct jit_uni_reduce_post_kernel_f32 : public jit_uni_reduce_post_kernel, publi if (mayiuse(avx512_core_bf16)) vcvtneps2bf16(ymm_dst, vmm_dst); else - emu_vcvtneps2bf16->emit({static_cast(vmm_dst.getIdx())}, {static_cast(ymm_dst.getIdx())}); + emu_vcvtneps2bf16->emit_code({static_cast(vmm_dst.getIdx())}, {static_cast(ymm_dst.getIdx())}); vmovdqu16(op, ymm_dst); break; case memory::data_type::s8: diff --git a/inference-engine/src/mkldnn_plugin/nodes/region_yolo.cpp b/inference-engine/src/mkldnn_plugin/nodes/region_yolo.cpp index 60b3fc27917156..03abe5a0bcd3df 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/region_yolo.cpp +++ b/inference-engine/src/mkldnn_plugin/nodes/region_yolo.cpp @@ -13,6 +13,7 @@ #include #include #include "utils/bfloat16.hpp" +#include "emitters/jit_bf16_emitters.hpp" #include "common/cpu_memcpy.h" #include "mkldnn.hpp" #include @@ -120,7 +121,7 @@ struct jit_uni_logistic_kernel_f32 : public jit_uni_logistic_kernel, public jit_ this->postamble(); if (!mayiuse(avx512_core_bf16) && mayiuse(avx512_core)) - emu_vcvtneps2bf16->emit_table(); + emu_vcvtneps2bf16->emit_data(); exp_injector->prepare_table(); @@ -223,7 +224,7 @@ struct jit_uni_logistic_kernel_f32 : public jit_uni_logistic_kernel, public jit_ if (mayiuse(avx512_core_bf16)) vcvtneps2bf16(ymm_dst, vmm_dst); else - emu_vcvtneps2bf16->emit({static_cast(vmm_dst.getIdx())}, {static_cast(ymm_dst.getIdx())}); + emu_vcvtneps2bf16->emit_code({static_cast(vmm_dst.getIdx())}, {static_cast(ymm_dst.getIdx())}); vmovdqu16(op, ymm_dst); break; default: diff --git a/inference-engine/src/mkldnn_plugin/utils/bfloat16.hpp b/inference-engine/src/mkldnn_plugin/utils/bfloat16.hpp index dabff00462e53a..dd98a63c1b3c30 100644 --- a/inference-engine/src/mkldnn_plugin/utils/bfloat16.hpp +++ b/inference-engine/src/mkldnn_plugin/utils/bfloat16.hpp @@ -6,7 +6,7 @@ #include #include -#include "nodes/common/emitter.h" +#include /** * The bfloat16_t class can be used as an arithmetic type. All arithmetic operations goes through conversion to the float data type. @@ -73,69 +73,6 @@ class bfloat16_t { uint16_t m_value; }; - -class jit_emu_vcvtneps2bf16 : public jit_emitter { -public: - jit_emu_vcvtneps2bf16(mkldnn::impl::cpu::x64::jit_generator* host, mkldnn::impl::cpu::x64::cpu_isa_t host_isa, const MKLDNNNode* node, - InferenceEngine::Precision exec_prc = InferenceEngine::Precision::BF16) : jit_emitter(host, host_isa, node, exec_prc) { - prepare_table(); - }; - - size_t get_inputs_num() override { return 1; }; - -private: - void emit_impl(const std::vector& in_vec_idxs, const std::vector& out_vec_idxs, - const std::vector& pool_vec_idxs, const std::vector& pool_gpr_idxs, - const emitter_context *emit_context) override { - if (host_isa_ == mkldnn::impl::cpu::x64::cpu_isa_t::avx512_common) { - Xbyak::Zmm in = Xbyak::Zmm(in_vec_idxs[0]); - Xbyak::Ymm out = Xbyak::Ymm(out_vec_idxs[0]); - Xbyak::Zmm aux = Xbyak::Zmm(aux_vec_idxs[0]); - Xbyak::Zmm aux1 = Xbyak::Zmm(aux_vec_idxs[1]); - - h->uni_vpsrld(aux, in, 16); - h->vpandd(aux, aux, table_val("one")); - h->uni_vmovups(aux1, table_val("even")); - h->uni_vpaddd(aux, aux1, aux); - h->uni_vpaddd(aux, in, aux); - h->vfixupimmps(aux, in, table_val("selector"), 0); - h->vpsrad(aux, aux, 16); - h->vpmovdw(out, aux); - } else { - assert(!"unsupported isa"); - } - }; - - - inline int encode_fixup_selector(int input, int output) { - return ((output) << (4 * (input))); - } - - void register_table_entries() override { - enum { - fixup_input_code_qnan_ = 0, - fixup_input_code_snan_ = 1, - fixup_input_code_ninf_ = 4, - fixup_input_code_pinf_ = 5, - fixup_output_code_copy_input_ = 1, - fixup_output_code_qnan_input_ = 2, - }; - const int selector_int32 = - /* qnan input to qnan output (presenrving input bits 0..21) */ - encode_fixup_selector(fixup_input_code_snan_, fixup_output_code_qnan_input_) | - /* snan input to qnan output (presenrving input bits 0..21) */ - encode_fixup_selector(fixup_input_code_qnan_, fixup_output_code_qnan_input_) | - /* neg inf input copied to output */ - encode_fixup_selector(fixup_input_code_ninf_, fixup_output_code_copy_input_) | - /* pos inf input copied to output */ - encode_fixup_selector(fixup_input_code_pinf_, fixup_output_code_copy_input_); - push_arg_entry_of("one", 0x00000001, true); - push_arg_entry_of("even", 0x00007fff, true); - push_arg_entry_of("selector", selector_int32, true); - } - - size_t aux_vecs_count() const override { return 2; } -}; } // namespace MKLDNNPlugin /** diff --git a/inference-engine/src/plugin_api/generic_ie.hpp b/inference-engine/src/plugin_api/generic_ie.hpp deleted file mode 100644 index 2cb48c9995667b..00000000000000 --- a/inference-engine/src/plugin_api/generic_ie.hpp +++ /dev/null @@ -1,137 +0,0 @@ -// Copyright (C) 2018-2020 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#pragma once - -#include -#include -#include -#include - -#include -#include - -#include -#include -#include - -namespace InferenceEngine { - -class IShapeInferExtension; -using IShapeInferExtensionPtr = std::shared_ptr; - -} // namespace InferenceEngine - -namespace ngraph { -namespace op { - -/** - * This generic operation is necessary for legacy scenario. - * If user has old shape inference extensions, this node allow to use it for shape inference - */ -class INFERENCE_ENGINE_API_CLASS(GenericIE) : public Op { -public: - struct PortIE { - InferenceEngine::Precision precision; - std::vector dims; - }; - - class DisableReshape { - public: - explicit DisableReshape(std::vector>& ops) { - for (auto& op : ops) { - addOp(op); - } - } - explicit DisableReshape(const std::shared_ptr& graph) { - IE_ASSERT(graph); - - for (auto& op : graph->get_ops()) { - addOp(op); - } - } - - ~DisableReshape() { - for (auto& generic : genericOps) { - generic->doReshape(true); - } - } - - private: - std::vector> genericOps; - - void addOp(std::shared_ptr& op) { - if (auto generic = std::dynamic_pointer_cast(op)) { - generic->doReshape(false); - genericOps.emplace_back(generic); - } - if (auto ti_node = std::dynamic_pointer_cast(op)) { - auto results = ti_node->get_body()->get_results(); - auto ti_params = ti_node->get_body()->get_parameters(); - ngraph::NodeVector nResults, nParams; - for (const auto& res : results) - nResults.emplace_back(res); - for (const auto& param : ti_params) - nParams.emplace_back(param); - ngraph::traverse_nodes(nResults, [&](std::shared_ptr node) { - if (auto genNode = std::dynamic_pointer_cast(node)) { - genNode->doReshape(false); - genericOps.emplace_back(genNode); - } - }, nParams); - } - } - }; - - static constexpr NodeTypeInfo type_info{"GenericIE", 1}; - const NodeTypeInfo& get_type_info() const override { return type_info; } - - /** - * @brief constructor of generic node - * - * @param inputs vector of inputs - * @param params map of parameters (std::string, Blob::Ptr, Blob::CPtr) - * @param type string with original layer type - * @param outputs information about output ports from IR - */ - GenericIE(const OutputVector& inputs, - const std::map& params, - const std::string type, - const std::vector& outputs); - - void validate_and_infer_types() override; - - std::shared_ptr clone_with_new_inputs(const OutputVector& new_args) const override; - - bool visit_attributes(ngraph::AttributeVisitor& visitor) override; - - static void addExtension(std::shared_ptr func, const InferenceEngine::IShapeInferExtensionPtr& ext); - static std::vector getExtensions(std::shared_ptr func); - - const std::string& getType() const { - return type; - } - - const std::map& getParameters() const { - return params; - } - -private: - void doReshape(bool flag) { - reshape = flag; - } - - std::vector extensions; - bool reshape = true; - std::map params; - std::vector outputs; - std::string type; - int initialized; - - void addExtension(const InferenceEngine::IShapeInferExtensionPtr& ext); - std::vector getExtensions(); -}; - -} // namespace op -} // namespace ngraph 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 6eb27e4fdd7320..8fb24e18db072e 100644 --- a/inference-engine/src/readers/ir_reader/ie_ir_parser.cpp +++ b/inference-engine/src/readers/ir_reader/ie_ir_parser.cpp @@ -29,7 +29,6 @@ #include "ie_blob_stream.hpp" #include "caseless.hpp" #include -#include "generic_ie.hpp" #include "precision_utils.h" #include "blob_factory.hpp" @@ -350,7 +349,7 @@ void V10Parser::XmlDeserializer::on_adapter(const std::string& name, ngraph::Val } } else { THROW_IE_EXCEPTION << "Error IR reading. Attribute adapter can not be found for " << name - << " parameter"; + << " parameter"; } } @@ -367,8 +366,6 @@ void V10Parser::XmlDeserializer::on_adapter(const std::string& name, ngraph::Val } else { THROW_IE_EXCEPTION << "Error: not recognized adapter name: " << name << "."; } - // Disabled reshape for generic operations in the TI body - ngraph::op::GenericIE::DisableReshape noReshape(ngraph_function); adapter.set(ngraph_function); } @@ -392,7 +389,7 @@ std::shared_ptr V10Parser::XmlDeserializer::parse_function(con // 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()) + if (opName.find(node_param.name) != opName.end() && node_param.type != "Result") THROW_IE_EXCEPTION << "Invalid IR! " << node_param.name << " name is not unique!"; opName.insert(node_param.name); params[node_param.layerId] = {node, node_param}; @@ -490,7 +487,6 @@ std::shared_ptr V10Parser::XmlDeserializer::parse_function(con OV_ITT_TASK_NEXT(taskChain, "ConstructNgraphFunction"); - ::ngraph::op::GenericIE::DisableReshape noReshape(allNodes); auto function = std::make_shared(result_nodes, sink_nodes, parameter_nodes, GetStrAttr(root, "name", "")); for (const auto& sink : sink_nodes) { if (const auto& assign = std::dynamic_pointer_cast(sink)) { @@ -764,7 +760,7 @@ std::shared_ptr V10Parser::XmlDeserializer::createNode( std::shared_ptr ngraphNode; - // Find registerd opset + // Find registered opset auto opsetIt = opsets.find(params.version); // Try to create operation from loaded opsets @@ -818,52 +814,6 @@ std::shared_ptr V10Parser::XmlDeserializer::createNode( ngraphNode = ngraphNode->clone_with_new_inputs(ngraphNode->input_values()); } - // Create GenericIE operation for backward compatibility - if (!ngraphNode && (params.version == "experimental" || params.version == "extension")) { - // Try to create Generic node for backward compatibility - std::map parameters; - pugi::xml_node dn = node.child("data"); - if (dn) { - for (const auto& attr : dn.attributes()) { - parameters[attr.name()] = std::string(attr.value()); - } - } - - auto blobs = node.child("blobs"); - if (!blobs.empty()) { - size_t length = weights->byteSize(); - - for (pugi::xml_node blob = blobs.first_child(); !blob.empty(); blob = blob.next_sibling()) { - size_t size = GetUInt64Attr(blob, "size", 0); - uint64_t offset = GetUInt64Attr(blob, "offset", 0); - Precision precision(Precision::U8); - const std::string& preStr = GetStrAttr(blob, "precision", ""); - if (!preStr.empty()) - precision = Precision::FromStr(preStr); - if (!size) continue; - if (!length) - THROW_IE_EXCEPTION << "Cannot read network! The model requires weights data! " - << "Bin file cannot be found! Please specify the path to bin file."; - if (static_cast(length) < offset + size) - THROW_IE_EXCEPTION << "Cannot create " << params.type << " layer with name: " << params.name - << ". Layer has incorrect weights!"; - uint8_t* data = weights->cbuffer().as() + offset; - Blob::Ptr wBlob = make_shared_blob({Precision::U8, { size / precision.size() }, C }, data); - - parameters[blob.name()] = wBlob; - } - } - std::vector outputs; - for (const auto& port : params.outputPorts) { - ngraph::op::GenericIE::PortIE iePort; - iePort.dims = port.dims; - iePort.precision = InferenceEngine::details::convertPrecision(port.precision); - outputs.emplace_back(iePort); - } - - ngraphNode = std::make_shared(inputs, parameters, params.type, outputs); - } - if (!ngraphNode) { THROW_IE_EXCEPTION << "Cannot create " << params.type << " layer " << params.name << " id:" << params.layerId << " from unsupported opset: " << params.version; 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 3fb46097fb6e89..cccab9038b8710 100644 --- a/inference-engine/src/readers/ir_reader/ie_ir_parser.hpp +++ b/inference-engine/src/readers/ir_reader/ie_ir_parser.hpp @@ -68,7 +68,6 @@ class V10Parser : public IParser { struct GenericLayerParams { struct LayerPortData { size_t portId; - // Precision and dimensions are needed only for GenericIE op ngraph::element::Type_t precision; SizeVector dims; std::unordered_set names; diff --git a/inference-engine/src/transformations/include/transformations/serialize.hpp b/inference-engine/src/transformations/include/transformations/serialize.hpp index e5cbc3ee075e6b..12395d7da4efd1 100644 --- a/inference-engine/src/transformations/include/transformations/serialize.hpp +++ b/inference-engine/src/transformations/include/transformations/serialize.hpp @@ -22,7 +22,6 @@ class TRANSFORMATIONS_API Serialize; * @brief Serialize transformation converts ngraph::Function into IR files * @attention * - dynamic shapes are not supported - * - GenericIE operation type (experimental opset) is not supported * - order of generated layers in xml file is ngraph specific (given by * get_ordered_ops()); MO generates file with different order, but they are * logically equivalent diff --git a/inference-engine/src/transformations/src/transformations/convert_precision.cpp b/inference-engine/src/transformations/src/transformations/convert_precision.cpp index e4b3d83378f7a9..0492bd4a9759d6 100644 --- a/inference-engine/src/transformations/src/transformations/convert_precision.cpp +++ b/inference-engine/src/transformations/src/transformations/convert_precision.cpp @@ -29,7 +29,6 @@ bool fuse_type_to_nms5(std::shared_ptr & node, ngraph::element::Ty bool fuse_type_to_topk(std::shared_ptr & node, ngraph::element::Type to, size_t idx); bool fuse_type_to_nonzero(std::shared_ptr & node, ngraph::element::Type to, size_t idx); bool fuse_type_to_bucketize(std::shared_ptr & node, ngraph::element::Type to, size_t idx); -bool fuse_type_to_generic_ie(std::shared_ptr & node, ngraph::element::Type to, size_t idx); bool extend_select_type(std::shared_ptr & node, ngraph::element::Type to, size_t idx); @@ -91,7 +90,6 @@ bool ngraph::pass::ConvertPrecision::run_on_function(std::shared_ptr}, {opset4::NotEqual::type_info, fuse_type_to_binary_comparision}, {opset4::Greater::type_info, fuse_type_to_binary_comparision}, @@ -282,12 +280,6 @@ bool fuse_type_to_bucketize(std::shared_ptr & node, ngraph::elemen return false; } -bool fuse_type_to_generic_ie(std::shared_ptr & node, ngraph::element::Type to, size_t idx) { - node->set_output_type(idx, to, node->output(idx).get_partial_shape()); - // return false as we do not replace original node - return false; -} - bool fuse_type_to_shapeof_v0(std::shared_ptr & node, ngraph::element::Type to, size_t idx) { if (auto type_relaxed = std::dynamic_pointer_cast(node)) { type_relaxed->set_overridden_output_type(to); diff --git a/inference-engine/src/transformations/src/transformations/serialize.cpp b/inference-engine/src/transformations/src/transformations/serialize.cpp index c14feb751a7a80..2b97a83f7919b2 100644 --- a/inference-engine/src/transformations/src/transformations/serialize.cpp +++ b/inference-engine/src/transformations/src/transformations/serialize.cpp @@ -267,16 +267,8 @@ class XmlSerializer : public ngraph::AttributeVisitor { } void on_adapter(const std::string& name, ngraph::ValueAccessor& adapter) override { - if ((m_node_type_name == "GenericIE") && - (name == "__generic_ie_type__")) { - // __generic_ie_type__ in GenericIE should not be serialized as a - // since it's purpose is to hold name of the layer type - // it is a WA to not introduce dependency on plugin_api library - m_node_type_name = adapter.get(); - } else { - m_xml_node.append_attribute(name.c_str()) - .set_value(adapter.get().c_str()); - } + m_xml_node.append_attribute(name.c_str()) + .set_value(adapter.get().c_str()); } void on_adapter(const std::string& name, ngraph::ValueAccessor& adapter) override { 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 b757f3bd486cbc..558e4ca9dd78f3 100644 --- a/inference-engine/src/vpu/graph_transformer/src/frontend/frontend.cpp +++ b/inference-engine/src/vpu/graph_transformer/src/frontend/frontend.cpp @@ -20,7 +20,6 @@ #include #include -#include #include #include #include @@ -164,8 +163,6 @@ ModelPtr FrontEnd::buildInitialModel(const ie::CNNNetwork& network) { ie::CNNNetwork FrontEnd::convertNetwork(ie::CNNNetwork& network) { auto nGraphFunc = network.getFunction(); - // Disable shape inference (WA for generic operations) - ngraph::op::GenericIE::DisableReshape noReshape(nGraphFunc); ngraph::pass::Manager manager; manager.register_pass<::ngraph::pass::InitNodeInfo>(); 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 cb7f88ff275cf0..1007cde8e62b18 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 @@ -4,12 +4,11 @@ #include "vpu/utils/runtime_graph.hpp" -#include "generic_ie.hpp" - #include #include #include #include +#include #include #include diff --git a/inference-engine/src/vpu/myriad_plugin/myriad_plugin.cpp b/inference-engine/src/vpu/myriad_plugin/myriad_plugin.cpp index ccffb14539b8ba..7f6d6f5e1bb84a 100644 --- a/inference-engine/src/vpu/myriad_plugin/myriad_plugin.cpp +++ b/inference-engine/src/vpu/myriad_plugin/myriad_plugin.cpp @@ -21,8 +21,6 @@ #include #include -#include "generic_ie.hpp" - #include "myriad_plugin.h" using namespace InferenceEngine; diff --git a/inference-engine/tests/functional/inference_engine/CMakeLists.txt b/inference-engine/tests/functional/inference_engine/CMakeLists.txt index a2ed13cb63ebee..fcfd945c5ca8ba 100644 --- a/inference-engine/tests/functional/inference_engine/CMakeLists.txt +++ b/inference-engine/tests/functional/inference_engine/CMakeLists.txt @@ -206,13 +206,11 @@ endif() # ie_headers_compilation_with_custom_flags(TEST_SUFFIX PluginApiCxx17 - HEADERS_TO_SKIP "generic_ie.hpp" CXX_STANDARD 17 PLUGIN_API) if(UNIX) if(CMAKE_CXX_COMPILER_ID STREQUAL "Intel") ie_headers_compilation_with_custom_flags(TEST_SUFFIX PluginApiWarningsAreErrors - HEADERS_TO_SKIP "generic_ie.hpp" FLAGS "-Werror-all -Werror -Wall" PLUGIN_API) else() diff --git a/inference-engine/tests/functional/inference_engine/cnn_network/cnn_ngraph_impl_tests.cpp b/inference-engine/tests/functional/inference_engine/cnn_network/cnn_ngraph_impl_tests.cpp index 6480bd219d2765..7f85e8abcb8a1b 100644 --- a/inference-engine/tests/functional/inference_engine/cnn_network/cnn_ngraph_impl_tests.cpp +++ b/inference-engine/tests/functional/inference_engine/cnn_network/cnn_ngraph_impl_tests.cpp @@ -17,7 +17,6 @@ #include #include #include -#include #include #include #include @@ -1438,8 +1437,6 @@ TEST(CNNNGraphImplTests, SaveOriginalResultNameForMultiOutputOp) { } auto nGraphFunc = network.getFunction(); - // Disable shape inference (WA for generic operations) - ngraph::op::GenericIE::DisableReshape noReshape(nGraphFunc); ngraph::pass::Manager manager; @@ -1630,8 +1627,6 @@ TEST(CNNNGraphImplTests, SaveOriginalResultNameForMultiOutputOpOpset6) { } auto nGraphFunc = network.getFunction(); - // Disable shape inference (WA for generic operations) - ngraph::op::GenericIE::DisableReshape noReshape(nGraphFunc); ngraph::pass::Manager manager; diff --git a/inference-engine/tests/functional/inference_engine/ir_serialization/models/add_abc_initializers_nan_const.bin b/inference-engine/tests/functional/inference_engine/ir_serialization/models/add_abc_initializers_nan_const.bin new file mode 100644 index 00000000000000..16a41a06ca8aa9 Binary files /dev/null and b/inference-engine/tests/functional/inference_engine/ir_serialization/models/add_abc_initializers_nan_const.bin differ diff --git a/inference-engine/tests/functional/inference_engine/ir_serialization/models/add_abc_initializers_nan_const.xml b/inference-engine/tests/functional/inference_engine/ir_serialization/models/add_abc_initializers_nan_const.xml new file mode 100644 index 00000000000000..c0ecd4025c550c --- /dev/null +++ b/inference-engine/tests/functional/inference_engine/ir_serialization/models/add_abc_initializers_nan_const.xml @@ -0,0 +1,93 @@ + + + + + + + + 2 + 2 + + + + + + + + 2 + 2 + + + + + + + 2 + 2 + + + 2 + 2 + + + + + 2 + 2 + + + + + + + 2 + 2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/inference-engine/tests/functional/inference_engine/ir_serialization/serialize.cpp b/inference-engine/tests/functional/inference_engine/ir_serialization/serialize.cpp index 067ed94bc7dc06..254622157ad7f0 100644 --- a/inference-engine/tests/functional/inference_engine/ir_serialization/serialize.cpp +++ b/inference-engine/tests/functional/inference_engine/ir_serialization/serialize.cpp @@ -64,6 +64,7 @@ INSTANTIATE_TEST_CASE_P(IRSerialization, SerializationTest, std::make_tuple("split_equal_parts_2d.xml", "split_equal_parts_2d.bin"), std::make_tuple("addmul_abc.xml", "addmul_abc.bin"), std::make_tuple("add_abc_initializers.xml", "add_abc_initializers.bin"), + std::make_tuple("add_abc_initializers_nan_const.xml", "add_abc_initializers_nan_const.bin"), std::make_tuple("experimental_detectron_roi_feature_extractor.xml", ""), std::make_tuple("experimental_detectron_roi_feature_extractor_opset6.xml", ""), std::make_tuple("experimental_detectron_detection_output.xml", ""), diff --git a/inference-engine/tests/functional/inference_engine/keep_constant_inputs_tests.cpp b/inference-engine/tests/functional/inference_engine/keep_constant_inputs_tests.cpp index ca0399088ce408..54c8391fe79aa8 100644 --- a/inference-engine/tests/functional/inference_engine/keep_constant_inputs_tests.cpp +++ b/inference-engine/tests/functional/inference_engine/keep_constant_inputs_tests.cpp @@ -20,7 +20,6 @@ #include #include #include -#include "generic_ie.hpp" #include "shared_test_classes/base/low_precision_transformations/layer_transformation.hpp" using namespace testing; diff --git a/inference-engine/tests/functional/inference_engine/net_reader_test.cpp b/inference-engine/tests/functional/inference_engine/net_reader_test.cpp index 017c0a69de6389..6c4cb650ed8cf2 100644 --- a/inference-engine/tests/functional/inference_engine/net_reader_test.cpp +++ b/inference-engine/tests/functional/inference_engine/net_reader_test.cpp @@ -167,7 +167,7 @@ TEST(NetReaderTest, IRSupportModelDetection) { - + 1 diff --git a/inference-engine/tests/functional/inference_engine/ngraph_reader/non_max_suppression_tests.cpp b/inference-engine/tests/functional/inference_engine/ngraph_reader/non_max_suppression_tests.cpp index 6be17382380800..2068296fc61a21 100644 --- a/inference-engine/tests/functional/inference_engine/ngraph_reader/non_max_suppression_tests.cpp +++ b/inference-engine/tests/functional/inference_engine/ngraph_reader/non_max_suppression_tests.cpp @@ -17,7 +17,6 @@ #include #include "common_test_utils/ngraph_test_utils.hpp" -#include "generic_ie.hpp" #include "legacy/convert_function_to_cnn_network.hpp" diff --git a/inference-engine/tests/functional/inference_engine/ngraph_reader/proposal_tests.cpp b/inference-engine/tests/functional/inference_engine/ngraph_reader/proposal_tests.cpp index 958cdd46e1b9e8..ef47afe343ade9 100644 --- a/inference-engine/tests/functional/inference_engine/ngraph_reader/proposal_tests.cpp +++ b/inference-engine/tests/functional/inference_engine/ngraph_reader/proposal_tests.cpp @@ -3,7 +3,6 @@ // #include -#include #include "ngraph/opsets/opset6.hpp" #include "ngraph_reader_tests.hpp" TEST_F(NGraphReaderTests, ReadProposalNetwork) { @@ -405,4 +404,4 @@ TEST_F(NGraphReaderTests, ReadExtensionProposalNetwork) { } } FAIL() << "Custom proposal layer is not an opset6 operation."; -} \ No newline at end of file +} 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 3ec3d1ada7743c..2c4a0b5c006bcb 100644 --- a/inference-engine/tests/functional/inference_engine/ngraph_reshape_tests.cpp +++ b/inference-engine/tests/functional/inference_engine/ngraph_reshape_tests.cpp @@ -30,7 +30,6 @@ #include "common_test_utils/data_utils.hpp" #include "common_test_utils/file_utils.hpp" #include "common_test_utils/common_utils.hpp" -#include "generic_ie.hpp" IE_SUPPRESS_DEPRECATED_START diff --git a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/low_precision_transformations/layer_transformation.cpp b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/low_precision_transformations/layer_transformation.cpp index bcdda383cf0d93..eb99a23efc8b92 100644 --- a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/low_precision_transformations/layer_transformation.cpp +++ b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/low_precision_transformations/layer_transformation.cpp @@ -10,7 +10,6 @@ #include #include -#include "generic_ie.hpp" #include #include @@ -79,8 +78,6 @@ InferenceEngine::CNNNetwork convert(std::shared_ptr function) std::dynamic_pointer_cast(node); }; auto nGraphFunc = clonedNetwork.getFunction(); - // Disable shape inference (WA for generic operations) - ::ngraph::op::GenericIE::DisableReshape noReshape(nGraphFunc); // Note: instead of running all Conversion Transformations you can make up your own transformation pipeline ngraph::pass::Manager manager; 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 01a33ad0c67033..a1567cac2c1dc0 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 @@ -59,6 +59,8 @@ std::vector disabledTestPatterns() { R"(.*Broadcast.*mode=BIDIRECTIONAL.*inNPrec=BOOL.*)", // TODO: Issue 43417 sporadic issue, looks like an issue in test, reproducible only on Windows platform R"(.*decomposition1_batch=5_hidden_size=10_input_size=30_.*tanh.relu.*_clip=0_linear_before_reset=1.*_targetDevice=CPU_.*)", + // Skip platforms that do not support BF16 (i.e. sse, avx, avx2) + R"(.*BF16.*(jit_avx(?!5)|jit_sse).*)", }; if (!InferenceEngine::with_cpu_x86_avx512_core()) { diff --git a/inference-engine/tests/functional/plugin/cpu/single_layer_tests/pooling.cpp b/inference-engine/tests/functional/plugin/cpu/single_layer_tests/pooling.cpp new file mode 100644 index 00000000000000..9b0021365947fa --- /dev/null +++ b/inference-engine/tests/functional/plugin/cpu/single_layer_tests/pooling.cpp @@ -0,0 +1,235 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "ngraph_functions/builders.hpp" +#include "test_utils/cpu_test_utils.hpp" +#include "shared_test_classes/single_layer/pooling.hpp" + +using namespace InferenceEngine; +using namespace CPUTestUtils; +using namespace LayerTestsDefinitions; + +namespace CPULayerTestsDefinitions { +typedef std::tuple< + poolLayerTestParamsSet, + CPUSpecificParams +> poolLayerCpuTestParamsSet; + +class PoolingLayerCPUTest : public testing::WithParamInterface, + virtual public LayerTestsUtils::LayerTestsCommon, public CPUTestsBase { +public: + static std::string getTestCaseName(const testing::TestParamInfo& obj) { + poolLayerTestParamsSet basicParamsSet; + CPUSpecificParams cpuParams; + std::tie(basicParamsSet, cpuParams) = obj.param; + + std::ostringstream result; + result << PoolingLayerTest::getTestCaseName(testing::TestParamInfo( + basicParamsSet, 0)); + result << CPUTestsBase::getTestCaseName(cpuParams); + + return result.str(); + } + +protected: + void SetUp() { + poolLayerTestParamsSet basicParamsSet; + CPUSpecificParams cpuParams; + std::tie(basicParamsSet, cpuParams) = this->GetParam(); + + poolSpecificParams poolParams; + std::vector inputShape; + InferenceEngine::Precision netPrecision; + std::tie(poolParams, netPrecision, inPrc, outPrc, inLayout, outLayout, inputShape, targetDevice) = basicParamsSet; + + if (outPrc == Precision::UNSPECIFIED) { + outPrc = inPrc; + } + + std::tie(inFmts, outFmts, priority, selectedType) = cpuParams; + + if (selectedType.empty()) { + selectedType = getPrimitiveType(); + } + + selectedType = selectedType + "_" + inPrc.name(); + + ngraph::helpers::PoolingTypes poolType; + std::vector kernel, stride; + std::vector padBegin, padEnd; + ngraph::op::PadType padType; + ngraph::op::RoundingType roundingType; + bool excludePad; + std::tie(poolType, kernel, stride, padBegin, padEnd, roundingType, padType, excludePad) = poolParams; + + auto ngPrc = FuncTestUtils::PrecisionUtils::convertIE2nGraphPrc(netPrecision); + auto params = ngraph::builder::makeParams(ngPrc, {inputShape}); + auto paramOuts = ngraph::helpers::convert2OutputVector( + ngraph::helpers::castOps2Nodes(params)); + + std::shared_ptr pooling = ngraph::builder::makePooling(paramOuts[0], + stride, + padBegin, + padEnd, + kernel, + roundingType, + padType, + excludePad, + poolType); + + + function = makeNgraphFunction(ngPrc, params, pooling, "Pooling"); + } +}; + +TEST_P(PoolingLayerCPUTest, CompareWithRefs) { + SKIP_IF_CURRENT_TEST_IS_DISABLED() + + Run(); + CheckPluginRelatedResults(executableNetwork, "Pooling"); +} + +namespace { +const auto avx512 = CPUSpecificParams{{}, {}, {"jit_avx512"}, "jit_avx512"}; +const auto avx = CPUSpecificParams{{}, {}, {"jit_avx"}, "jit_avx"}; +const auto sse42 = CPUSpecificParams{{}, {}, {"jit_sse42"}, "jit_sse42"}; +const auto ref = CPUSpecificParams{{}, {}, {"ref_any"}, "ref_any"}; + +const std::vector vecCpuConfigs = {ref, sse42, avx, avx512}; +const std::vector inpOutPrecision = {Precision::FP32, Precision::BF16}; + +const std::vector paramsMax4D = { + poolSpecificParams{ ngraph::helpers::PoolingTypes::MAX, {2, 2}, {2, 2}, {0, 0}, {0, 0}, + ngraph::op::RoundingType::CEIL, ngraph::op::PadType::EXPLICIT, false }, + poolSpecificParams{ ngraph::helpers::PoolingTypes::MAX, {4, 2}, {2, 2}, {0, 0}, {0, 0}, + ngraph::op::RoundingType::CEIL, ngraph::op::PadType::EXPLICIT, false }, + poolSpecificParams{ ngraph::helpers::PoolingTypes::MAX, {4, 2}, {2, 1}, {0, 0}, {0, 0}, + ngraph::op::RoundingType::CEIL, ngraph::op::PadType::EXPLICIT, false }, +}; + +const std::vector paramsAvg4D = { + poolSpecificParams{ ngraph::helpers::PoolingTypes::AVG, {2, 2}, {2, 2}, {1, 0}, {0, 0}, + ngraph::op::RoundingType::CEIL, ngraph::op::PadType::SAME_UPPER, false }, + poolSpecificParams{ ngraph::helpers::PoolingTypes::AVG, {2, 2}, {2, 2}, {0, 0}, {0, 0}, + ngraph::op::RoundingType::CEIL, ngraph::op::PadType::EXPLICIT, true }, + poolSpecificParams{ ngraph::helpers::PoolingTypes::AVG, {4, 4}, {4, 4}, {2, 2}, {2, 2}, + ngraph::op::RoundingType::CEIL, ngraph::op::PadType::EXPLICIT, true }, +}; + +const std::vector paramsAvg4D_RefOnly = { + poolSpecificParams{ ngraph::helpers::PoolingTypes::AVG, {2, 2}, {2, 2}, {2, 2}, {2, 2}, + ngraph::op::RoundingType::CEIL, ngraph::op::PadType::EXPLICIT, false }, +}; + +INSTANTIATE_TEST_CASE_P(smoke_MaxPool_CPU_4D, PoolingLayerCPUTest, + ::testing::Combine( + ::testing::Combine( + ::testing::ValuesIn(paramsMax4D), + ::testing::Values(Precision::FP32), + ::testing::ValuesIn(inpOutPrecision), + ::testing::Values(InferenceEngine::Precision::UNSPECIFIED), + ::testing::Values(InferenceEngine::Layout::ANY), + ::testing::Values(InferenceEngine::Layout::ANY), + ::testing::Values(std::vector({1, 3, 64, 64})), + ::testing::Values(CommonTestUtils::DEVICE_CPU)), + ::testing::ValuesIn(filterCPUInfoForDevice(vecCpuConfigs))), + PoolingLayerCPUTest::getTestCaseName); + +INSTANTIATE_TEST_CASE_P(smoke_AvgPool_CPU_4D, PoolingLayerCPUTest, + ::testing::Combine( + ::testing::Combine( + ::testing::ValuesIn(paramsAvg4D), + ::testing::Values(Precision::FP32), + ::testing::ValuesIn(inpOutPrecision), + ::testing::Values(InferenceEngine::Precision::UNSPECIFIED), + ::testing::Values(InferenceEngine::Layout::ANY), + ::testing::Values(InferenceEngine::Layout::ANY), + ::testing::Values(std::vector({1, 4, 64, 64})), + ::testing::Values(CommonTestUtils::DEVICE_CPU)), + ::testing::ValuesIn(filterCPUInfoForDevice(vecCpuConfigs))), + PoolingLayerCPUTest::getTestCaseName); + +INSTANTIATE_TEST_CASE_P(smoke_AvgPool_CPU_4D_NotOptimized, PoolingLayerCPUTest, + ::testing::Combine( + ::testing::Combine( + ::testing::ValuesIn(paramsAvg4D_RefOnly), + ::testing::Values(Precision::FP32), + ::testing::ValuesIn(inpOutPrecision), + ::testing::Values(InferenceEngine::Precision::UNSPECIFIED), + ::testing::Values(InferenceEngine::Layout::ANY), + ::testing::Values(InferenceEngine::Layout::ANY), + ::testing::Values(std::vector({1, 4, 64, 64})), + ::testing::Values(CommonTestUtils::DEVICE_CPU)), + ::testing::Values(ref)), + PoolingLayerCPUTest::getTestCaseName); + +const std::vector paramsMax5D = { + poolSpecificParams{ ngraph::helpers::PoolingTypes::MAX, {2, 2, 2}, {1, 1, 1}, {0, 0, 0}, {0, 0, 0}, + ngraph::op::RoundingType::CEIL, ngraph::op::PadType::EXPLICIT, false }, + poolSpecificParams{ ngraph::helpers::PoolingTypes::MAX, {2, 2, 2}, {1, 1, 1}, {1, 1, 1}, {1, 1, 1}, + ngraph::op::RoundingType::CEIL, ngraph::op::PadType::EXPLICIT, false }, + poolSpecificParams{ ngraph::helpers::PoolingTypes::MAX, {2, 3, 4}, {2, 2, 2}, {1, 1, 1}, {1, 2, 3}, + ngraph::op::RoundingType::CEIL, ngraph::op::PadType::EXPLICIT, false }, +}; + +const std::vector paramsAvg5D = { + poolSpecificParams{ ngraph::helpers::PoolingTypes::AVG, {2, 2, 2}, {2, 2, 2}, {1, 0, 0}, {0, 0, 0}, + ngraph::op::RoundingType::CEIL, ngraph::op::PadType::SAME_UPPER, false }, + poolSpecificParams{ ngraph::helpers::PoolingTypes::AVG, {2, 2, 2}, {2, 2, 2}, {0, 0, 0}, {0, 0, 0}, + ngraph::op::RoundingType::CEIL, ngraph::op::PadType::EXPLICIT, true }, + poolSpecificParams{ ngraph::helpers::PoolingTypes::AVG, {3, 3, 3}, {3, 3, 3}, {1, 1, 1}, {0, 0, 0}, + ngraph::op::RoundingType::CEIL, ngraph::op::PadType::EXPLICIT, true }, + poolSpecificParams{ ngraph::helpers::PoolingTypes::AVG, {4, 4, 4}, {4, 4, 4}, {2, 2, 2}, {2, 2, 2}, + ngraph::op::RoundingType::CEIL, ngraph::op::PadType::EXPLICIT, true }, +}; + +const std::vector paramsAvg5D_RefOnly = { + poolSpecificParams{ ngraph::helpers::PoolingTypes::AVG, {2, 2, 2}, {2, 2, 2}, {2, 2, 2}, {2, 2, 2}, + ngraph::op::RoundingType::CEIL, ngraph::op::PadType::EXPLICIT, false }, +}; + +INSTANTIATE_TEST_CASE_P(smoke_MaxPool_CPU_5D, PoolingLayerCPUTest, + ::testing::Combine( + ::testing::Combine( + ::testing::ValuesIn(paramsMax5D), + ::testing::Values(Precision::FP32), + ::testing::ValuesIn(inpOutPrecision), + ::testing::Values(InferenceEngine::Precision::UNSPECIFIED), + ::testing::Values(InferenceEngine::Layout::ANY), + ::testing::Values(InferenceEngine::Layout::ANY), + ::testing::Values(std::vector({1, 3, 16, 32, 32})), + ::testing::Values(CommonTestUtils::DEVICE_CPU)), + ::testing::ValuesIn(filterCPUInfoForDevice(vecCpuConfigs))), + PoolingLayerCPUTest::getTestCaseName); + +INSTANTIATE_TEST_CASE_P(smoke_AvgPool_CPU_5D, PoolingLayerCPUTest, + ::testing::Combine( + ::testing::Combine( + ::testing::ValuesIn(paramsAvg5D), + ::testing::Values(Precision::FP32), + ::testing::ValuesIn(inpOutPrecision), + ::testing::Values(InferenceEngine::Precision::UNSPECIFIED), + ::testing::Values(InferenceEngine::Layout::ANY), + ::testing::Values(InferenceEngine::Layout::ANY), + ::testing::Values(std::vector({1, 4, 32, 32, 32})), + ::testing::Values(CommonTestUtils::DEVICE_CPU)), + ::testing::ValuesIn(filterCPUInfoForDevice(vecCpuConfigs))), + PoolingLayerCPUTest::getTestCaseName); + +INSTANTIATE_TEST_CASE_P(smoke_AvgPool_CPU_5D_NotOptimized, PoolingLayerCPUTest, + ::testing::Combine( + ::testing::Combine( + ::testing::ValuesIn(paramsAvg5D_RefOnly), + ::testing::Values(Precision::FP32), + ::testing::ValuesIn(inpOutPrecision), + ::testing::Values(InferenceEngine::Precision::UNSPECIFIED), + ::testing::Values(InferenceEngine::Layout::ANY), + ::testing::Values(InferenceEngine::Layout::ANY), + ::testing::Values(std::vector({1, 4, 16, 16, 16})), + ::testing::Values(CommonTestUtils::DEVICE_CPU)), + ::testing::Values(ref)), + PoolingLayerCPUTest::getTestCaseName); + +} // namespace +} // namespace CPULayerTestsDefinitions \ No newline at end of file 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 9dda82530874f9..98613d8de1d2f5 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 @@ -260,6 +260,8 @@ std::vector filterCPUInfoForDevice(std::vector #include -#include "generic_ie.hpp" #include #include @@ -112,8 +111,6 @@ InferenceEngine::CNNNetwork convert(std::shared_ptr function) std::dynamic_pointer_cast(node); }; auto nGraphFunc = clonedNetwork.getFunction(); - // Disable shape inference (WA for generic operations) - ::ngraph::op::GenericIE::DisableReshape noReshape(nGraphFunc); // Note: instead of running all Conversion Transformations you can make up your own transformation pipeline ngraph::pass::Manager manager; diff --git a/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/single_layer_tests/ctc_greedy_decoder.cpp b/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/single_layer_tests/ctc_greedy_decoder.cpp index e0664e1951c363..75189f84024a28 100644 --- a/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/single_layer_tests/ctc_greedy_decoder.cpp +++ b/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/single_layer_tests/ctc_greedy_decoder.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020 Intel Corporation +// Copyright (C) 2020-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // @@ -10,24 +10,31 @@ using namespace LayerTestsDefinitions; using namespace ngraph::helpers; namespace { - // Common params - const std::vector netPrecisions = { - InferenceEngine::Precision::FP32, - InferenceEngine::Precision::FP16 - }; +// Common params +const std::vector netPrecisions = { + InferenceEngine::Precision::FP32, + InferenceEngine::Precision::FP16 +}; +std::vector mergeRepeated{true, false}; - const auto basicCases = ::testing::Combine( - ::testing::ValuesIn(netPrecisions), - ::testing::Values(InferenceEngine::Precision::UNSPECIFIED), - ::testing::Values(InferenceEngine::Precision::UNSPECIFIED), - ::testing::Values(InferenceEngine::Layout::ANY), - ::testing::Values(InferenceEngine::Layout::ANY), - ::testing::Values(std::vector({ 10, 1, 16 }), - std::vector({ 20, 2, 8 })), - ::testing::Values(true, false), - ::testing::Values(CommonTestUtils::DEVICE_GPU)); +const auto basicCases = ::testing::Combine( + ::testing::ValuesIn(netPrecisions), + ::testing::Values(InferenceEngine::Precision::UNSPECIFIED), + ::testing::Values(InferenceEngine::Precision::UNSPECIFIED), + ::testing::Values(InferenceEngine::Layout::ANY), + ::testing::Values(InferenceEngine::Layout::ANY), + ::testing::Values(std::vector({ 50, 3, 3 }), + std::vector({ 50, 3, 7 }), + std::vector({ 50, 3, 8 }), + std::vector({ 50, 3, 16 }), + std::vector({ 50, 3, 128 }), + std::vector({ 50, 3, 49 }), + std::vector({ 50, 3, 55 }), + std::vector({ 1, 1, 16 })), + ::testing::ValuesIn(mergeRepeated), + ::testing::Values(CommonTestUtils::DEVICE_GPU)); - INSTANTIATE_TEST_CASE_P(smoke_CTC_Greedy_decoder_Basic, CTCGreedyDecoderLayerTest, - basicCases, - CTCGreedyDecoderLayerTest::getTestCaseName); +INSTANTIATE_TEST_CASE_P(smoke_CtcGreedyDecoderBasic, CTCGreedyDecoderLayerTest, + basicCases, + CTCGreedyDecoderLayerTest::getTestCaseName); } // namespace diff --git a/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/single_layer_tests/ctc_greedy_decoder_seq_len.cpp b/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/single_layer_tests/ctc_greedy_decoder_seq_len.cpp new file mode 100644 index 00000000000000..92d0324bbb941e --- /dev/null +++ b/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/single_layer_tests/ctc_greedy_decoder_seq_len.cpp @@ -0,0 +1,50 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include +#include "single_layer_tests/ctc_greedy_decoder_seq_len.hpp" +#include "common_test_utils/test_constants.hpp" + +using namespace LayerTestsDefinitions; +using namespace ngraph::helpers; + +namespace { + +std::vector> inputShape{{1, 1, 1}, {1, 6, 10}, {3, 3, 16}, {5, 3, 55}}; + +const std::vector probPrecisions = { + InferenceEngine::Precision::FP32, + InferenceEngine::Precision::FP16 +}; +const std::vector idxPrecisions = { + InferenceEngine::Precision::I32, + InferenceEngine::Precision::I64 +}; + +std::vector mergeRepeated{true, false}; + +const auto basicCases = ::testing::Combine( + ::testing::ValuesIn(inputShape), + ::testing::Values(10), + ::testing::ValuesIn(probPrecisions), + ::testing::ValuesIn(idxPrecisions), + ::testing::Values(0), + ::testing::ValuesIn(mergeRepeated), + ::testing::Values(CommonTestUtils::DEVICE_GPU)); + +INSTANTIATE_TEST_CASE_P(smoke_set1, CTCGreedyDecoderSeqLenLayerTest, + basicCases, + CTCGreedyDecoderSeqLenLayerTest::getTestCaseName); + +INSTANTIATE_TEST_CASE_P(smoke_set2, CTCGreedyDecoderSeqLenLayerTest, + ::testing::Combine( + ::testing::ValuesIn(std::vector>{{2, 8, 11}, {4, 10, 55}}), + ::testing::ValuesIn(std::vector{5, 100}), + ::testing::ValuesIn(probPrecisions), + ::testing::ValuesIn(idxPrecisions), + ::testing::ValuesIn(std::vector{0, 5, 10}), + ::testing::ValuesIn(mergeRepeated), + ::testing::Values(CommonTestUtils::DEVICE_GPU)), + CTCGreedyDecoderSeqLenLayerTest::getTestCaseName); +} // namespace diff --git a/inference-engine/tests/ie_test_utils/common_test_utils/ngraph_test_utils.cpp b/inference-engine/tests/ie_test_utils/common_test_utils/ngraph_test_utils.cpp index 4045c8fd00e0af..81a207d9c6bc62 100644 --- a/inference-engine/tests/ie_test_utils/common_test_utils/ngraph_test_utils.cpp +++ b/inference-engine/tests/ie_test_utils/common_test_utils/ngraph_test_utils.cpp @@ -325,32 +325,44 @@ struct Equal { }; template <> -struct Equal { - static bool equal_value(float lhs, float rhs) { - return std::abs(lhs - rhs) < 1e-5; +struct Equal { + static bool equal_value(ngraph::bfloat16 lhs, ngraph::bfloat16 rhs) { + if (lhs.to_bits() == rhs.to_bits()) { + return true; } + return std::abs(lhs - rhs) < 1e-3; + } }; template <> -struct Equal { - static bool equal_value(double lhs, double rhs) { - return std::abs(lhs - rhs) < 1e-5; +struct Equal { + static bool equal_value(ngraph::float16 lhs, ngraph::float16 rhs) { + if (lhs.to_bits() == rhs.to_bits()) { + return true; } + return std::abs(lhs - rhs) < 1e-3; + } }; template <> -struct Equal> { - static bool equal_value(const std::vector& lhs, const std::vector& rhs) { - return lhs.size() == rhs.size() && - std::equal(begin(lhs), end(lhs), begin(rhs), Equal::equal_value); +struct Equal { + static bool equal_value(float lhs, float rhs) { + return std::abs(lhs - rhs) < 1e-4; } }; template <> -struct Equal> { - static bool equal_value(const std::vector& lhs, const std::vector& rhs) { +struct Equal { + static bool equal_value(double lhs, double rhs) { + return std::abs(lhs - rhs) < 1e-5; + } +}; + +template +struct Equal> { + static bool equal_value(const std::vector& lhs, const std::vector& rhs) { return lhs.size() == rhs.size() && - std::equal(begin(lhs), end(lhs), begin(rhs), Equal::equal_value); + std::equal(begin(lhs), end(lhs), begin(rhs), Equal::equal_value); } }; @@ -439,6 +451,45 @@ struct Equal { } }; +using Constant = ngraph::opset1::Constant; +template <> struct Equal> { + static bool equal_value(const std::shared_ptr& lhs, + const std::shared_ptr& rhs) { + const auto lhs_t = lhs->get_element_type(); + const auto rhs_t = rhs->get_element_type(); + if (lhs_t != rhs_t) { + return false; + } + + switch (lhs_t) { + case ngraph::element::Type_t::bf16: { + auto lhs_v = lhs->cast_vector(); + auto rhs_v = rhs->cast_vector(); + return Equal>::equal_value(lhs_v, rhs_v); + break; + } + case ngraph::element::Type_t::f16: { + const auto &lhs_v = lhs->cast_vector(); + const auto &rhs_v = rhs->cast_vector(); + return Equal>::equal_value(lhs_v, rhs_v); + break; + } + case ngraph::element::Type_t::f32: { + const auto &lhs_v = lhs->cast_vector(); + const auto &rhs_v = rhs->cast_vector(); + return Equal>::equal_value(lhs_v, rhs_v); + break; + } + default: { + const auto &lhs_v = lhs->cast_vector(); + const auto &rhs_v = rhs->cast_vector(); + return Equal>::equal_value(lhs_v, rhs_v); + break; + } + } + return false; + } +}; } // namespace equal namespace str { @@ -741,22 +792,13 @@ FunctionsComparator::Result FunctionsComparator::compare( using Constant = ngraph::opset1::Constant; auto const1 = ngraph::as_type_ptr(node1->get_input_node_shared_ptr(i)); auto const2 = ngraph::as_type_ptr(node2->get_input_node_shared_ptr(i)); - - const auto equal = [](std::shared_ptr c1, std::shared_ptr c2) { - const auto& c1v = c1->cast_vector(); - const auto& c2v = c2->cast_vector(); - - return c1v.size() == c2v.size() && std::equal( - begin(c1v), end(c1v), begin(c2v), - [](const double& s1, const double& s2) { - return std::abs(s1 - s2) < 0.001; - }); - }; - - if (const1 && const2 && !equal(const1, const2)) { + using namespace ::attr_comparison::equal; + if (const1 && const2 && + !Equal>::equal_value(const1, const2)) { err_log << "Different Constant values detected\n" << node1->description() << " Input(" << i << ") and " - << node2->description() << " Input(" << i << ")" << std::endl; + << node2->description() << " Input(" << i << ")" + << std::endl; } } diff --git a/inference-engine/tests/unit/gna/gna_wait_test.cpp b/inference-engine/tests/unit/gna/gna_wait_test.cpp index 790e7c9baaa81c..68173a67f96a28 100644 --- a/inference-engine/tests/unit/gna/gna_wait_test.cpp +++ b/inference-engine/tests/unit/gna/gna_wait_test.cpp @@ -25,7 +25,7 @@ class GNAPluginForGNAWaitTest : public GNAPlugin { public: // Prepare underlining object to enable GNAInferRequest::Wait() working GNAPluginForGNAWaitTest() { - InferenceEngine::TensorDesc td{ InferenceEngine::Precision::FP32, {}, InferenceEngine::Layout::HW }; + InferenceEngine::TensorDesc td{ InferenceEngine::Precision::FP32, {1, 1}, InferenceEngine::Layout::HW }; auto fakeInfo = std::make_shared(); auto fakePtr = std::make_shared("fakeName", td); fakeInfo->setInputData(fakePtr); diff --git a/inference-engine/tests_deprecated/functional/mkldnn/extensions_tests/extensions_test.cpp b/inference-engine/tests_deprecated/functional/mkldnn/extensions_tests/extensions_test.cpp index 2c456ef9c425f5..0adcc944d7a62e 100644 --- a/inference-engine/tests_deprecated/functional/mkldnn/extensions_tests/extensions_test.cpp +++ b/inference-engine/tests_deprecated/functional/mkldnn/extensions_tests/extensions_test.cpp @@ -23,55 +23,6 @@ struct extension_params { std::map config; }; -class FakePrimitiveImpl : public InferenceEngine::ILayerExecImpl { -public: - FakePrimitiveImpl(const InferenceEngine::CNNLayer *layer) { - cnnLayer = const_cast(layer); - } - InferenceEngine::StatusCode getSupportedConfigurations(std::vector& conf, InferenceEngine::ResponseDesc *resp) noexcept override { - InferenceEngine::LayerConfig config; - config.dynBatchSupport = true; - if (cnnLayer->outData.size() != 1 && cnnLayer->insData.size() != 1) - return InferenceEngine::GENERAL_ERROR; - InferenceEngine::DataConfig cfg; - cfg.constant = false; - cfg.inPlace = 0; - InferenceEngine::SizeVector order; - for(size_t i = 0; i < cnnLayer->outData[0]->getTensorDesc().getDims().size(); i++) { - order.push_back(i); - } - cfg.desc = InferenceEngine::TensorDesc(cnnLayer->outData[0]->getTensorDesc().getPrecision(), - cnnLayer->outData[0]->getTensorDesc().getDims(), - {cnnLayer->outData[0]->getTensorDesc().getDims(), order}); - config.outConfs.push_back(cfg); - config.inConfs.push_back(cfg); - conf.push_back(config); - return InferenceEngine::OK; - } - InferenceEngine::StatusCode init(InferenceEngine::LayerConfig& config, InferenceEngine::ResponseDesc *resp) noexcept override { - return InferenceEngine::OK; - } - InferenceEngine::StatusCode execute(std::vector& inputs, std::vector& outputs, InferenceEngine::ResponseDesc *resp) noexcept override { - return InferenceEngine::OK; - } - -private: - InferenceEngine::CNNLayer* cnnLayer; -}; - -class TestExtension : public InferenceEngine::IExtension { -public: - void Release() noexcept override { delete this; } - - void GetVersion(const InferenceEngine::Version *&versionInfo) const noexcept override - { - static const InferenceEngine::Version VERSION{{}, "", ""}; - versionInfo = &VERSION; - } - - void Unload() noexcept override {} -}; - class NewFakePrimitiveImpl : public InferenceEngine::ILayerExecImpl { public: NewFakePrimitiveImpl(const std::shared_ptr& node): node(node) {} @@ -179,7 +130,7 @@ class NewTestExtension : public InferenceEngine::IExtension { if (opsets.empty()) { ngraph::OpSet opset; opset.insert(); - opsets["experimental"] = opset; + opsets["custom_opset"] = opset; } return opsets; } @@ -213,7 +164,7 @@ class smoke_ExtensionTest : public TestsCommon, std::unique_ptr score_engine1; score_engine1.reset(new InferenceEnginePluginPtr(make_plugin_name(p.plugin()).c_str())); (*score_engine1)->SetConfig(p.config); - + std::unique_ptr score_engine2; score_engine2.reset(new InferenceEnginePluginPtr(make_plugin_name(p.plugin()).c_str())); (*score_engine2)->SetConfig(p.config); @@ -248,7 +199,7 @@ class smoke_ExtensionTest : public TestsCommon, - + 1 @@ -291,20 +242,14 @@ class smoke_ExtensionTest : public TestsCommon, Blob::Ptr weights; CNNNetwork cnnNet1 = ie.ReadNetwork(model, weights); - CNNNetwork cnnNet2 = ie2.ReadNetwork(model, weights); ASSERT_NO_THROW(ie.LoadNetwork(cnnNet1, device)); - ASSERT_THROW(ie2.LoadNetwork(cnnNet2, device), details::InferenceEngineException); + ASSERT_THROW(ie2.ReadNetwork(model, weights), details::InferenceEngineException); } catch (const InferenceEngine::details::InferenceEngineException& e) { FAIL() << e.what(); } } }; -/************************************************* - * !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! - * All ref values was obtained from Caffe scoring - * !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! - *************************************************/ #ifndef ENABLE_MKL_DNN #include "disable_tests.hpp" #endif diff --git a/inference-engine/thirdparty/clDNN/api/ctc_greedy_decoder.hpp b/inference-engine/thirdparty/clDNN/api/ctc_greedy_decoder.hpp index c9f3a40dbd74f6..64e25580d9b94f 100644 --- a/inference-engine/thirdparty/clDNN/api/ctc_greedy_decoder.hpp +++ b/inference-engine/thirdparty/clDNN/api/ctc_greedy_decoder.hpp @@ -1,5 +1,5 @@ /* -// Copyright (c) 2020 Intel Corporation +// Copyright (c) 2020-2021 Intel Corporation // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -32,24 +32,24 @@ struct ctc_greedy_decoder : public primitive_base { /// @brief Constructs ctc_greedy_decoder primitive. /// @param id This primitive id. - /// @param input Input primitive id. - /// @param input sequence_indicators primitive id. - /// @param ctc_merge_repeated int + /// @param input Input primitive id (input, sequence_indicators, second_output(optional)). + /// @param blank_index Specifies the class index to use for the blank class. + /// @param ctc_merge_repeated Flag for merging repeated labels during the CTC calculation ctc_greedy_decoder(const primitive_id& id, - const primitive_id& input, - const primitive_id& sequence_indicators, - const bool ctc_merge_repeated, - const data_types data_type, - const tensor output_tensor, - const padding& output_padding = padding()) - : primitive_base(id, { input, sequence_indicators }, - output_padding, optional_data_type{ data_type }), - ctc_merge_repeated(ctc_merge_repeated), - output_tensor(output_tensor) - {} + const std::vector& input, + const uint32_t blank_index, + const bool ctc_merge_repeated, + const tensor output_tensor, + const padding& output_padding = padding()) + : primitive_base(id, input, output_padding) + , blank_index(blank_index) + , ctc_merge_repeated(ctc_merge_repeated) + , output_tensor(output_tensor) {} + uint32_t blank_index; bool ctc_merge_repeated; tensor output_tensor; + primitive_id second_output; }; /// @} /// @} diff --git a/inference-engine/thirdparty/clDNN/kernel_selector/core/actual_kernels/ctc_greedy_decoder/ctc_greedy_decoder_kernel_base.cpp b/inference-engine/thirdparty/clDNN/kernel_selector/core/actual_kernels/ctc_greedy_decoder/ctc_greedy_decoder_kernel_base.cpp index c4cecd3ea7a7aa..6020e3bf93e7e5 100644 --- a/inference-engine/thirdparty/clDNN/kernel_selector/core/actual_kernels/ctc_greedy_decoder/ctc_greedy_decoder_kernel_base.cpp +++ b/inference-engine/thirdparty/clDNN/kernel_selector/core/actual_kernels/ctc_greedy_decoder/ctc_greedy_decoder_kernel_base.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Intel Corporation +// Copyright (c) 2020-2021 Intel Corporation // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -24,11 +24,23 @@ JitConstants CTCGreedyDecoderKernelBase::GetJitConstants(const ctc_greedy_decode jit.AddConstants({ MakeJitConstant("ctc_merge_repeated_", params.merge_repeated), - MakeJitConstant("T_", inp.Batch().v), - MakeJitConstant("N_", inp.Feature().v), + MakeJitConstant("blank_index_", params.blank_index), MakeJitConstant("C_", inp.Y().v) }); + if (params.outputs_num == 2) { + jit.AddConstants({ + MakeJitConstant("SECOND_OUTPUT_EXIST", 1), + MakeJitConstant("N_", inp.Batch().v), + MakeJitConstant("T_", inp.Feature().v) + }); + } else { + jit.AddConstants({ + MakeJitConstant("T_", inp.Batch().v), + MakeJitConstant("N_", inp.Feature().v) + }); + }; + return jit; } @@ -71,6 +83,10 @@ KernelsData CTCGreedyDecoderKernelBase::GetCommonKernelsData(const Params& param 2, // input and sequence indicatiors GetFusedPrimitiveInputsCount(params)); + if (orgParams.outputs_num == 2) { + kernel.arguments.push_back({ArgumentDescriptor::Types::INPUT, 2}); + } + return {kd}; } diff --git a/inference-engine/thirdparty/clDNN/kernel_selector/core/actual_kernels/ctc_greedy_decoder/ctc_greedy_decoder_kernel_base.h b/inference-engine/thirdparty/clDNN/kernel_selector/core/actual_kernels/ctc_greedy_decoder/ctc_greedy_decoder_kernel_base.h index 1074cb72f7c55b..218216bce32271 100644 --- a/inference-engine/thirdparty/clDNN/kernel_selector/core/actual_kernels/ctc_greedy_decoder/ctc_greedy_decoder_kernel_base.h +++ b/inference-engine/thirdparty/clDNN/kernel_selector/core/actual_kernels/ctc_greedy_decoder/ctc_greedy_decoder_kernel_base.h @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Intel Corporation +// Copyright (c) 2020-2021 Intel Corporation // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -25,6 +25,8 @@ struct ctc_greedy_decoder_params : public base_params { ctc_greedy_decoder_params() : base_params(KernelType::CTC_GREEDY_DECODER) {} bool merge_repeated = true; + uint32_t blank_index; + uint32_t outputs_num = 1; }; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/inference-engine/thirdparty/clDNN/kernel_selector/core/actual_kernels/ctc_greedy_decoder/ctc_greedy_decoder_kernel_ref.cpp b/inference-engine/thirdparty/clDNN/kernel_selector/core/actual_kernels/ctc_greedy_decoder/ctc_greedy_decoder_kernel_ref.cpp index e6f8d1c2fd3d01..4528c02e8ea271 100644 --- a/inference-engine/thirdparty/clDNN/kernel_selector/core/actual_kernels/ctc_greedy_decoder/ctc_greedy_decoder_kernel_ref.cpp +++ b/inference-engine/thirdparty/clDNN/kernel_selector/core/actual_kernels/ctc_greedy_decoder/ctc_greedy_decoder_kernel_ref.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Intel Corporation +// Copyright (c) 2020-2021 Intel Corporation // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -21,9 +21,13 @@ ParamsKey CTCGreedyDecoderKernelRef::GetSupportedKey() const { ParamsKey k; k.EnableInputDataType(Datatype::F16); k.EnableInputDataType(Datatype::F32); + k.EnableInputDataType(Datatype::INT32); + k.EnableInputDataType(Datatype::INT64); k.EnableOutputDataType(Datatype::F16); k.EnableOutputDataType(Datatype::F32); + k.EnableOutputDataType(Datatype::INT32); + k.EnableOutputDataType(Datatype::INT64); k.EnableInputLayout(DataLayout::bfyx); k.EnableOutputLayout(DataLayout::bfyx); diff --git a/inference-engine/thirdparty/clDNN/kernel_selector/core/cl_kernels/ctc_greedy_decoder_ref.cl b/inference-engine/thirdparty/clDNN/kernel_selector/core/cl_kernels/ctc_greedy_decoder_ref.cl index 8950718283fe38..14ee0e6b613bb5 100644 --- a/inference-engine/thirdparty/clDNN/kernel_selector/core/cl_kernels/ctc_greedy_decoder_ref.cl +++ b/inference-engine/thirdparty/clDNN/kernel_selector/core/cl_kernels/ctc_greedy_decoder_ref.cl @@ -1,4 +1,4 @@ -// Copyright (C) 2020 Intel Corporation +// Copyright (C) 2020-2021 Intel Corporation // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -13,10 +13,13 @@ // limitations under the License. #include "include/include_all.cl" -KERNEL(ctc_greedy_decoder_ref)( - const __global INPUT0_TYPE* probabilities, - const __global INPUT1_TYPE* sequence_indicators, - __global OUTPUT_TYPE* output_sequences) +KERNEL(ctc_greedy_decoder_ref)(const __global INPUT0_TYPE* probabilities + ,const __global INPUT1_TYPE* sequence_indicators + ,__global OUTPUT_TYPE* output_sequences +#ifdef SECOND_OUTPUT_EXIST + ,__global INPUT2_TYPE* second_output +#endif + ) { // Fill output_sequences with -1 for (int ii = 0; ii < T_ * N_; ii++) { @@ -27,11 +30,19 @@ KERNEL(ctc_greedy_decoder_ref)( int prev_class_idx = -1; int output_index = n * T_; - for (int t = 0; /* check at end */; ++t) { + for (int t = 0; t < T_; ++t) { // get maximum probability and its index +#ifdef SECOND_OUTPUT_EXIST + if (t >= sequence_indicators[n]) break; +#else + if (sequence_indicators[t * N_ + n] == 0) break; +#endif int max_class_idx = 0; - +#ifdef SECOND_OUTPUT_EXIST + const __global INPUT0_TYPE* probs = probabilities + n * C_ * T_ + t * C_; +#else const __global INPUT0_TYPE* probs = probabilities + t * C_ * N_ + n * C_; +#endif INPUT0_TYPE max_prob = probs[0]; ++probs; @@ -42,15 +53,15 @@ KERNEL(ctc_greedy_decoder_ref)( } } - if (max_class_idx != C_ - 1 && !(ctc_merge_repeated_ && max_class_idx == prev_class_idx)) { + if (max_class_idx != blank_index_ && !(ctc_merge_repeated_ && max_class_idx == prev_class_idx)) { output_sequences[output_index] = max_class_idx; output_index++; } prev_class_idx = max_class_idx; - if (t + 1 == T_ || sequence_indicators[(t + 1) * N_ + n] == 0) { - break; - } } +#ifdef SECOND_OUTPUT_EXIST + second_output[n] = output_index - n * T_; +#endif } } diff --git a/inference-engine/thirdparty/clDNN/src/ctc_greedy_decoder.cpp b/inference-engine/thirdparty/clDNN/src/ctc_greedy_decoder.cpp index 44b16adab153d2..970667fe0e6642 100644 --- a/inference-engine/thirdparty/clDNN/src/ctc_greedy_decoder.cpp +++ b/inference-engine/thirdparty/clDNN/src/ctc_greedy_decoder.cpp @@ -1,5 +1,5 @@ /* -// Copyright (c) 2020 Intel Corporation +// Copyright (c) 2020-2021 Intel Corporation // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -27,16 +27,17 @@ primitive_type_id ctc_greedy_decoder::type_id() { layout ctc_greedy_decoder_inst::calc_output_layout(ctc_greedy_decoder_node const& node) { auto input_node_layout = node.input().get_non_padded_output_layout(); - auto output_type = node.get_primitive()->output_data_type ? - *node.get_primitive()->output_data_type : input_node_layout.data_type; - auto output_tensor = node.get_primitive()->output_tensor; - return layout(output_type, input_node_layout.format, output_tensor); + auto prim = node.get_primitive(); + auto output_type = prim->output_data_type ? *prim->output_data_type : input_node_layout.data_type; + + return layout(output_type, input_node_layout.format, prim->output_tensor); } std::string ctc_greedy_decoder_inst::to_string(ctc_greedy_decoder_node const& node) { auto node_info = node.desc_to_json(); auto desc = node.get_primitive(); auto ctc_mr = desc->ctc_merge_repeated; + auto blank_index = desc->blank_index; auto& input = node.input(); auto& seq_ind = node.seq_indicators(); @@ -46,6 +47,7 @@ std::string ctc_greedy_decoder_inst::to_string(ctc_greedy_decoder_node const& no ctc_gd_info.add("input id", input.id()); ctc_gd_info.add("seq inidicatior id", seq_ind.id()); ctc_gd_info.add("ctc_mr", ctc_mr); + ctc_gd_info.add("blank_index", blank_index); node_info->add("ctc_greedy_decoder info", ctc_gd_info); node_info->dump(primitive_description); diff --git a/inference-engine/thirdparty/clDNN/src/gpu/ctc_greedy_decoder_gpu.cpp b/inference-engine/thirdparty/clDNN/src/gpu/ctc_greedy_decoder_gpu.cpp index 0d4e5ba40c1f32..349d12bc9a5af7 100644 --- a/inference-engine/thirdparty/clDNN/src/gpu/ctc_greedy_decoder_gpu.cpp +++ b/inference-engine/thirdparty/clDNN/src/gpu/ctc_greedy_decoder_gpu.cpp @@ -1,5 +1,5 @@ /* -// Copyright (c) 2020 Intel Corporation +// Copyright (c) 2020-2021 Intel Corporation // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -37,10 +37,18 @@ struct ctc_greedy_decoder_gpu : typed_primitive_gpu_impl { static primitive_impl* create(const ctc_greedy_decoder_node& arg) { auto ctc_gd_params = get_default_params(arg); auto ctc_gd_optional_params = get_default_optional_params(arg.get_program()); + auto prim = arg.get_primitive(); ctc_gd_params.inputs.push_back( convert_data_tensor(arg.seq_indicators().get_output_layout())); - ctc_gd_params.merge_repeated = arg.get_primitive()->ctc_merge_repeated; + ctc_gd_params.merge_repeated = prim->ctc_merge_repeated; + ctc_gd_params.blank_index = prim->blank_index; + ctc_gd_params.outputs_num = arg.has_second_output() ? 2 : 1; + + if (ctc_gd_params.outputs_num == 2) { + ctc_gd_params.inputs.push_back( + convert_data_tensor(arg.second_output().get_output_layout())); + } auto& kernel_selector = kernel_selector::ctc_greedy_decoder_kernel_selector::Instance(); auto best_kernels = kernel_selector.GetBestKernels( @@ -62,6 +70,8 @@ namespace detail { attach_ctc_greedy_decoder_gpu::attach_ctc_greedy_decoder_gpu() { implementation_map::add(std::make_tuple(engine_types::ocl, data_types::f32, format::bfyx), ctc_greedy_decoder_gpu::create); implementation_map::add(std::make_tuple(engine_types::ocl, data_types::f16, format::bfyx), ctc_greedy_decoder_gpu::create); + implementation_map::add(std::make_tuple(engine_types::ocl, data_types::i32, format::bfyx), ctc_greedy_decoder_gpu::create); + implementation_map::add(std::make_tuple(engine_types::ocl, data_types::i64, format::bfyx), ctc_greedy_decoder_gpu::create); } } // namespace detail diff --git a/inference-engine/thirdparty/clDNN/src/graph_optimizer/remove_redundant_reorders.cpp b/inference-engine/thirdparty/clDNN/src/graph_optimizer/remove_redundant_reorders.cpp index 5eda0dd35864b8..d7a1c4f311aa5e 100644 --- a/inference-engine/thirdparty/clDNN/src/graph_optimizer/remove_redundant_reorders.cpp +++ b/inference-engine/thirdparty/clDNN/src/graph_optimizer/remove_redundant_reorders.cpp @@ -168,7 +168,7 @@ void remove_redundant_reorders::run(program_impl& p) { bool no_output_optimization = remove_output_reorders ? r_node.is_output() && (r_node.get_dependency(0).is_output() || r_node.get_dependency(0).is_type() || - r_node.get_dependency(0).can_be_optimized()) : r_node.is_output(); + r_node.get_dependency(0).can_be_optimized() || r_node.get_dependency(0).get_users().size() != 1) : r_node.is_output(); if (r_node.has_mean() || !r_node.get_primitive()->subtract_per_feature.empty() || diff --git a/inference-engine/thirdparty/clDNN/src/include/ctc_greedy_decoder_inst.h b/inference-engine/thirdparty/clDNN/src/include/ctc_greedy_decoder_inst.h index c4a47f97675b0b..be395809102176 100644 --- a/inference-engine/thirdparty/clDNN/src/include/ctc_greedy_decoder_inst.h +++ b/inference-engine/thirdparty/clDNN/src/include/ctc_greedy_decoder_inst.h @@ -1,5 +1,5 @@ /* -// Copyright (c) 2020 Intel Corporation +// Copyright (c) 2020-2021 Intel Corporation // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -31,6 +31,9 @@ struct typed_program_node : public typed_program_node_basesecond_output.empty(); } + program_node& second_output() const { return get_dependency(2); } }; using ctc_greedy_decoder_node = typed_program_node; diff --git a/inference-engine/thirdparty/mkl-dnn b/inference-engine/thirdparty/mkl-dnn index cae1e0b8353299..f2b67dc5bc8de2 160000 --- a/inference-engine/thirdparty/mkl-dnn +++ b/inference-engine/thirdparty/mkl-dnn @@ -1 +1 @@ -Subproject commit cae1e0b835329999519b4e5563afd9a14a47563e +Subproject commit f2b67dc5bc8de2e6c5603bfb1c22ab1a3d865cc7 diff --git a/inference-engine/thirdparty/movidius/mvnc/src/mvnc_api.c b/inference-engine/thirdparty/movidius/mvnc/src/mvnc_api.c index b67a7fcb1f818b..b7a9f86fc0564c 100644 --- a/inference-engine/thirdparty/movidius/mvnc/src/mvnc_api.c +++ b/inference-engine/thirdparty/movidius/mvnc/src/mvnc_api.c @@ -1986,11 +1986,6 @@ ncStatus_t ncGraphAllocate(struct ncDeviceHandle_t * deviceHandle, struct _graphPrivate_t *g = graphHandle->private_data; struct _devicePrivate_t *d = devices; - if (graphBufferLength > d->dev_attr.max_memory) { - mvLog(MVLOG_ERROR, "The graph file is bigger than the device memory"); - return NC_OUT_OF_MEMORY; - } - GLOBAL_LOCK(); while (d) { if (d == deviceHandle->private_data) @@ -2006,6 +2001,11 @@ ncStatus_t ncGraphAllocate(struct ncDeviceHandle_t * deviceHandle, } GLOBAL_UNLOCK(); + if (graphBufferLength > d->dev_attr.max_memory) { + mvLog(MVLOG_ERROR, "The graph file is bigger than the device memory"); + return NC_OUT_OF_MEMORY; + } + lockAllInferences(); g->id = graphIdCount++; streamId_t streamId; diff --git a/model-optimizer/automation/package_BOM.txt b/model-optimizer/automation/package_BOM.txt index 33b38ca4a495f4..3f12fdc3882a0a 100644 --- a/model-optimizer/automation/package_BOM.txt +++ b/model-optimizer/automation/package_BOM.txt @@ -47,6 +47,7 @@ extensions/back/RemoveUselessConvert.py extensions/back/Reshape0DToSqueeze.py extensions/back/ReshapeMutation.py extensions/back/ResultNormalizer.py +extensions/back/ResultRename.py extensions/back/ReverseInputChannels.py extensions/back/RNNSequenceTypeRename.py extensions/back/ScalarConstNormalize.py @@ -605,6 +606,7 @@ extensions/middle/SliceLikeToStridedSlice.py extensions/middle/sparse_reshape.py extensions/middle/split_tdnn_memoryoffset.py extensions/middle/SplitConcatPairToInterpolate.py +extensions/middle/StridedSliceNormalizer.py extensions/middle/SwapAxesMiddleReplacer.py extensions/middle/TensorIterator_utils.py extensions/middle/TensorIteratorBackEdge.py @@ -799,7 +801,6 @@ 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/slice.py mo/front/common/partial_infer/utils.py mo/front/common/register_custom_ops.py mo/front/common/replacement.py diff --git a/model-optimizer/extensions/back/CropToStridedSlice.py b/model-optimizer/extensions/back/CropToStridedSlice.py index 0165105e798e8a..2ad55a9bcd6973 100644 --- a/model-optimizer/extensions/back/CropToStridedSlice.py +++ b/model-optimizer/extensions/back/CropToStridedSlice.py @@ -1,5 +1,5 @@ """ - Copyright (C) 2018-2020 Intel Corporation + Copyright (C) 2018-2021 Intel Corporation Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -64,8 +64,10 @@ def replace_pattern(self, graph: Graph, match: [str, Node]): end_mask = axis_mask.copy() ss = StridedSlice(graph, {'name': node.soft_get('name', node.id) + '/strided_slice', 'begin_mask': begin_mask, - 'end_mask': end_mask, 'new_axis_mask': np.array([0]), - 'shrink_axis_mask': np.array([0]), 'ellipsis_mask': np.array([0])}).create_node() + 'end_mask': end_mask, + 'new_axis_mask': np.zeros(len(end_mask)), + 'shrink_axis_mask': np.zeros(len(end_mask)), + 'ellipsis_mask': np.zeros(len(end_mask))}).create_node() if len(node.in_nodes()) == 2 and node.has_valid('offset'): # Crop Type 1 @@ -112,7 +114,7 @@ def replace_pattern(self, graph: Graph, match: [str, Node]): source = node.in_port(0).get_connection().get_source() stride = Const(graph, {'value': np.ones(shape_rank, dtype=np.int64), - 'name': ss.name + '/stride'}).create_node() + 'name': ss.name + '/stride'}).create_node() source.connect(ss.in_port(0)) begin.out_port(0).connect(ss.in_port(1)) diff --git a/model-optimizer/extensions/back/ProposalMutation.py b/model-optimizer/extensions/back/ProposalMutation.py index 1ceba78447b738..016d2f3fea9d73 100644 --- a/model-optimizer/extensions/back/ProposalMutation.py +++ b/model-optimizer/extensions/back/ProposalMutation.py @@ -60,9 +60,9 @@ def replace_pattern(graph: Graph, match: dict): {'name': 'cropped_im_info', 'begin_mask': int64_array([1, 1]), 'end_mask': int64_array([1, 1]), - 'new_axis_mask': int64_array([0]), - 'shrink_axis_mask': int64_array([0]), - 'ellipsis_mask': int64_array([0]), + 'new_axis_mask': int64_array([0, 0]), + 'shrink_axis_mask': int64_array([0, 0]), + 'ellipsis_mask': int64_array([0, 0]), 'override_output_shape': True, }) diff --git a/model-optimizer/extensions/back/ResultRename.py b/model-optimizer/extensions/back/ResultRename.py new file mode 100644 index 00000000000000..44bd4f9df4507e --- /dev/null +++ b/model-optimizer/extensions/back/ResultRename.py @@ -0,0 +1,38 @@ +""" + Copyright (C) 2018-2021 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +""" + +from mo.back.replacement import BackReplacementPattern +from mo.graph.graph import Graph + + +class ResultRename(BackReplacementPattern): + # This transformation sets the Result operation name equal to the incoming tensor name. + # For some frameworks like kaldi and onnx this may result in appearance of nodes with identical names, + # which can lead to errors in other transformations. + # So ResultRename should be launched at the end of back phase. + enabled = False + + def find_and_replace_pattern(self, graph: Graph): + for node in graph.get_op_nodes(type='Result'): + if node.in_ports(): + prev_node_out_port = node.in_port(0).get_connection().get_source() + tensor_names = prev_node_out_port.get_tensor_names() + if tensor_names: + result_name = tensor_names[0] + else: + result_name = prev_node_out_port.node.soft_get('name', prev_node_out_port.node.id) + \ + '/sink_port_' + str(prev_node_out_port.idx) + node['name'] = result_name diff --git a/model-optimizer/extensions/back/ResultRename_test.py b/model-optimizer/extensions/back/ResultRename_test.py new file mode 100644 index 00000000000000..ba75438d50ff01 --- /dev/null +++ b/model-optimizer/extensions/back/ResultRename_test.py @@ -0,0 +1,48 @@ +""" + Copyright (C) 2018-2021 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +""" + +import unittest + +from extensions.back.ResultRename import ResultRename +from mo.graph.graph import Node +from mo.utils.ir_engine.compare_graphs import compare_graphs +from mo.utils.unittest.graph import build_graph, regular_op, result + +nodes = { + **regular_op('Op1', {'type': 'Op1', 'kind': 'op', 'op': 'Op1'}), + **result('result'), + 'Op1_data': {'kind': 'data', 'fw_tensor_debug_info': [('Op1', 0, 'Op1_tensor')]} +} + + +class ResultRenameTest(unittest.TestCase): + def test_case1(self): + graph = build_graph(nodes, [('Op1', 'Op1_data'), ('Op1_data', 'result')]) + graph_ref = build_graph(nodes, [('Op1', 'Op1_data'), ('Op1_data', 'result')]) + res_node = Node(graph_ref, 'result') + res_node['name'] = 'Op1_tensor' + + ResultRename().find_and_replace_pattern(graph) + (flag, resp) = compare_graphs(graph, graph_ref, 'result', check_op_attrs=True) + self.assertTrue(flag, resp) + + def test_case2(self): + graph = build_graph(nodes, []) + graph_ref = build_graph(nodes, []) + + ResultRename().find_and_replace_pattern(graph) + (flag, resp) = compare_graphs(graph, graph_ref, 'result', check_op_attrs=True) + self.assertTrue(flag, resp) diff --git a/model-optimizer/extensions/back/StridedSliceMasksNormalizer.py b/model-optimizer/extensions/back/StridedSliceMasksNormalizer.py index f34d4fe78e1194..1b5d17b8d4a878 100644 --- a/model-optimizer/extensions/back/StridedSliceMasksNormalizer.py +++ b/model-optimizer/extensions/back/StridedSliceMasksNormalizer.py @@ -1,5 +1,5 @@ """ - Copyright (C) 2018-2020 Intel Corporation + Copyright (C) 2018-2021 Intel Corporation Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -14,11 +14,9 @@ limitations under the License. """ -from extensions.back.ConvolutionNormalizer import DeconvolutionNormalizer -from extensions.back.CropToStridedSlice import CropToStridedSlice from mo.back.replacement import BackReplacementPattern from mo.front.common.partial_infer.utils import int64_array -from mo.graph.graph import Graph, Node +from mo.graph.graph import Graph class StridedSliceMasksNormalizer(BackReplacementPattern): @@ -26,20 +24,13 @@ class StridedSliceMasksNormalizer(BackReplacementPattern): force_clean_up = True def run_after(self): + from extensions.back.ConvolutionNormalizer import DeconvolutionNormalizer + from extensions.back.CropToStridedSlice import CropToStridedSlice return [CropToStridedSlice, DeconvolutionNormalizer] - @staticmethod - def pattern(): - return dict( - nodes=[ - ('strided_slice', dict(type='StridedSlice')) - ], - edges=[] - ) - - def replace_pattern(self, graph: Graph, match: [str, Node]): - node = match['strided_slice'] - assert node.has_valid('begin_mask') - assert node.has_valid('end_mask') - node.begin_mask = int64_array([1 - i for i in node.begin_mask]) - node.end_mask = int64_array([1 - i for i in node.end_mask]) + def find_and_replace_pattern(self, graph: Graph): + for node in graph.get_op_nodes(op='StridedSlice'): + assert node.has_valid('begin_mask') + assert node.has_valid('end_mask') + node.begin_mask = int64_array([1 - i for i in node.begin_mask]) + node.end_mask = int64_array([1 - i for i in node.end_mask]) diff --git a/model-optimizer/extensions/middle/ApplyPermutations.py b/model-optimizer/extensions/middle/ApplyPermutations.py index d35d37cc86b2fd..874845c28b4992 100644 --- a/model-optimizer/extensions/middle/ApplyPermutations.py +++ b/model-optimizer/extensions/middle/ApplyPermutations.py @@ -1,5 +1,5 @@ """ - Copyright (C) 2018-2020 Intel Corporation + Copyright (C) 2018-2021 Intel Corporation Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -133,15 +133,14 @@ def permute_input_data(graph: Graph): input_permutations = [(in_port, edge_attrs['input_permutation']) for in_port, edge_attrs in node.in_edges().items() if edge_attrs.get('input_permutation') is not None] for in_port, input_perm in input_permutations: - permutation, port_info = input_perm + permutation, port_info, check_shape = input_perm direction, port = port_info.split(':') port = int(port) port_to_check = node.in_port(port) if direction == 'input' else node.out_port(port) permutation_data_node = get_node_with_permutation(node, port_info) if permutation_data_node.has_and_set('permutation') and \ - not is_input_data_in_correct_layout(node, in_port) and \ - len(port_to_check.data.get_shape()) >= 4: + not is_input_data_in_correct_layout(node, in_port) and check_shape(port_to_check): permutation(node, port_info, in_port) if node.has_and_set('need_shape_inference'): node.infer(node) diff --git a/model-optimizer/extensions/middle/ConvertGroupedStridedSlice.py b/model-optimizer/extensions/middle/ConvertGroupedStridedSlice.py index 42be617fcf14e0..9672230e15ccbf 100644 --- a/model-optimizer/extensions/middle/ConvertGroupedStridedSlice.py +++ b/model-optimizer/extensions/middle/ConvertGroupedStridedSlice.py @@ -69,7 +69,8 @@ class ConvertGroupedStridedSlice(MiddleReplacementPattern): enabled = True def run_after(self): - return [ConvertSlice] + from extensions.middle.StridedSliceNormalizer import StridedSliceNormalizer + return [ConvertSlice, StridedSliceNormalizer] def run_before(self): from extensions.middle.pass_separator import MiddleFinish diff --git a/model-optimizer/extensions/middle/StridedSliceNormalizer.py b/model-optimizer/extensions/middle/StridedSliceNormalizer.py new file mode 100644 index 00000000000000..c74023d85d4a52 --- /dev/null +++ b/model-optimizer/extensions/middle/StridedSliceNormalizer.py @@ -0,0 +1,243 @@ +""" + Copyright (C) 2018-2021 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +""" +import numpy as np + +from extensions.ops.split import VariadicSplit +from mo.front.common.partial_infer.utils import int64_array +from mo.ops.strided_slice import StridedSlice +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 +from mo.middle.replacement import MiddleReplacementPattern +from mo.ops.concat import Concat +from mo.utils.error import Error +from mo.ops.const import Const +from mo.ops.op import PermuteAttrs + + +class StridedSliceNormalizer(MiddleReplacementPattern): + """ + StridedSlice is not normal if it cannot be permuted by ApplyPermutations. This normalizer + inserts blank colons ':' in slice expression so that it can be correctly permuted + from NHWC to NCHW layout. It changes masks and inserts blank begin, end and strides values. + In order to successfully handle StridedSlice in ShapeOf subgraphs + changes must be done by inserting nodes not just by overwriting constants. + + StridedSlice is not normal in 2 cases: + 1. rank of a slice expression is less than rank of input tensor + 2. there is an ellipsis + + 1st case example + BEFORE: + | + begin + value=[0, 0] + | + + AFTER: + | + begin Const + value=[0, 0] value=[0, 0] + \ / + \ / + Concat + value=[0, 0, 0, 0] + | + + Input of a shape [16, 100, 100, 3] in NHWC layout, output = input[:, 0:50]. + StridedSlice ill be extended to input[:, 0:50, :, :]. + After permutation to NCHW output = input[:, :, 0:50, :]. + Above is show only for begin input, for end and strides changes are analogous. + + 2nd case example + BEFORE: + | + begin + value=[1, 50] + | + + AFTER: + | + begin + value=[1, 1, 1] + | + VariadicSplit + / \ + / \ + / Const \ + \ val=[0, 0] / + \ | / + \ | / + Concat + value=[1, 0, 0, 1, 1] + | + + Input of a shape [16, 10, 100, 100, 3] in NDHWC layout, output = input[1:4, ..., 1:51, 1:3], + output_shape = [3, 10, 100, 50, 2]. In order to perform correct layout permutation + ellipsis should be exended: input[1:4, ..., 1:51, 1:3] => input[1:4, :, :, 1:51, 1:3]. + Afterc layour permutation input[1:4, 1:3, :, : 1:5]. + + In the places of colons blank zero begin, end and strides values + should be inserted. In order to do that we split begin, and concatenate with the blank zeros in the middle. + Above is show only for begin input, for end and strides changes are analogous. + """ + enabled = True + + def run_before(self): + from extensions.middle.LayoutChangeForConstantShapePaths import LayoutChangeForConstantShapePaths + return [LayoutChangeForConstantShapePaths] + + def find_and_replace_pattern(self, graph: Graph): + for node in graph.get_op_nodes(op='StridedSlice'): + StridedSliceNormalizer.normalize_strided_slice(graph, node) + PermuteAttrs.create_permute_attrs(node, attrs=[('begin_mask', 'input:0'), # but indeed depends from slice_rank + ('end_mask', 'input:0'), + ('new_axis_mask', 'input:0'), + ('shrink_axis_mask', 'input:0'), + ('ellipsis_mask', 'input:0')]) + + # exceptional case, need to add permute edge ettributes here not during shape_infer + # if we specify during shape_infer we will get wrong ApplyPermutation because + # input data node will be changed + PermuteInputs().set_input_permutation(node.in_node(1), node, 'input:1', 'slice', 'dim_size') + PermuteInputs().set_input_permutation(node.in_node(2), node, 'input:2', 'slice', 'dim_size') + PermuteInputs().set_input_permutation(node.in_node(3), node, 'input:3', 'slice', 'dim_size') + + @staticmethod + def normalize_strided_slice(graph: Graph, node: Node): + input_shape = node.in_port(0).data.get_shape() + input_rank = len(input_shape) + slice_rank = node.in_port(1).data.get_shape()[0] + + StridedSlice.align_mask_with_slice_rank(node, slice_rank) # if StridedSlice is created after partial_infer + StridedSliceNormalizer.normalize_slices_attr(node) + + num_insertions = input_rank - slice_rank + np.count_nonzero(node.new_axis_mask) + if np.any(node.ellipsis_mask): + assert np.count_nonzero(node.ellipsis_mask) == 1, 'only one ellipsis_mask nonzero value is allowed' + ellipsis_start = np.nonzero(node.ellipsis_mask)[0][0] + # since we don't expect values in begin and end: take the whole range along ellipsis_start + node.begin_mask[ellipsis_start] = 0 + node.end_mask[ellipsis_start] = 0 + node.ellipsis_mask[ellipsis_start] = 0 + insertation_start_idx = ellipsis_start + 1 + + StridedSliceNormalizer.unroll_ellipsis_for_inputs(graph, node, ellipsis_start, num_insertions) + elif num_insertions > 0: + insertation_start_idx = slice_rank # insert blank values to mask ends + StridedSliceNormalizer.extend_inputs(node, num_insertions) + + if num_insertions > 0: + # insert blank values for ellipsis unrolling and extending + for mask_name in StridedSlice.get_mask_names(): + node[mask_name] = np.insert(node[mask_name], insertation_start_idx, [0] * num_insertions).astype(int) + + @staticmethod + def unroll_ellipsis_for_inputs(graph: Graph, node: Node, ellipsis_start: int, num_ellipsis_ext: int): + node_name = node.soft_get('name', node.id) + for i, slice_name in enumerate(('begin', 'end', 'strides')): + i += 1 + placeholder_arr = np.zeros(num_ellipsis_ext) if i != 3 else np.ones(num_ellipsis_ext) + placeholder_node = Const(graph, {'name': node_name + '/const_to_unroll_{}_ellipsis'.format(slice_name), + 'value': int64_array(placeholder_arr)}).create_node() + + concat_in_ports_count = 3 if ellipsis_start != 0 else 2 + concat = Concat(graph, {'axis': 0, 'name': node_name + '/concat_{}'.format(slice_name), + 'in_ports_count': concat_in_ports_count}).create_node() + + if ellipsis_start != 0: + split = create_op_with_const_inputs(graph, VariadicSplit, {1: int64_array(0), + 2: int64_array([ellipsis_start, -1])}, + {'name': node_name + '/split_for_{}_ellipsis'.format(slice_name), + 'out_ports_count': 2}) + node.in_port(i).get_connection().set_destination(split.in_port(0)) + + concat.in_port(0).connect(split.out_port(0)) + concat.in_port(1).connect(placeholder_node.out_port(0)) + concat.in_port(2).connect(split.out_port(1)) + else: + concat.in_port(0).connect(placeholder_node.out_port(0)) + node.in_port(i).get_connection().set_destination(concat.in_port(1)) + + concat.out_port(0).get_connection().set_destination(node.in_port(i)) + + @staticmethod + def extend_inputs(node: Node, num_insertations: int): + graph = node.graph + node_name = node.soft_get('name', node.id) + + for i, slice_name in enumerate(('begin', 'end', 'strides')): + i += 1 + if node.in_port(3).disconnected(): + break # if strides are not specified no need for extending + + # for strides blank ones should be inserted + blank_values_arr = np.zeros(num_insertations) if i != 3 else np.ones(num_insertations) + blank_values_node = Const(graph, {'name': node_name + '/extend_{}_const'.format(slice_name), + 'value': int64_array(blank_values_arr)}).create_node() + + if node.in_port(i).get_source().node.soft_get('type') == 'Concat': + # concat already exists + concat = node.in_port(i).get_source().node + last_in_port = max(concat.in_ports().keys()) + assert not concat.in_port(last_in_port).disconnected(), 'The last in_port of Concat node {}' \ + 'should be connected'.\ + format(concat.soft_get('name', node.id)) + + concat.add_input_port(last_in_port + 1) + concat.in_port(last_in_port + 1).connect(blank_values_node.out_port(0)) + else: + # have to create concat + concat = Concat(graph, {'axis': 0, 'name': node_name + '/concat_{}'.format(slice_name), + 'in_ports_count': 2}).create_node() + node.in_port(i).get_connection().set_destination(concat.in_port(0)) + concat.in_port(1).connect(blank_values_node.out_port(0)) + concat.out_port(0).get_connection().set_destination(node.in_port(i)) + + @staticmethod + def normalize_slices_attr(node: Node): + # removes negative starts, ends and magic numbers from 'slice' attr which is used by ConvertGroupedStridedSlice + slice_rank = len(node['slices']) + data_shape = node.in_port(0).data.get_shape() + + node_name = node.soft_get('name', node.id) + 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(slice_rank) + + num_ellipsis_inserts = len(data_shape) - slice_rank + np.count_nonzero(node.new_axis_mask) + 1 + res_slices = [] + + in_idx = 0 + for i, s in enumerate(node['slices']): + if node.new_axis_mask[i]: + res_slices.append(slice(0, 1, 1)) + elif node.shrink_axis_mask[i]: + res_slices.append(slice(s, s + 1, strides[i])) # need strides if shrink index is negative + elif node.ellipsis_mask[i]: + for idx in range(num_ellipsis_inserts): + res_slices.append(slice(0, data_shape[in_idx], 1)) + in_idx += 1 + else: + 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 + in_idx += 1 + node['slices'] = np.array(res_slices) diff --git a/model-optimizer/extensions/middle/StridedSliceNormalizer_test.py b/model-optimizer/extensions/middle/StridedSliceNormalizer_test.py new file mode 100644 index 00000000000000..5d1e52fde1433e --- /dev/null +++ b/model-optimizer/extensions/middle/StridedSliceNormalizer_test.py @@ -0,0 +1,1803 @@ +""" + Copyright (C) 2018-2021 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +""" +import unittest + +import numpy as np +import numpy.testing as npt + +from extensions.middle.StridedSliceNormalizer import StridedSliceNormalizer +from extensions.ops.parameter import Parameter +from extensions.ops.split import VariadicSplit +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 +from mo.middle.passes.infer import partial_infer +from mo.ops.strided_slice import StridedSlice +from mo.utils.ir_engine.compare_graphs import compare_graphs +from mo.utils.unittest.graph import build_graph, valued_const_with_data, regular_op_with_empty_data, \ + connect, regular_op, empty_data, regular_op_with_shaped_data + +edges = ( + *connect('input', '0:strided_slice'), + *connect('begin', '1:strided_slice'), + *connect('end', '2:strided_slice'), + *connect('strides', '3:strided_slice'), + *connect('strided_slice', 'res') +) + + +class TestStridedSliceNormalizer(unittest.TestCase): + + def test_strided_slice_extend_inputs(self): + input_shape = (16, 100, 100, 3) + nodes = { + **valued_const_with_data('input', np.arange(np.product(input_shape)).reshape(*input_shape)), + **regular_op_with_empty_data('strided_slice', {'op': 'StridedSlice', 'begin_mask': [1, 1, 1], 'end_mask': [1, 1, 1], + 'shrink_axis_mask': [0, 0, 0], + 'new_axis_mask': [0, 0, 0], + 'ellipsis_mask': [0, 0, 0], + 'infer': StridedSlice.infer}), + + **regular_op_with_empty_data('strided_slice_ref', {'op': 'StridedSlice', 'begin_mask': [1, 1, 1, 0], + 'end_mask': [1, 1, 1, 0], 'ellipsis_mask': [0, 0, 0, 0], + 'new_axis_mask': [0, 0, 0, 0], + 'shrink_axis_mask': [0, 0, 0, 0], + 'infer': StridedSlice.infer}), + **valued_const_with_data('begin', int64_array([0, 0, 0])), + **valued_const_with_data('begin_placeholder', int64_array([0])), + **regular_op_with_empty_data('begin_concat', + {'op': 'Concat', 'infer': concat_infer, 'axis': 0, 'dim_attrs': {}}), + **valued_const_with_data('end', int64_array([4, 25, 50])), + **valued_const_with_data('end_placeholder', int64_array([0])), + **regular_op_with_empty_data('end_concat', + {'op': 'Concat', 'infer': concat_infer, 'axis': 0, 'dim_attrs': {}}), + **valued_const_with_data('strides', int64_array([1, 1, 1])), + **valued_const_with_data('strides_placeholder', int64_array([1])), + **regular_op_with_empty_data('strides_concat', + {'op': 'Concat', 'infer': concat_infer, 'axis': 0, 'dim_attrs': {}}), + **regular_op('res', {'kind': 'op', 'type': 'Result', 'op': 'Result', 'infer': lambda x: None}) + } + + edges_ref_extended_inputs = ( + *connect('input', '0:strided_slice_ref'), + + *connect('begin', '0:begin_concat'), + *connect('begin_placeholder', '1:begin_concat'), + *connect('begin_concat', '1:strided_slice_ref'), + + *connect('end', '0:end_concat'), + *connect('end_placeholder', '1:end_concat'), + *connect('end_concat', '2:strided_slice_ref'), + + *connect('strides', '0:strides_concat'), + *connect('strides_placeholder', '1:strides_concat'), + *connect('strides_concat', '3:strided_slice_ref'), + + *connect('strided_slice_ref', 'res') + ) + + graph = build_graph(nodes, edges, nodes_with_edges_only=True) + graph_ref = build_graph(nodes, edges_ref_extended_inputs, nodes_with_edges_only=True) + graph.stage = 'middle' + graph_ref.stage = 'middle' + + graph = partial_infer(graph) + StridedSliceNormalizer().find_and_replace_pattern(graph) + graph = partial_infer(graph) + graph_ref = partial_infer(graph_ref) + + (flag, resp) = compare_graphs(graph, graph_ref, 'res', check_op_attrs=False) + self.assertTrue(flag, 'Graphs after StridedSliceNormalizer do not match to reference: {}'.format(resp)) + + def test_strided_slice_unrooll_ellipsis(self): + input_shape = (10, 10, 10, 10) + # out = inp[1:4, ..., 0:5] -> inp[1:4, :, :, 0:5] => out_shape = (3, 10, 10, 5) + ellipsis_start = 1 + + nodes = { + **valued_const_with_data('input', np.arange(np.product(input_shape)).reshape(*input_shape)), + **regular_op_with_empty_data('strided_slice', {'op': 'StridedSlice', 'begin_mask': [1, 1, 1], 'end_mask': [1, 1, 1], + 'shrink_axis_mask': [0, 0, 0], + 'new_axis_mask': [0, 0, 0], + 'ellipsis_mask': [0, 1, 0], + 'infer': StridedSlice.infer}), + + **regular_op_with_empty_data('strided_slice_ref', {'op': 'StridedSlice', 'begin_mask': [1, 0, 0, 1], + 'end_mask': [1, 0, 0, 1], 'ellipsis_mask': [0, 0, 0, 0], + 'new_axis_mask': [0, 0, 0, 0], + 'shrink_axis_mask': [0, 0, 0, 0], + 'infer': StridedSlice.infer}), + + **valued_const_with_data('begin', int64_array([1, 0, 0])), + **valued_const_with_data('split_axis_begin', int64_array(0)), + **valued_const_with_data('splits_lengths_begin', int64_array([ellipsis_start, -1])), + **regular_op_with_empty_data('split_for_begin', {'op': 'VariadicSplit', 'infer': VariadicSplit.infer}), + **empty_data('split_for_begin_data_1'), + **valued_const_with_data('begin_placeholder', int64_array([0])), + **regular_op_with_empty_data('begin_concat', + {'op': 'Concat', 'infer': concat_infer, 'axis': 0, 'dim_attrs': {}}), + + + **valued_const_with_data('end', int64_array([4, 0, 5])), + **valued_const_with_data('split_axis_end', int64_array(0)), + **valued_const_with_data('splits_lengths_end', int64_array([ellipsis_start, -1])), + **regular_op_with_empty_data('split_for_end', {'op': 'VariadicSplit', 'infer': VariadicSplit.infer}), + **empty_data('split_for_end_data_1'), + **valued_const_with_data('end_placeholder', int64_array([0])), + **regular_op_with_empty_data('end_concat', + {'op': 'Concat', 'infer': concat_infer, 'axis': 0, 'dim_attrs': {}}), + + **valued_const_with_data('strides', int64_array([1, 1, 1])), + **valued_const_with_data('split_axis_strides', int64_array(0)), + **valued_const_with_data('splits_lengths_strides', int64_array([ellipsis_start, -1])), + **regular_op_with_empty_data('split_for_strides', {'op': 'VariadicSplit', 'infer': VariadicSplit.infer}), + **empty_data('split_for_strides_data_1'), + **valued_const_with_data('strides_placeholder', int64_array([1])), + **regular_op_with_empty_data('strides_concat', + {'op': 'Concat', 'infer': concat_infer, 'axis': 0, 'dim_attrs': {}}), + + **regular_op('res', {'kind': 'op', 'type': 'Result', 'op': 'Result', 'infer': lambda x: None}) + } + + edges_ref_ellipsis_unrolled = ( + *connect('input', '0:strided_slice_ref'), + + *connect('begin', '0:split_for_begin'), + *connect('split_axis_begin', '1:split_for_begin'), + *connect('splits_lengths_begin', '2:split_for_begin'), + *connect('split_for_begin:0', '0:begin_concat'), + *connect('begin_placeholder', '1:begin_concat'), + ('split_for_begin', 'split_for_begin_data_1', {'out': 1, 'in': 2}), + ('split_for_begin_data_1', 'begin_concat', {'out': 1, 'in': 2}), + *connect('begin_concat', '1:strided_slice_ref'), + + *connect('end', '0:split_for_end'), + *connect('split_axis_end', '1:split_for_end'), + *connect('splits_lengths_end', '2:split_for_end'), + *connect('split_for_end:0', '0:end_concat'), + *connect('end_placeholder', '1:end_concat'), + ('split_for_end', 'split_for_end_data_1', {'out': 1, 'in': 2}), + ('split_for_end_data_1', 'end_concat', {'out': 1, 'in': 2}), + *connect('end_concat', '2:strided_slice_ref'), + + *connect('strides', '0:split_for_strides'), + *connect('split_axis_strides', '1:split_for_strides'), + *connect('splits_lengths_strides', '2:split_for_strides'), + *connect('split_for_strides:0', '0:strides_concat'), + *connect('strides_placeholder', '1:strides_concat'), + ('split_for_strides', 'split_for_strides_data_1', {'out': 1, 'in': 2}), + ('split_for_strides_data_1', 'strides_concat', {'out': 1, 'in': 2}), + *connect('strides_concat', '3:strided_slice_ref'), + + *connect('strided_slice_ref', 'res') + ) + + graph = build_graph(nodes, edges, nodes_with_edges_only=True) + graph_ref = build_graph(nodes, edges_ref_ellipsis_unrolled, nodes_with_edges_only=True) + graph.stage = 'middle' + graph_ref.stage = 'middle' + graph = partial_infer(graph) + StridedSliceNormalizer().find_and_replace_pattern(graph) + graph = partial_infer(graph) + graph_ref = partial_infer(graph_ref) + + (flag, resp) = compare_graphs(graph, graph_ref, 'res', check_op_attrs=False) + self.assertTrue(flag, 'Graphs after StridedSliceNormalizer do not match to reference: {}'.format(resp)) + + +class TestStridedSliceShapeInferAfterNormalizer(unittest.TestCase): + # check that after inserting Splits and Concats we still get the same shape + + def run_infer_test(self, inp, ref_res, begin, end, strides, begin_mask, end_mask, + shrink_axis_mask, new_axis_mask, ellipsis_mask): + nodes = { + **valued_const_with_data('input', np.arange(np.product(inp)).reshape(*inp)), + **valued_const_with_data('begin', int64_array(begin)), + **valued_const_with_data('end', int64_array(end)), + **valued_const_with_data('strides', int64_array(strides)), + **regular_op_with_empty_data('strided_slice', {'op': 'StridedSlice', + 'begin_mask': begin_mask, 'end_mask': end_mask, + 'shrink_axis_mask': shrink_axis_mask, + 'new_axis_mask': new_axis_mask, + 'ellipsis_mask': ellipsis_mask, + 'infer': StridedSlice.infer}), + **regular_op('res', {'kind': 'op', 'type': 'Result', 'op': 'Result', 'infer': lambda x: None}) + } + + graph = build_graph(nodes, edges, nodes_with_edges_only=True) + graph.stage = 'middle' + graph = partial_infer(graph) + StridedSliceNormalizer().find_and_replace_pattern(graph) + graph = partial_infer(graph) + + node = Node(graph, 'strided_slice') + res = node.out_port(0).data.get_shape() + npt.assert_array_equal(res, ref_res) + + def test_strided_slice_infer_after_normalizer_1( + self, # inp[0, :34, 20, :2] + inp=(1, 35, 35, 3), ref_res=(34, 2), + begin=(0, 0, 0, 0), end=(1, 34, 20, 2), strides=(1, 1, 1, 1), + begin_mask=(0,), end_mask=(0,), + shrink_axis_mask=(1, 0, 1, 0), new_axis_mask=(0,), + ellipsis_mask=(0,) + ): + self.run_infer_test(inp, ref_res, begin, end, strides, + begin_mask, end_mask, shrink_axis_mask, new_axis_mask, ellipsis_mask) + + def test_strided_slice_infer_after_normalizer_2( + self, # inp[0:3, 0:1, 5:0:-1] + inp=(10, 10, 10, 10), ref_res=(3, 1, 5, 10), + begin=(0, 0, 5), end=(3, 1, 0), 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_infer_test(inp, ref_res, begin, end, strides, + begin_mask, end_mask, shrink_axis_mask, new_axis_mask, ellipsis_mask) + + def test_strided_slice_infer_after_normalizer_3( + self, # inp[1:34, 0, :, :2] + inp=(1, 35, 35, 3), ref_res=(1, 35, 2), + begin=(0, 0, 0, 0), end=(1, 34, 0, 2), 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_infer_test(inp, ref_res, begin, end, strides, + begin_mask, end_mask, shrink_axis_mask, new_axis_mask, ellipsis_mask) + + def test_strided_slice_infer_after_normalizer_4( + self, # inp[1:34, :, :, :2] begin mask is (1,) so only one value can be specified + inp=(1, 35, 35, 3), ref_res=(1, 35, 2), + begin=(0, 0, 0, 0), end=(1, 34, 20, 2), strides=(1, 1, 1, 1), begin_mask=(1, 0, 0, ), end_mask=(1, 0, 0, 1), + shrink_axis_mask=(0, 1), new_axis_mask=(0,), ellipsis_mask=(0,) + ): + self.run_infer_test(inp, ref_res, begin, end, strides, + begin_mask, end_mask, shrink_axis_mask, new_axis_mask, ellipsis_mask) + + def test_strided_slice_infer_after_normalizer_5( + self, # inp[:, :, :, :] since all begin and end masks are zero + inp=(1, 35, 35, 3), ref_res=(1, 35, 35, 3), + begin=(1, 10, 10, 0), end=(1, 34, 20, 2), strides=(1, 1, 1, 1), begin_mask=(0, 0, 0, 0), end_mask=(0, 0, 0, 0), + shrink_axis_mask=(0,), new_axis_mask=(0,), ellipsis_mask=(0,) + ): + self.run_infer_test(inp, ref_res, begin, end, strides, + begin_mask, end_mask, shrink_axis_mask, new_axis_mask, ellipsis_mask) + + def test_strided_slice_infer_after_normalizer_6( + self, # inp[0] + inp=(1, 35, 35, 3), ref_res=(35, 35, 3), + begin=(0,), end=(1,), strides=(1,), begin_mask=(1,), end_mask=(0,), + shrink_axis_mask=(1,), new_axis_mask=(0,), ellipsis_mask=(0,) + ): + self.run_infer_test(inp, ref_res, begin, end, strides, + begin_mask, end_mask, shrink_axis_mask, new_axis_mask, ellipsis_mask) + + def test_strided_slice_infer_after_normalizer_7( + self, # inp[0, 20], ends can be of any value + inp=(1, 35, 35, 3), ref_res=(35, 3), + begin=(0, 20), end=(1, 9999), strides=(1, 1), begin_mask=(0,), end_mask=(0,), + shrink_axis_mask=(1, 1), new_axis_mask=(0,), ellipsis_mask=(0,) + ): + self.run_infer_test(inp, ref_res, begin, end, strides, + begin_mask, end_mask, shrink_axis_mask, new_axis_mask, ellipsis_mask) + + def test_strided_slice_infer_after_normalizer_8( + self, # inp[0, 0:34, 20:22, new_axis], both new_axis and shrink_axis are present + inp=(1, 35, 35, 3), ref_res=(34, 2, 1, 3), + begin=(0, 0, 20, 0), end=(1, 34, 22, 2), strides=(1, 1, 1, 1), begin_mask=(0,), end_mask=(0,), + shrink_axis_mask=(1,), new_axis_mask=(0, 0, 0, 1), ellipsis_mask=(0,) + ): + self.run_infer_test(inp, ref_res, begin, end, strides, + begin_mask, end_mask, shrink_axis_mask, new_axis_mask, ellipsis_mask) + + def test_strided_slice_infer_after_normalizer_9( + self, # inp[:, 0:4, 20, new_axis], both new_axis and shrink_axis are present + inp=(1, 35, 35, 3), ref_res=(1, 4, 1, 3), + begin=(0, 0, 20, 0), end=(0, 4, 0, 0), strides=(1, 1, 1, 1), begin_mask=(0, 1, 0, 0), end_mask=(0, 1, 0, 0), + shrink_axis_mask=(0, 0, 1, 0), new_axis_mask=(0, 0, 0, 1), ellipsis_mask=(0,) + ): + self.run_infer_test(inp, ref_res, begin, end, strides, + begin_mask, end_mask, shrink_axis_mask, new_axis_mask, ellipsis_mask) + + def test_strided_slice_infer_after_normalizer_10( + self, # inp[:, 0:4, new_axis, 20], both new_axis and shrink_axis are present + inp=(1, 35, 35, 3), ref_res=(1, 4, 1, 3), + begin=(0, 0, 0, 20), end=(0, 4, 0, 0), strides=(1, 1, 1, 1), begin_mask=(0, 1, 0, 0), end_mask=(0, 1, 0, 0), + shrink_axis_mask=(0, 0, 0, 1), new_axis_mask=(0, 0, 1, 0), ellipsis_mask=(0,) + ): + self.run_infer_test(inp, ref_res, begin, end, strides, + begin_mask, end_mask, shrink_axis_mask, new_axis_mask, ellipsis_mask) + + def test_strided_slice_infer_after_normalizer_11( + self, # inp[0, :, 0:34, 20:22, new_axis], both new_axis and shrink_axis are present + inp=(1, 3, 35, 35), ref_res=(3, 34, 2, 1), + begin=(0, 0, 0, 20, 0), end=(1, 0, 34, 22, 0), strides=(1, 1, 1, 1, 1), + begin_mask=(1, 0, 1, 1, 1), end_mask=(1, 0, 1, 1, 1), + shrink_axis_mask=(1,), new_axis_mask=(0, 0, 0, 0, 1), ellipsis_mask=(0,) + ): + self.run_infer_test(inp, ref_res, begin, end, strides, + begin_mask, end_mask, shrink_axis_mask, new_axis_mask, ellipsis_mask) + + def test_strided_slice_infer_after_normalizer_12( + self, # inp[0, :34, 20, :2] + inp=(1, 35, 35, 3), ref_res=(34, 2), + begin=(0, 0, 0, 0), end=(1, 34, 20, 2), strides=(1, 1, 1, 1), begin_mask=(0, 1, 1, 1), end_mask=(0, 1, 1, 1), + shrink_axis_mask=(1, 0, 1, 0), new_axis_mask=(0,), ellipsis_mask=(0,) + ): + self.run_infer_test(inp, ref_res, begin, end, strides, + begin_mask, end_mask, shrink_axis_mask, new_axis_mask, ellipsis_mask) + + def test_strided_slice_infer_after_normalizer_13( + self, # inp[0, 0, 0], since it's shrink_axis ends can be of any value + inp=(1, 35, 35, 3), ref_res=(3,), + begin=(0, 0, 0), end=(1, 34444, 20), strides=(1, 1, 1), begin_mask=(0, 0, 0), end_mask=(0, 0, 0), + shrink_axis_mask=(1, 1, 1), new_axis_mask=(0,), ellipsis_mask=(0,) + ): + self.run_infer_test(inp, ref_res, begin, end, strides, + begin_mask, end_mask, shrink_axis_mask, new_axis_mask, ellipsis_mask) + + def test_strided_slice_infer_after_normalizer_14( + self, # inp[0, 0, 0], since begin_mask is [0], begin can be of any value + inp=(1, 35, 35, 3), ref_res=(1, 18, 18, 3), + begin=(0, 0, 0), end=(1, 35, 35), strides=(2, 2, 2), begin_mask=(1, 1, 1), end_mask=(1, 1, 1), + shrink_axis_mask=(0, 0, 0), new_axis_mask=(0,), ellipsis_mask=(0,) + ): + self.run_infer_test(inp, ref_res, begin, end, strides, + begin_mask, end_mask, shrink_axis_mask, new_axis_mask, ellipsis_mask) + + # with ellipsis + def test_strided_slice_infer_after_normalizer_15( + self, # inp[..., np.newaxis] + inp=(1, 35, 35), ref_res=(1, 35, 35, 1), + begin=(101, 0), end=(0, 0), strides=(-1, -1), begin_mask=(0, 0), end_mask=(0, 0), + shrink_axis_mask=(0, 0), new_axis_mask=(0, 1), ellipsis_mask=(1, 0) + ): + self.run_infer_test(inp, ref_res, begin, end, strides, + begin_mask, end_mask, shrink_axis_mask, new_axis_mask, ellipsis_mask) + + def test_strided_slice_infer_after_normalizer_16( + self, # inp_shape = (1, 720, 1080), out = inp[..., :100, None] => out_shape = (1, 720, 100, 1) + inp=(1, 720, 1080), ref_res=(1, 720, 100, 1), + begin=(0, 0, 0), end=(0, 100, 0), strides=(1, 1, 1), begin_mask=(0, 1, 0), end_mask=(0, 1, 0), + shrink_axis_mask=(0,), new_axis_mask=(0, 0, 1), ellipsis_mask=(1,) + ): + self.run_infer_test(inp, ref_res, begin, end, strides, + begin_mask, end_mask, shrink_axis_mask, new_axis_mask, ellipsis_mask) + + def test_strided_slice_infer_after_normalizer_17( + self, # inp_shape = (1, 720, 1080, 3), out = inp[..., :-1] => out_shape = (1, 720, 100, 2) + inp=(1, 720, 1080, 3), ref_res=(1, 720, 1080, 2), + begin=(0, 0), end=(0, -1), strides=(1, 1), begin_mask=(0, 0), end_mask=(0, 1), + shrink_axis_mask=(0, 0), new_axis_mask=(0, 0), ellipsis_mask=(1, 0) + ): + self.run_infer_test(inp, ref_res, begin, end, strides, + begin_mask, end_mask, shrink_axis_mask, new_axis_mask, ellipsis_mask) + + def test_strided_slice_infer_after_normalizer_18( + self, # inp_shape = (1, 720, 1080, 3), out = inp[..., 2] => out_shape = (1, 720, 1080) + inp=(1, 720, 1080, 3), ref_res=(1, 720, 1080), + begin=(0, 2), end=(0, 0), strides=(1, 1), begin_mask=(0, 1), end_mask=(0, 0), + shrink_axis_mask=(0, 1), new_axis_mask=(0, 0), ellipsis_mask=(1, 0) + ): + self.run_infer_test(inp, ref_res, begin, end, strides, + begin_mask, end_mask, shrink_axis_mask, new_axis_mask, ellipsis_mask) + + # automatically generated the whole range of 2d slices over 2d, 3d and 4d input tensors + def test_normalizer_auto_infer_strided_slice_2d_over_2d_0(self): + """ + inp_shape = (1, 100), out = inp[:, :] => out_shape = (1, 100) + """ + self.run_infer_test( + inp=(1, 100), ref_res=(1, 100), + begin=(0, 0), end=(0, 0), strides=(1, 1), begin_mask=(0, 0), end_mask=(0, 0), + shrink_axis_mask=(0, 0), new_axis_mask=(0, 0), ellipsis_mask=(0, 0) + ) + + def test_normalizer_auto_infer_strided_slice_2d_over_2d_1(self): + """ + inp_shape = (1, 100), out = inp[:, None] => out_shape = (1, 1, 100) + """ + self.run_infer_test( + inp=(1, 100), ref_res=(1, 1, 100), + begin=(0, 0), end=(0, 0), strides=(1, 1), begin_mask=(0, 0), end_mask=(0, 0), + shrink_axis_mask=(0, 0), new_axis_mask=(0, 1), ellipsis_mask=(0, 0) + ) + + def test_normalizer_auto_infer_strided_slice_2d_over_2d_2(self): + """ + inp_shape = (1, 100), out = inp[:, 0] => out_shape = (1,) + """ + self.run_infer_test( + inp=(1, 100), ref_res=(1,), + begin=(0, 0), end=(0, 0), strides=(1, 1), begin_mask=(0, 0), end_mask=(0, 0), + shrink_axis_mask=(0, 1), new_axis_mask=(0, 0), ellipsis_mask=(0, 0) + ) + + def test_normalizer_auto_infer_strided_slice_2d_over_2d_3(self): + """ + inp_shape = (1, 100), out = inp[..., :] => out_shape = (1, 100) + """ + self.run_infer_test( + inp=(1, 100), ref_res=(1, 100), + begin=(0, 0), end=(0, 0), strides=(1, 1), begin_mask=(0, 0), end_mask=(0, 0), + shrink_axis_mask=(0, 0), new_axis_mask=(0, 0), ellipsis_mask=(1, 0) + ) + + def test_normalizer_auto_infer_strided_slice_2d_over_2d_4(self): + """ + inp_shape = (1, 100), out = inp[..., None] => out_shape = (1, 100, 1) + """ + self.run_infer_test( + inp=(1, 100), ref_res=(1, 100, 1), + begin=(0, 0), end=(0, 0), strides=(1, 1), begin_mask=(0, 0), end_mask=(0, 0), + shrink_axis_mask=(0, 0), new_axis_mask=(0, 1), ellipsis_mask=(1, 0) + ) + + def test_normalizer_auto_infer_strided_slice_2d_over_2d_5(self): + """ + inp_shape = (1, 100), out = inp[..., 0] => out_shape = (1,) + """ + self.run_infer_test( + inp=(1, 100), ref_res=(1,), + begin=(0, 0), end=(0, 0), strides=(1, 1), begin_mask=(0, 0), end_mask=(0, 0), + shrink_axis_mask=(0, 1), new_axis_mask=(0, 0), ellipsis_mask=(1, 0) + ) + + def test_normalizer_auto_infer_strided_slice_2d_over_2d_6(self): + """ + inp_shape = (1, 100), out = inp[None, :] => out_shape = (1, 1, 100) + """ + self.run_infer_test( + inp=(1, 100), ref_res=(1, 1, 100), + begin=(0, 0), end=(0, 0), strides=(1, 1), begin_mask=(0, 0), end_mask=(0, 0), + shrink_axis_mask=(0, 0), new_axis_mask=(1, 0), ellipsis_mask=(0, 0) + ) + + def test_normalizer_auto_infer_strided_slice_2d_over_2d_7(self): + """ + inp_shape = (1, 100), out = inp[None, None] => out_shape = (1, 1, 1, 100) + """ + self.run_infer_test( + inp=(1, 100), ref_res=(1, 1, 1, 100), + begin=(0, 0), end=(0, 0), strides=(1, 1), begin_mask=(0, 0), end_mask=(0, 0), + shrink_axis_mask=(0, 0), new_axis_mask=(1, 1), ellipsis_mask=(0, 0) + ) + + def test_normalizer_auto_infer_strided_slice_2d_over_2d_8(self): + """ + inp_shape = (1, 100), out = inp[None, 0] => out_shape = (1, 100) + """ + self.run_infer_test( + inp=(1, 100), ref_res=(1, 100), + begin=(0, 0), end=(0, 0), strides=(1, 1), begin_mask=(0, 0), end_mask=(0, 0), + shrink_axis_mask=(0, 1), new_axis_mask=(1, 0), ellipsis_mask=(0, 0) + ) + + def test_normalizer_auto_infer_strided_slice_2d_over_2d_9(self): + """ + inp_shape = (1, 100), out = inp[0, :] => out_shape = (100,) + """ + self.run_infer_test( + inp=(1, 100), ref_res=(100,), + begin=(0, 0), end=(0, 0), strides=(1, 1), begin_mask=(0, 0), end_mask=(0, 0), + shrink_axis_mask=(1, 0), new_axis_mask=(0, 0), ellipsis_mask=(0, 0) + ) + + def test_normalizer_auto_infer_strided_slice_2d_over_2d_10(self): + """ + inp_shape = (1, 100), out = inp[0, None] => out_shape = (1, 100) + """ + self.run_infer_test( + inp=(1, 100), ref_res=(1, 100), + begin=(0, 0), end=(0, 0), strides=(1, 1), begin_mask=(0, 0), end_mask=(0, 0), + shrink_axis_mask=(1, 0), new_axis_mask=(0, 1), ellipsis_mask=(0, 0) + ) + + def test_normalizer_auto_infer_strided_slice_2d_over_2d_11(self): + """ + inp_shape = (1, 100), out = inp[0, 0] => out_shape = () + """ + self.run_infer_test( + inp=(1, 100), ref_res=(), + begin=(0, 0), end=(0, 0), strides=(1, 1), begin_mask=(0, 0), end_mask=(0, 0), + shrink_axis_mask=(1, 1), new_axis_mask=(0, 0), ellipsis_mask=(0, 0) + ) + + def test_normalizer_auto_infer_strided_slice_2d_over_3d_0(self): + """ + inp_shape = (1, 100, 200), out = inp[:, :] => out_shape = (1, 100, 200) + """ + self.run_infer_test( + inp=(1, 100, 200), ref_res=(1, 100, 200), + begin=(0, 0), end=(0, 0), strides=(1, 1), begin_mask=(0, 0), end_mask=(0, 0), + shrink_axis_mask=(0, 0), new_axis_mask=(0, 0), ellipsis_mask=(0, 0) + ) + + def test_normalizer_auto_infer_strided_slice_2d_over_3d_1(self): + """ + inp_shape = (1, 100, 200), out = inp[:, None] => out_shape = (1, 1, 100, 200) + """ + self.run_infer_test( + inp=(1, 100, 200), ref_res=(1, 1, 100, 200), + begin=(0, 0), end=(0, 0), strides=(1, 1), begin_mask=(0, 0), end_mask=(0, 0), + shrink_axis_mask=(0, 0), new_axis_mask=(0, 1), ellipsis_mask=(0, 0) + ) + + def test_normalizer_auto_infer_strided_slice_2d_over_3d_2(self): + """ + inp_shape = (1, 100, 200), out = inp[:, 0] => out_shape = (1, 200) + """ + self.run_infer_test( + inp=(1, 100, 200), ref_res=(1, 200), + begin=(0, 0), end=(0, 0), strides=(1, 1), begin_mask=(0, 0), end_mask=(0, 0), + shrink_axis_mask=(0, 1), new_axis_mask=(0, 0), ellipsis_mask=(0, 0) + ) + + def test_normalizer_auto_infer_strided_slice_2d_over_3d_3(self): + """ + inp_shape = (1, 100, 200), out = inp[..., :] => out_shape = (1, 100, 200) + """ + self.run_infer_test( + inp=(1, 100, 200), ref_res=(1, 100, 200), + begin=(0, 0), end=(0, 0), strides=(1, 1), begin_mask=(0, 0), end_mask=(0, 0), + shrink_axis_mask=(0, 0), new_axis_mask=(0, 0), ellipsis_mask=(1, 0) + ) + + def test_normalizer_auto_infer_strided_slice_2d_over_3d_4(self): + """ + inp_shape = (1, 100, 200), out = inp[..., None] => out_shape = (1, 100, 200, 1) + """ + self.run_infer_test( + inp=(1, 100, 200), ref_res=(1, 100, 200, 1), + begin=(0, 0), end=(0, 0), strides=(1, 1), begin_mask=(0, 0), end_mask=(0, 0), + shrink_axis_mask=(0, 0), new_axis_mask=(0, 1), ellipsis_mask=(1, 0) + ) + + def test_normalizer_auto_infer_strided_slice_2d_over_3d_5(self): + """ + inp_shape = (1, 100, 200), out = inp[..., 0] => out_shape = (1, 100) + """ + self.run_infer_test( + inp=(1, 100, 200), ref_res=(1, 100), + begin=(0, 0), end=(0, 0), strides=(1, 1), begin_mask=(0, 0), end_mask=(0, 0), + shrink_axis_mask=(0, 1), new_axis_mask=(0, 0), ellipsis_mask=(1, 0) + ) + + def test_normalizer_auto_infer_strided_slice_2d_over_3d_6(self): + """ + inp_shape = (1, 100, 200), out = inp[None, :] => out_shape = (1, 1, 100, 200) + """ + self.run_infer_test( + inp=(1, 100, 200), ref_res=(1, 1, 100, 200), + begin=(0, 0), end=(0, 0), strides=(1, 1), begin_mask=(0, 0), end_mask=(0, 0), + shrink_axis_mask=(0, 0), new_axis_mask=(1, 0), ellipsis_mask=(0, 0) + ) + + def test_normalizer_auto_infer_strided_slice_2d_over_3d_7(self): + """ + inp_shape = (1, 100, 200), out = inp[None, None] => out_shape = (1, 1, 1, 100, 200) + """ + self.run_infer_test( + inp=(1, 100, 200), ref_res=(1, 1, 1, 100, 200), + begin=(0, 0), end=(0, 0), strides=(1, 1), begin_mask=(0, 0), end_mask=(0, 0), + shrink_axis_mask=(0, 0), new_axis_mask=(1, 1), ellipsis_mask=(0, 0) + ) + + def test_normalizer_auto_infer_strided_slice_2d_over_3d_8(self): + """ + inp_shape = (1, 100, 200), out = inp[None, 0] => out_shape = (1, 100, 200) + """ + self.run_infer_test( + inp=(1, 100, 200), ref_res=(1, 100, 200), + begin=(0, 0), end=(0, 0), strides=(1, 1), begin_mask=(0, 0), end_mask=(0, 0), + shrink_axis_mask=(0, 1), new_axis_mask=(1, 0), ellipsis_mask=(0, 0) + ) + + def test_normalizer_auto_infer_strided_slice_2d_over_3d_9(self): + """ + inp_shape = (1, 100, 200), out = inp[0, :] => out_shape = (100, 200) + """ + self.run_infer_test( + inp=(1, 100, 200), ref_res=(100, 200), + begin=(0, 0), end=(0, 0), strides=(1, 1), begin_mask=(0, 0), end_mask=(0, 0), + shrink_axis_mask=(1, 0), new_axis_mask=(0, 0), ellipsis_mask=(0, 0) + ) + + def test_normalizer_auto_infer_strided_slice_2d_over_3d_10(self): + """ + inp_shape = (1, 100, 200), out = inp[0, None] => out_shape = (1, 100, 200) + """ + self.run_infer_test( + inp=(1, 100, 200), ref_res=(1, 100, 200), + begin=(0, 0), end=(0, 0), strides=(1, 1), begin_mask=(0, 0), end_mask=(0, 0), + shrink_axis_mask=(1, 0), new_axis_mask=(0, 1), ellipsis_mask=(0, 0) + ) + + def test_normalizer_auto_infer_strided_slice_2d_over_3d_11(self): + """ + inp_shape = (1, 100, 200), out = inp[0, 0] => out_shape = (200,) + """ + self.run_infer_test( + inp=(1, 100, 200), ref_res=(200,), + begin=(0, 0), end=(0, 0), strides=(1, 1), begin_mask=(0, 0), end_mask=(0, 0), + shrink_axis_mask=(1, 1), new_axis_mask=(0, 0), ellipsis_mask=(0, 0) + ) + + def test_normalizer_auto_infer_strided_slice_2d_over_4d_0(self): + """ + inp_shape = (1, 100, 200, 3), out = inp[:, :] => out_shape = (1, 100, 200, 3) + """ + self.run_infer_test( + inp=(1, 100, 200, 3), ref_res=(1, 100, 200, 3), + begin=(0, 0), end=(0, 0), strides=(1, 1), begin_mask=(0, 0), end_mask=(0, 0), + shrink_axis_mask=(0, 0), new_axis_mask=(0, 0), ellipsis_mask=(0, 0) + ) + + def test_normalizer_auto_infer_strided_slice_2d_over_4d_1(self): + """ + inp_shape = (1, 100, 200, 3), out = inp[:, None] => out_shape = (1, 1, 100, 200, 3) + """ + self.run_infer_test( + inp=(1, 100, 200, 3), ref_res=(1, 1, 100, 200, 3), + begin=(0, 0), end=(0, 0), strides=(1, 1), begin_mask=(0, 0), end_mask=(0, 0), + shrink_axis_mask=(0, 0), new_axis_mask=(0, 1), ellipsis_mask=(0, 0) + ) + + def test_normalizer_auto_infer_strided_slice_2d_over_4d_2(self): + """ + inp_shape = (1, 100, 200, 3), out = inp[:, 0] => out_shape = (1, 200, 3) + """ + self.run_infer_test( + inp=(1, 100, 200, 3), ref_res=(1, 200, 3), + begin=(0, 0), end=(0, 0), strides=(1, 1), begin_mask=(0, 0), end_mask=(0, 0), + shrink_axis_mask=(0, 1), new_axis_mask=(0, 0), ellipsis_mask=(0, 0) + ) + + def test_normalizer_auto_infer_strided_slice_2d_over_4d_3(self): + """ + inp_shape = (1, 100, 200, 3), out = inp[..., :] => out_shape = (1, 100, 200, 3) + """ + self.run_infer_test( + inp=(1, 100, 200, 3), ref_res=(1, 100, 200, 3), + begin=(0, 0), end=(0, 0), strides=(1, 1), begin_mask=(0, 0), end_mask=(0, 0), + shrink_axis_mask=(0, 0), new_axis_mask=(0, 0), ellipsis_mask=(1, 0) + ) + + def test_normalizer_auto_infer_strided_slice_2d_over_4d_4(self): + """ + inp_shape = (1, 100, 200, 3), out = inp[..., None] => out_shape = (1, 100, 200, 3, 1) + """ + self.run_infer_test( + inp=(1, 100, 200, 3), ref_res=(1, 100, 200, 3, 1), + begin=(0, 0), end=(0, 0), strides=(1, 1), begin_mask=(0, 0), end_mask=(0, 0), + shrink_axis_mask=(0, 0), new_axis_mask=(0, 1), ellipsis_mask=(1, 0) + ) + + def test_normalizer_auto_infer_strided_slice_2d_over_4d_5(self): + """ + inp_shape = (1, 100, 200, 3), out = inp[..., 0] => out_shape = (1, 100, 200) + """ + self.run_infer_test( + inp=(1, 100, 200, 3), ref_res=(1, 100, 200), + begin=(0, 0), end=(0, 0), strides=(1, 1), begin_mask=(0, 0), end_mask=(0, 0), + shrink_axis_mask=(0, 1), new_axis_mask=(0, 0), ellipsis_mask=(1, 0) + ) + + def test_normalizer_auto_infer_strided_slice_2d_over_4d_6(self): + """ + inp_shape = (1, 100, 200, 3), out = inp[None, :] => out_shape = (1, 1, 100, 200, 3) + """ + self.run_infer_test( + inp=(1, 100, 200, 3), ref_res=(1, 1, 100, 200, 3), + begin=(0, 0), end=(0, 0), strides=(1, 1), begin_mask=(0, 0), end_mask=(0, 0), + shrink_axis_mask=(0, 0), new_axis_mask=(1, 0), ellipsis_mask=(0, 0) + ) + + def test_normalizer_auto_infer_strided_slice_2d_over_4d_7(self): + """ + inp_shape = (1, 100, 200, 3), out = inp[None, None] => out_shape = (1, 1, 1, 100, 200, 3) + """ + self.run_infer_test( + inp=(1, 100, 200, 3), ref_res=(1, 1, 1, 100, 200, 3), + begin=(0, 0), end=(0, 0), strides=(1, 1), begin_mask=(0, 0), end_mask=(0, 0), + shrink_axis_mask=(0, 0), new_axis_mask=(1, 1), ellipsis_mask=(0, 0) + ) + + def test_normalizer_auto_infer_strided_slice_2d_over_4d_8(self): + """ + inp_shape = (1, 100, 200, 3), out = inp[None, 0] => out_shape = (1, 100, 200, 3) + """ + self.run_infer_test( + inp=(1, 100, 200, 3), ref_res=(1, 100, 200, 3), + begin=(0, 0), end=(0, 0), strides=(1, 1), begin_mask=(0, 0), end_mask=(0, 0), + shrink_axis_mask=(0, 1), new_axis_mask=(1, 0), ellipsis_mask=(0, 0) + ) + + def test_normalizer_auto_infer_strided_slice_2d_over_4d_9(self): + """ + inp_shape = (1, 100, 200, 3), out = inp[0, :] => out_shape = (100, 200, 3) + """ + self.run_infer_test( + inp=(1, 100, 200, 3), ref_res=(100, 200, 3), + begin=(0, 0), end=(0, 0), strides=(1, 1), begin_mask=(0, 0), end_mask=(0, 0), + shrink_axis_mask=(1, 0), new_axis_mask=(0, 0), ellipsis_mask=(0, 0) + ) + + def test_normalizer_auto_infer_strided_slice_2d_over_4d_10(self): + """ + inp_shape = (1, 100, 200, 3), out = inp[0, None] => out_shape = (1, 100, 200, 3) + """ + self.run_infer_test( + inp=(1, 100, 200, 3), ref_res=(1, 100, 200, 3), + begin=(0, 0), end=(0, 0), strides=(1, 1), begin_mask=(0, 0), end_mask=(0, 0), + shrink_axis_mask=(1, 0), new_axis_mask=(0, 1), ellipsis_mask=(0, 0) + ) + + def test_normalizer_auto_infer_strided_slice_2d_over_4d_11(self): + """ + inp_shape = (1, 100, 200, 3), out = inp[0, 0] => out_shape = (200, 3) + """ + self.run_infer_test( + inp=(1, 100, 200, 3), ref_res=(200, 3), + begin=(0, 0), end=(0, 0), strides=(1, 1), begin_mask=(0, 0), end_mask=(0, 0), + shrink_axis_mask=(1, 1), new_axis_mask=(0, 0), ellipsis_mask=(0, 0) + ) + + # automatically generated slices from 3d to 5d d input tensors + # fixed number of ellipsis, newaxis and shrink_axis + def test_normalizer_auto_infer_strided_slice_3d_over_3d_0(self): + """ + inp_shape = (1, 100, 200), out = inp[None, ..., 0] => out_shape = (1, 1, 100) + """ + self.run_infer_test( + inp=(1, 100, 200), ref_res=(1, 1, 100), + begin=(0, 0, 0), end=(0, 0, 0), strides=(1, 1, 1), begin_mask=(0, 0, 0), end_mask=(0, 0, 0), + shrink_axis_mask=(0, 0, 1), new_axis_mask=(1, 0, 0), ellipsis_mask=(0, 1, 0) + ) + + def test_normalizer_auto_infer_strided_slice_3d_over_3d_1(self): + """ + inp_shape = (1, 100, 200), out = inp[..., None, 0] => out_shape = (1, 100, 1) + """ + self.run_infer_test( + inp=(1, 100, 200), ref_res=(1, 100, 1), + begin=(0, 0, 0), end=(0, 0, 0), strides=(1, 1, 1), begin_mask=(0, 0, 0), end_mask=(0, 0, 0), + shrink_axis_mask=(0, 0, 1), new_axis_mask=(0, 1, 0), ellipsis_mask=(1, 0, 0) + ) + + def test_normalizer_auto_infer_strided_slice_3d_over_3d_2(self): + """ + inp_shape = (1, 100, 200), out = inp[0, None, ...] => out_shape = (1, 100, 200) + """ + self.run_infer_test( + inp=(1, 100, 200), ref_res=(1, 100, 200), + begin=(0, 0, 0), end=(0, 0, 0), strides=(1, 1, 1), begin_mask=(0, 0, 0), end_mask=(0, 0, 0), + shrink_axis_mask=(1, 0, 0), new_axis_mask=(0, 1, 0), ellipsis_mask=(0, 0, 1) + ) + + def test_normalizer_auto_infer_strided_slice_3d_over_3d_3(self): + """ + inp_shape = (1, 100, 200), out = inp[0, ..., None] => out_shape = (100, 200, 1) + """ + self.run_infer_test( + inp=(1, 100, 200), ref_res=(100, 200, 1), + begin=(0, 0, 0), end=(0, 0, 0), strides=(1, 1, 1), begin_mask=(0, 0, 0), end_mask=(0, 0, 0), + shrink_axis_mask=(1, 0, 0), new_axis_mask=(0, 0, 1), ellipsis_mask=(0, 1, 0) + ) + + def test_normalizer_auto_infer_strided_slice_3d_over_3d_4(self): + """ + inp_shape = (1, 100, 200), out = inp[None, 0, ...] => out_shape = (1, 100, 200) + """ + self.run_infer_test( + inp=(1, 100, 200), ref_res=(1, 100, 200), + begin=(0, 0, 0), end=(0, 0, 0), strides=(1, 1, 1), begin_mask=(0, 0, 0), end_mask=(0, 0, 0), + shrink_axis_mask=(0, 1, 0), new_axis_mask=(1, 0, 0), ellipsis_mask=(0, 0, 1) + ) + + def test_normalizer_auto_infer_strided_slice_3d_over_3d_5(self): + """ + inp_shape = (1, 100, 200), out = inp[..., 0, None] => out_shape = (1, 100, 1) + """ + self.run_infer_test( + inp=(1, 100, 200), ref_res=(1, 100, 1), + begin=(0, 0, 0), end=(0, 0, 0), strides=(1, 1, 1), begin_mask=(0, 0, 0), end_mask=(0, 0, 0), + shrink_axis_mask=(0, 1, 0), new_axis_mask=(0, 0, 1), ellipsis_mask=(1, 0, 0) + ) + + def test_normalizer_auto_infer_strided_slice_3d_over_4d_0(self): + """ + inp_shape = (1, 100, 200, 3), out = inp[None, ..., 0, :] => out_shape = (1, 1, 100, 3) + """ + self.run_infer_test( + inp=(1, 100, 200, 3), ref_res=(1, 1, 100, 3), + begin=(0, 0, 0, 0), end=(0, 0, 0, 0), strides=(1, 1, 1, 1), begin_mask=(0, 0, 0, 0), end_mask=(0, 0, 0, 0), + shrink_axis_mask=(0, 0, 1, 0), new_axis_mask=(1, 0, 0, 0), ellipsis_mask=(0, 1, 0, 0) + ) + + def test_normalizer_auto_infer_strided_slice_3d_over_4d_1(self): + """ + inp_shape = (1, 100, 200, 3), out = inp[..., None, 0, :] => out_shape = (1, 100, 1, 3) + """ + self.run_infer_test( + inp=(1, 100, 200, 3), ref_res=(1, 100, 1, 3), + begin=(0, 0, 0, 0), end=(0, 0, 0, 0), strides=(1, 1, 1, 1), begin_mask=(0, 0, 0, 0), end_mask=(0, 0, 0, 0), + shrink_axis_mask=(0, 0, 1, 0), new_axis_mask=(0, 1, 0, 0), ellipsis_mask=(1, 0, 0, 0) + ) + + def test_normalizer_auto_infer_strided_slice_3d_over_4d_2(self): + """ + inp_shape = (1, 100, 200, 3), out = inp[0, None, ..., :] => out_shape = (1, 100, 200, 3) + """ + self.run_infer_test( + inp=(1, 100, 200, 3), ref_res=(1, 100, 200, 3), + begin=(0, 0, 0, 0), end=(0, 0, 0, 0), strides=(1, 1, 1, 1), begin_mask=(0, 0, 0, 0), end_mask=(0, 0, 0, 0), + shrink_axis_mask=(1, 0, 0, 0), new_axis_mask=(0, 1, 0, 0), ellipsis_mask=(0, 0, 1, 0) + ) + + def test_normalizer_auto_infer_strided_slice_3d_over_4d_3(self): + """ + inp_shape = (1, 100, 200, 3), out = inp[0, ..., None, :] => out_shape = (100, 200, 1, 3) + """ + self.run_infer_test( + inp=(1, 100, 200, 3), ref_res=(100, 200, 1, 3), + begin=(0, 0, 0, 0), end=(0, 0, 0, 0), strides=(1, 1, 1, 1), begin_mask=(0, 0, 0, 0), end_mask=(0, 0, 0, 0), + shrink_axis_mask=(1, 0, 0, 0), new_axis_mask=(0, 0, 1, 0), ellipsis_mask=(0, 1, 0, 0) + ) + + def test_normalizer_auto_infer_strided_slice_3d_over_4d_4(self): + """ + inp_shape = (1, 100, 200, 3), out = inp[None, 0, ..., :] => out_shape = (1, 100, 200, 3) + """ + self.run_infer_test( + inp=(1, 100, 200, 3), ref_res=(1, 100, 200, 3), + begin=(0, 0, 0, 0), end=(0, 0, 0, 0), strides=(1, 1, 1, 1), begin_mask=(0, 0, 0, 0), end_mask=(0, 0, 0, 0), + shrink_axis_mask=(0, 1, 0, 0), new_axis_mask=(1, 0, 0, 0), ellipsis_mask=(0, 0, 1, 0) + ) + + def test_normalizer_auto_infer_strided_slice_3d_over_4d_5(self): + """ + inp_shape = (1, 100, 200, 3), out = inp[..., 0, None, :] => out_shape = (1, 100, 1, 3) + """ + self.run_infer_test( + inp=(1, 100, 200, 3), ref_res=(1, 100, 1, 3), + begin=(0, 0, 0, 0), end=(0, 0, 0, 0), strides=(1, 1, 1, 1), begin_mask=(0, 0, 0, 0), end_mask=(0, 0, 0, 0), + shrink_axis_mask=(0, 1, 0, 0), new_axis_mask=(0, 0, 1, 0), ellipsis_mask=(1, 0, 0, 0) + ) + + def test_normalizer_auto_infer_strided_slice_3d_over_5d_0(self): + """ + inp_shape = (1, 100, 200, 10, 3), out = inp[None, ..., 0, :, :] => out_shape = (1, 1, 100, 10, 3) + """ + self.run_infer_test( + inp=(1, 100, 200, 10, 3), ref_res=(1, 1, 100, 10, 3), + begin=(0, 0, 0, 0, 0), end=(0, 0, 0, 0, 0), strides=(1, 1, 1, 1, 1), begin_mask=(0, 0, 0, 0, 0), + end_mask=(0, 0, 0, 0, 0), + shrink_axis_mask=(0, 0, 1, 0, 0), new_axis_mask=(1, 0, 0, 0, 0), ellipsis_mask=(0, 1, 0, 0, 0) + ) + + def test_normalizer_auto_infer_strided_slice_3d_over_5d_1(self): + """ + inp_shape = (1, 100, 200, 10, 3), out = inp[..., None, 0, :, :] => out_shape = (1, 100, 1, 10, 3) + """ + self.run_infer_test( + inp=(1, 100, 200, 10, 3), ref_res=(1, 100, 1, 10, 3), + begin=(0, 0, 0, 0, 0), end=(0, 0, 0, 0, 0), strides=(1, 1, 1, 1, 1), begin_mask=(0, 0, 0, 0, 0), + end_mask=(0, 0, 0, 0, 0), + shrink_axis_mask=(0, 0, 1, 0, 0), new_axis_mask=(0, 1, 0, 0, 0), ellipsis_mask=(1, 0, 0, 0, 0) + ) + + def test_normalizer_auto_infer_strided_slice_3d_over_5d_2(self): + """ + inp_shape = (1, 100, 200, 10, 3), out = inp[0, None, ..., :, :] => out_shape = (1, 100, 200, 10, 3) + """ + self.run_infer_test( + inp=(1, 100, 200, 10, 3), ref_res=(1, 100, 200, 10, 3), + begin=(0, 0, 0, 0, 0), end=(0, 0, 0, 0, 0), strides=(1, 1, 1, 1, 1), begin_mask=(0, 0, 0, 0, 0), + end_mask=(0, 0, 0, 0, 0), + shrink_axis_mask=(1, 0, 0, 0, 0), new_axis_mask=(0, 1, 0, 0, 0), ellipsis_mask=(0, 0, 1, 0, 0) + ) + + def test_normalizer_auto_infer_strided_slice_3d_over_5d_3(self): + """ + inp_shape = (1, 100, 200, 10, 3), out = inp[0, ..., None, :, :] => out_shape = (100, 200, 1, 10, 3) + """ + self.run_infer_test( + inp=(1, 100, 200, 10, 3), ref_res=(100, 200, 1, 10, 3), + begin=(0, 0, 0, 0, 0), end=(0, 0, 0, 0, 0), strides=(1, 1, 1, 1, 1), begin_mask=(0, 0, 0, 0, 0), + end_mask=(0, 0, 0, 0, 0), + shrink_axis_mask=(1, 0, 0, 0, 0), new_axis_mask=(0, 0, 1, 0, 0), ellipsis_mask=(0, 1, 0, 0, 0) + ) + + def test_normalizer_auto_infer_strided_slice_3d_over_5d_4(self): + """ + inp_shape = (1, 100, 200, 10, 3), out = inp[None, 0, ..., :, :] => out_shape = (1, 100, 200, 10, 3) + """ + self.run_infer_test( + inp=(1, 100, 200, 10, 3), ref_res=(1, 100, 200, 10, 3), + begin=(0, 0, 0, 0, 0), end=(0, 0, 0, 0, 0), strides=(1, 1, 1, 1, 1), begin_mask=(0, 0, 0, 0, 0), + end_mask=(0, 0, 0, 0, 0), + shrink_axis_mask=(0, 1, 0, 0, 0), new_axis_mask=(1, 0, 0, 0, 0), ellipsis_mask=(0, 0, 1, 0, 0) + ) + + def test_normalizer_auto_infer_strided_slice_3d_over_5d_5(self): + """ + inp_shape = (1, 100, 200, 10, 3), out = inp[..., 0, None, :, :] => out_shape = (1, 100, 1, 10, 3) + """ + self.run_infer_test( + inp=(1, 100, 200, 10, 3), ref_res=(1, 100, 1, 10, 3), + begin=(0, 0, 0, 0, 0), end=(0, 0, 0, 0, 0), strides=(1, 1, 1, 1, 1), begin_mask=(0, 0, 0, 0, 0), + end_mask=(0, 0, 0, 0, 0), + shrink_axis_mask=(0, 1, 0, 0, 0), new_axis_mask=(0, 0, 1, 0, 0), ellipsis_mask=(1, 0, 0, 0, 0) + ) + + def test_normalizer_auto_infer_strided_slice_4d_over_4d_0(self): + """ + inp_shape = (1, 100, 200, 3), out = inp[None, ..., 0, :] => out_shape = (1, 1, 100, 3) + """ + self.run_infer_test( + inp=(1, 100, 200, 3), ref_res=(1, 1, 100, 3), + begin=(0, 0, 0, 0), end=(0, 0, 0, 0), strides=(1, 1, 1, 1), begin_mask=(0, 0, 0, 0), end_mask=(0, 0, 0, 0), + shrink_axis_mask=(0, 0, 1, 0), new_axis_mask=(1, 0, 0, 0), ellipsis_mask=(0, 1, 0, 0) + ) + + def test_normalizer_auto_infer_strided_slice_4d_over_4d_1(self): + """ + inp_shape = (1, 100, 200, 3), out = inp[..., None, 0, :] => out_shape = (1, 100, 1, 3) + """ + self.run_infer_test( + inp=(1, 100, 200, 3), ref_res=(1, 100, 1, 3), + begin=(0, 0, 0, 0), end=(0, 0, 0, 0), strides=(1, 1, 1, 1), begin_mask=(0, 0, 0, 0), end_mask=(0, 0, 0, 0), + shrink_axis_mask=(0, 0, 1, 0), new_axis_mask=(0, 1, 0, 0), ellipsis_mask=(1, 0, 0, 0) + ) + + def test_normalizer_auto_infer_strided_slice_4d_over_4d_2(self): + """ + inp_shape = (1, 100, 200, 3), out = inp[0, None, ..., :] => out_shape = (1, 100, 200, 3) + """ + self.run_infer_test( + inp=(1, 100, 200, 3), ref_res=(1, 100, 200, 3), + begin=(0, 0, 0, 0), end=(0, 0, 0, 0), strides=(1, 1, 1, 1), begin_mask=(0, 0, 0, 0), end_mask=(0, 0, 0, 0), + shrink_axis_mask=(1, 0, 0, 0), new_axis_mask=(0, 1, 0, 0), ellipsis_mask=(0, 0, 1, 0) + ) + + def test_normalizer_auto_infer_strided_slice_4d_over_4d_3(self): + """ + inp_shape = (1, 100, 200, 3), out = inp[0, ..., None, :] => out_shape = (100, 200, 1, 3) + """ + self.run_infer_test( + inp=(1, 100, 200, 3), ref_res=(100, 200, 1, 3), + begin=(0, 0, 0, 0), end=(0, 0, 0, 0), strides=(1, 1, 1, 1), begin_mask=(0, 0, 0, 0), end_mask=(0, 0, 0, 0), + shrink_axis_mask=(1, 0, 0, 0), new_axis_mask=(0, 0, 1, 0), ellipsis_mask=(0, 1, 0, 0) + ) + + def test_normalizer_auto_infer_strided_slice_4d_over_4d_4(self): + """ + inp_shape = (1, 100, 200, 3), out = inp[None, 0, ..., :] => out_shape = (1, 100, 200, 3) + """ + self.run_infer_test( + inp=(1, 100, 200, 3), ref_res=(1, 100, 200, 3), + begin=(0, 0, 0, 0), end=(0, 0, 0, 0), strides=(1, 1, 1, 1), begin_mask=(0, 0, 0, 0), end_mask=(0, 0, 0, 0), + shrink_axis_mask=(0, 1, 0, 0), new_axis_mask=(1, 0, 0, 0), ellipsis_mask=(0, 0, 1, 0) + ) + + def test_normalizer_auto_infer_strided_slice_4d_over_4d_5(self): + """ + inp_shape = (1, 100, 200, 3), out = inp[..., 0, None, :] => out_shape = (1, 100, 1, 3) + """ + self.run_infer_test( + inp=(1, 100, 200, 3), ref_res=(1, 100, 1, 3), + begin=(0, 0, 0, 0), end=(0, 0, 0, 0), strides=(1, 1, 1, 1), begin_mask=(0, 0, 0, 0), end_mask=(0, 0, 0, 0), + shrink_axis_mask=(0, 1, 0, 0), new_axis_mask=(0, 0, 1, 0), ellipsis_mask=(1, 0, 0, 0) + ) + + def test_normalizer_auto_infer_strided_slice_4d_over_4d_6(self): + """ + inp_shape = (1, 100, 200, 3), out = inp[None, ..., :, 0] => out_shape = (1, 1, 100, 200) + """ + self.run_infer_test( + inp=(1, 100, 200, 3), ref_res=(1, 1, 100, 200), + begin=(0, 0, 0, 0), end=(0, 0, 0, 0), strides=(1, 1, 1, 1), begin_mask=(0, 0, 0, 0), end_mask=(0, 0, 0, 0), + shrink_axis_mask=(0, 0, 0, 1), new_axis_mask=(1, 0, 0, 0), ellipsis_mask=(0, 1, 0, 0) + ) + + def test_normalizer_auto_infer_strided_slice_4d_over_4d_7(self): + """ + inp_shape = (1, 100, 200, 3), out = inp[..., None, :, 0] => out_shape = (1, 100, 1, 200) + """ + self.run_infer_test( + inp=(1, 100, 200, 3), ref_res=(1, 100, 1, 200), + begin=(0, 0, 0, 0), end=(0, 0, 0, 0), strides=(1, 1, 1, 1), begin_mask=(0, 0, 0, 0), end_mask=(0, 0, 0, 0), + shrink_axis_mask=(0, 0, 0, 1), new_axis_mask=(0, 1, 0, 0), ellipsis_mask=(1, 0, 0, 0) + ) + + def test_normalizer_auto_infer_strided_slice_4d_over_4d_8(self): + """ + inp_shape = (1, 100, 200, 3), out = inp[0, None, :, ...] => out_shape = (1, 100, 200, 3) + """ + self.run_infer_test( + inp=(1, 100, 200, 3), ref_res=(1, 100, 200, 3), + begin=(0, 0, 0, 0), end=(0, 0, 0, 0), strides=(1, 1, 1, 1), begin_mask=(0, 0, 0, 0), end_mask=(0, 0, 0, 0), + shrink_axis_mask=(1, 0, 0, 0), new_axis_mask=(0, 1, 0, 0), ellipsis_mask=(0, 0, 0, 1) + ) + + def test_normalizer_auto_infer_strided_slice_4d_over_4d_9(self): + """ + inp_shape = (1, 100, 200, 3), out = inp[0, ..., :, None] => out_shape = (100, 200, 3, 1) + """ + self.run_infer_test( + inp=(1, 100, 200, 3), ref_res=(100, 200, 3, 1), + begin=(0, 0, 0, 0), end=(0, 0, 0, 0), strides=(1, 1, 1, 1), begin_mask=(0, 0, 0, 0), end_mask=(0, 0, 0, 0), + shrink_axis_mask=(1, 0, 0, 0), new_axis_mask=(0, 0, 0, 1), ellipsis_mask=(0, 1, 0, 0) + ) + + def test_normalizer_auto_infer_strided_slice_4d_over_4d_10(self): + """ + inp_shape = (1, 100, 200, 3), out = inp[None, 0, :, ...] => out_shape = (1, 100, 200, 3) + """ + self.run_infer_test( + inp=(1, 100, 200, 3), ref_res=(1, 100, 200, 3), + begin=(0, 0, 0, 0), end=(0, 0, 0, 0), strides=(1, 1, 1, 1), begin_mask=(0, 0, 0, 0), end_mask=(0, 0, 0, 0), + shrink_axis_mask=(0, 1, 0, 0), new_axis_mask=(1, 0, 0, 0), ellipsis_mask=(0, 0, 0, 1) + ) + + def test_normalizer_auto_infer_strided_slice_4d_over_4d_11(self): + """ + inp_shape = (1, 100, 200, 3), out = inp[..., 0, :, None] => out_shape = (1, 100, 3, 1) + """ + self.run_infer_test( + inp=(1, 100, 200, 3), ref_res=(1, 100, 3, 1), + begin=(0, 0, 0, 0), end=(0, 0, 0, 0), strides=(1, 1, 1, 1), begin_mask=(0, 0, 0, 0), end_mask=(0, 0, 0, 0), + shrink_axis_mask=(0, 1, 0, 0), new_axis_mask=(0, 0, 0, 1), ellipsis_mask=(1, 0, 0, 0) + ) + + def test_normalizer_auto_infer_strided_slice_4d_over_4d_12(self): + """ + inp_shape = (1, 100, 200, 3), out = inp[None, :, ..., 0] => out_shape = (1, 1, 100, 200) + """ + self.run_infer_test( + inp=(1, 100, 200, 3), ref_res=(1, 1, 100, 200), + begin=(0, 0, 0, 0), end=(0, 0, 0, 0), strides=(1, 1, 1, 1), begin_mask=(0, 0, 0, 0), end_mask=(0, 0, 0, 0), + shrink_axis_mask=(0, 0, 0, 1), new_axis_mask=(1, 0, 0, 0), ellipsis_mask=(0, 0, 1, 0) + ) + + def test_normalizer_auto_infer_strided_slice_4d_over_4d_13(self): + """ + inp_shape = (1, 100, 200, 3), out = inp[..., :, None, 0] => out_shape = (1, 100, 200, 1) + """ + self.run_infer_test( + inp=(1, 100, 200, 3), ref_res=(1, 100, 200, 1), + begin=(0, 0, 0, 0), end=(0, 0, 0, 0), strides=(1, 1, 1, 1), begin_mask=(0, 0, 0, 0), end_mask=(0, 0, 0, 0), + shrink_axis_mask=(0, 0, 0, 1), new_axis_mask=(0, 0, 1, 0), ellipsis_mask=(1, 0, 0, 0) + ) + + def test_normalizer_auto_infer_strided_slice_4d_over_4d_14(self): + """ + inp_shape = (1, 100, 200, 3), out = inp[0, :, None, ...] => out_shape = (100, 1, 200, 3) + """ + self.run_infer_test( + inp=(1, 100, 200, 3), ref_res=(100, 1, 200, 3), + begin=(0, 0, 0, 0), end=(0, 0, 0, 0), strides=(1, 1, 1, 1), begin_mask=(0, 0, 0, 0), end_mask=(0, 0, 0, 0), + shrink_axis_mask=(1, 0, 0, 0), new_axis_mask=(0, 0, 1, 0), ellipsis_mask=(0, 0, 0, 1) + ) + + def test_normalizer_auto_infer_strided_slice_4d_over_4d_15(self): + """ + inp_shape = (1, 100, 200, 3), out = inp[0, :, ..., None] => out_shape = (100, 200, 3, 1) + """ + self.run_infer_test( + inp=(1, 100, 200, 3), ref_res=(100, 200, 3, 1), + begin=(0, 0, 0, 0), end=(0, 0, 0, 0), strides=(1, 1, 1, 1), begin_mask=(0, 0, 0, 0), end_mask=(0, 0, 0, 0), + shrink_axis_mask=(1, 0, 0, 0), new_axis_mask=(0, 0, 0, 1), ellipsis_mask=(0, 0, 1, 0) + ) + + def test_normalizer_auto_infer_strided_slice_4d_over_4d_16(self): + """ + inp_shape = (1, 100, 200, 3), out = inp[None, :, 0, ...] => out_shape = (1, 1, 200, 3) + """ + self.run_infer_test( + inp=(1, 100, 200, 3), ref_res=(1, 1, 200, 3), + begin=(0, 0, 0, 0), end=(0, 0, 0, 0), strides=(1, 1, 1, 1), begin_mask=(0, 0, 0, 0), end_mask=(0, 0, 0, 0), + shrink_axis_mask=(0, 0, 1, 0), new_axis_mask=(1, 0, 0, 0), ellipsis_mask=(0, 0, 0, 1) + ) + + def test_normalizer_auto_infer_strided_slice_4d_over_4d_17(self): + """ + inp_shape = (1, 100, 200, 3), out = inp[..., :, 0, None] => out_shape = (1, 100, 200, 1) + """ + self.run_infer_test( + inp=(1, 100, 200, 3), ref_res=(1, 100, 200, 1), + begin=(0, 0, 0, 0), end=(0, 0, 0, 0), strides=(1, 1, 1, 1), begin_mask=(0, 0, 0, 0), end_mask=(0, 0, 0, 0), + shrink_axis_mask=(0, 0, 1, 0), new_axis_mask=(0, 0, 0, 1), ellipsis_mask=(1, 0, 0, 0) + ) + + def test_normalizer_auto_infer_strided_slice_4d_over_4d_18(self): + """ + inp_shape = (1, 100, 200, 3), out = inp[:, None, ..., 0] => out_shape = (1, 1, 100, 200) + """ + self.run_infer_test( + inp=(1, 100, 200, 3), ref_res=(1, 1, 100, 200), + begin=(0, 0, 0, 0), end=(0, 0, 0, 0), strides=(1, 1, 1, 1), begin_mask=(0, 0, 0, 0), end_mask=(0, 0, 0, 0), + shrink_axis_mask=(0, 0, 0, 1), new_axis_mask=(0, 1, 0, 0), ellipsis_mask=(0, 0, 1, 0) + ) + + def test_normalizer_auto_infer_strided_slice_4d_over_4d_19(self): + """ + inp_shape = (1, 100, 200, 3), out = inp[:, ..., None, 0] => out_shape = (1, 100, 200, 1) + """ + self.run_infer_test( + inp=(1, 100, 200, 3), ref_res=(1, 100, 200, 1), + begin=(0, 0, 0, 0), end=(0, 0, 0, 0), strides=(1, 1, 1, 1), begin_mask=(0, 0, 0, 0), end_mask=(0, 0, 0, 0), + shrink_axis_mask=(0, 0, 0, 1), new_axis_mask=(0, 0, 1, 0), ellipsis_mask=(0, 1, 0, 0) + ) + + def test_normalizer_auto_infer_strided_slice_4d_over_4d_20(self): + """ + inp_shape = (1, 100, 200, 3), out = inp[:, 0, None, ...] => out_shape = (1, 1, 200, 3) + """ + self.run_infer_test( + inp=(1, 100, 200, 3), ref_res=(1, 1, 200, 3), + begin=(0, 0, 0, 0), end=(0, 0, 0, 0), strides=(1, 1, 1, 1), begin_mask=(0, 0, 0, 0), end_mask=(0, 0, 0, 0), + shrink_axis_mask=(0, 1, 0, 0), new_axis_mask=(0, 0, 1, 0), ellipsis_mask=(0, 0, 0, 1) + ) + + def test_normalizer_auto_infer_strided_slice_4d_over_4d_21(self): + """ + inp_shape = (1, 100, 200, 3), out = inp[:, 0, ..., None] => out_shape = (1, 200, 3, 1) + """ + self.run_infer_test( + inp=(1, 100, 200, 3), ref_res=(1, 200, 3, 1), + begin=(0, 0, 0, 0), end=(0, 0, 0, 0), strides=(1, 1, 1, 1), begin_mask=(0, 0, 0, 0), end_mask=(0, 0, 0, 0), + shrink_axis_mask=(0, 1, 0, 0), new_axis_mask=(0, 0, 0, 1), ellipsis_mask=(0, 0, 1, 0) + ) + + def test_normalizer_auto_infer_strided_slice_4d_over_4d_22(self): + """ + inp_shape = (1, 100, 200, 3), out = inp[:, None, 0, ...] => out_shape = (1, 1, 200, 3) + """ + self.run_infer_test( + inp=(1, 100, 200, 3), ref_res=(1, 1, 200, 3), + begin=(0, 0, 0, 0), end=(0, 0, 0, 0), strides=(1, 1, 1, 1), begin_mask=(0, 0, 0, 0), end_mask=(0, 0, 0, 0), + shrink_axis_mask=(0, 0, 1, 0), new_axis_mask=(0, 1, 0, 0), ellipsis_mask=(0, 0, 0, 1) + ) + + def test_normalizer_auto_infer_strided_slice_4d_over_4d_23(self): + """ + inp_shape = (1, 100, 200, 3), out = inp[:, ..., 0, None] => out_shape = (1, 100, 200, 1) + """ + self.run_infer_test( + inp=(1, 100, 200, 3), ref_res=(1, 100, 200, 1), + begin=(0, 0, 0, 0), end=(0, 0, 0, 0), strides=(1, 1, 1, 1), begin_mask=(0, 0, 0, 0), end_mask=(0, 0, 0, 0), + shrink_axis_mask=(0, 0, 1, 0), new_axis_mask=(0, 0, 0, 1), ellipsis_mask=(0, 1, 0, 0) + ) + + def test_normalizer_auto_infer_strided_slice_4d_over_5d_0(self): + """ + inp_shape = (1, 100, 200, 10, 3), out = inp[None, ..., 0, :, :] => out_shape = (1, 1, 100, 10, 3) + """ + self.run_infer_test( + inp=(1, 100, 200, 10, 3), ref_res=(1, 1, 100, 10, 3), + begin=(0, 0, 0, 0, 0), end=(0, 0, 0, 0, 0), strides=(1, 1, 1, 1, 1), begin_mask=(0, 0, 0, 0, 0), + end_mask=(0, 0, 0, 0, 0), + shrink_axis_mask=(0, 0, 1, 0, 0), new_axis_mask=(1, 0, 0, 0, 0), ellipsis_mask=(0, 1, 0, 0, 0) + ) + + def test_normalizer_auto_infer_strided_slice_4d_over_5d_1(self): + """ + inp_shape = (1, 100, 200, 10, 3), out = inp[..., None, 0, :, :] => out_shape = (1, 100, 1, 10, 3) + """ + self.run_infer_test( + inp=(1, 100, 200, 10, 3), ref_res=(1, 100, 1, 10, 3), + begin=(0, 0, 0, 0, 0), end=(0, 0, 0, 0, 0), strides=(1, 1, 1, 1, 1), begin_mask=(0, 0, 0, 0, 0), + end_mask=(0, 0, 0, 0, 0), + shrink_axis_mask=(0, 0, 1, 0, 0), new_axis_mask=(0, 1, 0, 0, 0), ellipsis_mask=(1, 0, 0, 0, 0) + ) + + def test_normalizer_auto_infer_strided_slice_4d_over_5d_2(self): + """ + inp_shape = (1, 100, 200, 10, 3), out = inp[0, None, ..., :, :] => out_shape = (1, 100, 200, 10, 3) + """ + self.run_infer_test( + inp=(1, 100, 200, 10, 3), ref_res=(1, 100, 200, 10, 3), + begin=(0, 0, 0, 0, 0), end=(0, 0, 0, 0, 0), strides=(1, 1, 1, 1, 1), begin_mask=(0, 0, 0, 0, 0), + end_mask=(0, 0, 0, 0, 0), + shrink_axis_mask=(1, 0, 0, 0, 0), new_axis_mask=(0, 1, 0, 0, 0), ellipsis_mask=(0, 0, 1, 0, 0) + ) + + def test_normalizer_auto_infer_strided_slice_4d_over_5d_3(self): + """ + inp_shape = (1, 100, 200, 10, 3), out = inp[0, ..., None, :, :] => out_shape = (100, 200, 1, 10, 3) + """ + self.run_infer_test( + inp=(1, 100, 200, 10, 3), ref_res=(100, 200, 1, 10, 3), + begin=(0, 0, 0, 0, 0), end=(0, 0, 0, 0, 0), strides=(1, 1, 1, 1, 1), begin_mask=(0, 0, 0, 0, 0), + end_mask=(0, 0, 0, 0, 0), + shrink_axis_mask=(1, 0, 0, 0, 0), new_axis_mask=(0, 0, 1, 0, 0), ellipsis_mask=(0, 1, 0, 0, 0) + ) + + def test_normalizer_auto_infer_strided_slice_4d_over_5d_4(self): + """ + inp_shape = (1, 100, 200, 10, 3), out = inp[None, 0, ..., :, :] => out_shape = (1, 100, 200, 10, 3) + """ + self.run_infer_test( + inp=(1, 100, 200, 10, 3), ref_res=(1, 100, 200, 10, 3), + begin=(0, 0, 0, 0, 0), end=(0, 0, 0, 0, 0), strides=(1, 1, 1, 1, 1), begin_mask=(0, 0, 0, 0, 0), + end_mask=(0, 0, 0, 0, 0), + shrink_axis_mask=(0, 1, 0, 0, 0), new_axis_mask=(1, 0, 0, 0, 0), ellipsis_mask=(0, 0, 1, 0, 0) + ) + + def test_normalizer_auto_infer_strided_slice_4d_over_5d_5(self): + """ + inp_shape = (1, 100, 200, 10, 3), out = inp[..., 0, None, :, :] => out_shape = (1, 100, 1, 10, 3) + """ + self.run_infer_test( + inp=(1, 100, 200, 10, 3), ref_res=(1, 100, 1, 10, 3), + begin=(0, 0, 0, 0, 0), end=(0, 0, 0, 0, 0), strides=(1, 1, 1, 1, 1), begin_mask=(0, 0, 0, 0, 0), + end_mask=(0, 0, 0, 0, 0), + shrink_axis_mask=(0, 1, 0, 0, 0), new_axis_mask=(0, 0, 1, 0, 0), ellipsis_mask=(1, 0, 0, 0, 0) + ) + + def test_normalizer_auto_infer_strided_slice_4d_over_5d_6(self): + """ + inp_shape = (1, 100, 200, 10, 3), out = inp[None, ..., :, 0, :] => out_shape = (1, 1, 100, 200, 3) + """ + self.run_infer_test( + inp=(1, 100, 200, 10, 3), ref_res=(1, 1, 100, 200, 3), + begin=(0, 0, 0, 0, 0), end=(0, 0, 0, 0, 0), strides=(1, 1, 1, 1, 1), begin_mask=(0, 0, 0, 0, 0), + end_mask=(0, 0, 0, 0, 0), + shrink_axis_mask=(0, 0, 0, 1, 0), new_axis_mask=(1, 0, 0, 0, 0), ellipsis_mask=(0, 1, 0, 0, 0) + ) + + def test_normalizer_auto_infer_strided_slice_4d_over_5d_7(self): + """ + inp_shape = (1, 100, 200, 10, 3), out = inp[..., None, :, 0, :] => out_shape = (1, 100, 1, 200, 3) + """ + self.run_infer_test( + inp=(1, 100, 200, 10, 3), ref_res=(1, 100, 1, 200, 3), + begin=(0, 0, 0, 0, 0), end=(0, 0, 0, 0, 0), strides=(1, 1, 1, 1, 1), begin_mask=(0, 0, 0, 0, 0), + end_mask=(0, 0, 0, 0, 0), + shrink_axis_mask=(0, 0, 0, 1, 0), new_axis_mask=(0, 1, 0, 0, 0), ellipsis_mask=(1, 0, 0, 0, 0) + ) + + def test_normalizer_auto_infer_strided_slice_4d_over_5d_8(self): + """ + inp_shape = (1, 100, 200, 10, 3), out = inp[0, None, :, ..., :] => out_shape = (1, 100, 200, 10, 3) + """ + self.run_infer_test( + inp=(1, 100, 200, 10, 3), ref_res=(1, 100, 200, 10, 3), + begin=(0, 0, 0, 0, 0), end=(0, 0, 0, 0, 0), strides=(1, 1, 1, 1, 1), begin_mask=(0, 0, 0, 0, 0), + end_mask=(0, 0, 0, 0, 0), + shrink_axis_mask=(1, 0, 0, 0, 0), new_axis_mask=(0, 1, 0, 0, 0), ellipsis_mask=(0, 0, 0, 1, 0) + ) + + def test_normalizer_auto_infer_strided_slice_4d_over_5d_9(self): + """ + inp_shape = (1, 100, 200, 10, 3), out = inp[0, ..., :, None, :] => out_shape = (100, 200, 10, 1, 3) + """ + self.run_infer_test( + inp=(1, 100, 200, 10, 3), ref_res=(100, 200, 10, 1, 3), + begin=(0, 0, 0, 0, 0), end=(0, 0, 0, 0, 0), strides=(1, 1, 1, 1, 1), begin_mask=(0, 0, 0, 0, 0), + end_mask=(0, 0, 0, 0, 0), + shrink_axis_mask=(1, 0, 0, 0, 0), new_axis_mask=(0, 0, 0, 1, 0), ellipsis_mask=(0, 1, 0, 0, 0) + ) + + def test_normalizer_auto_infer_strided_slice_4d_over_5d_10(self): + """ + inp_shape = (1, 100, 200, 10, 3), out = inp[None, 0, :, ..., :] => out_shape = (1, 100, 200, 10, 3) + """ + self.run_infer_test( + inp=(1, 100, 200, 10, 3), ref_res=(1, 100, 200, 10, 3), + begin=(0, 0, 0, 0, 0), end=(0, 0, 0, 0, 0), strides=(1, 1, 1, 1, 1), begin_mask=(0, 0, 0, 0, 0), + end_mask=(0, 0, 0, 0, 0), + shrink_axis_mask=(0, 1, 0, 0, 0), new_axis_mask=(1, 0, 0, 0, 0), ellipsis_mask=(0, 0, 0, 1, 0) + ) + + def test_normalizer_auto_infer_strided_slice_4d_over_5d_11(self): + """ + inp_shape = (1, 100, 200, 10, 3), out = inp[..., 0, :, None, :] => out_shape = (1, 100, 10, 1, 3) + """ + self.run_infer_test( + inp=(1, 100, 200, 10, 3), ref_res=(1, 100, 10, 1, 3), + begin=(0, 0, 0, 0, 0), end=(0, 0, 0, 0, 0), strides=(1, 1, 1, 1, 1), begin_mask=(0, 0, 0, 0, 0), + end_mask=(0, 0, 0, 0, 0), + shrink_axis_mask=(0, 1, 0, 0, 0), new_axis_mask=(0, 0, 0, 1, 0), ellipsis_mask=(1, 0, 0, 0, 0) + ) + + def test_normalizer_auto_infer_strided_slice_4d_over_5d_12(self): + """ + inp_shape = (1, 100, 200, 10, 3), out = inp[None, :, ..., 0, :] => out_shape = (1, 1, 100, 200, 3) + """ + self.run_infer_test( + inp=(1, 100, 200, 10, 3), ref_res=(1, 1, 100, 200, 3), + begin=(0, 0, 0, 0, 0), end=(0, 0, 0, 0, 0), strides=(1, 1, 1, 1, 1), begin_mask=(0, 0, 0, 0, 0), + end_mask=(0, 0, 0, 0, 0), + shrink_axis_mask=(0, 0, 0, 1, 0), new_axis_mask=(1, 0, 0, 0, 0), ellipsis_mask=(0, 0, 1, 0, 0) + ) + + def test_normalizer_auto_infer_strided_slice_4d_over_5d_13(self): + """ + inp_shape = (1, 100, 200, 10, 3), out = inp[..., :, None, 0, :] => out_shape = (1, 100, 200, 1, 3) + """ + self.run_infer_test( + inp=(1, 100, 200, 10, 3), ref_res=(1, 100, 200, 1, 3), + begin=(0, 0, 0, 0, 0), end=(0, 0, 0, 0, 0), strides=(1, 1, 1, 1, 1), begin_mask=(0, 0, 0, 0, 0), + end_mask=(0, 0, 0, 0, 0), + shrink_axis_mask=(0, 0, 0, 1, 0), new_axis_mask=(0, 0, 1, 0, 0), ellipsis_mask=(1, 0, 0, 0, 0) + ) + + def test_normalizer_auto_infer_strided_slice_4d_over_5d_14(self): + """ + inp_shape = (1, 100, 200, 10, 3), out = inp[0, :, None, ..., :] => out_shape = (100, 1, 200, 10, 3) + """ + self.run_infer_test( + inp=(1, 100, 200, 10, 3), ref_res=(100, 1, 200, 10, 3), + begin=(0, 0, 0, 0, 0), end=(0, 0, 0, 0, 0), strides=(1, 1, 1, 1, 1), begin_mask=(0, 0, 0, 0, 0), + end_mask=(0, 0, 0, 0, 0), + shrink_axis_mask=(1, 0, 0, 0, 0), new_axis_mask=(0, 0, 1, 0, 0), ellipsis_mask=(0, 0, 0, 1, 0) + ) + + def test_normalizer_auto_infer_strided_slice_4d_over_5d_15(self): + """ + inp_shape = (1, 100, 200, 10, 3), out = inp[0, :, ..., None, :] => out_shape = (100, 200, 10, 1, 3) + """ + self.run_infer_test( + inp=(1, 100, 200, 10, 3), ref_res=(100, 200, 10, 1, 3), + begin=(0, 0, 0, 0, 0), end=(0, 0, 0, 0, 0), strides=(1, 1, 1, 1, 1), begin_mask=(0, 0, 0, 0, 0), + end_mask=(0, 0, 0, 0, 0), + shrink_axis_mask=(1, 0, 0, 0, 0), new_axis_mask=(0, 0, 0, 1, 0), ellipsis_mask=(0, 0, 1, 0, 0) + ) + + def test_normalizer_auto_infer_strided_slice_4d_over_5d_16(self): + """ + inp_shape = (1, 100, 200, 10, 3), out = inp[None, :, 0, ..., :] => out_shape = (1, 1, 200, 10, 3) + """ + self.run_infer_test( + inp=(1, 100, 200, 10, 3), ref_res=(1, 1, 200, 10, 3), + begin=(0, 0, 0, 0, 0), end=(0, 0, 0, 0, 0), strides=(1, 1, 1, 1, 1), begin_mask=(0, 0, 0, 0, 0), + end_mask=(0, 0, 0, 0, 0), + shrink_axis_mask=(0, 0, 1, 0, 0), new_axis_mask=(1, 0, 0, 0, 0), ellipsis_mask=(0, 0, 0, 1, 0) + ) + + def test_normalizer_auto_infer_strided_slice_4d_over_5d_17(self): + """ + inp_shape = (1, 100, 200, 10, 3), out = inp[..., :, 0, None, :] => out_shape = (1, 100, 200, 1, 3) + """ + self.run_infer_test( + inp=(1, 100, 200, 10, 3), ref_res=(1, 100, 200, 1, 3), + begin=(0, 0, 0, 0, 0), end=(0, 0, 0, 0, 0), strides=(1, 1, 1, 1, 1), begin_mask=(0, 0, 0, 0, 0), + end_mask=(0, 0, 0, 0, 0), + shrink_axis_mask=(0, 0, 1, 0, 0), new_axis_mask=(0, 0, 0, 1, 0), ellipsis_mask=(1, 0, 0, 0, 0) + ) + + def test_normalizer_auto_infer_strided_slice_4d_over_5d_18(self): + """ + inp_shape = (1, 100, 200, 10, 3), out = inp[:, None, ..., 0, :] => out_shape = (1, 1, 100, 200, 3) + """ + self.run_infer_test( + inp=(1, 100, 200, 10, 3), ref_res=(1, 1, 100, 200, 3), + begin=(0, 0, 0, 0, 0), end=(0, 0, 0, 0, 0), strides=(1, 1, 1, 1, 1), begin_mask=(0, 0, 0, 0, 0), + end_mask=(0, 0, 0, 0, 0), + shrink_axis_mask=(0, 0, 0, 1, 0), new_axis_mask=(0, 1, 0, 0, 0), ellipsis_mask=(0, 0, 1, 0, 0) + ) + + def test_normalizer_auto_infer_strided_slice_4d_over_5d_19(self): + """ + inp_shape = (1, 100, 200, 10, 3), out = inp[:, ..., None, 0, :] => out_shape = (1, 100, 200, 1, 3) + """ + self.run_infer_test( + inp=(1, 100, 200, 10, 3), ref_res=(1, 100, 200, 1, 3), + begin=(0, 0, 0, 0, 0), end=(0, 0, 0, 0, 0), strides=(1, 1, 1, 1, 1), begin_mask=(0, 0, 0, 0, 0), + end_mask=(0, 0, 0, 0, 0), + shrink_axis_mask=(0, 0, 0, 1, 0), new_axis_mask=(0, 0, 1, 0, 0), ellipsis_mask=(0, 1, 0, 0, 0) + ) + + def test_normalizer_auto_infer_strided_slice_4d_over_5d_20(self): + """ + inp_shape = (1, 100, 200, 10, 3), out = inp[:, 0, None, ..., :] => out_shape = (1, 1, 200, 10, 3) + """ + self.run_infer_test( + inp=(1, 100, 200, 10, 3), ref_res=(1, 1, 200, 10, 3), + begin=(0, 0, 0, 0, 0), end=(0, 0, 0, 0, 0), strides=(1, 1, 1, 1, 1), begin_mask=(0, 0, 0, 0, 0), + end_mask=(0, 0, 0, 0, 0), + shrink_axis_mask=(0, 1, 0, 0, 0), new_axis_mask=(0, 0, 1, 0, 0), ellipsis_mask=(0, 0, 0, 1, 0) + ) + + def test_normalizer_auto_infer_strided_slice_4d_over_5d_21(self): + """ + inp_shape = (1, 100, 200, 10, 3), out = inp[:, 0, ..., None, :] => out_shape = (1, 200, 10, 1, 3) + """ + self.run_infer_test( + inp=(1, 100, 200, 10, 3), ref_res=(1, 200, 10, 1, 3), + begin=(0, 0, 0, 0, 0), end=(0, 0, 0, 0, 0), strides=(1, 1, 1, 1, 1), begin_mask=(0, 0, 0, 0, 0), + end_mask=(0, 0, 0, 0, 0), + shrink_axis_mask=(0, 1, 0, 0, 0), new_axis_mask=(0, 0, 0, 1, 0), ellipsis_mask=(0, 0, 1, 0, 0) + ) + + def test_normalizer_auto_infer_strided_slice_4d_over_5d_22(self): + """ + inp_shape = (1, 100, 200, 10, 3), out = inp[:, None, 0, ..., :] => out_shape = (1, 1, 200, 10, 3) + """ + self.run_infer_test( + inp=(1, 100, 200, 10, 3), ref_res=(1, 1, 200, 10, 3), + begin=(0, 0, 0, 0, 0), end=(0, 0, 0, 0, 0), strides=(1, 1, 1, 1, 1), begin_mask=(0, 0, 0, 0, 0), + end_mask=(0, 0, 0, 0, 0), + shrink_axis_mask=(0, 0, 1, 0, 0), new_axis_mask=(0, 1, 0, 0, 0), ellipsis_mask=(0, 0, 0, 1, 0) + ) + + def test_normalizer_auto_infer_strided_slice_4d_over_5d_23(self): + """ + inp_shape = (1, 100, 200, 10, 3), out = inp[:, ..., 0, None, :] => out_shape = (1, 100, 200, 1, 3) + """ + self.run_infer_test( + inp=(1, 100, 200, 10, 3), ref_res=(1, 100, 200, 1, 3), + begin=(0, 0, 0, 0, 0), end=(0, 0, 0, 0, 0), strides=(1, 1, 1, 1, 1), begin_mask=(0, 0, 0, 0, 0), + end_mask=(0, 0, 0, 0, 0), + shrink_axis_mask=(0, 0, 1, 0, 0), new_axis_mask=(0, 0, 0, 1, 0), ellipsis_mask=(0, 1, 0, 0, 0) + ) + + +class TestStridedSlicePermute(unittest.TestCase): + def run_permute_test(self, inp, ref_res, begin, end, strides, begin_mask, end_mask, + shrink_axis_mask, new_axis_mask, ellipsis_mask): + from extensions.middle.ApplyPermutations import ApplyPermutation + from extensions.middle.ApplyNHWCtoNCHWpermutation import ApplyNHWCtoNCHWpermutation + nodes = { + **regular_op_with_shaped_data('input', int64_array(inp), {'op': 'Parameter', 'type': 'Parameter', + # need to specify shape in 2 places + 'shape': int64_array(inp), + 'infer': Parameter.infer}), + **valued_const_with_data('begin', int64_array(begin)), + **valued_const_with_data('end', int64_array(end)), + **valued_const_with_data('strides', int64_array(strides)), + **regular_op_with_empty_data('strided_slice', {'op': 'StridedSlice', 'type': 'StridedSlice', # need for permute + 'begin_mask': begin_mask, 'end_mask': end_mask, + 'shrink_axis_mask': shrink_axis_mask, + 'new_axis_mask': new_axis_mask, + 'ellipsis_mask': ellipsis_mask, + 'infer': StridedSlice.infer}), + **regular_op('res', {'kind': 'op', 'type': 'Result', 'op': 'Result', 'infer': lambda x: None}) + } + + graph = build_graph(nodes, edges, nodes_with_edges_only=True) + graph.stage = 'middle' + graph.graph['layout'] = 'NHWC' + + graph = partial_infer(graph) + StridedSliceNormalizer().find_and_replace_pattern(graph) + graph = partial_infer(graph) + ApplyNHWCtoNCHWpermutation().find_and_replace_pattern(graph) + ApplyPermutation().find_and_replace_pattern(graph) + graph = partial_infer(graph) + + node = Node(graph, 'strided_slice') + res = node.out_port(0).data.get_shape() + npt.assert_array_equal(res, ref_res) + + def test_strided_slice_permute_1( + self, # inp[0, :34, 20, :2] + inp=(1, 35, 35, 3), ref_res=(2, 34), + begin=(0, 0, 0, 0), end=(1, 34, 20, 2), strides=(1, 1, 1, 1), + begin_mask=(0,), end_mask=(0,), + shrink_axis_mask=(1, 0, 1, 0), new_axis_mask=(0,), + ellipsis_mask=(0,) + ): + self.run_permute_test(inp, ref_res, begin, end, strides, + begin_mask, end_mask, shrink_axis_mask, new_axis_mask, ellipsis_mask) + + def test_strided_slice_permute_2( + self, # inp[0:3, 0:1, 5:0:-1] + inp=(10, 10, 10, 10), ref_res=(3, 10, 1, 5), + begin=(0, 0, 5), end=(3, 1, 0), 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_permute_test(inp, ref_res, begin, end, strides, + begin_mask, end_mask, shrink_axis_mask, new_axis_mask, ellipsis_mask) + + def test_strided_slice_permute_3( + self, # inp[1:34, 0, :, :2] + inp=(1, 35, 35, 3), ref_res=(1, 2, 35), + begin=(0, 0, 0, 0), end=(1, 34, 0, 2), 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_permute_test(inp, ref_res, begin, end, strides, + begin_mask, end_mask, shrink_axis_mask, new_axis_mask, ellipsis_mask) + + def test_strided_slice_permute_4( + self, # inp[1:34, :, :, :2] begin mask is (1,) so only one value can be specified + inp=(1, 35, 35, 3), ref_res=(1, 2, 35), + begin=(0, 0, 0, 0), end=(1, 34, 20, 2), strides=(1, 1, 1, 1), begin_mask=(1, 0, 0, ), end_mask=(1, 0, 0, 1), + shrink_axis_mask=(0, 1), new_axis_mask=(0,), ellipsis_mask=(0,) + ): + self.run_permute_test(inp, ref_res, begin, end, strides, + begin_mask, end_mask, shrink_axis_mask, new_axis_mask, ellipsis_mask) + + def test_strided_slice_permute_5( + self, # inp[:, :, :, :] since all begin and end masks are zero + inp=(1, 35, 35, 3), ref_res=(1, 3, 35, 35), + begin=(1, 10, 10, 0), end=(1, 34, 20, 2), strides=(1, 1, 1, 1), begin_mask=(0, 0, 0, 0), end_mask=(0, 0, 0, 0), + shrink_axis_mask=(0,), new_axis_mask=(0,), ellipsis_mask=(0,) + ): + self.run_permute_test(inp, ref_res, begin, end, strides, + begin_mask, end_mask, shrink_axis_mask, new_axis_mask, ellipsis_mask) + + def test_strided_slice_permute_6( + self, # inp[0] + inp=(1, 35, 35, 3), ref_res=(3, 35, 35), + begin=(0,), end=(1,), strides=(1,), begin_mask=(1,), end_mask=(0,), + shrink_axis_mask=(1,), new_axis_mask=(0,), ellipsis_mask=(0,) + ): + self.run_permute_test(inp, ref_res, begin, end, strides, + begin_mask, end_mask, shrink_axis_mask, new_axis_mask, ellipsis_mask) + + def test_strided_slice_permute_7( + self, # inp[0, 20], ends can be of any value + inp=(1, 35, 35, 3), ref_res=(3, 35), + begin=(0, 20), end=(1, 9999), strides=(1, 1), begin_mask=(0,), end_mask=(0,), + shrink_axis_mask=(1, 1), new_axis_mask=(0,), ellipsis_mask=(0,) + ): + self.run_permute_test(inp, ref_res, begin, end, strides, + begin_mask, end_mask, shrink_axis_mask, new_axis_mask, ellipsis_mask) + + def test_strided_slice_permute_8( + self, # inp[0, 0:34, 20:22, new_axis], both new_axis and shrink_axis are present + inp=(1, 35, 35, 3), ref_res=(3, 34, 2, 1), + begin=(0, 0, 20, 0), end=(1, 34, 22, 2), strides=(1, 1, 1, 1), begin_mask=(0,), end_mask=(0,), + shrink_axis_mask=(1,), new_axis_mask=(0, 0, 0, 1), ellipsis_mask=(0,) + ): + self.run_permute_test(inp, ref_res, begin, end, strides, + begin_mask, end_mask, shrink_axis_mask, new_axis_mask, ellipsis_mask) + + def test_strided_slice_permute_9( + self, # inp[:, 0:4, 20, new_axis], both new_axis and shrink_axis are present + inp=(1, 35, 35, 3), ref_res=(1, 3, 4, 1), + begin=(0, 0, 20, 0), end=(0, 4, 0, 0), strides=(1, 1, 1, 1), begin_mask=(0, 1, 0, 0), end_mask=(0, 1, 0, 0), + shrink_axis_mask=(0, 0, 1, 0), new_axis_mask=(0, 0, 0, 1), ellipsis_mask=(0,) + ): + self.run_permute_test(inp, ref_res, begin, end, strides, + begin_mask, end_mask, shrink_axis_mask, new_axis_mask, ellipsis_mask) + + def test_strided_slice_permute_10( + self, # inp[:, 0:4, new_axis, 20], both new_axis and shrink_axis are present + inp=(1, 35, 35, 3), ref_res=(1, 3, 4, 1), + begin=(0, 0, 0, 20), end=(0, 4, 0, 0), strides=(1, 1, 1, 1), begin_mask=(0, 1, 0, 0), end_mask=(0, 1, 0, 0), + shrink_axis_mask=(0, 0, 0, 1), new_axis_mask=(0, 0, 1, 0), ellipsis_mask=(0,) + ): + self.run_permute_test(inp, ref_res, begin, end, strides, + begin_mask, end_mask, shrink_axis_mask, new_axis_mask, ellipsis_mask) + + def test_strided_slice_permute_11( + self, # inp[0, :, 0:34, 20:22, new_axis], both new_axis and shrink_axis are present + inp=(1, 35, 35, 3), ref_res=(1, 3, 34, 2), + begin=(0, 0, 0, 20, 0), end=(1, 0, 34, 22, 0), strides=(1, 1, 1, 1, 1), + begin_mask=(1, 0, 1, 1, 1), end_mask=(1, 0, 1, 1, 1), + shrink_axis_mask=(1, 0, 0, 0), new_axis_mask=(0, 0, 0, 0, 1), ellipsis_mask=(0,) + ): + self.run_permute_test(inp, ref_res, begin, end, strides, + begin_mask, end_mask, shrink_axis_mask, new_axis_mask, ellipsis_mask) + + def test_strided_slice_permute_12( + self, # inp[0, :34, 20, :2] + inp=(1, 35, 35, 3), ref_res=(2, 34), + begin=(0, 0, 0, 0), end=(1, 34, 20, 2), strides=(1, 1, 1, 1), begin_mask=(0, 1, 1, 1), end_mask=(0, 1, 1, 1), + shrink_axis_mask=(1, 0, 1, 0), new_axis_mask=(0,), ellipsis_mask=(0,) + ): + self.run_permute_test(inp, ref_res, begin, end, strides, + begin_mask, end_mask, shrink_axis_mask, new_axis_mask, ellipsis_mask) + + def test_strided_slice_permute_13( + self, # inp[0, 0, 0], since it's shrink_axis ends can be of any value + inp=(1, 35, 35, 3), ref_res=(3,), + begin=(0, 0, 0), end=(1, 34444, 20), strides=(1, 1, 1), begin_mask=(0, 0, 0), end_mask=(0, 0, 0), + shrink_axis_mask=(1, 1, 1), new_axis_mask=(0,), ellipsis_mask=(0,) + ): + self.run_permute_test(inp, ref_res, begin, end, strides, + begin_mask, end_mask, shrink_axis_mask, new_axis_mask, ellipsis_mask) + + def test_strided_slice_permute_14( + self, # inp[0, 0, 0], since begin_mask is [0], begin can be of any value + inp=(1, 35, 35, 3), ref_res=(1, 3, 18, 18), + begin=(0, 0, 0), end=(1, 35, 35), strides=(2, 2, 2), begin_mask=(1, 1, 1), end_mask=(1, 1, 1), + shrink_axis_mask=(0, 0, 0), new_axis_mask=(0,), ellipsis_mask=(0,) + ): + self.run_permute_test(inp, ref_res, begin, end, strides, + begin_mask, end_mask, shrink_axis_mask, new_axis_mask, ellipsis_mask) + + # with ellipsis + def test_strided_slice_permute_15( + self, # inp[..., np.newaxis] + inp=(1, 35, 35), ref_res=(1, 1, 35, 35), + begin=(101, 0), end=(0, 0), strides=(-1, -1), begin_mask=(0, 0), end_mask=(0, 0), + shrink_axis_mask=(0, 0), new_axis_mask=(0, 1), ellipsis_mask=(1, 0) + ): + self.run_permute_test(inp, ref_res, begin, end, strides, + begin_mask, end_mask, shrink_axis_mask, new_axis_mask, ellipsis_mask) + + def test_strided_slice_permute_16( + self, # inp_shape = (1, 720, 1080), out = inp[..., :100, None] => out_shape = (1, 720, 100, 1) + inp=(1, 720, 1080), ref_res=(1, 1, 720, 100), + begin=(0, 0, 0), end=(0, 100, 0), strides=(1, 1, 1), begin_mask=(0, 1, 0), end_mask=(0, 1, 0), + shrink_axis_mask=(0,), new_axis_mask=(0, 0, 1), ellipsis_mask=(1,) + ): + self.run_permute_test(inp, ref_res, begin, end, strides, + begin_mask, end_mask, shrink_axis_mask, new_axis_mask, ellipsis_mask) + + def test_strided_slice_permute_17( + self, # inp_shape = (1, 720, 1080, 3), out = inp[..., :-1] => out_shape = (1, 720, 100, 2) + inp=(1, 720, 1080, 3), ref_res=(1, 2, 720, 1080), + begin=(0, 0), end=(0, -1), strides=(1, 1), begin_mask=(0, 0), end_mask=(0, 1), + shrink_axis_mask=(0, 0), new_axis_mask=(0, 0), ellipsis_mask=(1, 0) + ): + self.run_permute_test(inp, ref_res, begin, end, strides, + begin_mask, end_mask, shrink_axis_mask, new_axis_mask, ellipsis_mask) + + def test_strided_slice_permute_18( + self, # inp_shape = (1, 720, 1080, 3), out = inp[..., 2] => out_shape = (1, 720, 1080) + inp=(1, 720, 1080, 3), ref_res=(1, 720, 1080), + begin=(0, 2), end=(0, 0), strides=(1, 1), begin_mask=(0, 1), end_mask=(0, 0), + shrink_axis_mask=(0, 1), new_axis_mask=(0, 0), ellipsis_mask=(1, 0) + ): + self.run_permute_test(inp, ref_res, begin, end, strides, + begin_mask, end_mask, shrink_axis_mask, new_axis_mask, ellipsis_mask) + + def test_strided_slice_permute_19( + self, # inp_shape = (1, 720, 1080, 3), out = input[..., 0:10, 0:3] => out_shape = (1, 720, 10, 3) + inp=(1, 720, 1080, 3), ref_res=(1, 3, 720, 10), + begin=(0, 0, 0), end=(0, 10, 3), strides=(1, 1, 1), begin_mask=(0, 1, 1), end_mask=(0, 1, 1), + shrink_axis_mask=(0,), new_axis_mask=(0,), ellipsis_mask=(1,) + ): + self.run_permute_test(inp, ref_res, begin, end, strides, + begin_mask, end_mask, shrink_axis_mask, new_axis_mask, ellipsis_mask) + + # automatically generated permutation tests + def test_permute_auto_infer_strided_slice_2d_slice_over_4d_0(self): + """ + inp_shape = (1, 100, 200, 3) in NHWC, (1, 3, 100, 200) in NCHW, + out_nhwc = inp[:, :], + out_nchw = inp[:, :, :, :] => out_shape = (1, 3, 100, 200) + """ + self.run_permute_test( + inp=(1, 100, 200, 3), ref_res=(1, 3, 100, 200), + begin=(0, 0), end=(0, 0), strides=(1, 1), begin_mask=(0, 0), end_mask=(0, 0), + shrink_axis_mask=(0, 0), new_axis_mask=(0, 0), ellipsis_mask=(0, 0) + ) + + def test_permute_auto_infer_strided_slice_2d_slice_over_4d_1(self): + """ + inp_shape = (1, 100, 200, 3) in NHWC, (1, 3, 100, 200) in NCHW, + out_nhwc = inp[:, None], + out_nchw = inp[:, :, None, :, :] => out_shape = (1, 3, 1, 100, 200) + """ + self.run_permute_test( + inp=(1, 100, 200, 3), ref_res=(1, 3, 1, 100, 200), + begin=(0, 0), end=(0, 0), strides=(1, 1), begin_mask=(0, 0), end_mask=(0, 0), + shrink_axis_mask=(0, 0), new_axis_mask=(0, 1), ellipsis_mask=(0, 0) + ) + + def test_permute_auto_infer_strided_slice_2d_slice_over_4d_2(self): + """ + inp_shape = (1, 100, 200, 3) in NHWC, (1, 3, 100, 200) in NCHW, + out_nhwc = inp[:, 0], + out_nchw = inp[:, :, 0, :] => out_shape = (1, 3, 200) + """ + self.run_permute_test( + inp=(1, 100, 200, 3), ref_res=(1, 3, 200), + begin=(0, 0), end=(0, 0), strides=(1, 1), begin_mask=(0, 0), end_mask=(0, 0), + shrink_axis_mask=(0, 1), new_axis_mask=(0, 0), ellipsis_mask=(0, 0) + ) + + def test_permute_auto_infer_strided_slice_2d_slice_over_4d_3(self): + """ + inp_shape = (1, 100, 200, 3) in NHWC, (1, 3, 100, 200) in NCHW, + out_nhwc = inp[..., :], + out_nchw = inp[:, :, :, ...] => out_shape = (1, 3, 100, 200) + """ + self.run_permute_test( + inp=(1, 100, 200, 3), ref_res=(1, 3, 100, 200), + begin=(0, 0), end=(0, 0), strides=(1, 1), begin_mask=(0, 0), end_mask=(0, 0), + shrink_axis_mask=(0, 0), new_axis_mask=(0, 0), ellipsis_mask=(1, 0) + ) + + def test_permute_auto_infer_strided_slice_2d_slice_over_4d_4(self): + """ + inp_shape = (1, 100, 200, 3) in NHWC, (1, 3, 100, 200) in NCHW, + out_nhwc = inp[..., None], + out_nchw = inp[:, None, :, :, ...] => out_shape = (1, 1, 3, 100, 200) + """ + self.run_permute_test( + inp=(1, 100, 200, 3), ref_res=(1, 1, 3, 100, 200), + begin=(0, 0), end=(0, 0), strides=(1, 1), begin_mask=(0, 0), end_mask=(0, 0), + shrink_axis_mask=(0, 0), new_axis_mask=(0, 1), ellipsis_mask=(1, 0) + ) + + def test_permute_auto_infer_strided_slice_2d_slice_over_4d_5(self): + """ + inp_shape = (1, 100, 200, 3) in NHWC, (1, 3, 100, 200) in NCHW, + out_nhwc = inp[..., 0], + out_nchw = inp[:, 0, :, ...] => out_shape = (1, 100, 200) + """ + self.run_permute_test( + inp=(1, 100, 200, 3), ref_res=(1, 100, 200), + begin=(0, 0), end=(0, 0), strides=(1, 1), begin_mask=(0, 0), end_mask=(0, 0), + shrink_axis_mask=(0, 1), new_axis_mask=(0, 0), ellipsis_mask=(1, 0) + ) + + def test_permute_auto_infer_strided_slice_2d_slice_over_4d_6(self): + """ + inp_shape = (1, 100, 200, 3) in NHWC, (1, 3, 100, 200) in NCHW, + out_nhwc = inp[None, :], + out_nchw = inp[None, :, :, :, :] => out_shape = (1, 1, 3, 100, 200) + """ + self.run_permute_test( + inp=(1, 100, 200, 3), ref_res=(1, 1, 3, 100, 200), + begin=(0, 0), end=(0, 0), strides=(1, 1), begin_mask=(0, 0), end_mask=(0, 0), + shrink_axis_mask=(0, 0), new_axis_mask=(1, 0), ellipsis_mask=(0, 0) + ) + + def test_permute_auto_infer_strided_slice_2d_slice_over_4d_7(self): + """ + inp_shape = (1, 100, 200, 3) in NHWC, (1, 3, 100, 200) in NCHW, + out_nhwc = inp[None, None], + out_nchw = inp[None, :, None, :, :, :] => out_shape = (1, 1, 1, 3, 100, 200) + """ + self.run_permute_test( + inp=(1, 100, 200, 3), ref_res=(1, 1, 1, 3, 100, 200), + begin=(0, 0), end=(0, 0), strides=(1, 1), begin_mask=(0, 0), end_mask=(0, 0), + shrink_axis_mask=(0, 0), new_axis_mask=(1, 1), ellipsis_mask=(0, 0) + ) + + def test_permute_auto_infer_strided_slice_2d_slice_over_4d_8(self): + """ + inp_shape = (1, 100, 200, 3) in NHWC, (1, 3, 100, 200) in NCHW, + out_nhwc = inp[None, 0], + out_nchw = inp[None, :, 0, :, :] => out_shape = (1, 1, 100, 200) + """ + self.run_permute_test( + inp=(1, 100, 200, 3), ref_res=(1, 1, 100, 200), + begin=(0, 0), end=(0, 0), strides=(1, 1), begin_mask=(0, 0), end_mask=(0, 0), + shrink_axis_mask=(0, 1), new_axis_mask=(1, 0), ellipsis_mask=(0, 0) + ) + + def test_permute_auto_infer_strided_slice_2d_slice_over_4d_9(self): + """ + inp_shape = (1, 100, 200, 3) in NHWC, (1, 3, 100, 200) in NCHW, + out_nhwc = inp[0, :], + out_nchw = inp[0, :, :, :] => out_shape = (3, 100, 200) + """ + self.run_permute_test( + inp=(1, 100, 200, 3), ref_res=(3, 100, 200), + begin=(0, 0), end=(0, 0), strides=(1, 1), begin_mask=(0, 0), end_mask=(0, 0), + shrink_axis_mask=(1, 0), new_axis_mask=(0, 0), ellipsis_mask=(0, 0) + ) + + def test_permute_auto_infer_strided_slice_2d_slice_over_4d_10(self): + """ + inp_shape = (1, 100, 200, 3) in NHWC, (1, 3, 100, 200) in NCHW, + out_nhwc = inp[0, None], + out_nchw = inp[0, :, None, :, :] => out_shape = (3, 1, 100, 200) + """ + self.run_permute_test( + inp=(1, 100, 200, 3), ref_res=(3, 1, 100, 200), + begin=(0, 0), end=(0, 0), strides=(1, 1), begin_mask=(0, 0), end_mask=(0, 0), + shrink_axis_mask=(1, 0), new_axis_mask=(0, 1), ellipsis_mask=(0, 0) + ) + + def test_permute_auto_infer_strided_slice_2d_slice_over_4d_11(self): + """ + inp_shape = (1, 100, 200, 3) in NHWC, (1, 3, 100, 200) in NCHW, + out_nhwc = inp[0, 0], + out_nchw = inp[0, :, 0, :] => out_shape = (3, 200) + """ + self.run_permute_test( + inp=(1, 100, 200, 3), ref_res=(3, 200), + begin=(0, 0), end=(0, 0), strides=(1, 1), begin_mask=(0, 0), end_mask=(0, 0), + shrink_axis_mask=(1, 1), new_axis_mask=(0, 0), ellipsis_mask=(0, 0) + ) 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 c4a11d3765cd2f..1b422ad6c5cd32 100644 --- a/model-optimizer/mo/back/ie_ir_ver_2/emitter.py +++ b/model-optimizer/mo/back/ie_ir_ver_2/emitter.py @@ -174,8 +174,8 @@ def xml_ports(node: Node, element: Element, edges: Element): assert node.graph.node[v]['shape'] is not None, 'Output shape is not calculated properly for node {}' \ ''.format(node.id) tensor_names = node.out_port(port_id).get_tensor_names(port_renumber=True) - if tensor_names is not None: - port.set('names', tensor_names) + if tensor_names: + port.set('names', ','.join(tensor_names)) xml_shape(node.graph.node[v]['shape'], port) diff --git a/model-optimizer/mo/front/common/partial_infer/slice.py b/model-optimizer/mo/front/common/partial_infer/slice.py deleted file mode 100644 index 00dbc257a1eca6..00000000000000 --- a/model-optimizer/mo/front/common/partial_infer/slice.py +++ /dev/null @@ -1,158 +0,0 @@ -""" - Copyright (C) 2018-2020 Intel Corporation - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -""" - -import numpy as np - -from mo.front.caffe.extractors.utils import get_canonical_axis_index -from mo.utils.error import Error - - -def tf_strided_slice_infer(node): - if node.in_node(1).value is None or node.in_node(2).value is None: - raise Error('Strided slice layer supports only constant begin and end inputs') - begin_id = node.in_node(1).value.copy() - end_id = node.in_node(2).value.copy() - if len(node.in_nodes()) > 3: - if node.in_node(3).value is None: - raise Error('Strided slice layer supports only constant stride input') - stride = node.in_node(3).value - else: - stride = [] - - shape = node.in_node(0).shape - - if shape is None or any([x < 0 for x in shape]): - return - - convert_negative_indices(begin_id, shape) - convert_negative_indices(end_id, shape) - - slice_idx = [] - dims = np.amax(np.array([len(begin_id), len(end_id), len(stride), - len(node.shrink_axis_mask), len(node.new_axis_mask), len(node.ellipsis_mask), - len(node.begin_mask), len(node.end_mask)])) - - # make mask correct length - def extend_mask(in_mask, fin_len, zeros=True): - mask = list(in_mask) - if len(mask) < fin_len: - if zeros: - mask.extend(np.zeros(dims-len(mask), dtype=np.int32)) - else: - mask.extend(np.ones(dims-len(mask), dtype=np.int32)) - return np.array(mask, dtype=np.int32) - - for mask in {'new_axis_mask', 'shrink_axis_mask', 'ellipsis_mask'}: - node[mask] = extend_mask(node[mask], dims) - node.begin_mask = extend_mask(node.begin_mask, dims, False) - node.end_mask = extend_mask(node.end_mask, dims, False) - - old_idx = 0 - ellips_ext = 0 - id_em = 0 - for idx in range(dims): - if node.new_axis_mask[idx]: - slice_idx.append(np.newaxis) - elif node.ellipsis_mask[idx]: - ellips_ext = len(shape) - (dims - np.count_nonzero(node.new_axis_mask) - 1) - id_em = idx - for i in range(0, ellips_ext): - slice_idx.append(slice(0, shape[old_idx], 1)) - old_idx = old_idx + 1 - else: - s = stride[idx] if len(stride) > idx else 1 - def_beg = 0 if s > 0 else -1 - def_end = shape[old_idx] if s > 0 else -shape[old_idx]-1 - l = begin_id[idx] if node.begin_mask[idx] and idx < len(begin_id) else def_beg - r = end_id[idx] if node.end_mask[idx] and idx < len(end_id) else def_end - - # Check shrink_axis_mask - if node.shrink_axis_mask[idx] and idx < len(shape): - slice_idx.append(slice(l, l+1, s)) - else: - slice_idx.append(slice(l, r, s)) - old_idx = old_idx + 1 - - value = node.in_node(0).value if node.in_node(0).value is not None else np.zeros(shape) - # fix for the warning: "FutureWarning: Using a non-tuple sequence for multidimensional indexing is deprecated use - # `arr[tuple(seq)]` instead of `arr[seq]`" - value = value[tuple(slice_idx)] - - for idx, flag in reversed(list(enumerate(node.shrink_axis_mask))): - if flag: - if ellips_ext > 0 and idx > id_em: - idx = idx + ellips_ext - 1 - try: - value = np.squeeze(value, idx) - except ValueError: - # ignore this error - continue - - for i, s in enumerate(slice_idx): - if s is None: - slice_idx[i] = slice(0, 1, 1) - - node['slices'] = np.array(slice_idx) - for attr in ('shrink_axis_mask', 'new_axis_mask', 'ellipsis_mask', 'begin_mask', 'end_mask'): - node[attr] = np.array(node[attr], dtype=np.int32) - - node['force_precision_in_ports'] = {port: 'int64' for port in range(1, len(node.in_nodes()))} - - node.out_node().value = value.copy() if node.in_node(0).value is not None else None - node.out_node().shape = np.array(value.shape, dtype=np.int64) - - -def convert_negative_indices(indices: np.array, shape: np.array): - for ind, value in enumerate(indices): - if value < 0: - indices[ind] += shape[ind] - - -def mxnet_slice_axis_infer(node): - in_shape = node.in_node(0).shape - node.axis = get_canonical_axis_index(in_shape, node.axis) - slice_axis = node.axis - - new_shape = np.array(in_shape, dtype=np.int64) - new_shape[slice_axis] = new_shape[slice_axis] / len(node.out_nodes()) - - axis_size = in_shape[slice_axis] - if node.offset < 0: - node.offset += axis_size - - if not node.dim: - node.dim = axis_size - elif node.dim < 0: - node.dim += axis_size - - input_dim = in_shape.size - node.dim = (node.dim - node.offset) - if node.dim > in_shape[slice_axis]: - raise Error( - '{0} node dimension value is bigger than the corresponding value in the input shape {1}. ' + - '\nIn particular {2} is bigger than {3}. The Model Optimizer does not support this case. ' + - '\nTo overcome, try to edit the original model "end" property of the {0} layer.', - node.name, ','.join(str(i) for i in in_shape), str(node.dim), str(in_shape[slice_axis]) - ) - - for i in range(0, input_dim): - if i == slice_axis: - new_shape[i] = node.dim - else: - new_shape[i] = in_shape[i] - - for i in range(0, len(node.out_nodes())): - node.out_node(i)['shape'] = new_shape diff --git a/model-optimizer/mo/front/common/partial_infer/slice_test.py b/model-optimizer/mo/front/common/partial_infer/slice_test.py deleted file mode 100644 index fd42947e31bea3..00000000000000 --- a/model-optimizer/mo/front/common/partial_infer/slice_test.py +++ /dev/null @@ -1,278 +0,0 @@ -""" - Copyright (C) 2018-2020 Intel Corporation - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -""" - -import unittest - -import numpy as np - -from mo.front.common.partial_infer.slice import tf_strided_slice_infer, convert_negative_indices, mxnet_slice_axis_infer -from mo.graph.graph import Node -from mo.utils.unittest.graph import build_graph - -nodes_attributes = {'node_1': {'value': None, 'kind': 'data'}, - 'Slice_node': {'type': 'Slice', 'kind': 'op'}, - 'node_2': {'value': None, 'kind': 'data'}, - 'node_3': {'value': None, 'kind': 'data'}, - 'node_4': {'value': None, 'kind': 'data'}, - # StridedSlice node with attrs - 'sslice_input': {'value': None, 'shape': None, 'kind': 'data'}, - 'sslice_1': {'type': 'StridedSlice', 'value': None, 'kind': 'op', 'op': 'StridedSlice'}, - 'sslice_begin_1': {'value': None, 'shape': None, 'kind': 'data'}, - 'sslice_end_1': {'value': None, 'shape': None, 'kind': 'data'}, - 'sslice_stride_1': {'value': None, 'shape': None, 'kind': 'data'}, - 'sslice_data_1': {'value': None, 'shape': None, 'kind': 'data'}, - # TF slice - 'tf_slice_input': {'value': None, 'shape': None, 'kind': 'data'}, - 'tf_slice_begin': {'value': None, 'shape': None, 'kind': 'data'}, - 'tf_slice_size': {'value': None, 'shape': None, 'kind': 'data'}, - 'tf_slice': {'kind': 'op'}, - 'tf_slice_output': {'value': None, 'shape': None, 'kind': 'data'}, - 'op_output': {'kind': 'op', 'op': 'Result'}, - 'op_output_1': {'kind': 'op', 'op': 'Result'}, - 'op_output_2': {'kind': 'op', 'op': 'Result'} - } - -tf_slice_edges = [('tf_slice_input', 'tf_slice'), ('tf_slice_begin', 'tf_slice'), ('tf_slice_size', 'tf_slice'), - ('tf_slice', 'tf_slice_output')] - - -class TestTFStridedSliceInfer(unittest.TestCase): - def build_test_graph2(self): - return build_graph(nodes_attributes, - [('sslice_input', 'sslice_1'), - ('sslice_begin_1', 'sslice_1'), - ('sslice_end_1', 'sslice_1'), - ('sslice_stride_1', 'sslice_1'), - ('sslice_1', 'sslice_data_1'), - ('sslice_data_1', 'op_output') - ], - { - 'sslice_input': {'value': np.array([1, 34, 34, 62]), - 'shape': np.array([3])}, - 'sslice_begin_1': {'value': np.array([0]), 'shape': np.array([1])}, - 'sslice_end_1': {'value': np.array([4]), 'shape': np.array([1])}, - 'sslice_stride_1': {'value': np.array([1]), 'shape': np.array([1])}, - 'sslice_1': {'shrink_axis_mask': [0], 'ellipsis_mask': [0], 'new_axis_mask': [0], - 'begin_mask': [1], 'end_mask': [1]}, - }) - - def build_test_graph(self): - return build_graph(nodes_attributes, - [('sslice_input', 'sslice_1'), - ('sslice_begin_1', 'sslice_1'), - ('sslice_end_1', 'sslice_1'), - ('sslice_stride_1', 'sslice_1'), - ('sslice_1', 'sslice_data_1'), - ('sslice_data_1', 'op_output') - ], - { - 'sslice_input': {'value': None, 'shape': np.array([1, 35, 35, 3])}, - 'sslice_begin_1': {'value': np.array([0, 0, 0, 0]), 'shape': np.array([4])}, - 'sslice_end_1': {'value': np.array([1, 34, 30, 2]), 'shape': np.array([4])}, - 'sslice_stride_1': {'value': np.array([1, 1, 1, 1]), - 'shape': np.array([4])}, - 'sslice_1': {'shrink_axis_mask': [0], 'ellipsis_mask': [0], 'new_axis_mask': [0], - 'begin_mask': [1], 'end_mask': [1]}, - }) - - def build_test_graph_dim_beg(self): - return build_graph(nodes_attributes, - [('sslice_input', 'sslice_1'), - ('sslice_begin_1', 'sslice_1'), - ('sslice_end_1', 'sslice_1'), - ('sslice_stride_1', 'sslice_1'), - ('sslice_1', 'sslice_data_1'), - ('sslice_data_1', 'op_output') - ], - { - 'sslice_input': {'value': np.array([[1, 34, 34, 62]]), - 'shape': np.array([1, 4])}, - 'sslice_begin_1': {'value': np.array([0]), 'shape': np.array([1])}, - 'sslice_end_1': {'value': np.array([4]), 'shape': np.array([1])}, - 'sslice_stride_1': {'value': np.array([1]), 'shape': np.array([1])}, - 'sslice_1': {'shrink_axis_mask': [0], 'ellipsis_mask': [0], 'new_axis_mask': [0], - 'begin_mask': [1], 'end_mask': [1]}, - }) - - def test_slice_infer_1(self): - graph = self.build_test_graph() - node = Node(graph, 'sslice_1') - tf_strided_slice_infer(node) - self.assertTrue(np.array_equal(node.out_node().shape, np.array([1, 34, 30, 2])), 'Wrong output shape detected') - - def test_slice_infer_2(self): - graph = self.build_test_graph() - node = Node(graph, 'sslice_1') - node.end_mask = [1, 0, 0, 1] # 6 - tf_strided_slice_infer(node) - self.assertTrue(np.array_equal(node.out_node().shape, np.array([1, 35, 35, 2])), 'Wrong output shape detected') - - def test_slice_infer_3(self): - graph = self.build_test_graph() - node = Node(graph, 'sslice_1') - node.in_node(1).value = np.array([0, 10, 10, 0]) - node.end_mask = [1, 0, 0, 1] # 6 - tf_strided_slice_infer(node) - self.assertTrue(np.array_equal(node.out_node().shape, np.array([1, 25, 25, 2])), 'Wrong output shape detected') - - def test_slice_infer_4(self): - graph = self.build_test_graph() - node = Node(graph, 'sslice_1') - node.in_node(1).value = np.array([0, 10, 10, 0]) - node.begin_mask = [1, 0, 0, 1] # 6 - tf_strided_slice_infer(node) - self.assertTrue(np.array_equal(node.out_node().shape, np.array([1, 34, 30, 2])), 'Wrong output shape detected') - - def test_slice_infer_5(self): - graph = self.build_test_graph() - node = Node(graph, 'sslice_1') - node.in_node(1).value = np.array([0, 10, 10, 0]) - node.begin_mask = [0, 0, 0, 0] # 15 - node.end_mask = [0, 0, 0, 0] # 15 - tf_strided_slice_infer(node) - self.assertTrue(np.array_equal(node.out_node().shape, np.array([1, 35, 35, 3])), 'Wrong output shape detected') - - def test_slice_infer_6(self): - graph = self.build_test_graph2() - node = Node(graph, 'sslice_1') - tf_strided_slice_infer(node) - self.assertTrue(np.array_equal(node.out_node().shape, np.array([4])), 'Wrong output shape detected') - self.assertTrue(np.array_equal(node.out_node().value, np.array([1, 34, 34, 62])), 'Wrong output value detected') - - def test_slice_infer_7(self): - graph = self.build_test_graph2() - node = Node(graph, 'sslice_1') - node.in_node(1).value = np.array([1]) - node.in_node(2).value = np.array([3]) - tf_strided_slice_infer(node) - self.assertTrue(np.array_equal(node.out_node().shape, np.array([2])), 'Wrong output shape detected') - self.assertTrue(np.array_equal(node.out_node().value, np.array([34, 34])), 'Wrong output value detected') - - def test_slice_infer_8(self): - graph = self.build_test_graph2() - node = Node(graph, 'sslice_1') - node.new_axis_mask = [1] - tf_strided_slice_infer(node) - self.assertTrue(np.array_equal(node.out_node().shape, np.array([1, 4])), 'Wrong output shape detected') - self.assertTrue(np.array_equal(node.out_node().value, np.array([[1, 34, 34, 62]])), - 'Wrong output value detected') - - def test_slice_infer_9(self): - graph = self.build_test_graph() - node = Node(graph, 'sslice_1') - node.begin_mask = [0, 0, 0, 0] # 15 - node.end_mask = [0, 0, 0, 0] # 15 - node.shrink_axis_mask = [1] - tf_strided_slice_infer(node) - self.assertTrue(np.array_equal(node.out_node().shape, np.array([35, 35, 3])), 'Wrong output shape detected') - - def test_slice_infer_10(self): - graph = self.build_test_graph() - node = Node(graph, 'sslice_1') - node.begin_mask = [0, 0, 0, 0] # 15 - node.end_mask = [0, 0, 0, 0] # 15 - node.shrink_axis_mask = [1, 0, 0, 0] - node.new_axis_mask = [0, 0, 0, 1] # 8 - tf_strided_slice_infer(node) - self.assertTrue(np.array_equal(node.out_node().shape, np.array([35, 35, 1, 3])), 'Wrong output shape detected') - - def test_slice_infer_11(self): - graph = self.build_test_graph() - node = Node(graph, 'sslice_1') - node.begin_mask = [0, 0, 0, 0] # 15 - node.end_mask = [0, 0, 0, 0] # 15 - node.shrink_axis_mask = [1, 0, 1, 0] # 5 - tf_strided_slice_infer(node) - self.assertTrue(np.array_equal(node.out_node().shape, np.array([35, 3])), 'Wrong output shape detected') - - def test_slice_infer_12(self): - graph = self.build_test_graph() - node = Node(graph, 'sslice_1') - node.begin_mask = [0, 0, 0, 0] # 15 - node.end_mask = [0, 0, 0, 0] # 15 - node.shrink_axis_mask = [1, 1, 1, 0] # 7 - tf_strided_slice_infer(node) - self.assertTrue(np.array_equal(node.out_node().shape, np.array([3])), 'Wrong output shape detected') - - def test_slice_infer_13(self): - graph = self.build_test_graph2() - node = Node(graph, 'sslice_1') - node.in_node(1).value = np.array([1]) - node.shrink_axis_mask = [1] - tf_strided_slice_infer(node) - self.assertTrue(np.array_equal(node.out_node().shape, np.array([])), 'Wrong output shape detected') - self.assertTrue(np.array_equal(node.out_node().value, np.array(34)), 'Wrong output shape detected') - - def test_slice_infer_14(self): - graph = self.build_test_graph2() - node = Node(graph, 'sslice_1') - node.in_node(3).value = np.array([-1]) - node.end_mask = [0] - node.begin_mask = [0] - node.in_node(0).shape = [4] - tf_strided_slice_infer(node) - self.assertTrue(np.array_equal(node.out_node().shape, np.array([4])), 'Wrong output shape detected') - print(node.out_node().value) - self.assertTrue(np.array_equal(node.out_node().value, np.array([62, 34, 34, 1])), 'Wrong output shape detected') - - def test_slice_infer_dim_beg(self): - graph = self.build_test_graph_dim_beg() - node = Node(graph, 'sslice_1') - node.shrink_axis_mask = [1] - tf_strided_slice_infer(node) - self.assertTrue(np.array_equal(node.out_node().shape, np.array([4])), 'Wrong output shape detected') - self.assertTrue(np.array_equal(node.out_node().value, np.array([1, 34, 34, 62])), 'Wrong output shape detected') - - def test_slice_infer_neg_end(self): - graph = self.build_test_graph() - node = Node(graph, 'sslice_1') - end_node = Node(graph, 'sslice_end_1') - end_node.value = np.array([1, -1, -5, -1]) - tf_strided_slice_infer(node) - self.assertTrue(np.array_equal(node.out_node().shape, np.array([1, 34, 30, 2])), 'Wrong output shape detected') - self.assertTrue(np.array_equal(end_node.value, np.array([1, -1, -5, -1])), 'Negative values in end were converted to positive') - - -class TestConvertNegativeIndices(unittest.TestCase): - def test_convert_negative_indices(self): - dimensions = np.array([3, 4, 8, 10]) - indices = np.array([2, 0, -3, -4]) - convert_negative_indices(indices, dimensions) - self.assertTrue(np.array_equal(indices, np.array([2, 0, 5, 6])), 'Wrong dimension indices') - - -class TestMXNetSliceAxisInfer(unittest.TestCase): - def test_slice_axis_infer_layer(self): - graph = build_graph( - {'node_1': {'name': 'data', 'type': 'Identity', 'value': None, 'kind': 'op', 'op': 'Parameter'}, - 'slice_axis_node': {'name': 'slice_axis_node', 'type': 'sigmoid', 'value': None, - 'kind': 'op', 'op': 'slice_axis', }, - 'node_3': {'name': 'node_3', 'type': 'Identity', 'value': None, 'kind': 'op'}, - }, - [ - ('node_1', 'slice_axis_node'), - ('slice_axis_node', 'node_3'), - ], - { - 'node_1': {'shape': np.array([1, 1024, 19, 19])}, - 'slice_axis_node': {'axis': 1, 'offset': 10, 'dim': 25}, - }) - - slice_axis_node = Node(graph, 'slice_axis_node') - mxnet_slice_axis_infer(slice_axis_node) - res_shape = [1, 15, 19, 19] - for i in range(0, len(graph.node['node_3']['shape'])): - self.assertEqual(graph.node['node_3']['shape'][i], res_shape[i]) diff --git a/model-optimizer/mo/front/common/partial_infer/utils.py b/model-optimizer/mo/front/common/partial_infer/utils.py index 74ece932a27e31..ba692dea7ba984 100644 --- a/model-optimizer/mo/front/common/partial_infer/utils.py +++ b/model-optimizer/mo/front/common/partial_infer/utils.py @@ -1,5 +1,5 @@ """ - Copyright (C) 2018-2020 Intel Corporation + Copyright (C) 2018-2021 Intel Corporation Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -15,7 +15,7 @@ """ import logging as log -from typing import Iterable +from typing import Iterable, List, Union import numpy as np @@ -113,4 +113,34 @@ def broadcast_shape(first_shape, second_shape): 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) \ No newline at end of file + return int64_array(new_shape) + + +def get_shape_from_slice(input_shape: np.ndarray, slices: List) -> np.ndarray: + """ + Calculate shape of a tensor after slicing without actually creating the resulting tensor. + Is introduced to prevent potentially large memory consumption. + """ + output_shape = [] + num_new_axes = np.count_nonzero(list(map(lambda x: x is np.newaxis, slices))) + num_ellipsis_inserts = len(input_shape) - len(slices) + num_new_axes + 1 + + in_idx = 0 + for i, s in enumerate(slices): + if isinstance(s, slice): + output_shape.append(len(range(*s.indices(input_shape[in_idx])))) + in_idx += 1 + elif s is np.newaxis: + output_shape.append(1) + elif isinstance(s, int): # shrink_axis + in_idx += 1 + elif s is Ellipsis: + for idx in range(num_ellipsis_inserts): + 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))) + for i in range(in_idx, len(input_shape)): + output_shape.append(input_shape[i]) + return int64_array(output_shape) diff --git a/model-optimizer/mo/front/mxnet/extractors/slice_axis.py b/model-optimizer/mo/front/mxnet/extractors/slice_axis.py index 741fbe632bbab0..3cc6f6b86f6124 100644 --- a/model-optimizer/mo/front/mxnet/extractors/slice_axis.py +++ b/model-optimizer/mo/front/mxnet/extractors/slice_axis.py @@ -1,5 +1,5 @@ """ - Copyright (C) 2018-2020 Intel Corporation + Copyright (C) 2018-2021 Intel Corporation Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -14,7 +14,10 @@ limitations under the License. """ -from mo.front.common.partial_infer.slice import mxnet_slice_axis_infer +from mo.front.caffe.extractors.utils import get_canonical_axis_index +import numpy as np +from mo.utils.error import Error + def slice_axis_ext(attrs): axis = attrs.int("axis", 0) @@ -29,3 +32,40 @@ def slice_axis_ext(attrs): 'infer': mxnet_slice_axis_infer } return node_attrs + + +def mxnet_slice_axis_infer(node): + in_shape = node.in_port(0).data.get_shape() + node.axis = get_canonical_axis_index(in_shape, node.axis) + slice_axis = node.axis + + new_shape = np.array(in_shape, dtype=np.int64) + new_shape[slice_axis] = new_shape[slice_axis] / len(node.out_nodes()) + + axis_size = in_shape[slice_axis] + if node.offset < 0: + node.offset += axis_size + + if not node.dim: + node.dim = axis_size + elif node.dim < 0: + node.dim += axis_size + + input_dim = in_shape.size + node.dim = (node.dim - node.offset) + if node.dim > in_shape[slice_axis]: + raise Error( + '{0} node dimension value is bigger than the corresponding value in the input shape {1}. ' + + '\nIn particular {2} is bigger than {3}. The Model Optimizer does not support this case. ' + + '\nTo overcome, try to edit the original model "end" property of the {0} layer.', + node.name, ','.join(str(i) for i in in_shape), str(node.dim), str(in_shape[slice_axis]) + ) + + for i in range(0, input_dim): + if i == slice_axis: + new_shape[i] = node.dim + else: + new_shape[i] = in_shape[i] + + for i in range(0, len(node.out_nodes())): + node.out_node(i)['shape'] = new_shape diff --git a/model-optimizer/mo/front/mxnet/extractors/slice_axis_test.py b/model-optimizer/mo/front/mxnet/extractors/slice_axis_test.py index 70e4bc1117f657..73b66e9b17bb2e 100644 --- a/model-optimizer/mo/front/mxnet/extractors/slice_axis_test.py +++ b/model-optimizer/mo/front/mxnet/extractors/slice_axis_test.py @@ -1,5 +1,5 @@ """ - Copyright (C) 2018-2020 Intel Corporation + Copyright (C) 2018-2021 Intel Corporation Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -16,6 +16,9 @@ import unittest +import numpy as np + +from mo.front.mxnet.extractors.slice_axis import mxnet_slice_axis_infer from mo.front.mxnet.extractors.slice_axis import slice_axis_ext from mo.front.mxnet.extractors.utils import AttrDictionary from mo.graph.graph import Node @@ -49,3 +52,27 @@ def test_extract_slice_axis_layer(self): for key in exp_attrs.keys(): self.assertEqual(res[key], exp_attrs[key]) + + +class TestMXNetSliceAxisInfer(unittest.TestCase): + def test_slice_axis_infer_layer(self): + graph = build_graph( + {'node_1': {'name': 'data', 'type': 'Identity', 'value': None, 'kind': 'op', 'op': 'Parameter'}, + 'slice_axis_node': {'name': 'slice_axis_node', 'type': 'sigmoid', 'value': None, + 'kind': 'op', 'op': 'slice_axis', }, + 'node_3': {'name': 'node_3', 'type': 'Identity', 'value': None, 'kind': 'op'}, + }, + [ + ('node_1', 'slice_axis_node'), + ('slice_axis_node', 'node_3'), + ], + { + 'node_1': {'shape': np.array([1, 1024, 19, 19])}, + 'slice_axis_node': {'axis': 1, 'offset': 10, 'dim': 25}, + }) + + slice_axis_node = Node(graph, 'slice_axis_node') + mxnet_slice_axis_infer(slice_axis_node) + res_shape = [1, 15, 19, 19] + for i in range(0, len(graph.node['node_3']['shape'])): + self.assertEqual(graph.node['node_3']['shape'][i], res_shape[i]) diff --git a/model-optimizer/mo/front/tf/extractors/strided_slice.py b/model-optimizer/mo/front/tf/extractors/strided_slice.py index e81328f7a6f6fc..6f22f5089b721e 100644 --- a/model-optimizer/mo/front/tf/extractors/strided_slice.py +++ b/model-optimizer/mo/front/tf/extractors/strided_slice.py @@ -1,5 +1,5 @@ """ - Copyright (C) 2018-2020 Intel Corporation + Copyright (C) 2018-2021 Intel Corporation Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/model-optimizer/mo/graph/perm_inputs.py b/model-optimizer/mo/graph/perm_inputs.py index 87ab580cc4b033..0d25644b660a58 100644 --- a/model-optimizer/mo/graph/perm_inputs.py +++ b/model-optimizer/mo/graph/perm_inputs.py @@ -1,5 +1,5 @@ """ - Copyright (C) 2018-2020 Intel Corporation + Copyright (C) 2018-2021 Intel Corporation Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -126,20 +126,49 @@ def order(op_node: Node, port_info: str, input_port: int): op_node['need_shape_inference'] = True +def strided_slice(op_node: Node, port_info: str, input_port: int): + """ + StridedSLice must be permuted even if input or output tensors have rank lesser than 4 + e.g. input_shape = (1, 10, 10), out = input[:, 0:10, :, new_axis], input_rank < 4 + input_shape = (1, 10, 10, 3), out = input[:, 0:5, 0:4, 0], output_rank < 4 + in both examples slice_rank is >= 4 + slice_rank is defined by length of begin, end, strides (they all are of the same length) + """ + permutation_data_node = get_node_with_permutation(op_node, port_info) + assert permutation_data_node.has_and_set('permutation'), 'Data node "{}" does not have permutation for node {}, ' \ + 'port_info "{}".'.format(permutation_data_node.id, + op_node.id, port_info) + permute_indices_for_gather = permutation_data_node.permutation.perm + if len(permute_indices_for_gather) == 0: + return + from mo.ops.op import PermuteAttrs + + slice_rank = op_node.in_port(input_port).data.get_shape()[0] # length of begin, end or strides + permute_indices_for_gather = PermuteAttrs.get_nhwc_to_nchw_permutation(slice_rank).perm + reorder_inputs_for_shape_or_slice(op_node, input_port, permute_indices_for_gather) + + def shape(op_node: Node, port_info: str, input_port: int): - graph = op_node.graph permutation_data_node = get_node_with_permutation(op_node, port_info) assert permutation_data_node.has_and_set('permutation'), 'Data node "{}" does not have permutation for node {}, ' \ 'port_info "{}".'.format(permutation_data_node.id, op_node.id, port_info) - permutation = permutation_data_node.permutation - if len(permutation.perm) == 0: + permute_indices_for_gather = permutation_data_node.permutation.perm + if len(permute_indices_for_gather) == 0: return + reorder_inputs_for_shape_or_slice(op_node, input_port, permute_indices_for_gather) + +def reorder_inputs_for_shape_or_slice(op_node: Node, input_port: int, permute_indices_for_gather: list): + """ + axis and slice permutations are almost the same the only difference is that for slice in general + case permutation depends from slice_rank not from input_rank or output_rank + """ + graph = op_node.graph data_node = op_node.in_node(input_port) gather_name = op_node.soft_get('name', op_node.id) + '/ShapeGather' - const = Const(graph, {'value': permutation.perm, 'name': gather_name + '/const', + const = Const(graph, {'value': permute_indices_for_gather, 'name': gather_name + '/const', 'need_shape_inference': True}).create_node_with_data() axis_const = Const(graph, {'value': int64_array(0), 'name': gather_name + '/axis'}).create_node_with_data() gather = Gather(graph, {'name': gather_name, @@ -191,10 +220,9 @@ def transpose_nchw_to_nhwc(op_node: Node, port_info: str, input_port: int): class PermuteInputs: - common_inv_permutation = lambda node, port_info, input_port: axis(node, port_info, input_port) - input_permutes = { - 'axis': common_inv_permutation, + 'axis': lambda node, port_info, input_port: axis(node, port_info, input_port), + 'slice': lambda node, port_info, input_port: strided_slice(node, port_info, input_port), 'order': lambda node, port_info, input_port: order(node, port_info, input_port), 'shape': lambda node, port_info, input_port: shape(node, port_info, input_port), 'transpose': lambda node, port_info, input_port: transpose(node, port_info, input_port), @@ -202,16 +230,27 @@ class PermuteInputs: input_port), } - def set_input_permutation(self, node1: Node, node2: Node, port_info: str, permutation_rule: str): + shape_check_rules = { + 'rank': lambda port: bool(len(port.data.get_shape()) >= 4), + 'dim_size': lambda port: bool(port.data.get_shape()[0] >= 4), # if input 'dim_size' >= 4 need to permute + } + + def set_input_permutation(self, node1: Node, node2: Node, port_info: str, permutation_rule: str, + shape_check_rule: str = 'rank'): """ Sets input permutation attribute on the edge between node1 and node2. Input permutation consists of function that perform input permutation and input port info 'input' or 'output' + that points on the input with PermuteAttr.Permutation which - current input depends on + current input depends on. + + shape_check_rule defines the check rule if the op node inputs need to be permuted. + By default 'rank' rule is applied, 'dim_size' is used only for StridedSlice so far. """ assert permutation_rule in self.input_permutes, 'No `{}` permutation rule in {}'.format(permutation_rule, __class__.__name__) + assert shape_check_rule in self.shape_check_rules, 'No `{}` permutation shape check rule ' \ + 'in {}'.format(shape_check_rule, __class__.__name__) nx.set_edge_attributes(G=node1.graph, - values={(node1.id, node2.id, 0): (self.input_permutes[permutation_rule], - port_info)}, + values={(node1.id, node2.id, 0): (self.input_permutes[permutation_rule], port_info, + self.shape_check_rules[shape_check_rule])}, name='input_permutation') diff --git a/model-optimizer/mo/graph/port.py b/model-optimizer/mo/graph/port.py index 2ddb239b244311..163d0e5d5a262c 100644 --- a/model-optimizer/mo/graph/port.py +++ b/model-optimizer/mo/graph/port.py @@ -1,5 +1,5 @@ """ - Copyright (C) 2018-2020 Intel Corporation + Copyright (C) 2018-2021 Intel Corporation Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -310,9 +310,7 @@ def get_tensor_names_list(attrs): if node_idx in self.node.out_nodes(): out_node = self.node.out_node(node_idx) fw_names += get_tensor_names_list(out_node.attrs()) - if len(fw_names) > 0: - return ','.join(fw_names) - return None + return fw_names def disconnect(self): if self.type == 'out': diff --git a/model-optimizer/mo/graph/port_test.py b/model-optimizer/mo/graph/port_test.py index 42b03c327da649..a8ef569bd2f5d4 100644 --- a/model-optimizer/mo/graph/port_test.py +++ b/model-optimizer/mo/graph/port_test.py @@ -39,50 +39,50 @@ def test_front(self): ('Op1', 0, 'Op1,Op2')]})]) graph.stage = 'front' input_node = Node(graph, 'input') - self.assertTrue(input_node.out_port(0).get_tensor_names() == 'input,Op1\\,Op2') + self.assertTrue(input_node.out_port(0).get_tensor_names() == ['input', 'Op1\\,Op2']) op1_node = Node(graph, 'Op1') op1_node.add_output_port(0) - self.assertTrue(op1_node.out_port(0).get_tensor_names() is None) + self.assertTrue(op1_node.out_port(0).get_tensor_names() == []) def test_middle(self): graph = build_graph(nodes, [('input', 'input_data'), ('input_data', 'Op1'), ('input_data', 'Op2')]) input_node = Node(graph, 'input') - self.assertTrue(input_node.out_port(0).get_tensor_names() == 'input,Op1\\,Op2') + self.assertTrue(input_node.out_port(0).get_tensor_names() == ['input', 'Op1\\,Op2']) op1_node = Node(graph, 'Op1') op1_node.add_output_port(0) - self.assertTrue(op1_node.out_port(0).get_tensor_names() is None) + self.assertTrue(op1_node.out_port(0).get_tensor_names() == []) op2_node = Node(graph, 'Op2') op2_node.add_output_port(0) - self.assertTrue(op2_node.out_port(0).get_tensor_names() is None) + self.assertTrue(op2_node.out_port(0).get_tensor_names() == []) def test_port_renumber(self): graph = build_graph(nodes, [('input', 'input_data'), ('input_data', 'Op1'), ('Op1', 'Op1_data', {'out': 1}), ('Op1_data', 'Op2')]) input_node = Node(graph, 'input') - self.assertTrue(input_node.out_port(0).get_tensor_names(port_renumber=True) == 'input,Op1\\,Op2') + self.assertTrue(input_node.out_port(0).get_tensor_names(port_renumber=True) == ['input', 'Op1\\,Op2']) op1_node = Node(graph, 'Op1') op1_node.add_output_port(0) - self.assertTrue(op1_node.out_port(0).get_tensor_names(port_renumber=True) == 'Op1\\,Op2') + self.assertTrue(op1_node.out_port(0).get_tensor_names(port_renumber=True) == ['Op1\\,Op2']) def test_reconnect_middle_case1(self): graph = build_graph(nodes, [('input', 'input_data'), ('input_data', 'Op1'), ('Op3', 'Op3_data')]) input_node = Node(graph, 'input') input_node_out_port = input_node.out_port(0) - self.assertTrue(input_node_out_port.get_tensor_names() == 'input,Op1\\,Op2') + self.assertTrue(input_node_out_port.get_tensor_names() == ['input', 'Op1\\,Op2']) op3_node = Node(graph, 'Op3') input_node_out_port.get_connection().set_source(op3_node.out_port(0)) self.assertTrue(input_node_out_port.get_tensor_names() is None) - self.assertTrue(op3_node.out_port(0).get_tensor_names() == 'Op3,input,Op1\\,Op2') + self.assertTrue(op3_node.out_port(0).get_tensor_names() == ['Op3', 'input', 'Op1\\,Op2']) def test_reconnect_front_case1(self): graph = build_graph(nodes, [('input', 'Op1', {'in': 0, 'out': 0, 'fw_tensor_debug_info': [('input', 0, 'input'), @@ -93,26 +93,26 @@ def test_reconnect_front_case1(self): input_node = Node(graph, 'input') input_node_out_port = input_node.out_port(0) - self.assertTrue(input_node_out_port.get_tensor_names() == 'input,Op1\\,Op2') + self.assertTrue(input_node_out_port.get_tensor_names() == ['input', 'Op1\\,Op2']) op3_node = Node(graph, 'Op3') input_node_out_port.get_connection().set_source(op3_node.out_port(0)) - self.assertTrue(input_node_out_port.get_tensor_names() is None) - self.assertTrue(op3_node.out_port(0).get_tensor_names() == 'Op3,input,Op1\\,Op2') + self.assertTrue(input_node_out_port.get_tensor_names() == []) + self.assertTrue(op3_node.out_port(0).get_tensor_names() == ['Op3', 'input', 'Op1\\,Op2']) def test_reconnect_middle_case1(self): graph = build_graph(nodes, [('input', 'input_data'), ('input_data', 'Op1'), ('Op3', 'Op3_data')]) input_node = Node(graph, 'input') input_node_out_port = input_node.out_port(0) - self.assertTrue(input_node_out_port.get_tensor_names() == 'input,Op1\\,Op2') + self.assertTrue(input_node_out_port.get_tensor_names() == ['input', 'Op1\\,Op2']) op3_node = Node(graph, 'Op3') input_node_out_port.get_connection().set_source(op3_node.out_port(0)) - self.assertTrue(input_node_out_port.get_tensor_names() is None) - self.assertTrue(op3_node.out_port(0).get_tensor_names() == 'Op3,input,Op1\\,Op2') + self.assertTrue(input_node_out_port.get_tensor_names() == []) + self.assertTrue(op3_node.out_port(0).get_tensor_names() == ['Op3', 'input', 'Op1\\,Op2']) def test_reconnect_middle_case2(self): graph = build_graph(nodes, [('input', 'input_data'), ('input_data', 'Op1', {'out': 0}), @@ -120,10 +120,10 @@ def test_reconnect_middle_case2(self): input_node = Node(graph, 'input') input_node_out_port = input_node.out_port(0) - self.assertTrue(input_node_out_port.get_tensor_names() == 'input,Op1\\,Op2') + self.assertTrue(input_node_out_port.get_tensor_names() == ['input', 'Op1\\,Op2']) op3_node = Node(graph, 'Op3') input_node_out_port.get_connection().set_source(op3_node.out_port(0)) - self.assertTrue(input_node_out_port.get_tensor_names() is None) - self.assertTrue(op3_node.out_port(0).get_tensor_names() == 'Op3,input,Op1\\,Op2') + self.assertTrue(input_node_out_port.get_tensor_names() == []) + self.assertTrue(op3_node.out_port(0).get_tensor_names() == ['Op3', 'input', 'Op1\\,Op2']) diff --git a/model-optimizer/mo/ops/op.py b/model-optimizer/mo/ops/op.py index cf4c44aa4204fe..3141c996467b51 100644 --- a/model-optimizer/mo/ops/op.py +++ b/model-optimizer/mo/ops/op.py @@ -340,6 +340,8 @@ class PermuteAttrs: Attr = namedtuple('Attr', ['name', 'port', 'func']) common_permutation = lambda node, permutation, attr: node[attr][permutation.perm] + slice_permutation = lambda node, permutation, attr: node[attr][ # doesn't depend from permutation variable + PermuteAttrs.get_nhwc_to_nchw_permutation(len(node[attr])).perm] common_permutation_inv = lambda node, permutation, attr: permutation.inv[node[attr]] # List of default permutations @@ -354,9 +356,11 @@ class PermuteAttrs: 'dilation': common_permutation, 'kernel_shape': common_permutation, 'output_shape': common_permutation, - 'slices': common_permutation, - 'shrink_axis_mask': common_permutation, - 'new_axis_mask': common_permutation, + 'begin_mask': slice_permutation, + 'end_mask': slice_permutation, + 'shrink_axis_mask': slice_permutation, + 'new_axis_mask': slice_permutation, + 'ellipsis_mask': slice_permutation, 'axes': common_permutation_inv, 'axis': common_permutation_inv, 'batch_dims': common_permutation_inv, diff --git a/model-optimizer/mo/ops/slice.py b/model-optimizer/mo/ops/slice.py index 181857ad0b42ca..d9772bf43f4bf6 100644 --- a/model-optimizer/mo/ops/slice.py +++ b/model-optimizer/mo/ops/slice.py @@ -1,5 +1,5 @@ """ - Copyright (C) 2018-2020 Intel Corporation + Copyright (C) 2018-2021 Intel Corporation Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -13,10 +13,10 @@ See the License for the specific language governing permissions and limitations under the License. """ -from typing import List import numpy as np +from mo.front.common.partial_infer.utils import get_shape_from_slice from mo.graph.graph import Node, Graph from mo.ops.op import Op from mo.utils.error import Error @@ -157,20 +157,9 @@ def infer(node: Node): # Ranged for output value for specified axis slice_idx[axes[i]] = slice(starts[i], ends[i], steps[i]) if input_value is None: - output_shape = get_shape_after_slice(input_shape, slice_idx) + output_shape = get_shape_from_slice(input_shape, slice_idx) if np.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: node.out_port(0).data.set_value(input_value[tuple(slice_idx)]) - - -def get_shape_after_slice(input_shape: np.ndarray, slice_idx: List[slice]) -> np.ndarray: - """ - Calculate shape of a tensor after slicing without actually creating the resulting tensor. - Is introduced to prevent potentially large memory consumption. - """ - output_shape = np.zeros(len(input_shape), dtype=np.int32) - for i, s in enumerate(slice_idx): - output_shape[i] = len(range(*s.indices(input_shape[i]))) - return output_shape diff --git a/model-optimizer/mo/ops/strided_slice.py b/model-optimizer/mo/ops/strided_slice.py index 9deb73a3cadbe7..13bfc43e8c3370 100644 --- a/model-optimizer/mo/ops/strided_slice.py +++ b/model-optimizer/mo/ops/strided_slice.py @@ -1,5 +1,5 @@ """ - Copyright (C) 2018-2020 Intel Corporation + Copyright (C) 2018-2021 Intel Corporation Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -14,58 +14,17 @@ limitations under the License. """ +from typing import List, Tuple + import numpy as np -from mo.front.common.partial_infer.slice import tf_strided_slice_infer -from mo.front.common.partial_infer.utils import int64_array +from mo.front.common.partial_infer.utils import get_shape_from_slice from mo.graph.graph import Node, Graph -from mo.ops.op import Op, PermuteAttrs +from mo.ops.op import Op +from mo.utils.error import Error from mo.utils.utils import array_to_str -def extend_mask_according_ellipsis(ellipsis_mask, shrink_axis_mask, length_output_shape, attr_mask_extended, ins_value): - # ellipsis is set, add dimensions in right place otherwise insert in the end - if np.any(ellipsis_mask): - idx = np.nonzero(ellipsis_mask) - assert len(idx[0]) == 1 - insert_ind = idx[0][0] - else: - insert_ind = len(attr_mask_extended) - 1 - - ellipse_ext = length_output_shape + np.count_nonzero(shrink_axis_mask) - len(attr_mask_extended) - for i in range(0, ellipse_ext): - attr_mask_extended.insert(insert_ind + i + 1, ins_value) - - return attr_mask_extended - - -def permute_array(node: Node, array: np.array): - """ - This function permutes masks according to permutation parameter. Mask have the same or more length than output - """ - attr_mask_extended = list(array) - - # If input and output have length of shape 3 and less, no need to permute - if len(node.in_port(0).data.get_shape()) < 4 and len(node.out_port(0).data.get_shape()) < 4: - return attr_mask_extended - - perm_len = len(node.out_port(0).data.get_shape()) + np.count_nonzero(node.shrink_axis_mask) - perm = PermuteAttrs.get_nhwc_to_nchw_permutation(perm_len) - perm_list = list(perm.perm) - # if mask length is more than output, just add tail that will not be permuted to avoid error - for i in range(perm_len, len(attr_mask_extended)): - perm_list.append(i) - return int64_array(attr_mask_extended)[int64_array(perm_list)] - - -def permute_masks(node: Node, permutation: PermuteAttrs.Permutation, attr: str): - if not node.has_valid(attr): - return None - - node[attr] = permute_array(node, node[attr]) - return node[attr] - - class StridedSlice(Op): op = 'StridedSlice' enabled = True @@ -79,11 +38,12 @@ def __init__(self, graph: Graph, attrs: dict): 'out_ports_count': 1, 'infer': __class__.infer }, attrs) - assert 'new_axis_mask' in attrs, "Attribute 'new_axis_mask' of the StridedSlice node is not given." - assert 'shrink_axis_mask' in attrs, "Attribute 'shrink_axis_mask' of the StridedSlice node is not given." - assert 'ellipsis_mask' in attrs, "Attribute 'ellipsis_mask' of the StridedSlice node is not given." - assert 'begin_mask' in attrs, "Attribute 'begin_mask' of the StridedSlice node is not given." - assert 'end_mask' in attrs, "Attribute 'end_mask' of the StridedSlice node is not given." + for mask_name in StridedSlice.get_mask_names(): + assert mask_name in attrs, 'Attribute {} of the StridedSlice node is not given.'.format(mask_name) + + @staticmethod + def get_mask_names(): + return ['begin_mask', 'end_mask', 'new_axis_mask', 'shrink_axis_mask', 'ellipsis_mask'] def backend_attrs(self): al = list() @@ -91,61 +51,76 @@ def backend_attrs(self): def convert(attr): return lambda node: array_to_str(node, attr) - for a in list(['new_axis_mask', 'shrink_axis_mask', 'ellipsis_mask', 'begin_mask', 'end_mask']): + for a in StridedSlice.get_mask_names(): al.append((a, convert(a))) return al @staticmethod def infer(node: Node): - tf_strided_slice_infer(node) - - out_shape = node.out_port(0).data.get_shape() - assert out_shape is not None, \ - 'Output shape was not calculated for node {}'.format(node.name) - # extend inputs according to ellipsis mask and/or input_shape - for i_port in node.in_ports().values(): - if i_port.idx == 0 or i_port.disconnected(): - continue - old_value = i_port.data.get_value() - # additional check for non-const input - # error will be return in shape inference if non-const will be added - # it is paranoid check for case if shape inference will be changed - assert old_value is not None, \ - '{} input of {} node is not constant: \'value\' attribute for edge ' + \ - 'contains None'.format(i_port.idx, node.name) - # insert 0 for begin and end and 1 for stride - new_value = int64_array(extend_mask_according_ellipsis(node.ellipsis_mask, node.shrink_axis_mask, - len(out_shape), list(old_value), - int(i_port.idx == 3))) - # set_value additionally set_shape and propagate value to Const node - if not np.array_equal(new_value, old_value): - i_port.data.set_value(new_value) - - # extend masks before removing ellipsis - for attr in ["new_axis_mask", "shrink_axis_mask", "begin_mask", "end_mask", "ellipsis_mask"]: - node[attr] = int64_array(extend_mask_according_ellipsis(node.ellipsis_mask, node.shrink_axis_mask, - len(out_shape), list(node[attr]), 0)) - - # we will extend all masks and inputs to simplify future transformations - idx = np.nonzero(node.ellipsis_mask) - node.ellipsis_mask[idx] = 0 - - if node.graph.graph['layout'] == 'NHWC' and node.out_port(0).data.get_value() is None: - PermuteAttrs.create_permute_attrs(node, attrs=[('shrink_axis_mask', 'input:0', permute_masks), - ('new_axis_mask', 'input:0', permute_masks), - ('ellipsis_mask', 'input:0', permute_masks), - ('begin_mask', 'input:0', permute_masks), - ('end_mask', 'input:0', permute_masks), - ]) - # permute inputs - in_shape = node.in_port(0).get_source().data.get_shape() - assert in_shape is not None, \ - 'Input shape is unknown for 0 input of node {}'.format(node.name) - input_rank = len(in_shape) - if input_rank > 3: - for i_port in node.in_ports().values(): - if i_port.idx == 0 or i_port.disconnected(): - continue - new_value = permute_array(node, i_port.data.get_value()) - # set_value additionally set_shape and propagate value to Const node - i_port.data.set_value(new_value) + 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) + + data_shape = node.in_port(0).data.get_shape() + data_value = node.in_port(0).data.get_value() + assert len(begin) == len(end) == len(strides), 'begin, end, and strides of StridedSlice node {} must ' \ + 'be of the same length'.format(node_name) + + StridedSlice.align_mask_with_slice_rank(node, len(begin)) + + slices = StridedSlice.get_slices(node, data_shape, begin, end, strides) + if data_value is not None: + 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)) + + node['slices'] = slices + node['force_precision_in_ports'] = {port: 'int64' for port in range(1, len(node.in_nodes()))} + + # InputPermutations will be set after Normalizer, this is exceptional case + # if we specify input permute here ApplyPermutations will be wrong + + @staticmethod + def get_slices(node: Node, data_shape: Tuple, begin: np.array, end: np.array, strides: np.array) -> List: + input_rank = len(data_shape) + slice_rank = len(begin) + # 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 + for i in range(slice_rank): + 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]) + 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]) + 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) + 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) diff --git a/model-optimizer/mo/ops/strided_slice_test.py b/model-optimizer/mo/ops/strided_slice_test.py index 871e0cd4102ee8..b7b2ca078590ba 100644 --- a/model-optimizer/mo/ops/strided_slice_test.py +++ b/model-optimizer/mo/ops/strided_slice_test.py @@ -1,5 +1,5 @@ """ - Copyright (C) 2018-2020 Intel Corporation + Copyright (C) 2018-2021 Intel Corporation Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -16,547 +16,1517 @@ import unittest import numpy as np +import numpy.testing as npt from mo.front.common.partial_infer.utils import int64_array from mo.graph.graph import Node -from mo.ops.op import PermuteAttrs -from mo.ops.strided_slice import extend_mask_according_ellipsis, permute_masks, permute_array, \ - StridedSlice -from mo.utils.error import Error +from mo.ops.strided_slice import StridedSlice from mo.utils.unittest.graph import build_graph +from mo.utils.unittest.graph import valued_const_with_data, result, regular_op_with_empty_data, shaped_const_with_data, \ + connect -nodes_attributes = { - 'input': { - 'kind': 'op', - 'op': None - }, - 'data_1': { - 'kind': 'data', - 'shape': None, - 'value': None, - }, - 'begin': { - 'kind': 'op', - 'op': 'Const', - 'type': 'Const', - 'value': None, - 'shape': None - }, - 'begin_data': { - 'kind': 'data', - 'shape': None, - 'value': np.array([]), - }, - 'end': { - 'kind': 'op', - 'op': 'Const', - 'type': 'Const', - 'value': None, - 'shape': None - }, - 'end_data': { - 'kind': 'data', - 'shape': None, - 'value': np.array([]), - }, - 'stride': { - 'kind': 'op', - 'op': 'Const', - 'type': 'Const', - 'value': None, - 'shape': None - }, - 'stride_data': { - 'kind': 'data', - 'shape': None, - 'value': np.array([]), - }, - 'strided_slice': { - 'op': 'StridedSlice', - 'begin_mask': None, - 'end_mask': None, - 'new_axis_mask': None, - 'shrink_axis_mask': None, - 'ellipsis_mask': None, - 'kind': 'op', - }, - 'data_2': { - 'kind': 'data', - 'shape': None, - 'value': None, - } -} - - -class TestPermutationStridedSlice(unittest.TestCase): - def test_permute_begin_end(self): - # Testing constant path case - graph = build_graph(nodes_attributes, - [('data_1', 'strided_slice'), - ('begin', 'strided_slice'), - ('end', 'strided_slice'), - ('stride', 'strided_slice'), - ('strided_slice', 'data_2')], - {'data_1': {'shape': np.array([1, 2, 3, 4]), 'value': None}, - 'strided_slice': {'begin_mask': np.array([1, 1, 0, 0]), 'end_mask': np.array([0, 1, 0, 0]), - 'new_axis_mask': np.array([0, 0, 0]), 'shrink_axis_mask': [0, 0, 0], - 'ellipsis_mask': np.array([0, 0, 0])}, - 'data_2': {'shape': np.array([1, 2, 3, 4]), 'value': None}, - }) - - slice_node = Node(graph, 'strided_slice') - permute_masks(slice_node, PermuteAttrs.Permutation(perm=[0, 3, 1, 2], inv=[0, 2, 3, 1]), 'begin_mask') - self.assertTrue(np.array_equal(slice_node.begin_mask, np.array([1, 0, 1, 0]))) - - permute_masks(slice_node, PermuteAttrs.Permutation(perm=[0, 3, 1, 2], inv=[0, 2, 3, 1]), 'end_mask') - self.assertTrue(np.array_equal(slice_node.end_mask, np.array([0, 0, 1, 0]))) - - def test_permute_begin_end_short(self): - # Testing constant path case - graph = build_graph(nodes_attributes, - [('data_1', 'strided_slice'), - ('begin', 'strided_slice'), - ('end', 'strided_slice'), - ('stride', 'strided_slice'), - ('strided_slice', 'data_2')], - {'data_1': {'shape': np.array([1, 2, 3, 4]), 'value': None}, - 'strided_slice': {'begin_mask': np.array([1, 0, 0]), 'end_mask': np.array([0, 1, 0]), - 'new_axis_mask': np.array([0, 0, 0]), 'shrink_axis_mask': [0, 0, 0], - 'ellipsis_mask': np.array([0, 0, 0])}, - 'data_2': {'shape': np.array([1, 2, 3, 4]), 'value': None}, - }) - - slice_node = Node(graph, 'strided_slice') - slice_node['begin_mask'] = int64_array(extend_mask_according_ellipsis(slice_node['ellipsis_mask'], - slice_node['shrink_axis_mask'], 4, - list(slice_node['begin_mask']), 0)) - permute_masks(slice_node, PermuteAttrs.Permutation(perm=[0, 3, 1, 2], inv=[0, 2, 3, 1]), 'begin_mask') - self.assertTrue(np.array_equal(slice_node.begin_mask, np.array([1, 0, 0, 0]))) - - slice_node['end_mask'] = int64_array(extend_mask_according_ellipsis(slice_node['ellipsis_mask'], - slice_node['shrink_axis_mask'], 4, - list(slice_node['end_mask']), 0)) - permute_masks(slice_node, PermuteAttrs.Permutation(perm=[0, 3, 1, 2], inv=[0, 2, 3, 1]), 'end_mask') - self.assertTrue(np.array_equal(slice_node.end_mask, np.array([0, 0, 1, 0]))) - - def test_permute_begin_end_long(self): - # Testing constant path case - graph = build_graph(nodes_attributes, - [('data_1', 'strided_slice'), - ('begin', 'strided_slice'), - ('end', 'strided_slice'), - ('stride', 'strided_slice'), - ('strided_slice', 'data_2')], - {'data_1': {'shape': np.array([1, 2, 3, 4]), 'value': None}, - 'strided_slice': {'begin_mask': np.array([1, 0, 0, 1, 0]), - 'end_mask': np.array([0, 1, 0, 1, 1]), - 'new_axis_mask': np.array([0, 0, 0]), - 'shrink_axis_mask': [0, 0, 0], - 'ellipsis_mask': np.array([0, 0, 0])}, - 'data_2': {'shape': np.array([1, 2, 3, 4]), 'value': None}, - }) - - slice_node = Node(graph, 'strided_slice') - permute_masks(slice_node, PermuteAttrs.Permutation(perm=[0, 3, 1, 2], inv=[0, 2, 3, 1]), 'begin_mask') - self.assertTrue(np.array_equal(slice_node.begin_mask, np.array([1, 1, 0, 0, 0]))) - - permute_masks(slice_node, PermuteAttrs.Permutation(perm=[0, 3, 1, 2], inv=[0, 2, 3, 1]), 'end_mask') - self.assertTrue(np.array_equal(slice_node.end_mask, np.array([0, 1, 1, 0, 1]))) - - def test_permute_begin_end_new(self): - # Testing constant path case - graph = build_graph(nodes_attributes, - [('data_1', 'strided_slice'), - ('begin', 'strided_slice'), - ('end', 'strided_slice'), - ('stride', 'strided_slice'), - ('strided_slice', 'data_2')], - {'data_1': {'shape': np.array([1, 2, 3, 4]), 'value': None}, - 'strided_slice': {'begin_mask': np.array([1, 0, 0, 1, 0]), - 'end_mask': np.array([0, 1, 0, 1, 1]), - 'new_axis_mask': np.array([1, 0, 0]), - 'shrink_axis_mask': [0, 0, 0], - 'ellipsis_mask': np.array([0, 0, 0])}, - 'data_2': {'shape': np.array([1, 1, 2, 3, 4]), 'value': None}, - }) - - slice_node = Node(graph, 'strided_slice') - permute_masks(slice_node, PermuteAttrs.Permutation(perm=[0, 4, 1, 2, 3], inv=[0, 2, 3, 4, 1]), 'begin_mask') - self.assertTrue(np.array_equal(slice_node.begin_mask, np.array([1, 0, 0, 0, 1]))) - - permute_masks(slice_node, PermuteAttrs.Permutation(perm=[0, 4, 1, 2, 3], inv=[0, 2, 3, 4, 1]), 'end_mask') - self.assertTrue(np.array_equal(slice_node.end_mask, np.array([0, 1, 1, 0, 1]))) - - def test_permute_begin_end_new_short(self): - # Testing constant path case - graph = build_graph(nodes_attributes, - [('data_1', 'strided_slice'), - ('begin', 'strided_slice'), - ('end', 'strided_slice'), - ('stride', 'strided_slice'), - ('strided_slice', 'data_2')], - {'data_1': {'shape': np.array([1, 2, 3, 4]), 'value': None}, - 'strided_slice': {'begin_mask': np.array([1, 0, 0]), 'end_mask': np.array([0, 1, 0]), - 'new_axis_mask': np.array([1, 0, 0]), 'shrink_axis_mask': [0, 0, 0], - 'ellipsis_mask': np.array([0, 0, 0])}, - 'data_2': {'shape': np.array([1, 1, 2, 3, 4]), 'value': None}, - }) - - slice_node = Node(graph, 'strided_slice') - slice_node['begin_mask'] = int64_array(extend_mask_according_ellipsis(slice_node['ellipsis_mask'], - slice_node['shrink_axis_mask'], 5, - list(slice_node['begin_mask']), 0)) - permute_masks(slice_node, PermuteAttrs.Permutation(perm=[0, 4, 1, 2, 3], inv=[0, 2, 3, 4, 1]), 'begin_mask') - self.assertTrue(np.array_equal(slice_node.begin_mask, np.array([1, 0, 0, 0, 0]))) - - slice_node['end_mask'] = int64_array(extend_mask_according_ellipsis(slice_node['ellipsis_mask'], - slice_node['shrink_axis_mask'], 5, - list(slice_node['end_mask']), 0)) - permute_masks(slice_node, PermuteAttrs.Permutation(perm=[0, 4, 1, 2, 3], inv=[0, 2, 3, 4, 1]), 'end_mask') - self.assertTrue(np.array_equal(slice_node.end_mask, np.array([0, 0, 1, 0, 0]))) - - def test_permute_begin_end_shrink(self): - # Testing constant path case - graph = build_graph(nodes_attributes, - [('data_1', 'strided_slice'), - ('begin', 'strided_slice'), - ('end', 'strided_slice'), - ('stride', 'strided_slice'), - ('strided_slice', 'data_2')], - {'data_1': {'shape': np.array([1, 2, 3, 4]), 'value': None}, - 'strided_slice': {'begin_mask': np.array([1, 0, 0, 1]), 'end_mask': np.array([0, 1, 0, 1]), - 'new_axis_mask': np.array([0, 0, 0]), 'shrink_axis_mask': [1, 0, 0], - 'ellipsis_mask': np.array([0, 0, 0])}, - 'data_2': {'shape': np.array([2, 3, 4]), 'value': None}, - }) - - slice_node = Node(graph, 'strided_slice') - permute_masks(slice_node, PermuteAttrs.Permutation(perm=[0, 3, 1, 2], inv=[0, 2, 3, 1]), 'begin_mask') - - self.assertTrue(np.array_equal(slice_node.begin_mask, np.array([1, 1, 0, 0]))) - - permute_masks(slice_node, PermuteAttrs.Permutation(perm=[0, 3, 1, 2], inv=[0, 2, 3, 1]), 'end_mask') - self.assertTrue(np.array_equal(slice_node.end_mask, np.array([0, 1, 1, 0]))) - - def test_permute_begin_end_shrink_short(self): - # Testing constant path case - graph = build_graph(nodes_attributes, - [('data_1', 'strided_slice'), - ('begin', 'strided_slice'), - ('end', 'strided_slice'), - ('stride', 'strided_slice'), - ('strided_slice', 'data_2')], - {'data_1': {'shape': np.array([1, 2, 3, 4]), 'value': None}, - 'strided_slice': {'begin_mask': np.array([1, 0, 0]), 'end_mask': np.array([0, 1, 0]), - 'new_axis_mask': np.array([0, 0, 0]), 'shrink_axis_mask': [1, 0, 0], - 'ellipsis_mask': np.array([0, 0, 0])}, - 'data_2': {'shape': np.array([2, 3, 4]), 'value': None}, - }) - - slice_node = Node(graph, 'strided_slice') - slice_node['begin_mask'] = int64_array(extend_mask_according_ellipsis(slice_node['ellipsis_mask'], - slice_node['shrink_axis_mask'], 3, - list(slice_node['begin_mask']), 0)) - permute_masks(slice_node, PermuteAttrs.Permutation(perm=[0, 3, 1, 2], inv=[0, 2, 3, 1]), 'begin_mask') - self.assertTrue(np.array_equal(slice_node.begin_mask, np.array([1, 0, 0, 0]))) - - slice_node['end_mask'] = int64_array(extend_mask_according_ellipsis(slice_node['ellipsis_mask'], - slice_node['shrink_axis_mask'], 3, - list(slice_node['end_mask']), 0)) - permute_masks(slice_node, PermuteAttrs.Permutation(perm=[0, 3, 1, 2], inv=[0, 2, 3, 1]), 'end_mask') - self.assertTrue(np.array_equal(slice_node.end_mask, np.array([0, 0, 1, 0]))) - - def test_permute_begin_end_ellipsis(self): - # Testing constant path case - graph = build_graph(nodes_attributes, - [('input', 'data_1'), - ('data_1', 'strided_slice'), - ('begin', 'begin_data'), - ('begin_data', 'strided_slice'), - ('end', 'end_data'), - ('end_data', 'strided_slice'), - ('stride', 'stride_data'), - ('stride_data', 'strided_slice'), - ('strided_slice', 'data_2')], - {'data_1': {'shape': np.array([1, 2, 3, 4]), 'value': None}, - 'begin': {'value': [0, 1], 'shape': [2]}, - 'end': {'value': [1, 0], 'shape': [2]}, - 'stride': {'value': [1, 2], 'shape': [2]}, - 'strided_slice': {'begin_mask': np.array([0, 0]), 'end_mask': np.array([1, 0]), - 'new_axis_mask': np.array([0]), 'shrink_axis_mask': [0], - 'ellipsis_mask': np.array([1, 0])}, - 'data_2': {'shape': np.array([1, 2, 3, 4]), 'value': None}, - }) - - slice_node = Node(graph, 'strided_slice') - slice_node['begin_mask'] = int64_array(extend_mask_according_ellipsis(slice_node['ellipsis_mask'], - slice_node['shrink_axis_mask'], 4, - list(slice_node['begin_mask']), 0)) - permute_masks(slice_node, PermuteAttrs.Permutation(perm=[0, 3, 1, 2], inv=[0, 2, 3, 1]), 'begin_mask') - self.assertTrue(np.array_equal(slice_node.begin_mask, np.array([0, 0, 0, 0]))) - - slice_node['end_mask'] = int64_array(extend_mask_according_ellipsis(slice_node['ellipsis_mask'], - slice_node['shrink_axis_mask'], 4, - list(slice_node['end_mask']), 0)) - permute_masks(slice_node, PermuteAttrs.Permutation(perm=[0, 3, 1, 2], inv=[0, 2, 3, 1]), 'end_mask') - self.assertTrue(np.array_equal(slice_node.end_mask, np.array([1, 0, 0, 0]))) - - def test_permute_begin_end_ellipsis_infer(self): - # Testing constant path case - graph = build_graph(nodes_attributes, - [('input', 'data_1'), - ('data_1', 'strided_slice', {'in': 0}), - ('begin', 'begin_data'), - ('begin_data', 'strided_slice', {'in': 1}), - ('end', 'end_data'), - ('end_data', 'strided_slice', {'in': 2}), - ('stride', 'stride_data'), - ('stride_data', 'strided_slice', {'in': 3}), - ('strided_slice', 'data_2')], - {'data_1': {'shape': np.array([1, 2, 3, 4]), 'value': None}, - 'begin': {'value': [0, 1], 'shape': [2]}, - 'end': {'value': [1, 0], 'shape': [2]}, - 'stride': {'value': [1, 2], 'shape': [2]}, - 'begin_data': {'value': [0, 1], 'shape': [2]}, - 'end_data': {'value': [1, 0], 'shape': [2]}, - 'stride_data': {'value': [1, 2], 'shape': [2]}, - 'strided_slice': {'begin_mask': np.array([0, 0]), 'end_mask': np.array([1, 0]), - 'new_axis_mask': np.array([0]), 'shrink_axis_mask': [0], - 'ellipsis_mask': np.array([1, 0])}, - 'data_2': {'shape': np.array([1, 2, 3, 4]), 'value': None}, - }) - graph.graph['layout'] = "NHWC" - - slice_node = Node(graph, 'strided_slice') - begin_node = Node(graph, 'begin') - end_node = Node(graph, 'end') - stride_node = Node(graph, 'stride') - StridedSlice.infer(slice_node) - self.assertTrue(np.array_equal(slice_node.begin_mask, np.array([0, 0, 0, 0]))) - self.assertTrue(np.array_equal(slice_node.end_mask, np.array([1, 0, 0, 0]))) - self.assertTrue(np.array_equal(slice_node.shrink_axis_mask, np.array([0, 0, 0, 0]))) - self.assertTrue(np.array_equal(slice_node.new_axis_mask, np.array([0, 0, 0, 0]))) - self.assertTrue(np.array_equal(begin_node.value, np.array([0, 1, 0, 0]))) - self.assertTrue(np.array_equal(end_node.value, np.array([1, 0, 0, 0]))) - self.assertTrue(np.array_equal(stride_node.value, np.array([1, 2, 1, 1]))) - - def test_ss_shrink_only_short_ellipsis(self): - graph = build_graph(nodes_attributes, - [('input', 'data_1'), - ('data_1', 'strided_slice', {'in': 0}), - ('begin', 'begin_data'), - ('begin_data', 'strided_slice', {'in': 1}), - ('end', 'end_data'), - ('end_data', 'strided_slice', {'in': 2}), - ('stride', 'stride_data'), - ('stride_data', 'strided_slice', {'in': 3}), - ('strided_slice', 'data_2')], - {'data_1': {'shape': np.array([1, 127, 1, 54]), 'value': None}, - 'begin': {'value': [0, 0, 0], 'shape': [3]}, - 'end': {'value': [0, 0, 24], 'shape': [3]}, - 'stride': {'value': [1, 1, 1], 'shape': [3]}, - 'begin_data': {'value': [0, 0, 0], 'shape': [3]}, - 'end_data': {'value': [0, 0, 24], 'shape': [3]}, - 'stride_data': {'value': [1, 1, 1], 'shape': [3]}, - 'strided_slice': {'begin_mask': np.array([0, 0, 1]), 'end_mask': np.array([0, 0, 1]), - 'new_axis_mask': np.array([0, 0, 0]), 'shrink_axis_mask': [0, 1, 0], - 'ellipsis_mask': np.array([1, 0, 0])}, - 'data_2': {'shape': None} - }, nodes_with_edges_only=True) - graph.graph['layout'] = 'NCHW' - - slice_node = Node(graph, 'strided_slice') - begin_node = Node(graph, 'begin') - end_node = Node(graph, 'end') - stride_node = Node(graph, 'stride') - out_node = Node(graph, 'data_2') - StridedSlice.infer(slice_node) - self.assertTrue(np.array_equal(slice_node.begin_mask, np.array([0, 0, 0, 1]))) - self.assertTrue(np.array_equal(slice_node.end_mask, np.array([0, 0, 0, 1]))) - self.assertTrue(np.array_equal(slice_node.shrink_axis_mask, np.array([0, 0, 1, 0]))) - self.assertTrue(np.array_equal(slice_node.new_axis_mask, np.array([0, 0, 0, 0]))) - self.assertTrue(np.array_equal(slice_node.ellipsis_mask, np.array([0, 0, 0, 0]))) - self.assertTrue(np.array_equal(begin_node.value, np.array([0, 0, 0, 0]))) - self.assertTrue(np.array_equal(end_node.value, np.array([0, 0, 0, 24]))) - self.assertTrue(np.array_equal(stride_node.value, np.array([1, 1, 1, 1]))) - self.assertTrue(np.array_equal(out_node.shape, np.array([1, 127, 24]))) - - def test_ss_shrink_only_short(self): - graph = build_graph(nodes_attributes, - [('input', 'data_1'), - ('data_1', 'strided_slice', {'in': 0}), - ('begin', 'begin_data'), - ('begin_data', 'strided_slice', {'in': 1}), - ('end', 'end_data'), - ('end_data', 'strided_slice', {'in': 2}), - ('stride', 'stride_data'), - ('stride_data', 'strided_slice', {'in': 3}), - ('strided_slice', 'data_2')], - {'data_1': {'shape': np.array([1, 1, 127, 54]), 'value': None}, - 'begin': {'value': [0, 0, 0], 'shape': [3]}, - 'end': {'value': [0, 0, 0], 'shape': [3]}, - 'stride': {'value': [1, 1, 1], 'shape': [3]}, - 'begin_data': {'value': [0, 0, 0], 'shape': [3]}, - 'end_data': {'value': [0, 0, 0], 'shape': [3]}, - 'stride_data': {'value': [1, 1, 1], 'shape': [3]}, - 'strided_slice': {'begin_mask': np.array([0, 0, 0]), 'end_mask': np.array([0, 0, 0]), - 'new_axis_mask': np.array([0, 0, 0]), 'shrink_axis_mask': [0, 1, 0], - 'ellipsis_mask': np.array([0, 0, 0])}, - 'data_2': {'shape': None} - }, nodes_with_edges_only=True) - graph.graph['layout'] = 'NCHW' - - slice_node = Node(graph, 'strided_slice') - begin_node = Node(graph, 'begin') - end_node = Node(graph, 'end') - stride_node = Node(graph, 'stride') - out_node = Node(graph, 'data_2') - StridedSlice.infer(slice_node) - self.assertTrue(np.array_equal(slice_node.begin_mask, np.array([0, 0, 0, 0]))) - self.assertTrue(np.array_equal(slice_node.end_mask, np.array([0, 0, 0, 0]))) - self.assertTrue(np.array_equal(slice_node.shrink_axis_mask, np.array([0, 1, 0, 0]))) - self.assertTrue(np.array_equal(slice_node.new_axis_mask, np.array([0, 0, 0, 0]))) - self.assertTrue(np.array_equal(slice_node.ellipsis_mask, np.array([0, 0, 0, 0]))) - self.assertTrue(np.array_equal(begin_node.value, np.array([0, 0, 0, 0]))) - self.assertTrue(np.array_equal(end_node.value, np.array([0, 0, 0, 0]))) - self.assertTrue(np.array_equal(stride_node.value, np.array([1, 1, 1, 1]))) - self.assertTrue(np.array_equal(out_node.shape, np.array([1, 127, 54]))) - - def test_permute_begin_end_ellipsis_new(self): - # Testing constant path case - graph = build_graph(nodes_attributes, - [('input', 'data_1'), - ('data_1', 'strided_slice', {'in': 0}), - ('begin', 'begin_data'), - ('begin_data', 'strided_slice', {'in': 1}), - ('end', 'end_data'), - ('end_data', 'strided_slice', {'in': 2}), - ('stride', 'stride_data'), - ('stride_data', 'strided_slice', {'in': 3}), - ('strided_slice', 'data_2')], - {'data_1': {'shape': np.array([1, 2, 3, 4]), 'value': None}, - 'begin': {'value': [0, 1, 0], 'shape': [3]}, - 'begin_data': {'value': [0, 1, 0], 'shape': [3]}, - 'end': {'value': [1, 0, 1], 'shape': [3]}, - 'end_data': {'value': [1, 0, 1], 'shape': [3]}, - 'stride': {'value': [1, 2, 3], 'shape': [3]}, - 'stride_data': {'value': [1, 2, 3], 'shape': [3]}, - 'strided_slice': {'begin_mask': np.array([1, 2, 3]), 'end_mask': np.array([1, 2, 3]), - 'new_axis_mask': np.array([1, 0, 0]), 'shrink_axis_mask': [0], - 'ellipsis_mask': np.array([0, 1, 0])}, - 'data_2': {'shape': np.array([1, 1, 2, 3, 4]), 'value': None}, - }) - - slice_node = Node(graph, 'strided_slice') - slice_node['begin_mask'] = int64_array(extend_mask_according_ellipsis(slice_node['ellipsis_mask'], - slice_node['shrink_axis_mask'], 5, - list(slice_node['begin_mask']), 0)) - permute_masks(slice_node, PermuteAttrs.Permutation(perm=[0, 4, 1, 2, 3], inv=[0, 2, 3, 4, 1]), 'begin_mask') - self.assertTrue(np.array_equal(slice_node.begin_mask, np.array([1, 3, 2, 0, 0]))) - - slice_node['end_mask'] = int64_array(extend_mask_according_ellipsis(slice_node['ellipsis_mask'], - slice_node['shrink_axis_mask'], 5, - list(slice_node['end_mask']), 0)) - permute_masks(slice_node, PermuteAttrs.Permutation(perm=[0, 4, 1, 2, 3], inv=[0, 2, 3, 4, 1]), 'end_mask') - self.assertTrue(np.array_equal(slice_node.end_mask, np.array([1, 3, 2, 0, 0]))) - - def test_permute_begin_end_ellipsis_new_inputs(self): - # Testing constant path case - graph = build_graph(nodes_attributes, - [('input', 'data_1'), - ('data_1', 'strided_slice', {'in': 0}), - ('begin', 'begin_data'), - ('begin_data', 'strided_slice', {'in': 1}), - ('end', 'end_data'), - ('end_data', 'strided_slice', {'in': 2}), - ('stride', 'stride_data'), - ('stride_data', 'strided_slice', {'in': 3}), - ('strided_slice', 'data_2')], - {'data_1': {'shape': np.array([1, 2, 3, 4]), 'value': None}, - 'strided_slice': {'begin_mask': np.array([0, 0, 0]), 'end_mask': np.array([1, 0, 0]), - 'new_axis_mask': np.array([1, 0, 0]), 'shrink_axis_mask': [0], - 'ellipsis_mask': np.array([0, 1, 0])}, - 'begin': {'value': np.array([0, 1, 2])}, - 'end': {'value': np.array([1, 2, 3])}, - 'stride': {'value': np.array([1, 1, 1])}, - 'begin_data': {'value': np.array([0, 1, 2])}, - 'end_data': {'value': np.array([1, 2, 3])}, - 'stride_data': {'value': np.array([1, 1, 1])}, - 'data_2': {'shape': np.array([1, 1, 2, 3, 4]), 'value': None}, - }) - - slice_node = Node(graph, 'strided_slice') - slice_node.in_node(1).value = int64_array(extend_mask_according_ellipsis(slice_node['ellipsis_mask'], - slice_node['shrink_axis_mask'], 5, - list(slice_node.in_node(1).value), 0)) - slice_node.in_node(1).value = permute_array(slice_node, slice_node.in_node(1).value) - self.assertTrue(np.array_equal(slice_node.in_node(1).value, np.array([0, 2, 1, 0, 0]))) - - slice_node.in_node(2).value = int64_array(extend_mask_according_ellipsis(slice_node['ellipsis_mask'], - slice_node['shrink_axis_mask'], 5, - list(slice_node.in_node(2).value), 0)) - slice_node.in_node(2).value = permute_array(slice_node, slice_node.in_node(2).value) - self.assertTrue(np.array_equal(slice_node.in_node(2).value, np.array([1, 3, 2, 0, 0]))) - - def test_extend_mask(self): - ellipsis_mask = int64_array([1, 0]) - shrink_mask = int64_array([0, 0]) - length_shape = 4 - mask = int64_array([0, 1]) - ins_value = 0 - mask = extend_mask_according_ellipsis(ellipsis_mask, shrink_mask, length_shape, list(mask), ins_value) - self.assertEquals(mask, [0, 0, 0, 1]) - - def test_extend_mask_twice(self): - ellipsis_mask = int64_array([1, 0]) - shrink_mask = int64_array([0, 0]) - length_shape = 4 - mask = int64_array([0, 1]) - ins_value = 0 - mask = extend_mask_according_ellipsis(ellipsis_mask, shrink_mask, length_shape, list(mask), ins_value) - mask = extend_mask_according_ellipsis(ellipsis_mask, shrink_mask, length_shape, list(mask), ins_value) - self.assertEquals(mask, [0, 0, 0, 1]) - - def test_extend_mask_shrinked(self): - ellipsis_mask = int64_array([1, 0]) - shrink_mask = int64_array([0, 1]) - length_shape = 4 - mask = int64_array([0, 1]) - ins_value = 2 - mask = extend_mask_according_ellipsis(ellipsis_mask, shrink_mask, length_shape, list(mask), ins_value) - self.assertEquals(mask, [0, 2, 2, 2, 1]) - - def test_extend_mask_shrinked_shrink_mask(self): - ellipsis_mask = int64_array([0, 1, 0]) - shrink_mask = int64_array([0, 0, 1]) - length_shape = 4 - ins_value = 2 - shrink_mask = extend_mask_according_ellipsis(ellipsis_mask, shrink_mask, length_shape, list(shrink_mask), - ins_value) - self.assertEquals(shrink_mask, [0, 0, 2, 2, 1]) - - def test_non_const_infer(self): - # Testing constant path case - graph = build_graph(nodes_attributes, - [('input', 'data_1'), - ('data_1', 'strided_slice', {'in': 0}), - ('data_1', 'strided_slice', {'in': 1}), - ('end', 'end_data'), - ('end_data', 'strided_slice', {'in': 2}), - ('stride', 'stride_data'), - ('stride_data', 'strided_slice', {'in': 3}), - ('strided_slice', 'data_2')], - {'data_1': {'shape': np.array([1, 2, 3, 4]), 'value': None}, - 'end': {'value': [1, 0], 'shape': [2]}, - 'stride': {'value': [1, 2], 'shape': [2]}, - 'strided_slice': {'begin_mask': np.array([0, 0]), 'end_mask': np.array([1, 0]), - 'new_axis_mask': np.array([0]), 'shrink_axis_mask': [0], - 'ellipsis_mask': np.array([1, 0])}, - 'data_2': {'shape': np.array([1, 2, 3, 4]), 'value': None}, - }) - graph.graph['layout'] = "NHWC" - - slice_node = Node(graph, 'strided_slice') - with self.assertRaises(Error) as error: - StridedSlice.infer(slice_node) - self.assertTrue('Strided slice layer supports only constant begin and end inputs' in str(error.exception)) + +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)) + else: + input_node = valued_const_with_data('input', int64_array(inp)) + + nodes = { + **input_node, + **regular_op_with_empty_data('sslice', + {'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)), + **result('res'), + } + + edges = [ + *connect('input', '0:sslice'), + *connect('begin', '1:sslice'), + *connect('end', '2:sslice'), + *connect('strides', '3:sslice'), + *connect('sslice', 'res') + ] + + graph = build_graph(nodes, edges) + 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) + + 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, + begin=(0,), end=(4,), strides=(1,), begin_mask=(0,), end_mask=(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_value_2(self, # inp[1:3:1] = [34, 34] + inp=(1, 34, 34, 62), ref_res=(34, 34), is_shape=False, + begin=(1,), end=(3,), strides=(1,), begin_mask=(1,), end_mask=(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_value_3(self, # inp[np.newaxis, :4:1] = [[1, 34, 34, 62]] + inp=(1, 34, 34, 62), ref_res=((1, 34, 34, 62),), is_shape=False, + begin=(0, 0,), end=(0, 4,), strides=(1, 1), begin_mask=(0, 0), end_mask=(1, 1), + shrink_axis_mask=(0,), new_axis_mask=(1,), 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_value_4(self, # inp[1] = 34 + inp=(1, 34, 34, 62), ref_res=34, is_shape=False, + begin=(1,), end=(4,), strides=(1,), begin_mask=(1,), end_mask=(1,), + shrink_axis_mask=(1,), 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_value_5(self, # inp[::-1] = [62, 34, 34, 1] + inp=(1, 34, 34, 62), ref_res=(62, 34, 34, 1), is_shape=False, + begin=(0,), end=(4,), strides=(-1,), begin_mask=(0,), end_mask=(0,), + 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_value_6(self, # inp[0, 0:4:1] + inp=((1, 34, 34, 62),), ref_res=(1, 34, 34, 62), is_shape=False, + begin=(0, 0), end=(0, 4), strides=(1, 1), begin_mask=(0, 1), end_mask=(0, 1), + shrink_axis_mask=(1, 0), new_axis_mask=(0, 0), ellipsis_mask=(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_slice_infer_value_7(self, # inp[:-1:1] = [1, 34, 34], since begin_mask is [0], begin can be of any value + inp=(1, 34, 34, 62), ref_res=(1, 34, 34), is_shape=False, + begin=(0,), end=(-1,), strides=(1,), begin_mask=(0,), end_mask=(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_value_8( + self, # inp_shape = (1, 2, 4), out = inp[..., :2, None] => out_shape = (1, 2, 2, 1) + inp=(((0, 1, 2, 3), (4, 5, 6, 7)),), ref_res=((((0.,), (1.,)), ((4.,), (5.,))),), is_shape=False, + begin=(0, 0, 0), end=(0, 2, 0), strides=(1, 1, 1), begin_mask=(0, 0, 0), end_mask=(0, 1, 0), + shrink_axis_mask=(0, 0, 0), new_axis_mask=(0, 0, 1), ellipsis_mask=(1, 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_slice_infer_shape_1( + self, # inp[0:3, 0:1, 0:5] + inp=(10, 10, 10, 10), ref_res=(3, 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_shape_2( + self, # inp[0:3, 0:1, 5:0:-1] + inp=(10, 10, 10, 10), ref_res=(3, 1, 5, 10), is_shape=True, + begin=(0, 0, 5), end=(3, 1, 0), 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_shape_3( + self, # inp[1:34, 0, :, :2] + inp=(1, 35, 35, 3), ref_res=(1, 35, 2), is_shape=True, + begin=(0, 0, 0, 0), end=(1, 34, 0, 2), 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_slice_infer_shape_4( + self, # inp[1:34, :, :, :2] begin mask is (1,) so only one value can be specified + inp=(1, 35, 35, 3), ref_res=(1, 35, 2), is_shape=True, + begin=(0, 0, 0, 0), end=(1, 34, 20, 2), strides=(1, 1, 1, 1), begin_mask=(1, 0, 0, ), end_mask=(1, 0, 0, 1), + shrink_axis_mask=(0, 1), 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_shape_5( + self, # inp[:, :, :, :] since all begin and end masks are zero + inp=(1, 35, 35, 3), ref_res=(1, 35, 35, 3), is_shape=True, + begin=(1, 10, 10, 0), end=(1, 34, 20, 2), strides=(1, 1, 1, 1), begin_mask=(0, 0, 0, 0), end_mask=(0, 0, 0, 0), + 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_shape_6( + self, # inp[0] + inp=(1, 35, 35, 3), ref_res=(35, 35, 3), is_shape=True, + begin=(0,), end=(1,), strides=(1,), begin_mask=(1,), end_mask=(0,), + shrink_axis_mask=(1,), 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_shape_7( + self, # inp[0, 20], ends can be of any value + inp=(1, 35, 35, 3), ref_res=(35, 3), is_shape=True, + begin=(0, 20), end=(1, 9999), strides=(1, 1), begin_mask=(0,), end_mask=(0,), + shrink_axis_mask=(1, 1), 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_shape_8( + self, # inp[0, 0:34, 20:22, new_axis], both new_axis and shrink_axis are present + inp=(1, 35, 35, 3), ref_res=(34, 2, 1, 3), is_shape=True, + begin=(0, 0, 20, 0), end=(1, 34, 22, 2), strides=(1, 1, 1, 1), begin_mask=(0,), end_mask=(0,), + shrink_axis_mask=(1,), new_axis_mask=(0, 0, 0, 1), 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_shape_9( + self, # inp[:, 0:4, 20, new_axis], both new_axis and shrink_axis are present + inp=(1, 35, 35, 3), ref_res=(1, 4, 1, 3), is_shape=True, + begin=(0, 0, 20, 0), end=(0, 4, 0, 0), strides=(1, 1, 1, 1), begin_mask=(0, 1, 0, 0), end_mask=(0, 1, 0, 0), + shrink_axis_mask=(0, 0, 1, 0), new_axis_mask=(0, 0, 0, 1), 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_shape_10( + self, # inp[:, 0:4, new_axis, 20], both new_axis and shrink_axis are present + inp=(1, 35, 35, 3), ref_res=(1, 4, 1, 3), is_shape=True, + begin=(0, 0, 0, 20), end=(0, 4, 0, 0), strides=(1, 1, 1, 1), begin_mask=(0, 1, 0, 0), end_mask=(0, 1, 0, 0), + shrink_axis_mask=(0, 0, 0, 1), new_axis_mask=(0, 0, 1, 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_shape_11( + self, # inp[0, :, 0:34, 20:22, new_axis], both new_axis and shrink_axis are present + inp=(1, 3, 35, 35), ref_res=(3, 34, 2, 1), is_shape=True, + begin=(0, 0, 0, 20, 0), end=(1, 0, 34, 22, 0), strides=(1, 1, 1, 1, 1), + begin_mask=(1, 0, 1, 1, 1), end_mask=(1, 0, 1, 1, 1), + shrink_axis_mask=(1,), new_axis_mask=(0, 0, 0, 0, 1), 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_shape_12( + self, # inp[0, :34, 20, :2] + inp=(1, 35, 35, 3), ref_res=(34, 2), is_shape=True, + begin=(0, 0, 0, 0), end=(1, 34, 20, 2), strides=(1, 1, 1, 1), begin_mask=(0, 1, 1, 1), end_mask=(0, 1, 1, 1), + shrink_axis_mask=(1, 0, 1, 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_shape_13( + self, # inp[0, 0, 0], since it's shrink_axis ends can be of any value + inp=(1, 35, 35, 3), ref_res=(3,), is_shape=True, + begin=(0, 0, 0), end=(1, 34444, 20), strides=(1, 1, 1), begin_mask=(0, 0, 0), end_mask=(0, 0, 0), + shrink_axis_mask=(1, 1, 1), 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_shape_14( + self, # inp[0, 0, 0], since begin_mask is [0], begin can be of any value + inp=(1, 35, 35, 3), ref_res=(1, 18, 18, 3), is_shape=True, + begin=(0, 0, 0), end=(1, 35, 35), strides=(2, 2, 2), begin_mask=(1, 1, 1), end_mask=(1, 1, 1), + shrink_axis_mask=(0, 0, 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) + + # with ellipsis + def test_slice_infer_shape_15( + self, # inp[..., np.newaxis] + inp=(1, 35, 35), ref_res=(1, 35, 35, 1), is_shape=True, + begin=(101, 0), end=(0, 0), strides=(-1, -1), begin_mask=(0, 0), end_mask=(0, 0), + shrink_axis_mask=(0, 0), new_axis_mask=(0, 1), ellipsis_mask=(1, 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_shape_16( + self, # inp_shape = (1, 720, 1080), out = inp[..., :100, None] => out_shape = (1, 720, 100, 1) + inp=(1, 720, 1080), ref_res=(1, 720, 100, 1), is_shape=True, + begin=(0, 0, 0), end=(0, 100, 0), strides=(1, 1, 1), begin_mask=(0, 1, 0), end_mask=(0, 1, 0), + shrink_axis_mask=(0,), new_axis_mask=(0, 0, 1), ellipsis_mask=(1,) + ): + 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_shape_17( + self, # inp_shape = (1, 720, 1080, 3), out = inp[..., :-1] => out_shape = (1, 720, 100, 2) + inp=(1, 720, 1080, 3), ref_res=(1, 720, 1080, 2), is_shape=True, + begin=(0, 0), end=(0, -1), strides=(1, 1), begin_mask=(0, 0), end_mask=(0, 1), + shrink_axis_mask=(0, 0), new_axis_mask=(0, 0), ellipsis_mask=(1, 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_shape_18( + self, # inp_shape = (1, 720, 1080, 3), out = inp[..., -2] => out_shape = (1, 720, 1080) + inp=(1, 720, 1080, 3), ref_res=(1, 720, 1080), is_shape=True, + begin=(0, -2), end=(0, 0), strides=(1, 1), begin_mask=(0, 1), end_mask=(0, 0), + shrink_axis_mask=(0, 1), new_axis_mask=(0, 0), ellipsis_mask=(1, 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_shape_19( + self, # inp_shape = (1, 720, 1080, 3), out = input[..., 0:10, 0:3] => out_shape = (1, 720, 10, 3) + inp=(1, 720, 1080, 3), ref_res=(1, 720, 10, 3), is_shape=True, + begin=(0, 0, 0), end=(0, 10, 3), strides=(1, 1, 1), begin_mask=(0, 1, 1), end_mask=(0, 1, 1), + shrink_axis_mask=(0,), new_axis_mask=(0,), ellipsis_mask=(1,) + ): + 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, + begin=(0, 0, 0, 0), end=(0, 0, 0, 0), strides=(1, 1, 1, 1), begin_mask=(0, 0, 0, 0), end_mask=(0, 0, 0, 0), + shrink_axis_mask=(0, 0, 1, 0), new_axis_mask=(1, 0, 0, 0), ellipsis_mask=(0, 1, 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_1( + self, # inp_shape = (1, 100, 200, 3), out = inp[..., np.newaxis, 0, :], out_shape=(1, 100, 1, 3) + inp=(1, 100, 200, 3), ref_res=(1, 100, 1, 3), is_shape=True, + begin=(0, 0, 0, 0), end=(0, 0, 0, 0), strides=(1, 1, 1, 1), begin_mask=(0, 0, 0, 0), end_mask=(0, 0, 0, 0), + shrink_axis_mask=(0, 0, 1, 0), new_axis_mask=(0, 1, 0, 0), ellipsis_mask=(1, 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_2( + self, # inp_shape = (1, 100, 200, 3), out = inp[0, np.newaxis, ..., :], out_shape=(1, 100, 200, 3) + inp=(1, 100, 200, 3), ref_res=(1, 100, 200, 3), is_shape=True, + begin=(0, 0, 0, 0), end=(0, 0, 0, 0), strides=(1, 1, 1, 1), begin_mask=(0, 0, 0, 0), end_mask=(0, 0, 0, 0), + shrink_axis_mask=(1, 0, 0, 0), new_axis_mask=(0, 1, 0, 0), ellipsis_mask=(0, 0, 1, 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_3( + self, # inp_shape = (1, 100, 200, 3), out = inp[0, ..., np.newaxis, :], out_shape=(100, 200, 1, 3) + inp=(1, 100, 200, 3), ref_res=(100, 200, 1, 3), is_shape=True, + begin=(0, 0, 0, 0), end=(0, 0, 0, 0), strides=(1, 1, 1, 1), begin_mask=(0, 0, 0, 0), end_mask=(0, 0, 0, 0), + shrink_axis_mask=(1, 0, 0, 0), new_axis_mask=(0, 0, 1, 0), ellipsis_mask=(0, 1, 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_4( + self, # inp_shape = (1, 100, 200, 3), out = inp[np.newaxis, 0, ..., :], out_shape=(1, 100, 200, 3) + inp=(1, 100, 200, 3), ref_res=(1, 100, 200, 3), is_shape=True, + begin=(0, 0, 0, 0), end=(0, 0, 0, 0), strides=(1, 1, 1, 1), begin_mask=(0, 0, 0, 0), end_mask=(0, 0, 0, 0), + shrink_axis_mask=(0, 1, 0, 0), new_axis_mask=(1, 0, 0, 0), ellipsis_mask=(0, 0, 1, 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_5( + self, # inp_shape = (1, 100, 200, 3), out = inp[..., 0, np.newaxis, :], out_shape=(1, 100, 1, 3) + inp=(1, 100, 200, 3), ref_res=(1, 100, 1, 3), is_shape=True, + begin=(0, 0, 0, 0), end=(0, 0, 0, 0), strides=(1, 1, 1, 1), begin_mask=(0, 0, 0, 0), end_mask=(0, 0, 0, 0), + shrink_axis_mask=(0, 1, 0, 0), new_axis_mask=(0, 0, 1, 0), ellipsis_mask=(1, 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_6( + self, # inp_shape = (1, 100, 200, 3), out = inp[np.newaxis, ..., :, 0], out_shape=(1, 1, 100, 200) + inp=(1, 100, 200, 3), ref_res=(1, 1, 100, 200), is_shape=True, + begin=(0, 0, 0, 0), end=(0, 0, 0, 0), strides=(1, 1, 1, 1), begin_mask=(0, 0, 0, 0), end_mask=(0, 0, 0, 0), + shrink_axis_mask=(0, 0, 0, 1), new_axis_mask=(1, 0, 0, 0), ellipsis_mask=(0, 1, 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_7( + self, # inp_shape = (1, 100, 200, 3), out = inp[..., np.newaxis, :, 0], out_shape=(1, 100, 1, 200) + inp=(1, 100, 200, 3), ref_res=(1, 100, 1, 200), is_shape=True, + begin=(0, 0, 0, 0), end=(0, 0, 0, 0), strides=(1, 1, 1, 1), begin_mask=(0, 0, 0, 0), end_mask=(0, 0, 0, 0), + shrink_axis_mask=(0, 0, 0, 1), new_axis_mask=(0, 1, 0, 0), ellipsis_mask=(1, 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_8( + self, # inp_shape = (1, 100, 200, 3), out = inp[0, np.newaxis, :, ...], out_shape=(1, 100, 200, 3) + inp=(1, 100, 200, 3), ref_res=(1, 100, 200, 3), is_shape=True, + begin=(0, 0, 0, 0), end=(0, 0, 0, 0), strides=(1, 1, 1, 1), begin_mask=(0, 0, 0, 0), end_mask=(0, 0, 0, 0), + shrink_axis_mask=(1, 0, 0, 0), new_axis_mask=(0, 1, 0, 0), ellipsis_mask=(0, 0, 0, 1) + ): + 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_9( + self, # inp_shape = (1, 100, 200, 3), out = inp[0, ..., :, np.newaxis], out_shape=(100, 200, 3, 1) + inp=(1, 100, 200, 3), ref_res=(100, 200, 3, 1), is_shape=True, + begin=(0, 0, 0, 0), end=(0, 0, 0, 0), strides=(1, 1, 1, 1), begin_mask=(0, 0, 0, 0), end_mask=(0, 0, 0, 0), + shrink_axis_mask=(1, 0, 0, 0), new_axis_mask=(0, 0, 0, 1), ellipsis_mask=(0, 1, 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_10( + self, # inp_shape = (1, 100, 200, 3), out = inp[np.newaxis, 0, :, ...], out_shape=(1, 100, 200, 3) + inp=(1, 100, 200, 3), ref_res=(1, 100, 200, 3), is_shape=True, + begin=(0, 0, 0, 0), end=(0, 0, 0, 0), strides=(1, 1, 1, 1), begin_mask=(0, 0, 0, 0), end_mask=(0, 0, 0, 0), + shrink_axis_mask=(0, 1, 0, 0), new_axis_mask=(1, 0, 0, 0), ellipsis_mask=(0, 0, 0, 1) + ): + 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_11( + self, # inp_shape = (1, 100, 200, 3), out = inp[..., 0, :, np.newaxis], out_shape=(1, 100, 3, 1) + inp=(1, 100, 200, 3), ref_res=(1, 100, 3, 1), is_shape=True, + begin=(0, 0, 0, 0), end=(0, 0, 0, 0), strides=(1, 1, 1, 1), begin_mask=(0, 0, 0, 0), end_mask=(0, 0, 0, 0), + shrink_axis_mask=(0, 1, 0, 0), new_axis_mask=(0, 0, 0, 1), ellipsis_mask=(1, 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_12( + self, # inp_shape = (1, 100, 200, 3), out = inp[np.newaxis, :, ..., 0], out_shape=(1, 1, 100, 200) + inp=(1, 100, 200, 3), ref_res=(1, 1, 100, 200), is_shape=True, + begin=(0, 0, 0, 0), end=(0, 0, 0, 0), strides=(1, 1, 1, 1), begin_mask=(0, 0, 0, 0), end_mask=(0, 0, 0, 0), + shrink_axis_mask=(0, 0, 0, 1), new_axis_mask=(1, 0, 0, 0), ellipsis_mask=(0, 0, 1, 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_13( + self, # inp_shape = (1, 100, 200, 3), out = inp[..., :, np.newaxis, 0], out_shape=(1, 100, 200, 1) + inp=(1, 100, 200, 3), ref_res=(1, 100, 200, 1), is_shape=True, + begin=(0, 0, 0, 0), end=(0, 0, 0, 0), strides=(1, 1, 1, 1), begin_mask=(0, 0, 0, 0), end_mask=(0, 0, 0, 0), + shrink_axis_mask=(0, 0, 0, 1), new_axis_mask=(0, 0, 1, 0), ellipsis_mask=(1, 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_14( + self, # inp_shape = (1, 100, 200, 3), out = inp[0, :, np.newaxis, ...], out_shape=(100, 1, 200, 3) + inp=(1, 100, 200, 3), ref_res=(100, 1, 200, 3), is_shape=True, + begin=(0, 0, 0, 0), end=(0, 0, 0, 0), strides=(1, 1, 1, 1), begin_mask=(0, 0, 0, 0), end_mask=(0, 0, 0, 0), + shrink_axis_mask=(1, 0, 0, 0), new_axis_mask=(0, 0, 1, 0), ellipsis_mask=(0, 0, 0, 1) + ): + 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_15( + self, # inp_shape = (1, 100, 200, 3), out = inp[0, :, ..., np.newaxis], out_shape=(100, 200, 3, 1) + inp=(1, 100, 200, 3), ref_res=(100, 200, 3, 1), is_shape=True, + begin=(0, 0, 0, 0), end=(0, 0, 0, 0), strides=(1, 1, 1, 1), begin_mask=(0, 0, 0, 0), end_mask=(0, 0, 0, 0), + shrink_axis_mask=(1, 0, 0, 0), new_axis_mask=(0, 0, 0, 1), ellipsis_mask=(0, 0, 1, 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_16( + self, # inp_shape = (1, 100, 200, 3), out = inp[np.newaxis, :, 0, ...], out_shape=(1, 1, 200, 3) + inp=(1, 100, 200, 3), ref_res=(1, 1, 200, 3), is_shape=True, + begin=(0, 0, 0, 0), end=(0, 0, 0, 0), strides=(1, 1, 1, 1), begin_mask=(0, 0, 0, 0), end_mask=(0, 0, 0, 0), + shrink_axis_mask=(0, 0, 1, 0), new_axis_mask=(1, 0, 0, 0), ellipsis_mask=(0, 0, 0, 1) + ): + 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_17( + self, # inp_shape = (1, 100, 200, 3), out = inp[..., :, 0, np.newaxis], out_shape=(1, 100, 200, 1) + inp=(1, 100, 200, 3), ref_res=(1, 100, 200, 1), is_shape=True, + begin=(0, 0, 0, 0), end=(0, 0, 0, 0), strides=(1, 1, 1, 1), begin_mask=(0, 0, 0, 0), end_mask=(0, 0, 0, 0), + shrink_axis_mask=(0, 0, 1, 0), new_axis_mask=(0, 0, 0, 1), ellipsis_mask=(1, 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_18( + self, # inp_shape = (1, 100, 200, 3), out = inp[:, np.newaxis, ..., 0], out_shape=(1, 1, 100, 200) + inp=(1, 100, 200, 3), ref_res=(1, 1, 100, 200), is_shape=True, + begin=(0, 0, 0, 0), end=(0, 0, 0, 0), strides=(1, 1, 1, 1), begin_mask=(0, 0, 0, 0), end_mask=(0, 0, 0, 0), + shrink_axis_mask=(0, 0, 0, 1), new_axis_mask=(0, 1, 0, 0), ellipsis_mask=(0, 0, 1, 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_19( + self, # inp_shape = (1, 100, 200, 3), out = inp[:, ..., np.newaxis, 0], out_shape=(1, 100, 200, 1) + inp=(1, 100, 200, 3), ref_res=(1, 100, 200, 1), is_shape=True, + begin=(0, 0, 0, 0), end=(0, 0, 0, 0), strides=(1, 1, 1, 1), begin_mask=(0, 0, 0, 0), end_mask=(0, 0, 0, 0), + shrink_axis_mask=(0, 0, 0, 1), new_axis_mask=(0, 0, 1, 0), ellipsis_mask=(0, 1, 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_20( + self, # inp_shape = (1, 100, 200, 3), out = inp[:, 0, np.newaxis, ...], out_shape=(1, 1, 200, 3) + inp=(1, 100, 200, 3), ref_res=(1, 1, 200, 3), is_shape=True, + begin=(0, 0, 0, 0), end=(0, 0, 0, 0), strides=(1, 1, 1, 1), begin_mask=(0, 0, 0, 0), end_mask=(0, 0, 0, 0), + shrink_axis_mask=(0, 1, 0, 0), new_axis_mask=(0, 0, 1, 0), ellipsis_mask=(0, 0, 0, 1) + ): + 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_21( + self, # inp_shape = (1, 100, 200, 3), out = inp[:, 0, ..., np.newaxis], out_shape=(1, 200, 3, 1) + inp=(1, 100, 200, 3), ref_res=(1, 200, 3, 1), is_shape=True, + begin=(0, 0, 0, 0), end=(0, 0, 0, 0), strides=(1, 1, 1, 1), begin_mask=(0, 0, 0, 0), end_mask=(0, 0, 0, 0), + shrink_axis_mask=(0, 1, 0, 0), new_axis_mask=(0, 0, 0, 1), ellipsis_mask=(0, 0, 1, 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_22( + self, # inp_shape = (1, 100, 200, 3), out = inp[:, np.newaxis, 0, ...], out_shape=(1, 1, 200, 3) + inp=(1, 100, 200, 3), ref_res=(1, 1, 200, 3), is_shape=True, + begin=(0, 0, 0, 0), end=(0, 0, 0, 0), strides=(1, 1, 1, 1), begin_mask=(0, 0, 0, 0), end_mask=(0, 0, 0, 0), + shrink_axis_mask=(0, 0, 1, 0), new_axis_mask=(0, 1, 0, 0), ellipsis_mask=(0, 0, 0, 1) + ): + 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_23( + self, # inp_shape = (1, 100, 200, 3), out = inp[:, ..., 0, np.newaxis], out_shape=(1, 100, 200, 1) + inp=(1, 100, 200, 3), ref_res=(1, 100, 200, 1), is_shape=True, + begin=(0, 0, 0, 0), end=(0, 0, 0, 0), strides=(1, 1, 1, 1), begin_mask=(0, 0, 0, 0), end_mask=(0, 0, 0, 0), + shrink_axis_mask=(0, 0, 1, 0), new_axis_mask=(0, 0, 0, 1), ellipsis_mask=(0, 1, 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) + + # automatically generated the whole range of 2d slices over 2d, 3d and 4d input tensors + def test_auto_infer_strided_slice_2d_over_2d_0(self): + """ + inp_shape = (1, 100), out = inp[:, :] => out_shape = (1, 100) + """ + self.run_test( + inp=(1, 100), is_shape=True, ref_res=(1, 100), + begin=(0, 0), end=(0, 0), strides=(1, 1), begin_mask=(0, 0), end_mask=(0, 0), + shrink_axis_mask=(0, 0), new_axis_mask=(0, 0), ellipsis_mask=(0, 0) + ) + + def test_auto_infer_strided_slice_2d_over_2d_1(self): + """ + inp_shape = (1, 100), out = inp[:, None] => out_shape = (1, 1, 100) + """ + self.run_test( + inp=(1, 100), is_shape=True, ref_res=(1, 1, 100), + begin=(0, 0), end=(0, 0), strides=(1, 1), begin_mask=(0, 0), end_mask=(0, 0), + shrink_axis_mask=(0, 0), new_axis_mask=(0, 1), ellipsis_mask=(0, 0) + ) + + def test_auto_infer_strided_slice_2d_over_2d_2(self): + """ + inp_shape = (1, 100), out = inp[:, 0] => out_shape = (1,) + """ + self.run_test( + inp=(1, 100), is_shape=True, ref_res=(1,), + begin=(0, 0), end=(0, 0), strides=(1, 1), begin_mask=(0, 0), end_mask=(0, 0), + shrink_axis_mask=(0, 1), new_axis_mask=(0, 0), ellipsis_mask=(0, 0) + ) + + def test_auto_infer_strided_slice_2d_over_2d_3(self): + """ + inp_shape = (1, 100), out = inp[..., :] => out_shape = (1, 100) + """ + self.run_test( + inp=(1, 100), is_shape=True, ref_res=(1, 100), + begin=(0, 0), end=(0, 0), strides=(1, 1), begin_mask=(0, 0), end_mask=(0, 0), + shrink_axis_mask=(0, 0), new_axis_mask=(0, 0), ellipsis_mask=(1, 0) + ) + + def test_auto_infer_strided_slice_2d_over_2d_4(self): + """ + inp_shape = (1, 100), out = inp[..., None] => out_shape = (1, 100, 1) + """ + self.run_test( + inp=(1, 100), is_shape=True, ref_res=(1, 100, 1), + begin=(0, 0), end=(0, 0), strides=(1, 1), begin_mask=(0, 0), end_mask=(0, 0), + shrink_axis_mask=(0, 0), new_axis_mask=(0, 1), ellipsis_mask=(1, 0) + ) + + def test_auto_infer_strided_slice_2d_over_2d_5(self): + """ + inp_shape = (1, 100), out = inp[..., 0] => out_shape = (1,) + """ + self.run_test( + inp=(1, 100), is_shape=True, ref_res=(1,), + begin=(0, 0), end=(0, 0), strides=(1, 1), begin_mask=(0, 0), end_mask=(0, 0), + shrink_axis_mask=(0, 1), new_axis_mask=(0, 0), ellipsis_mask=(1, 0) + ) + + def test_auto_infer_strided_slice_2d_over_2d_6(self): + """ + inp_shape = (1, 100), out = inp[None, :] => out_shape = (1, 1, 100) + """ + self.run_test( + inp=(1, 100), is_shape=True, ref_res=(1, 1, 100), + begin=(0, 0), end=(0, 0), strides=(1, 1), begin_mask=(0, 0), end_mask=(0, 0), + shrink_axis_mask=(0, 0), new_axis_mask=(1, 0), ellipsis_mask=(0, 0) + ) + + def test_auto_infer_strided_slice_2d_over_2d_7(self): + """ + inp_shape = (1, 100), out = inp[None, None] => out_shape = (1, 1, 1, 100) + """ + self.run_test( + inp=(1, 100), is_shape=True, ref_res=(1, 1, 1, 100), + begin=(0, 0), end=(0, 0), strides=(1, 1), begin_mask=(0, 0), end_mask=(0, 0), + shrink_axis_mask=(0, 0), new_axis_mask=(1, 1), ellipsis_mask=(0, 0) + ) + + def test_auto_infer_strided_slice_2d_over_2d_8(self): + """ + inp_shape = (1, 100), out = inp[None, 0] => out_shape = (1, 100) + """ + self.run_test( + inp=(1, 100), is_shape=True, ref_res=(1, 100), + begin=(0, 0), end=(0, 0), strides=(1, 1), begin_mask=(0, 0), end_mask=(0, 0), + shrink_axis_mask=(0, 1), new_axis_mask=(1, 0), ellipsis_mask=(0, 0) + ) + + def test_auto_infer_strided_slice_2d_over_2d_9(self): + """ + inp_shape = (1, 100), out = inp[0, :] => out_shape = (100,) + """ + self.run_test( + inp=(1, 100), is_shape=True, ref_res=(100,), + begin=(0, 0), end=(0, 0), strides=(1, 1), begin_mask=(0, 0), end_mask=(0, 0), + shrink_axis_mask=(1, 0), new_axis_mask=(0, 0), ellipsis_mask=(0, 0) + ) + + def test_auto_infer_strided_slice_2d_over_2d_10(self): + """ + inp_shape = (1, 100), out = inp[0, None] => out_shape = (1, 100) + """ + self.run_test( + inp=(1, 100), is_shape=True, ref_res=(1, 100), + begin=(0, 0), end=(0, 0), strides=(1, 1), begin_mask=(0, 0), end_mask=(0, 0), + shrink_axis_mask=(1, 0), new_axis_mask=(0, 1), ellipsis_mask=(0, 0) + ) + + def test_auto_infer_strided_slice_2d_over_2d_11(self): + """ + inp_shape = (1, 100), out = inp[0, 0] => out_shape = () + """ + self.run_test( + inp=(1, 100), is_shape=True, ref_res=(), + begin=(0, 0), end=(0, 0), strides=(1, 1), begin_mask=(0, 0), end_mask=(0, 0), + shrink_axis_mask=(1, 1), new_axis_mask=(0, 0), ellipsis_mask=(0, 0) + ) + + def test_auto_infer_strided_slice_2d_over_3d_0(self): + """ + inp_shape = (1, 100, 200), out = inp[:, :] => out_shape = (1, 100, 200) + """ + self.run_test( + inp=(1, 100, 200), is_shape=True, ref_res=(1, 100, 200), + begin=(0, 0), end=(0, 0), strides=(1, 1), begin_mask=(0, 0), end_mask=(0, 0), + shrink_axis_mask=(0, 0), new_axis_mask=(0, 0), ellipsis_mask=(0, 0) + ) + + def test_auto_infer_strided_slice_2d_over_3d_1(self): + """ + inp_shape = (1, 100, 200), out = inp[:, None] => out_shape = (1, 1, 100, 200) + """ + self.run_test( + inp=(1, 100, 200), is_shape=True, ref_res=(1, 1, 100, 200), + begin=(0, 0), end=(0, 0), strides=(1, 1), begin_mask=(0, 0), end_mask=(0, 0), + shrink_axis_mask=(0, 0), new_axis_mask=(0, 1), ellipsis_mask=(0, 0) + ) + + def test_auto_infer_strided_slice_2d_over_3d_2(self): + """ + inp_shape = (1, 100, 200), out = inp[:, 0] => out_shape = (1, 200) + """ + self.run_test( + inp=(1, 100, 200), is_shape=True, ref_res=(1, 200), + begin=(0, 0), end=(0, 0), strides=(1, 1), begin_mask=(0, 0), end_mask=(0, 0), + shrink_axis_mask=(0, 1), new_axis_mask=(0, 0), ellipsis_mask=(0, 0) + ) + + def test_auto_infer_strided_slice_2d_over_3d_3(self): + """ + inp_shape = (1, 100, 200), out = inp[..., :] => out_shape = (1, 100, 200) + """ + self.run_test( + inp=(1, 100, 200), is_shape=True, ref_res=(1, 100, 200), + begin=(0, 0), end=(0, 0), strides=(1, 1), begin_mask=(0, 0), end_mask=(0, 0), + shrink_axis_mask=(0, 0), new_axis_mask=(0, 0), ellipsis_mask=(1, 0) + ) + + def test_auto_infer_strided_slice_2d_over_3d_4(self): + """ + inp_shape = (1, 100, 200), out = inp[..., None] => out_shape = (1, 100, 200, 1) + """ + self.run_test( + inp=(1, 100, 200), is_shape=True, ref_res=(1, 100, 200, 1), + begin=(0, 0), end=(0, 0), strides=(1, 1), begin_mask=(0, 0), end_mask=(0, 0), + shrink_axis_mask=(0, 0), new_axis_mask=(0, 1), ellipsis_mask=(1, 0) + ) + + def test_auto_infer_strided_slice_2d_over_3d_5(self): + """ + inp_shape = (1, 100, 200), out = inp[..., 0] => out_shape = (1, 100) + """ + self.run_test( + inp=(1, 100, 200), is_shape=True, ref_res=(1, 100), + begin=(0, 0), end=(0, 0), strides=(1, 1), begin_mask=(0, 0), end_mask=(0, 0), + shrink_axis_mask=(0, 1), new_axis_mask=(0, 0), ellipsis_mask=(1, 0) + ) + + def test_auto_infer_strided_slice_2d_over_3d_6(self): + """ + inp_shape = (1, 100, 200), out = inp[None, :] => out_shape = (1, 1, 100, 200) + """ + self.run_test( + inp=(1, 100, 200), is_shape=True, ref_res=(1, 1, 100, 200), + begin=(0, 0), end=(0, 0), strides=(1, 1), begin_mask=(0, 0), end_mask=(0, 0), + shrink_axis_mask=(0, 0), new_axis_mask=(1, 0), ellipsis_mask=(0, 0) + ) + + def test_auto_infer_strided_slice_2d_over_3d_7(self): + """ + inp_shape = (1, 100, 200), out = inp[None, None] => out_shape = (1, 1, 1, 100, 200) + """ + self.run_test( + inp=(1, 100, 200), is_shape=True, ref_res=(1, 1, 1, 100, 200), + begin=(0, 0), end=(0, 0), strides=(1, 1), begin_mask=(0, 0), end_mask=(0, 0), + shrink_axis_mask=(0, 0), new_axis_mask=(1, 1), ellipsis_mask=(0, 0) + ) + + def test_auto_infer_strided_slice_2d_over_3d_8(self): + """ + inp_shape = (1, 100, 200), out = inp[None, 0] => out_shape = (1, 100, 200) + """ + self.run_test( + inp=(1, 100, 200), is_shape=True, ref_res=(1, 100, 200), + begin=(0, 0), end=(0, 0), strides=(1, 1), begin_mask=(0, 0), end_mask=(0, 0), + shrink_axis_mask=(0, 1), new_axis_mask=(1, 0), ellipsis_mask=(0, 0) + ) + + def test_auto_infer_strided_slice_2d_over_3d_9(self): + """ + inp_shape = (1, 100, 200), out = inp[0, :] => out_shape = (100, 200) + """ + self.run_test( + inp=(1, 100, 200), is_shape=True, ref_res=(100, 200), + begin=(0, 0), end=(0, 0), strides=(1, 1), begin_mask=(0, 0), end_mask=(0, 0), + shrink_axis_mask=(1, 0), new_axis_mask=(0, 0), ellipsis_mask=(0, 0) + ) + + def test_auto_infer_strided_slice_2d_over_3d_10(self): + """ + inp_shape = (1, 100, 200), out = inp[0, None] => out_shape = (1, 100, 200) + """ + self.run_test( + inp=(1, 100, 200), is_shape=True, ref_res=(1, 100, 200), + begin=(0, 0), end=(0, 0), strides=(1, 1), begin_mask=(0, 0), end_mask=(0, 0), + shrink_axis_mask=(1, 0), new_axis_mask=(0, 1), ellipsis_mask=(0, 0) + ) + + def test_auto_infer_strided_slice_2d_over_3d_11(self): + """ + inp_shape = (1, 100, 200), out = inp[0, 0] => out_shape = (200,) + """ + self.run_test( + inp=(1, 100, 200), is_shape=True, ref_res=(200,), + begin=(0, 0), end=(0, 0), strides=(1, 1), begin_mask=(0, 0), end_mask=(0, 0), + shrink_axis_mask=(1, 1), new_axis_mask=(0, 0), ellipsis_mask=(0, 0) + ) + + def test_auto_infer_strided_slice_2d_over_4d_0(self): + """ + inp_shape = (1, 100, 200, 3), out = inp[:, :] => out_shape = (1, 100, 200, 3) + """ + self.run_test( + inp=(1, 100, 200, 3), is_shape=True, ref_res=(1, 100, 200, 3), + begin=(0, 0), end=(0, 0), strides=(1, 1), begin_mask=(0, 0), end_mask=(0, 0), + shrink_axis_mask=(0, 0), new_axis_mask=(0, 0), ellipsis_mask=(0, 0) + ) + + def test_auto_infer_strided_slice_2d_over_4d_1(self): + """ + inp_shape = (1, 100, 200, 3), out = inp[:, None] => out_shape = (1, 1, 100, 200, 3) + """ + self.run_test( + inp=(1, 100, 200, 3), is_shape=True, ref_res=(1, 1, 100, 200, 3), + begin=(0, 0), end=(0, 0), strides=(1, 1), begin_mask=(0, 0), end_mask=(0, 0), + shrink_axis_mask=(0, 0), new_axis_mask=(0, 1), ellipsis_mask=(0, 0) + ) + + def test_auto_infer_strided_slice_2d_over_4d_2(self): + """ + inp_shape = (1, 100, 200, 3), out = inp[:, 0] => out_shape = (1, 200, 3) + """ + self.run_test( + inp=(1, 100, 200, 3), is_shape=True, ref_res=(1, 200, 3), + begin=(0, 0), end=(0, 0), strides=(1, 1), begin_mask=(0, 0), end_mask=(0, 0), + shrink_axis_mask=(0, 1), new_axis_mask=(0, 0), ellipsis_mask=(0, 0) + ) + + def test_auto_infer_strided_slice_2d_over_4d_3(self): + """ + inp_shape = (1, 100, 200, 3), out = inp[..., :] => out_shape = (1, 100, 200, 3) + """ + self.run_test( + inp=(1, 100, 200, 3), is_shape=True, ref_res=(1, 100, 200, 3), + begin=(0, 0), end=(0, 0), strides=(1, 1), begin_mask=(0, 0), end_mask=(0, 0), + shrink_axis_mask=(0, 0), new_axis_mask=(0, 0), ellipsis_mask=(1, 0) + ) + + def test_auto_infer_strided_slice_2d_over_4d_4(self): + """ + inp_shape = (1, 100, 200, 3), out = inp[..., None] => out_shape = (1, 100, 200, 3, 1) + """ + self.run_test( + inp=(1, 100, 200, 3), is_shape=True, ref_res=(1, 100, 200, 3, 1), + begin=(0, 0), end=(0, 0), strides=(1, 1), begin_mask=(0, 0), end_mask=(0, 0), + shrink_axis_mask=(0, 0), new_axis_mask=(0, 1), ellipsis_mask=(1, 0) + ) + + def test_auto_infer_strided_slice_2d_over_4d_5(self): + """ + inp_shape = (1, 100, 200, 3), out = inp[..., 0] => out_shape = (1, 100, 200) + """ + self.run_test( + inp=(1, 100, 200, 3), is_shape=True, ref_res=(1, 100, 200), + begin=(0, 0), end=(0, 0), strides=(1, 1), begin_mask=(0, 0), end_mask=(0, 0), + shrink_axis_mask=(0, 1), new_axis_mask=(0, 0), ellipsis_mask=(1, 0) + ) + + def test_auto_infer_strided_slice_2d_over_4d_6(self): + """ + inp_shape = (1, 100, 200, 3), out = inp[None, :] => out_shape = (1, 1, 100, 200, 3) + """ + self.run_test( + inp=(1, 100, 200, 3), is_shape=True, ref_res=(1, 1, 100, 200, 3), + begin=(0, 0), end=(0, 0), strides=(1, 1), begin_mask=(0, 0), end_mask=(0, 0), + shrink_axis_mask=(0, 0), new_axis_mask=(1, 0), ellipsis_mask=(0, 0) + ) + + def test_auto_infer_strided_slice_2d_over_4d_7(self): + """ + inp_shape = (1, 100, 200, 3), out = inp[None, None] => out_shape = (1, 1, 1, 100, 200, 3) + """ + self.run_test( + inp=(1, 100, 200, 3), is_shape=True, ref_res=(1, 1, 1, 100, 200, 3), + begin=(0, 0), end=(0, 0), strides=(1, 1), begin_mask=(0, 0), end_mask=(0, 0), + shrink_axis_mask=(0, 0), new_axis_mask=(1, 1), ellipsis_mask=(0, 0) + ) + + def test_auto_infer_strided_slice_2d_over_4d_8(self): + """ + inp_shape = (1, 100, 200, 3), out = inp[None, 0] => out_shape = (1, 100, 200, 3) + """ + self.run_test( + inp=(1, 100, 200, 3), is_shape=True, ref_res=(1, 100, 200, 3), + begin=(0, 0), end=(0, 0), strides=(1, 1), begin_mask=(0, 0), end_mask=(0, 0), + shrink_axis_mask=(0, 1), new_axis_mask=(1, 0), ellipsis_mask=(0, 0) + ) + + def test_auto_infer_strided_slice_2d_over_4d_9(self): + """ + inp_shape = (1, 100, 200, 3), out = inp[0, :] => out_shape = (100, 200, 3) + """ + self.run_test( + inp=(1, 100, 200, 3), is_shape=True, ref_res=(100, 200, 3), + begin=(0, 0), end=(0, 0), strides=(1, 1), begin_mask=(0, 0), end_mask=(0, 0), + shrink_axis_mask=(1, 0), new_axis_mask=(0, 0), ellipsis_mask=(0, 0) + ) + + def test_auto_infer_strided_slice_2d_over_4d_10(self): + """ + inp_shape = (1, 100, 200, 3), out = inp[0, None] => out_shape = (1, 100, 200, 3) + """ + self.run_test( + inp=(1, 100, 200, 3), is_shape=True, ref_res=(1, 100, 200, 3), + begin=(0, 0), end=(0, 0), strides=(1, 1), begin_mask=(0, 0), end_mask=(0, 0), + shrink_axis_mask=(1, 0), new_axis_mask=(0, 1), ellipsis_mask=(0, 0) + ) + + def test_auto_infer_strided_slice_2d_over_4d_11(self): + """ + inp_shape = (1, 100, 200, 3), out = inp[0, 0] => out_shape = (200, 3) + """ + self.run_test( + inp=(1, 100, 200, 3), is_shape=True, ref_res=(200, 3), + begin=(0, 0), end=(0, 0), strides=(1, 1), begin_mask=(0, 0), end_mask=(0, 0), + shrink_axis_mask=(1, 1), new_axis_mask=(0, 0), ellipsis_mask=(0, 0) + ) + + # automatically generated slices from 3d to 5d d input tensors + # fixed number of ellipsis, newaxis and shrink_axis + def test_auto_infer_strided_slice_3d_over_3d_0(self): + """ + inp_shape = (1, 100, 200), out = inp[None, ..., 0] => out_shape = (1, 1, 100) + """ + self.run_test( + inp=(1, 100, 200), is_shape=True, ref_res=(1, 1, 100), + begin=(0, 0, 0), end=(0, 0, 0), strides=(1, 1, 1), begin_mask=(0, 0, 0), end_mask=(0, 0, 0), + shrink_axis_mask=(0, 0, 1), new_axis_mask=(1, 0, 0), ellipsis_mask=(0, 1, 0) + ) + + def test_auto_infer_strided_slice_3d_over_3d_1(self): + """ + inp_shape = (1, 100, 200), out = inp[..., None, 0] => out_shape = (1, 100, 1) + """ + self.run_test( + inp=(1, 100, 200), is_shape=True, ref_res=(1, 100, 1), + begin=(0, 0, 0), end=(0, 0, 0), strides=(1, 1, 1), begin_mask=(0, 0, 0), end_mask=(0, 0, 0), + shrink_axis_mask=(0, 0, 1), new_axis_mask=(0, 1, 0), ellipsis_mask=(1, 0, 0) + ) + + def test_auto_infer_strided_slice_3d_over_3d_2(self): + """ + inp_shape = (1, 100, 200), out = inp[0, None, ...] => out_shape = (1, 100, 200) + """ + self.run_test( + inp=(1, 100, 200), is_shape=True, ref_res=(1, 100, 200), + begin=(0, 0, 0), end=(0, 0, 0), strides=(1, 1, 1), begin_mask=(0, 0, 0), end_mask=(0, 0, 0), + shrink_axis_mask=(1, 0, 0), new_axis_mask=(0, 1, 0), ellipsis_mask=(0, 0, 1) + ) + + def test_auto_infer_strided_slice_3d_over_3d_3(self): + """ + inp_shape = (1, 100, 200), out = inp[0, ..., None] => out_shape = (100, 200, 1) + """ + self.run_test( + inp=(1, 100, 200), is_shape=True, ref_res=(100, 200, 1), + begin=(0, 0, 0), end=(0, 0, 0), strides=(1, 1, 1), begin_mask=(0, 0, 0), end_mask=(0, 0, 0), + shrink_axis_mask=(1, 0, 0), new_axis_mask=(0, 0, 1), ellipsis_mask=(0, 1, 0) + ) + + def test_auto_infer_strided_slice_3d_over_3d_4(self): + """ + inp_shape = (1, 100, 200), out = inp[None, 0, ...] => out_shape = (1, 100, 200) + """ + self.run_test( + inp=(1, 100, 200), is_shape=True, ref_res=(1, 100, 200), + begin=(0, 0, 0), end=(0, 0, 0), strides=(1, 1, 1), begin_mask=(0, 0, 0), end_mask=(0, 0, 0), + shrink_axis_mask=(0, 1, 0), new_axis_mask=(1, 0, 0), ellipsis_mask=(0, 0, 1) + ) + + def test_auto_infer_strided_slice_3d_over_3d_5(self): + """ + inp_shape = (1, 100, 200), out = inp[..., 0, None] => out_shape = (1, 100, 1) + """ + self.run_test( + inp=(1, 100, 200), is_shape=True, ref_res=(1, 100, 1), + begin=(0, 0, 0), end=(0, 0, 0), strides=(1, 1, 1), begin_mask=(0, 0, 0), end_mask=(0, 0, 0), + shrink_axis_mask=(0, 1, 0), new_axis_mask=(0, 0, 1), ellipsis_mask=(1, 0, 0) + ) + + def test_auto_infer_strided_slice_3d_over_4d_0(self): + """ + inp_shape = (1, 100, 200, 3), out = inp[None, ..., 0, :] => out_shape = (1, 1, 100, 3) + """ + self.run_test( + inp=(1, 100, 200, 3), is_shape=True, ref_res=(1, 1, 100, 3), + begin=(0, 0, 0, 0), end=(0, 0, 0, 0), strides=(1, 1, 1, 1), begin_mask=(0, 0, 0, 0), end_mask=(0, 0, 0, 0), + shrink_axis_mask=(0, 0, 1, 0), new_axis_mask=(1, 0, 0, 0), ellipsis_mask=(0, 1, 0, 0) + ) + + def test_auto_infer_strided_slice_3d_over_4d_1(self): + """ + inp_shape = (1, 100, 200, 3), out = inp[..., None, 0, :] => out_shape = (1, 100, 1, 3) + """ + self.run_test( + inp=(1, 100, 200, 3), is_shape=True, ref_res=(1, 100, 1, 3), + begin=(0, 0, 0, 0), end=(0, 0, 0, 0), strides=(1, 1, 1, 1), begin_mask=(0, 0, 0, 0), end_mask=(0, 0, 0, 0), + shrink_axis_mask=(0, 0, 1, 0), new_axis_mask=(0, 1, 0, 0), ellipsis_mask=(1, 0, 0, 0) + ) + + def test_auto_infer_strided_slice_3d_over_4d_2(self): + """ + inp_shape = (1, 100, 200, 3), out = inp[0, None, ..., :] => out_shape = (1, 100, 200, 3) + """ + self.run_test( + inp=(1, 100, 200, 3), is_shape=True, ref_res=(1, 100, 200, 3), + begin=(0, 0, 0, 0), end=(0, 0, 0, 0), strides=(1, 1, 1, 1), begin_mask=(0, 0, 0, 0), end_mask=(0, 0, 0, 0), + shrink_axis_mask=(1, 0, 0, 0), new_axis_mask=(0, 1, 0, 0), ellipsis_mask=(0, 0, 1, 0) + ) + + def test_auto_infer_strided_slice_3d_over_4d_3(self): + """ + inp_shape = (1, 100, 200, 3), out = inp[0, ..., None, :] => out_shape = (100, 200, 1, 3) + """ + self.run_test( + inp=(1, 100, 200, 3), is_shape=True, ref_res=(100, 200, 1, 3), + begin=(0, 0, 0, 0), end=(0, 0, 0, 0), strides=(1, 1, 1, 1), begin_mask=(0, 0, 0, 0), end_mask=(0, 0, 0, 0), + shrink_axis_mask=(1, 0, 0, 0), new_axis_mask=(0, 0, 1, 0), ellipsis_mask=(0, 1, 0, 0) + ) + + def test_auto_infer_strided_slice_3d_over_4d_4(self): + """ + inp_shape = (1, 100, 200, 3), out = inp[None, 0, ..., :] => out_shape = (1, 100, 200, 3) + """ + self.run_test( + inp=(1, 100, 200, 3), is_shape=True, ref_res=(1, 100, 200, 3), + begin=(0, 0, 0, 0), end=(0, 0, 0, 0), strides=(1, 1, 1, 1), begin_mask=(0, 0, 0, 0), end_mask=(0, 0, 0, 0), + shrink_axis_mask=(0, 1, 0, 0), new_axis_mask=(1, 0, 0, 0), ellipsis_mask=(0, 0, 1, 0) + ) + + def test_auto_infer_strided_slice_3d_over_4d_5(self): + """ + inp_shape = (1, 100, 200, 3), out = inp[..., 0, None, :] => out_shape = (1, 100, 1, 3) + """ + self.run_test( + inp=(1, 100, 200, 3), is_shape=True, ref_res=(1, 100, 1, 3), + begin=(0, 0, 0, 0), end=(0, 0, 0, 0), strides=(1, 1, 1, 1), begin_mask=(0, 0, 0, 0), end_mask=(0, 0, 0, 0), + shrink_axis_mask=(0, 1, 0, 0), new_axis_mask=(0, 0, 1, 0), ellipsis_mask=(1, 0, 0, 0) + ) + + def test_auto_infer_strided_slice_3d_over_5d_0(self): + """ + inp_shape = (1, 100, 200, 10, 3), out = inp[None, ..., 0, :, :] => out_shape = (1, 1, 100, 10, 3) + """ + self.run_test( + inp=(1, 100, 200, 10, 3), is_shape=True, ref_res=(1, 1, 100, 10, 3), + begin=(0, 0, 0, 0, 0), end=(0, 0, 0, 0, 0), strides=(1, 1, 1, 1, 1), begin_mask=(0, 0, 0, 0, 0), end_mask=(0, 0, 0, 0, 0), + shrink_axis_mask=(0, 0, 1, 0, 0), new_axis_mask=(1, 0, 0, 0, 0), ellipsis_mask=(0, 1, 0, 0, 0) + ) + + def test_auto_infer_strided_slice_3d_over_5d_1(self): + """ + inp_shape = (1, 100, 200, 10, 3), out = inp[..., None, 0, :, :] => out_shape = (1, 100, 1, 10, 3) + """ + self.run_test( + inp=(1, 100, 200, 10, 3), is_shape=True, ref_res=(1, 100, 1, 10, 3), + begin=(0, 0, 0, 0, 0), end=(0, 0, 0, 0, 0), strides=(1, 1, 1, 1, 1), begin_mask=(0, 0, 0, 0, 0), end_mask=(0, 0, 0, 0, 0), + shrink_axis_mask=(0, 0, 1, 0, 0), new_axis_mask=(0, 1, 0, 0, 0), ellipsis_mask=(1, 0, 0, 0, 0) + ) + + def test_auto_infer_strided_slice_3d_over_5d_2(self): + """ + inp_shape = (1, 100, 200, 10, 3), out = inp[0, None, ..., :, :] => out_shape = (1, 100, 200, 10, 3) + """ + self.run_test( + inp=(1, 100, 200, 10, 3), is_shape=True, ref_res=(1, 100, 200, 10, 3), + begin=(0, 0, 0, 0, 0), end=(0, 0, 0, 0, 0), strides=(1, 1, 1, 1, 1), begin_mask=(0, 0, 0, 0, 0), end_mask=(0, 0, 0, 0, 0), + shrink_axis_mask=(1, 0, 0, 0, 0), new_axis_mask=(0, 1, 0, 0, 0), ellipsis_mask=(0, 0, 1, 0, 0) + ) + + def test_auto_infer_strided_slice_3d_over_5d_3(self): + """ + inp_shape = (1, 100, 200, 10, 3), out = inp[0, ..., None, :, :] => out_shape = (100, 200, 1, 10, 3) + """ + self.run_test( + inp=(1, 100, 200, 10, 3), is_shape=True, ref_res=(100, 200, 1, 10, 3), + begin=(0, 0, 0, 0, 0), end=(0, 0, 0, 0, 0), strides=(1, 1, 1, 1, 1), begin_mask=(0, 0, 0, 0, 0), end_mask=(0, 0, 0, 0, 0), + shrink_axis_mask=(1, 0, 0, 0, 0), new_axis_mask=(0, 0, 1, 0, 0), ellipsis_mask=(0, 1, 0, 0, 0) + ) + + def test_auto_infer_strided_slice_3d_over_5d_4(self): + """ + inp_shape = (1, 100, 200, 10, 3), out = inp[None, 0, ..., :, :] => out_shape = (1, 100, 200, 10, 3) + """ + self.run_test( + inp=(1, 100, 200, 10, 3), is_shape=True, ref_res=(1, 100, 200, 10, 3), + begin=(0, 0, 0, 0, 0), end=(0, 0, 0, 0, 0), strides=(1, 1, 1, 1, 1), begin_mask=(0, 0, 0, 0, 0), end_mask=(0, 0, 0, 0, 0), + shrink_axis_mask=(0, 1, 0, 0, 0), new_axis_mask=(1, 0, 0, 0, 0), ellipsis_mask=(0, 0, 1, 0, 0) + ) + + def test_auto_infer_strided_slice_3d_over_5d_5(self): + """ + inp_shape = (1, 100, 200, 10, 3), out = inp[..., 0, None, :, :] => out_shape = (1, 100, 1, 10, 3) + """ + self.run_test( + inp=(1, 100, 200, 10, 3), is_shape=True, ref_res=(1, 100, 1, 10, 3), + begin=(0, 0, 0, 0, 0), end=(0, 0, 0, 0, 0), strides=(1, 1, 1, 1, 1), begin_mask=(0, 0, 0, 0, 0), end_mask=(0, 0, 0, 0, 0), + shrink_axis_mask=(0, 1, 0, 0, 0), new_axis_mask=(0, 0, 1, 0, 0), ellipsis_mask=(1, 0, 0, 0, 0) + ) + + def test_auto_infer_strided_slice_4d_over_4d_0(self): + """ + inp_shape = (1, 100, 200, 3), out = inp[None, ..., 0, :] => out_shape = (1, 1, 100, 3) + """ + self.run_test( + inp=(1, 100, 200, 3), is_shape=True, ref_res=(1, 1, 100, 3), + begin=(0, 0, 0, 0), end=(0, 0, 0, 0), strides=(1, 1, 1, 1), begin_mask=(0, 0, 0, 0), end_mask=(0, 0, 0, 0), + shrink_axis_mask=(0, 0, 1, 0), new_axis_mask=(1, 0, 0, 0), ellipsis_mask=(0, 1, 0, 0) + ) + + def test_auto_infer_strided_slice_4d_over_4d_1(self): + """ + inp_shape = (1, 100, 200, 3), out = inp[..., None, 0, :] => out_shape = (1, 100, 1, 3) + """ + self.run_test( + inp=(1, 100, 200, 3), is_shape=True, ref_res=(1, 100, 1, 3), + begin=(0, 0, 0, 0), end=(0, 0, 0, 0), strides=(1, 1, 1, 1), begin_mask=(0, 0, 0, 0), end_mask=(0, 0, 0, 0), + shrink_axis_mask=(0, 0, 1, 0), new_axis_mask=(0, 1, 0, 0), ellipsis_mask=(1, 0, 0, 0) + ) + + def test_auto_infer_strided_slice_4d_over_4d_2(self): + """ + inp_shape = (1, 100, 200, 3), out = inp[0, None, ..., :] => out_shape = (1, 100, 200, 3) + """ + self.run_test( + inp=(1, 100, 200, 3), is_shape=True, ref_res=(1, 100, 200, 3), + begin=(0, 0, 0, 0), end=(0, 0, 0, 0), strides=(1, 1, 1, 1), begin_mask=(0, 0, 0, 0), end_mask=(0, 0, 0, 0), + shrink_axis_mask=(1, 0, 0, 0), new_axis_mask=(0, 1, 0, 0), ellipsis_mask=(0, 0, 1, 0) + ) + + def test_auto_infer_strided_slice_4d_over_4d_3(self): + """ + inp_shape = (1, 100, 200, 3), out = inp[0, ..., None, :] => out_shape = (100, 200, 1, 3) + """ + self.run_test( + inp=(1, 100, 200, 3), is_shape=True, ref_res=(100, 200, 1, 3), + begin=(0, 0, 0, 0), end=(0, 0, 0, 0), strides=(1, 1, 1, 1), begin_mask=(0, 0, 0, 0), end_mask=(0, 0, 0, 0), + shrink_axis_mask=(1, 0, 0, 0), new_axis_mask=(0, 0, 1, 0), ellipsis_mask=(0, 1, 0, 0) + ) + + def test_auto_infer_strided_slice_4d_over_4d_4(self): + """ + inp_shape = (1, 100, 200, 3), out = inp[None, 0, ..., :] => out_shape = (1, 100, 200, 3) + """ + self.run_test( + inp=(1, 100, 200, 3), is_shape=True, ref_res=(1, 100, 200, 3), + begin=(0, 0, 0, 0), end=(0, 0, 0, 0), strides=(1, 1, 1, 1), begin_mask=(0, 0, 0, 0), end_mask=(0, 0, 0, 0), + shrink_axis_mask=(0, 1, 0, 0), new_axis_mask=(1, 0, 0, 0), ellipsis_mask=(0, 0, 1, 0) + ) + + def test_auto_infer_strided_slice_4d_over_4d_5(self): + """ + inp_shape = (1, 100, 200, 3), out = inp[..., 0, None, :] => out_shape = (1, 100, 1, 3) + """ + self.run_test( + inp=(1, 100, 200, 3), is_shape=True, ref_res=(1, 100, 1, 3), + begin=(0, 0, 0, 0), end=(0, 0, 0, 0), strides=(1, 1, 1, 1), begin_mask=(0, 0, 0, 0), end_mask=(0, 0, 0, 0), + shrink_axis_mask=(0, 1, 0, 0), new_axis_mask=(0, 0, 1, 0), ellipsis_mask=(1, 0, 0, 0) + ) + + def test_auto_infer_strided_slice_4d_over_4d_6(self): + """ + inp_shape = (1, 100, 200, 3), out = inp[None, ..., :, 0] => out_shape = (1, 1, 100, 200) + """ + self.run_test( + inp=(1, 100, 200, 3), is_shape=True, ref_res=(1, 1, 100, 200), + begin=(0, 0, 0, 0), end=(0, 0, 0, 0), strides=(1, 1, 1, 1), begin_mask=(0, 0, 0, 0), end_mask=(0, 0, 0, 0), + shrink_axis_mask=(0, 0, 0, 1), new_axis_mask=(1, 0, 0, 0), ellipsis_mask=(0, 1, 0, 0) + ) + + def test_auto_infer_strided_slice_4d_over_4d_7(self): + """ + inp_shape = (1, 100, 200, 3), out = inp[..., None, :, 0] => out_shape = (1, 100, 1, 200) + """ + self.run_test( + inp=(1, 100, 200, 3), is_shape=True, ref_res=(1, 100, 1, 200), + begin=(0, 0, 0, 0), end=(0, 0, 0, 0), strides=(1, 1, 1, 1), begin_mask=(0, 0, 0, 0), end_mask=(0, 0, 0, 0), + shrink_axis_mask=(0, 0, 0, 1), new_axis_mask=(0, 1, 0, 0), ellipsis_mask=(1, 0, 0, 0) + ) + + def test_auto_infer_strided_slice_4d_over_4d_8(self): + """ + inp_shape = (1, 100, 200, 3), out = inp[0, None, :, ...] => out_shape = (1, 100, 200, 3) + """ + self.run_test( + inp=(1, 100, 200, 3), is_shape=True, ref_res=(1, 100, 200, 3), + begin=(0, 0, 0, 0), end=(0, 0, 0, 0), strides=(1, 1, 1, 1), begin_mask=(0, 0, 0, 0), end_mask=(0, 0, 0, 0), + shrink_axis_mask=(1, 0, 0, 0), new_axis_mask=(0, 1, 0, 0), ellipsis_mask=(0, 0, 0, 1) + ) + + def test_auto_infer_strided_slice_4d_over_4d_9(self): + """ + inp_shape = (1, 100, 200, 3), out = inp[0, ..., :, None] => out_shape = (100, 200, 3, 1) + """ + self.run_test( + inp=(1, 100, 200, 3), is_shape=True, ref_res=(100, 200, 3, 1), + begin=(0, 0, 0, 0), end=(0, 0, 0, 0), strides=(1, 1, 1, 1), begin_mask=(0, 0, 0, 0), end_mask=(0, 0, 0, 0), + shrink_axis_mask=(1, 0, 0, 0), new_axis_mask=(0, 0, 0, 1), ellipsis_mask=(0, 1, 0, 0) + ) + + def test_auto_infer_strided_slice_4d_over_4d_10(self): + """ + inp_shape = (1, 100, 200, 3), out = inp[None, 0, :, ...] => out_shape = (1, 100, 200, 3) + """ + self.run_test( + inp=(1, 100, 200, 3), is_shape=True, ref_res=(1, 100, 200, 3), + begin=(0, 0, 0, 0), end=(0, 0, 0, 0), strides=(1, 1, 1, 1), begin_mask=(0, 0, 0, 0), end_mask=(0, 0, 0, 0), + shrink_axis_mask=(0, 1, 0, 0), new_axis_mask=(1, 0, 0, 0), ellipsis_mask=(0, 0, 0, 1) + ) + + def test_auto_infer_strided_slice_4d_over_4d_11(self): + """ + inp_shape = (1, 100, 200, 3), out = inp[..., 0, :, None] => out_shape = (1, 100, 3, 1) + """ + self.run_test( + inp=(1, 100, 200, 3), is_shape=True, ref_res=(1, 100, 3, 1), + begin=(0, 0, 0, 0), end=(0, 0, 0, 0), strides=(1, 1, 1, 1), begin_mask=(0, 0, 0, 0), end_mask=(0, 0, 0, 0), + shrink_axis_mask=(0, 1, 0, 0), new_axis_mask=(0, 0, 0, 1), ellipsis_mask=(1, 0, 0, 0) + ) + + def test_auto_infer_strided_slice_4d_over_4d_12(self): + """ + inp_shape = (1, 100, 200, 3), out = inp[None, :, ..., 0] => out_shape = (1, 1, 100, 200) + """ + self.run_test( + inp=(1, 100, 200, 3), is_shape=True, ref_res=(1, 1, 100, 200), + begin=(0, 0, 0, 0), end=(0, 0, 0, 0), strides=(1, 1, 1, 1), begin_mask=(0, 0, 0, 0), end_mask=(0, 0, 0, 0), + shrink_axis_mask=(0, 0, 0, 1), new_axis_mask=(1, 0, 0, 0), ellipsis_mask=(0, 0, 1, 0) + ) + + def test_auto_infer_strided_slice_4d_over_4d_13(self): + """ + inp_shape = (1, 100, 200, 3), out = inp[..., :, None, 0] => out_shape = (1, 100, 200, 1) + """ + self.run_test( + inp=(1, 100, 200, 3), is_shape=True, ref_res=(1, 100, 200, 1), + begin=(0, 0, 0, 0), end=(0, 0, 0, 0), strides=(1, 1, 1, 1), begin_mask=(0, 0, 0, 0), end_mask=(0, 0, 0, 0), + shrink_axis_mask=(0, 0, 0, 1), new_axis_mask=(0, 0, 1, 0), ellipsis_mask=(1, 0, 0, 0) + ) + + def test_auto_infer_strided_slice_4d_over_4d_14(self): + """ + inp_shape = (1, 100, 200, 3), out = inp[0, :, None, ...] => out_shape = (100, 1, 200, 3) + """ + self.run_test( + inp=(1, 100, 200, 3), is_shape=True, ref_res=(100, 1, 200, 3), + begin=(0, 0, 0, 0), end=(0, 0, 0, 0), strides=(1, 1, 1, 1), begin_mask=(0, 0, 0, 0), end_mask=(0, 0, 0, 0), + shrink_axis_mask=(1, 0, 0, 0), new_axis_mask=(0, 0, 1, 0), ellipsis_mask=(0, 0, 0, 1) + ) + + def test_auto_infer_strided_slice_4d_over_4d_15(self): + """ + inp_shape = (1, 100, 200, 3), out = inp[0, :, ..., None] => out_shape = (100, 200, 3, 1) + """ + self.run_test( + inp=(1, 100, 200, 3), is_shape=True, ref_res=(100, 200, 3, 1), + begin=(0, 0, 0, 0), end=(0, 0, 0, 0), strides=(1, 1, 1, 1), begin_mask=(0, 0, 0, 0), end_mask=(0, 0, 0, 0), + shrink_axis_mask=(1, 0, 0, 0), new_axis_mask=(0, 0, 0, 1), ellipsis_mask=(0, 0, 1, 0) + ) + + def test_auto_infer_strided_slice_4d_over_4d_16(self): + """ + inp_shape = (1, 100, 200, 3), out = inp[None, :, 0, ...] => out_shape = (1, 1, 200, 3) + """ + self.run_test( + inp=(1, 100, 200, 3), is_shape=True, ref_res=(1, 1, 200, 3), + begin=(0, 0, 0, 0), end=(0, 0, 0, 0), strides=(1, 1, 1, 1), begin_mask=(0, 0, 0, 0), end_mask=(0, 0, 0, 0), + shrink_axis_mask=(0, 0, 1, 0), new_axis_mask=(1, 0, 0, 0), ellipsis_mask=(0, 0, 0, 1) + ) + + def test_auto_infer_strided_slice_4d_over_4d_17(self): + """ + inp_shape = (1, 100, 200, 3), out = inp[..., :, 0, None] => out_shape = (1, 100, 200, 1) + """ + self.run_test( + inp=(1, 100, 200, 3), is_shape=True, ref_res=(1, 100, 200, 1), + begin=(0, 0, 0, 0), end=(0, 0, 0, 0), strides=(1, 1, 1, 1), begin_mask=(0, 0, 0, 0), end_mask=(0, 0, 0, 0), + shrink_axis_mask=(0, 0, 1, 0), new_axis_mask=(0, 0, 0, 1), ellipsis_mask=(1, 0, 0, 0) + ) + + def test_auto_infer_strided_slice_4d_over_4d_18(self): + """ + inp_shape = (1, 100, 200, 3), out = inp[:, None, ..., 0] => out_shape = (1, 1, 100, 200) + """ + self.run_test( + inp=(1, 100, 200, 3), is_shape=True, ref_res=(1, 1, 100, 200), + begin=(0, 0, 0, 0), end=(0, 0, 0, 0), strides=(1, 1, 1, 1), begin_mask=(0, 0, 0, 0), end_mask=(0, 0, 0, 0), + shrink_axis_mask=(0, 0, 0, 1), new_axis_mask=(0, 1, 0, 0), ellipsis_mask=(0, 0, 1, 0) + ) + + def test_auto_infer_strided_slice_4d_over_4d_19(self): + """ + inp_shape = (1, 100, 200, 3), out = inp[:, ..., None, 0] => out_shape = (1, 100, 200, 1) + """ + self.run_test( + inp=(1, 100, 200, 3), is_shape=True, ref_res=(1, 100, 200, 1), + begin=(0, 0, 0, 0), end=(0, 0, 0, 0), strides=(1, 1, 1, 1), begin_mask=(0, 0, 0, 0), end_mask=(0, 0, 0, 0), + shrink_axis_mask=(0, 0, 0, 1), new_axis_mask=(0, 0, 1, 0), ellipsis_mask=(0, 1, 0, 0) + ) + + def test_auto_infer_strided_slice_4d_over_4d_20(self): + """ + inp_shape = (1, 100, 200, 3), out = inp[:, 0, None, ...] => out_shape = (1, 1, 200, 3) + """ + self.run_test( + inp=(1, 100, 200, 3), is_shape=True, ref_res=(1, 1, 200, 3), + begin=(0, 0, 0, 0), end=(0, 0, 0, 0), strides=(1, 1, 1, 1), begin_mask=(0, 0, 0, 0), end_mask=(0, 0, 0, 0), + shrink_axis_mask=(0, 1, 0, 0), new_axis_mask=(0, 0, 1, 0), ellipsis_mask=(0, 0, 0, 1) + ) + + def test_auto_infer_strided_slice_4d_over_4d_21(self): + """ + inp_shape = (1, 100, 200, 3), out = inp[:, 0, ..., None] => out_shape = (1, 200, 3, 1) + """ + self.run_test( + inp=(1, 100, 200, 3), is_shape=True, ref_res=(1, 200, 3, 1), + begin=(0, 0, 0, 0), end=(0, 0, 0, 0), strides=(1, 1, 1, 1), begin_mask=(0, 0, 0, 0), end_mask=(0, 0, 0, 0), + shrink_axis_mask=(0, 1, 0, 0), new_axis_mask=(0, 0, 0, 1), ellipsis_mask=(0, 0, 1, 0) + ) + + def test_auto_infer_strided_slice_4d_over_4d_22(self): + """ + inp_shape = (1, 100, 200, 3), out = inp[:, None, 0, ...] => out_shape = (1, 1, 200, 3) + """ + self.run_test( + inp=(1, 100, 200, 3), is_shape=True, ref_res=(1, 1, 200, 3), + begin=(0, 0, 0, 0), end=(0, 0, 0, 0), strides=(1, 1, 1, 1), begin_mask=(0, 0, 0, 0), end_mask=(0, 0, 0, 0), + shrink_axis_mask=(0, 0, 1, 0), new_axis_mask=(0, 1, 0, 0), ellipsis_mask=(0, 0, 0, 1) + ) + + def test_auto_infer_strided_slice_4d_over_4d_23(self): + """ + inp_shape = (1, 100, 200, 3), out = inp[:, ..., 0, None] => out_shape = (1, 100, 200, 1) + """ + self.run_test( + inp=(1, 100, 200, 3), is_shape=True, ref_res=(1, 100, 200, 1), + begin=(0, 0, 0, 0), end=(0, 0, 0, 0), strides=(1, 1, 1, 1), begin_mask=(0, 0, 0, 0), end_mask=(0, 0, 0, 0), + shrink_axis_mask=(0, 0, 1, 0), new_axis_mask=(0, 0, 0, 1), ellipsis_mask=(0, 1, 0, 0) + ) + + def test_auto_infer_strided_slice_4d_over_5d_0(self): + """ + inp_shape = (1, 100, 200, 10, 3), out = inp[None, ..., 0, :, :] => out_shape = (1, 1, 100, 10, 3) + """ + self.run_test( + inp=(1, 100, 200, 10, 3), is_shape=True, ref_res=(1, 1, 100, 10, 3), + begin=(0, 0, 0, 0, 0), end=(0, 0, 0, 0, 0), strides=(1, 1, 1, 1, 1), begin_mask=(0, 0, 0, 0, 0), end_mask=(0, 0, 0, 0, 0), + shrink_axis_mask=(0, 0, 1, 0, 0), new_axis_mask=(1, 0, 0, 0, 0), ellipsis_mask=(0, 1, 0, 0, 0) + ) + + def test_auto_infer_strided_slice_4d_over_5d_1(self): + """ + inp_shape = (1, 100, 200, 10, 3), out = inp[..., None, 0, :, :] => out_shape = (1, 100, 1, 10, 3) + """ + self.run_test( + inp=(1, 100, 200, 10, 3), is_shape=True, ref_res=(1, 100, 1, 10, 3), + begin=(0, 0, 0, 0, 0), end=(0, 0, 0, 0, 0), strides=(1, 1, 1, 1, 1), begin_mask=(0, 0, 0, 0, 0), end_mask=(0, 0, 0, 0, 0), + shrink_axis_mask=(0, 0, 1, 0, 0), new_axis_mask=(0, 1, 0, 0, 0), ellipsis_mask=(1, 0, 0, 0, 0) + ) + + def test_auto_infer_strided_slice_4d_over_5d_2(self): + """ + inp_shape = (1, 100, 200, 10, 3), out = inp[0, None, ..., :, :] => out_shape = (1, 100, 200, 10, 3) + """ + self.run_test( + inp=(1, 100, 200, 10, 3), is_shape=True, ref_res=(1, 100, 200, 10, 3), + begin=(0, 0, 0, 0, 0), end=(0, 0, 0, 0, 0), strides=(1, 1, 1, 1, 1), begin_mask=(0, 0, 0, 0, 0), end_mask=(0, 0, 0, 0, 0), + shrink_axis_mask=(1, 0, 0, 0, 0), new_axis_mask=(0, 1, 0, 0, 0), ellipsis_mask=(0, 0, 1, 0, 0) + ) + + def test_auto_infer_strided_slice_4d_over_5d_3(self): + """ + inp_shape = (1, 100, 200, 10, 3), out = inp[0, ..., None, :, :] => out_shape = (100, 200, 1, 10, 3) + """ + self.run_test( + inp=(1, 100, 200, 10, 3), is_shape=True, ref_res=(100, 200, 1, 10, 3), + begin=(0, 0, 0, 0, 0), end=(0, 0, 0, 0, 0), strides=(1, 1, 1, 1, 1), begin_mask=(0, 0, 0, 0, 0), end_mask=(0, 0, 0, 0, 0), + shrink_axis_mask=(1, 0, 0, 0, 0), new_axis_mask=(0, 0, 1, 0, 0), ellipsis_mask=(0, 1, 0, 0, 0) + ) + + def test_auto_infer_strided_slice_4d_over_5d_4(self): + """ + inp_shape = (1, 100, 200, 10, 3), out = inp[None, 0, ..., :, :] => out_shape = (1, 100, 200, 10, 3) + """ + self.run_test( + inp=(1, 100, 200, 10, 3), is_shape=True, ref_res=(1, 100, 200, 10, 3), + begin=(0, 0, 0, 0, 0), end=(0, 0, 0, 0, 0), strides=(1, 1, 1, 1, 1), begin_mask=(0, 0, 0, 0, 0), end_mask=(0, 0, 0, 0, 0), + shrink_axis_mask=(0, 1, 0, 0, 0), new_axis_mask=(1, 0, 0, 0, 0), ellipsis_mask=(0, 0, 1, 0, 0) + ) + + def test_auto_infer_strided_slice_4d_over_5d_5(self): + """ + inp_shape = (1, 100, 200, 10, 3), out = inp[..., 0, None, :, :] => out_shape = (1, 100, 1, 10, 3) + """ + self.run_test( + inp=(1, 100, 200, 10, 3), is_shape=True, ref_res=(1, 100, 1, 10, 3), + begin=(0, 0, 0, 0, 0), end=(0, 0, 0, 0, 0), strides=(1, 1, 1, 1, 1), begin_mask=(0, 0, 0, 0, 0), end_mask=(0, 0, 0, 0, 0), + shrink_axis_mask=(0, 1, 0, 0, 0), new_axis_mask=(0, 0, 1, 0, 0), ellipsis_mask=(1, 0, 0, 0, 0) + ) + + def test_auto_infer_strided_slice_4d_over_5d_6(self): + """ + inp_shape = (1, 100, 200, 10, 3), out = inp[None, ..., :, 0, :] => out_shape = (1, 1, 100, 200, 3) + """ + self.run_test( + inp=(1, 100, 200, 10, 3), is_shape=True, ref_res=(1, 1, 100, 200, 3), + begin=(0, 0, 0, 0, 0), end=(0, 0, 0, 0, 0), strides=(1, 1, 1, 1, 1), begin_mask=(0, 0, 0, 0, 0), end_mask=(0, 0, 0, 0, 0), + shrink_axis_mask=(0, 0, 0, 1, 0), new_axis_mask=(1, 0, 0, 0, 0), ellipsis_mask=(0, 1, 0, 0, 0) + ) + + def test_auto_infer_strided_slice_4d_over_5d_7(self): + """ + inp_shape = (1, 100, 200, 10, 3), out = inp[..., None, :, 0, :] => out_shape = (1, 100, 1, 200, 3) + """ + self.run_test( + inp=(1, 100, 200, 10, 3), is_shape=True, ref_res=(1, 100, 1, 200, 3), + begin=(0, 0, 0, 0, 0), end=(0, 0, 0, 0, 0), strides=(1, 1, 1, 1, 1), begin_mask=(0, 0, 0, 0, 0), end_mask=(0, 0, 0, 0, 0), + shrink_axis_mask=(0, 0, 0, 1, 0), new_axis_mask=(0, 1, 0, 0, 0), ellipsis_mask=(1, 0, 0, 0, 0) + ) + + def test_auto_infer_strided_slice_4d_over_5d_8(self): + """ + inp_shape = (1, 100, 200, 10, 3), out = inp[0, None, :, ..., :] => out_shape = (1, 100, 200, 10, 3) + """ + self.run_test( + inp=(1, 100, 200, 10, 3), is_shape=True, ref_res=(1, 100, 200, 10, 3), + begin=(0, 0, 0, 0, 0), end=(0, 0, 0, 0, 0), strides=(1, 1, 1, 1, 1), begin_mask=(0, 0, 0, 0, 0), end_mask=(0, 0, 0, 0, 0), + shrink_axis_mask=(1, 0, 0, 0, 0), new_axis_mask=(0, 1, 0, 0, 0), ellipsis_mask=(0, 0, 0, 1, 0) + ) + + def test_auto_infer_strided_slice_4d_over_5d_9(self): + """ + inp_shape = (1, 100, 200, 10, 3), out = inp[0, ..., :, None, :] => out_shape = (100, 200, 10, 1, 3) + """ + self.run_test( + inp=(1, 100, 200, 10, 3), is_shape=True, ref_res=(100, 200, 10, 1, 3), + begin=(0, 0, 0, 0, 0), end=(0, 0, 0, 0, 0), strides=(1, 1, 1, 1, 1), begin_mask=(0, 0, 0, 0, 0), end_mask=(0, 0, 0, 0, 0), + shrink_axis_mask=(1, 0, 0, 0, 0), new_axis_mask=(0, 0, 0, 1, 0), ellipsis_mask=(0, 1, 0, 0, 0) + ) + + def test_auto_infer_strided_slice_4d_over_5d_10(self): + """ + inp_shape = (1, 100, 200, 10, 3), out = inp[None, 0, :, ..., :] => out_shape = (1, 100, 200, 10, 3) + """ + self.run_test( + inp=(1, 100, 200, 10, 3), is_shape=True, ref_res=(1, 100, 200, 10, 3), + begin=(0, 0, 0, 0, 0), end=(0, 0, 0, 0, 0), strides=(1, 1, 1, 1, 1), begin_mask=(0, 0, 0, 0, 0), end_mask=(0, 0, 0, 0, 0), + shrink_axis_mask=(0, 1, 0, 0, 0), new_axis_mask=(1, 0, 0, 0, 0), ellipsis_mask=(0, 0, 0, 1, 0) + ) + + def test_auto_infer_strided_slice_4d_over_5d_11(self): + """ + inp_shape = (1, 100, 200, 10, 3), out = inp[..., 0, :, None, :] => out_shape = (1, 100, 10, 1, 3) + """ + self.run_test( + inp=(1, 100, 200, 10, 3), is_shape=True, ref_res=(1, 100, 10, 1, 3), + begin=(0, 0, 0, 0, 0), end=(0, 0, 0, 0, 0), strides=(1, 1, 1, 1, 1), begin_mask=(0, 0, 0, 0, 0), end_mask=(0, 0, 0, 0, 0), + shrink_axis_mask=(0, 1, 0, 0, 0), new_axis_mask=(0, 0, 0, 1, 0), ellipsis_mask=(1, 0, 0, 0, 0) + ) + + def test_auto_infer_strided_slice_4d_over_5d_12(self): + """ + inp_shape = (1, 100, 200, 10, 3), out = inp[None, :, ..., 0, :] => out_shape = (1, 1, 100, 200, 3) + """ + self.run_test( + inp=(1, 100, 200, 10, 3), is_shape=True, ref_res=(1, 1, 100, 200, 3), + begin=(0, 0, 0, 0, 0), end=(0, 0, 0, 0, 0), strides=(1, 1, 1, 1, 1), begin_mask=(0, 0, 0, 0, 0), end_mask=(0, 0, 0, 0, 0), + shrink_axis_mask=(0, 0, 0, 1, 0), new_axis_mask=(1, 0, 0, 0, 0), ellipsis_mask=(0, 0, 1, 0, 0) + ) + + def test_auto_infer_strided_slice_4d_over_5d_13(self): + """ + inp_shape = (1, 100, 200, 10, 3), out = inp[..., :, None, 0, :] => out_shape = (1, 100, 200, 1, 3) + """ + self.run_test( + inp=(1, 100, 200, 10, 3), is_shape=True, ref_res=(1, 100, 200, 1, 3), + begin=(0, 0, 0, 0, 0), end=(0, 0, 0, 0, 0), strides=(1, 1, 1, 1, 1), begin_mask=(0, 0, 0, 0, 0), end_mask=(0, 0, 0, 0, 0), + shrink_axis_mask=(0, 0, 0, 1, 0), new_axis_mask=(0, 0, 1, 0, 0), ellipsis_mask=(1, 0, 0, 0, 0) + ) + + def test_auto_infer_strided_slice_4d_over_5d_14(self): + """ + inp_shape = (1, 100, 200, 10, 3), out = inp[0, :, None, ..., :] => out_shape = (100, 1, 200, 10, 3) + """ + self.run_test( + inp=(1, 100, 200, 10, 3), is_shape=True, ref_res=(100, 1, 200, 10, 3), + begin=(0, 0, 0, 0, 0), end=(0, 0, 0, 0, 0), strides=(1, 1, 1, 1, 1), begin_mask=(0, 0, 0, 0, 0), end_mask=(0, 0, 0, 0, 0), + shrink_axis_mask=(1, 0, 0, 0, 0), new_axis_mask=(0, 0, 1, 0, 0), ellipsis_mask=(0, 0, 0, 1, 0) + ) + + def test_auto_infer_strided_slice_4d_over_5d_15(self): + """ + inp_shape = (1, 100, 200, 10, 3), out = inp[0, :, ..., None, :] => out_shape = (100, 200, 10, 1, 3) + """ + self.run_test( + inp=(1, 100, 200, 10, 3), is_shape=True, ref_res=(100, 200, 10, 1, 3), + begin=(0, 0, 0, 0, 0), end=(0, 0, 0, 0, 0), strides=(1, 1, 1, 1, 1), begin_mask=(0, 0, 0, 0, 0), end_mask=(0, 0, 0, 0, 0), + shrink_axis_mask=(1, 0, 0, 0, 0), new_axis_mask=(0, 0, 0, 1, 0), ellipsis_mask=(0, 0, 1, 0, 0) + ) + + def test_auto_infer_strided_slice_4d_over_5d_16(self): + """ + inp_shape = (1, 100, 200, 10, 3), out = inp[None, :, 0, ..., :] => out_shape = (1, 1, 200, 10, 3) + """ + self.run_test( + inp=(1, 100, 200, 10, 3), is_shape=True, ref_res=(1, 1, 200, 10, 3), + begin=(0, 0, 0, 0, 0), end=(0, 0, 0, 0, 0), strides=(1, 1, 1, 1, 1), begin_mask=(0, 0, 0, 0, 0), end_mask=(0, 0, 0, 0, 0), + shrink_axis_mask=(0, 0, 1, 0, 0), new_axis_mask=(1, 0, 0, 0, 0), ellipsis_mask=(0, 0, 0, 1, 0) + ) + + def test_auto_infer_strided_slice_4d_over_5d_17(self): + """ + inp_shape = (1, 100, 200, 10, 3), out = inp[..., :, 0, None, :] => out_shape = (1, 100, 200, 1, 3) + """ + self.run_test( + inp=(1, 100, 200, 10, 3), is_shape=True, ref_res=(1, 100, 200, 1, 3), + begin=(0, 0, 0, 0, 0), end=(0, 0, 0, 0, 0), strides=(1, 1, 1, 1, 1), begin_mask=(0, 0, 0, 0, 0), end_mask=(0, 0, 0, 0, 0), + shrink_axis_mask=(0, 0, 1, 0, 0), new_axis_mask=(0, 0, 0, 1, 0), ellipsis_mask=(1, 0, 0, 0, 0) + ) + + def test_auto_infer_strided_slice_4d_over_5d_18(self): + """ + inp_shape = (1, 100, 200, 10, 3), out = inp[:, None, ..., 0, :] => out_shape = (1, 1, 100, 200, 3) + """ + self.run_test( + inp=(1, 100, 200, 10, 3), is_shape=True, ref_res=(1, 1, 100, 200, 3), + begin=(0, 0, 0, 0, 0), end=(0, 0, 0, 0, 0), strides=(1, 1, 1, 1, 1), begin_mask=(0, 0, 0, 0, 0), end_mask=(0, 0, 0, 0, 0), + shrink_axis_mask=(0, 0, 0, 1, 0), new_axis_mask=(0, 1, 0, 0, 0), ellipsis_mask=(0, 0, 1, 0, 0) + ) + + def test_auto_infer_strided_slice_4d_over_5d_19(self): + """ + inp_shape = (1, 100, 200, 10, 3), out = inp[:, ..., None, 0, :] => out_shape = (1, 100, 200, 1, 3) + """ + self.run_test( + inp=(1, 100, 200, 10, 3), is_shape=True, ref_res=(1, 100, 200, 1, 3), + begin=(0, 0, 0, 0, 0), end=(0, 0, 0, 0, 0), strides=(1, 1, 1, 1, 1), begin_mask=(0, 0, 0, 0, 0), end_mask=(0, 0, 0, 0, 0), + shrink_axis_mask=(0, 0, 0, 1, 0), new_axis_mask=(0, 0, 1, 0, 0), ellipsis_mask=(0, 1, 0, 0, 0) + ) + + def test_auto_infer_strided_slice_4d_over_5d_20(self): + """ + inp_shape = (1, 100, 200, 10, 3), out = inp[:, 0, None, ..., :] => out_shape = (1, 1, 200, 10, 3) + """ + self.run_test( + inp=(1, 100, 200, 10, 3), is_shape=True, ref_res=(1, 1, 200, 10, 3), + begin=(0, 0, 0, 0, 0), end=(0, 0, 0, 0, 0), strides=(1, 1, 1, 1, 1), begin_mask=(0, 0, 0, 0, 0), end_mask=(0, 0, 0, 0, 0), + shrink_axis_mask=(0, 1, 0, 0, 0), new_axis_mask=(0, 0, 1, 0, 0), ellipsis_mask=(0, 0, 0, 1, 0) + ) + + def test_auto_infer_strided_slice_4d_over_5d_21(self): + """ + inp_shape = (1, 100, 200, 10, 3), out = inp[:, 0, ..., None, :] => out_shape = (1, 200, 10, 1, 3) + """ + self.run_test( + inp=(1, 100, 200, 10, 3), is_shape=True, ref_res=(1, 200, 10, 1, 3), + begin=(0, 0, 0, 0, 0), end=(0, 0, 0, 0, 0), strides=(1, 1, 1, 1, 1), begin_mask=(0, 0, 0, 0, 0), end_mask=(0, 0, 0, 0, 0), + shrink_axis_mask=(0, 1, 0, 0, 0), new_axis_mask=(0, 0, 0, 1, 0), ellipsis_mask=(0, 0, 1, 0, 0) + ) + + def test_auto_infer_strided_slice_4d_over_5d_22(self): + """ + inp_shape = (1, 100, 200, 10, 3), out = inp[:, None, 0, ..., :] => out_shape = (1, 1, 200, 10, 3) + """ + self.run_test( + inp=(1, 100, 200, 10, 3), is_shape=True, ref_res=(1, 1, 200, 10, 3), + begin=(0, 0, 0, 0, 0), end=(0, 0, 0, 0, 0), strides=(1, 1, 1, 1, 1), begin_mask=(0, 0, 0, 0, 0), end_mask=(0, 0, 0, 0, 0), + shrink_axis_mask=(0, 0, 1, 0, 0), new_axis_mask=(0, 1, 0, 0, 0), ellipsis_mask=(0, 0, 0, 1, 0) + ) + + def test_auto_infer_strided_slice_4d_over_5d_23(self): + """ + inp_shape = (1, 100, 200, 10, 3), out = inp[:, ..., 0, None, :] => out_shape = (1, 100, 200, 1, 3) + """ + self.run_test( + inp=(1, 100, 200, 10, 3), is_shape=True, ref_res=(1, 100, 200, 1, 3), + begin=(0, 0, 0, 0, 0), end=(0, 0, 0, 0, 0), strides=(1, 1, 1, 1, 1), begin_mask=(0, 0, 0, 0, 0), end_mask=(0, 0, 0, 0, 0), + shrink_axis_mask=(0, 0, 1, 0, 0), new_axis_mask=(0, 0, 0, 1, 0), ellipsis_mask=(0, 1, 0, 0, 0) + ) diff --git a/model-optimizer/mo/pipeline/common.py b/model-optimizer/mo/pipeline/common.py index 65e28cfb33b100..51b8d8bc795199 100644 --- a/model-optimizer/mo/pipeline/common.py +++ b/model-optimizer/mo/pipeline/common.py @@ -22,6 +22,7 @@ import networkx as nx from extensions.back.RemoveUselessConvert import RemoveUselessConvert +from extensions.back.ResultRename import ResultRename from extensions.back.op_versioning import OpVersioning from extensions.ops.Cast import Cast from mo.back.ie_ir_ver_2.emitter import port_renumber, serialize_constants, generate_ie_ir, serialize_mean_image @@ -208,6 +209,8 @@ def prepare_emit_ir(graph: Graph, data_type: str, output_dir: str, output_model_ type_infer(graph) RemoveUselessConvert().find_and_replace_pattern(graph) + ResultRename().find_and_replace_pattern(graph) + for sub_graph in [graph] + collect_sub_graphs(graph): op_order, data_order = determined_sort(get_sorted_outputs(sub_graph)) mapping = {v: u for u, v in enumerate(op_order)} diff --git a/model-optimizer/mo/utils/ir_reader/extenders/strided_slice_extender.py b/model-optimizer/mo/utils/ir_reader/extenders/strided_slice_extender.py index dfc7c843062785..ec82049ad679fe 100644 --- a/model-optimizer/mo/utils/ir_reader/extenders/strided_slice_extender.py +++ b/model-optimizer/mo/utils/ir_reader/extenders/strided_slice_extender.py @@ -1,5 +1,5 @@ """ - Copyright (C) 2018-2020 Intel Corporation + Copyright (C) 2018-2021 Intel Corporation Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -15,6 +15,7 @@ """ from mo.front.common.partial_infer.utils import int64_array +from mo.ops.strided_slice import StridedSlice from mo.utils.graph import Node from mo.utils.ir_reader.extender import Extender @@ -24,9 +25,7 @@ class StridedSlice_extender(Extender): @staticmethod def extend(op: Node): - - attrs = ['shrink_axis_mask', 'new_axis_mask', 'ellipsis_mask', 'begin_mask', 'end_mask'] - for attr in attrs: + for attr in StridedSlice.get_mask_names(): Extender.attr_to_list(op, attr) op.begin_mask = int64_array([1 - i for i in op.begin_mask]) diff --git a/ngraph/cmake/external_protobuf.cmake b/ngraph/cmake/external_protobuf.cmake index 33a1c66cfe9824..22c4eb8d445e05 100644 --- a/ngraph/cmake/external_protobuf.cmake +++ b/ngraph/cmake/external_protobuf.cmake @@ -143,7 +143,7 @@ else() message(FATAL_ERROR "Minimum supported version of protobuf library is 3.0.0") endif() - set(Protobuf_INCLUDE_DIRS ${ext_protobuf_SOURCE_DIR}) + set(Protobuf_INCLUDE_DIRS ${ext_protobuf_SOURCE_DIR}/src) if(NGRAPH_USE_PROTOBUF_LITE) set(Protobuf_LIBRARIES libprotobuf-lite) else() diff --git a/ngraph/frontend/onnx_import/src/core/transform.hpp b/ngraph/frontend/onnx_import/src/core/transform.hpp index 70014ed58cae29..f2b5f579f40a58 100644 --- a/ngraph/frontend/onnx_import/src/core/transform.hpp +++ b/ngraph/frontend/onnx_import/src/core/transform.hpp @@ -64,6 +64,7 @@ namespace ngraph "GroupNorm", "Normalize", "PriorBox", + "PriorBoxClustered", "Swish"}; /// \brief Add support for models with custom operators mistakenly registered in diff --git a/ngraph/frontend/onnx_import/src/op/org.openvinotoolkit/prior_box.cpp b/ngraph/frontend/onnx_import/src/op/org.openvinotoolkit/prior_box.cpp index a27440a5e34d67..14a7b48e11d019 100644 --- a/ngraph/frontend/onnx_import/src/op/org.openvinotoolkit/prior_box.cpp +++ b/ngraph/frontend/onnx_import/src/op/org.openvinotoolkit/prior_box.cpp @@ -16,6 +16,7 @@ #include "ngraph/op/prior_box.hpp" #include "default_opset.hpp" +#include "exceptions.hpp" #include "ngraph/node.hpp" #include "onnx_import/core/node.hpp" #include "op/org.openvinotoolkit/prior_box.hpp" @@ -83,6 +84,48 @@ namespace ngraph axes)}; } + OutputVector prior_box_clustered(const Node& node) + { + auto inputs = node.get_ng_inputs(); + NGRAPH_CHECK(inputs.size() == 2, "Invalid number of inputs"); + + auto output_shape_rank = inputs[0].get_partial_shape().rank().get_length(); + auto image_shape_rank = inputs[1].get_partial_shape().rank().get_length(); + CHECK_VALID_NODE(node, + output_shape_rank == 4, + "Only 4D inputs are supported. First input rank: ", + output_shape_rank, + " (should be 4)"); + CHECK_VALID_NODE(node, + image_shape_rank == 4, + "Only 4D inputs are supported. Second input rank: ", + image_shape_rank, + " (should be 4)"); + + auto output_shape = std::make_shared(inputs[0]); + auto image_shape = std::make_shared(inputs[1]); + auto output_shape_slice = detail::make_slice(output_shape, 2, 4); + auto image_shape_slice = detail::make_slice(image_shape, 2, 4); + + ngraph::op::PriorBoxClusteredAttrs attrs{}; + attrs.widths = node.get_attribute_value>("width"); + attrs.heights = node.get_attribute_value>("height"); + attrs.clip = static_cast(node.get_attribute_value("clip", 0)); + attrs.variances = + node.get_attribute_value>("variance", {0.1f}); + attrs.step_heights = node.get_attribute_value("step_h", 0.0f); + attrs.step_widths = node.get_attribute_value("step_w", 0.0f); + attrs.offset = node.get_attribute_value("offset", 0.0f); + + auto axes = default_opset::Constant::create( + element::i64, Shape{1}, std::vector{0}); + + return {std::make_shared( + std::make_shared( + output_shape_slice, image_shape_slice, attrs), + axes)}; + } + } // namespace set_1 } // namespace op diff --git a/ngraph/frontend/onnx_import/src/op/org.openvinotoolkit/prior_box.hpp b/ngraph/frontend/onnx_import/src/op/org.openvinotoolkit/prior_box.hpp index 800b50f2c785cd..2966ec461dea9d 100644 --- a/ngraph/frontend/onnx_import/src/op/org.openvinotoolkit/prior_box.hpp +++ b/ngraph/frontend/onnx_import/src/op/org.openvinotoolkit/prior_box.hpp @@ -29,6 +29,8 @@ namespace ngraph { OutputVector prior_box(const Node& node); + OutputVector prior_box_clustered(const Node& node); + } // namespace set_1 } // namespace op diff --git a/ngraph/frontend/onnx_import/src/ops_bridge.cpp b/ngraph/frontend/onnx_import/src/ops_bridge.cpp index 6c631798619b53..d276ac4ed39e6d 100644 --- a/ngraph/frontend/onnx_import/src/ops_bridge.cpp +++ b/ngraph/frontend/onnx_import/src/ops_bridge.cpp @@ -493,6 +493,8 @@ namespace ngraph REGISTER_OPERATOR_WITH_DOMAIN(OPENVINO_ONNX_DOMAIN, "GroupNorm", 1, group_norm); REGISTER_OPERATOR_WITH_DOMAIN(OPENVINO_ONNX_DOMAIN, "Normalize", 1, normalize); REGISTER_OPERATOR_WITH_DOMAIN(OPENVINO_ONNX_DOMAIN, "PriorBox", 1, prior_box); + REGISTER_OPERATOR_WITH_DOMAIN( + OPENVINO_ONNX_DOMAIN, "PriorBoxClustered", 1, prior_box_clustered); REGISTER_OPERATOR_WITH_DOMAIN(OPENVINO_ONNX_DOMAIN, "Swish", 1, swish); } diff --git a/ngraph/frontend/onnx_import/src/utils/recurrent.cpp b/ngraph/frontend/onnx_import/src/utils/recurrent.cpp index 8ac27148278b74..cc4a0b73d146de 100644 --- a/ngraph/frontend/onnx_import/src/utils/recurrent.cpp +++ b/ngraph/frontend/onnx_import/src/utils/recurrent.cpp @@ -41,26 +41,25 @@ namespace ngraph m_map[OpInput::W] = ng_inputs.at(1); m_map[OpInput::R] = ng_inputs.at(2); - const auto el_type = ng_inputs.at(0).get_element_type(); - const auto x_pshape = m_map[OpInput::X].get_partial_shape(); const auto w_pshape = m_map[OpInput::W].get_partial_shape(); const auto r_pshape = m_map[OpInput::R].get_partial_shape(); - NGRAPH_CHECK(x_pshape.rank().is_static() && x_pshape[0].is_static() && - x_pshape[1].is_static(), - "RecurrentSequence input X must have static \"seq_length\" and " - "\"batch_size\" dimensions."); - NGRAPH_CHECK(w_pshape.rank().is_static() && w_pshape[0].is_static(), - "RecurrentSequence input W must have static \"num_directions\" " - "(outermost) dimension."); - NGRAPH_CHECK(r_pshape.rank().is_static() && r_pshape[2].is_static(), - "RecurrentSequence input R must have static \"hidden_size\" " - "(innermost) dimension."); - const std::size_t hidden_size = m_map[OpInput::R].get_shape().back(); - const std::size_t batch_size = m_map[OpInput::X].get_shape().at(0); - const std::size_t num_directions = m_map[OpInput::W].get_shape().front(); + // Get dimensions needed for default inputs creation + auto shape_of_x = std::make_shared(m_map[OpInput::X]); + auto axes = default_opset::Constant::create(element::i32, Shape{1}, {0}); + auto batch_size_node = std::make_shared( + shape_of_x, default_opset::Constant::create(element::i32, Shape{1}, {0}), axes); + auto seq_length_node = std::make_shared( + shape_of_x, default_opset::Constant::create(element::i32, Shape{1}, {1}), axes); + + auto shape_of_r = std::make_shared(m_map[OpInput::R]); + auto num_directions_node = std::make_shared( + shape_of_r, default_opset::Constant::create(element::i32, Shape{1}, {0}), axes); + auto hidden_size_node = std::make_shared( + shape_of_r, default_opset::Constant::create(element::i32, Shape{1}, {2}), axes); + // ------ Optional inputs ------ if (ng_inputs.size() > 3 && !ngraph::op::is_null(ng_inputs.at(3))) { auto bias = ng_inputs.at(3); @@ -72,8 +71,17 @@ namespace ngraph } else { - m_map[OpInput::B] = std::make_shared( - el_type, Shape{num_directions, gates_count * hidden_size}, 0.f); + auto b_shape = std::make_shared( + OutputVector{num_directions_node, + std::make_shared( + default_opset::Constant::create( + element::Type_t::i64, Shape{1}, {gates_count}), + hidden_size_node)}, + 0); + m_map[OpInput::B] = std::make_shared( + default_opset::Constant::create( + m_map[OpInput::X].get_element_type(), Shape{}, {0}), + b_shape); } if (ng_inputs.size() > 4 && !ngraph::op::is_null(ng_inputs.at(4))) { @@ -81,8 +89,8 @@ namespace ngraph } else { - m_map[OpInput::SEQ_LENGTHS] = std::make_shared( - element::i32, Shape{batch_size}, m_map[OpInput::X].get_shape().at(1)); + m_map[OpInput::SEQ_LENGTHS] = std::make_shared( + seq_length_node, batch_size_node); } // The initial value of the hidden. if (ng_inputs.size() > 5 && !ngraph::op::is_null(ng_inputs.at(5))) @@ -92,8 +100,12 @@ namespace ngraph } else { - m_map[OpInput::INIT_H] = std::make_shared( - el_type, Shape{batch_size, num_directions, hidden_size}, 0.f); + auto init_h_shape = std::make_shared( + OutputVector{batch_size_node, num_directions_node, hidden_size_node}, 0); + m_map[OpInput::INIT_H] = std::make_shared( + default_opset::Constant::create( + m_map[OpInput::X].get_element_type(), Shape{}, {0}), + init_h_shape); } } diff --git a/ngraph/test/CMakeLists.txt b/ngraph/test/CMakeLists.txt index aacc74257fecd1..799355a165c223 100644 --- a/ngraph/test/CMakeLists.txt +++ b/ngraph/test/CMakeLists.txt @@ -17,8 +17,6 @@ add_definitions("-DSERIALIZED_ZOO=\"${CMAKE_CURRENT_SOURCE_DIR}/models\"") set(NGRAPH_ONNX_NAMESPACE ngraph_onnx) -set(ONNX_LIBRARIES onnx onnx_proto) - add_subdirectory(runtime) if(NOT NGRAPH_UNIT_TEST_ENABLE) @@ -375,12 +373,6 @@ if (NGRAPH_ONNX_IMPORT_ENABLE AND NOT NGRAPH_USE_PROTOBUF_LITE) endif() foreach(BACKEND_NAME ${ACTIVE_BACKEND_LIST}) - if(${BACKEND_NAME} MATCHES ^INTERPRETER$) - set(TEST_LOOPS 100) - else() - set(TEST_LOOPS 2) - endif() - string(TOLOWER ${BACKEND_NAME} BACKEND_DIR) string(REGEX REPLACE "([a-z0-9]+):(.*)" "\\1" BACKEND_DIR ${BACKEND_DIR}) set(MANIFEST ${CMAKE_CURRENT_SOURCE_DIR}/runtime/${BACKEND_DIR}/unit_test.manifest) @@ -422,9 +414,15 @@ target_link_libraries(unit-test PRIVATE ngraph_test_util # Protobuf-lite does not support parsing files from prototxt format # Since most of the onnx models are stored in this format it have to be disabled if (NGRAPH_ONNX_IMPORT_ENABLE AND NOT NGRAPH_USE_PROTOBUF_LITE) + # It's needed by onnx_import_library.cpp and onnx_import_exceptions.cpp tests to include onnx_pb.h. + # Not linking statically to libprotobuf (linked into libonnx) avoids false-failing onnx_editor tests. target_include_directories(unit-test - SYSTEM PRIVATE ${ONNX_INCLUDE_DIR} ${ONNX_PROTO_INCLUDE_DIR} ${Protobuf_INCLUDE_DIRS}) - target_link_libraries(unit-test PRIVATE ${Protobuf_LIBRARIES} ${ONNX_LIBRARIES}) + SYSTEM PRIVATE + $ + $ + ${Protobuf_INCLUDE_DIRS}) + target_compile_definitions(unit-test + PRIVATE $) get_target_property(ONNX_IMPORTER_SRC_DIR onnx_importer SOURCE_DIR) target_include_directories(unit-test PRIVATE ${ONNX_IMPORTER_SRC_DIR}/src) diff --git a/ngraph/test/models/onnx/dynamic_shapes/gru_defaults_fwd_const_dynamic.prototxt b/ngraph/test/models/onnx/dynamic_shapes/gru_defaults_fwd_const_dynamic.prototxt new file mode 100644 index 00000000000000..30098cc9998f88 --- /dev/null +++ b/ngraph/test/models/onnx/dynamic_shapes/gru_defaults_fwd_const_dynamic.prototxt @@ -0,0 +1,220 @@ +ir_version: 3 +producer_name: "nGraph ONNX Importer" +graph { + node { + output: "W" + op_type: "Constant" + attribute { + name: "value" + t { + dims: 1 # num_directions + dims: 15 # gates_count*hidden_size + dims: 2 # input_size + data_type: 1 + float_data: 0.31403765 + float_data: -0.16793324 + float_data: 1.388258 + float_data: -0.6902954 + float_data: -0.3994045 + float_data: -0.7833511 + + float_data: -0.30992958 + float_data: 0.3557573 + float_data: -0.4682631 + float_data: 1.1741459 + float_data: -2.414789 + float_data: -0.42783254 + + float_data: -0.82199496 + float_data: -0.0390086 + float_data: -0.43670088 + float_data: -0.53810567 + float_data: -0.10769883 + float_data: 0.75242394 + + float_data: -0.2507971 + float_data: 1.0447186 + float_data: -1.4777364 + float_data: 0.19993274 + float_data: 0.925649 + float_data: -2.282516 + + float_data: 0.95039636 + float_data: 1.5379831 + float_data: -0.88576007 + float_data: 0.28566247 + float_data: 0.79292643 + float_data: -0.04261953 + name: "W_tensor" + } + type: TENSOR + } + } + node { + output: "R" + op_type: "Constant" + attribute { + name: "value" + t { + dims: 1 # num_directions + dims: 15 # gates_count*hidden_size + dims: 5 # input_size + data_type: 1 + float_data: 0.8490583 + float_data: 0.45121244 + float_data: -1.1799014 + float_data: 0.13536449 + float_data: 0.81328654 + float_data: 0.6017516 + float_data: 0.48475724 + float_data: -1.2136037 + float_data: 0.16383322 + float_data: 1.5106261 + float_data: 1.1177503 + float_data: 0.23582461 + float_data: 0.5754652 + float_data: 0.43879887 + float_data: 0.7399294 + float_data: 0.4517558 + float_data: 1.3536783 + float_data: -0.4843166 + float_data: -1.1503736 + float_data: -0.2458678 + float_data: 0.54523313 + float_data: -0.08649993 + float_data: -0.6936281 + float_data: 1.002422 + float_data: -1.770847 + float_data: -0.94642 + float_data: -1.8135757 + float_data: 1.8819852 + float_data: -0.10852333 + float_data: -0.26120332 + float_data: 1.0223165 + float_data: -0.7468837 + float_data: 0.28566906 + float_data: 0.92321056 + float_data: 0.22521864 + float_data: 1.1123824 + float_data: -0.9298287 + float_data: 1.2141289 + float_data: 1.3470556 + float_data: -0.32972014 + float_data: -1.6552197 + float_data: -1.0998285 + float_data: 0.71901864 + float_data: 0.962846 + float_data: -0.1366851 + float_data: -2.6534476 + float_data: -1.4992771 + float_data: -0.45793465 + float_data: 0.4290477 + float_data: 0.9893151 + float_data: 0.2511034 + float_data: 0.12906462 + float_data: 0.7491512 + float_data: 0.3316756 + float_data: 1.0576645 + float_data: -0.04618666 + float_data: 1.3556088 + float_data: 1.2842374 + float_data: 0.7103014 + float_data: 0.52889013 + float_data: 0.30327162 + float_data: 1.5069056 + float_data: 0.16591893 + float_data: 1.5719851 + float_data: -2.099427 + float_data: -1.010277 + float_data: -0.52800924 + float_data: -0.22292352 + float_data: -0.55177474 + float_data: 1.3432894 + float_data: 0.8731192 + float_data: -0.01055307 + float_data: -0.01138215 + float_data: 0.85698843 + float_data: -1.2615703 + name: "R_tensor" + } + type: TENSOR + } + } + node { + input: "X" + input: "W" + input: "R" + output: "Y" + output: "Y_h" + op_type: "GRU" + attribute { + name: "hidden_size" + i: 5 + type: INT + } + } + name: "test_gru_defaults_const" + input { + name: "X" + type { + tensor_type { + elem_type: 1 + shape { + dim { + dim_value: -1 # seq_length + } + dim { + dim_value: -1 # batch size + } + dim { + dim_value: 2 # input size + } + } + } + } + } + output { + name: "Y" + type { + tensor_type { + elem_type: 1 + shape { + dim { + dim_value: -1 # seq_length + } + dim { + dim_value: 1 # num_directions + } + dim { + dim_value: -1 # batch_size + } + dim { + dim_value: 5 # hidden_size + } + } + } + } + } + output { + name: "Y_h" + type { + tensor_type { + elem_type: 1 + shape { + dim { + dim_value: 1 # num_directions + } + dim { + dim_value: -1 # batch_size + } + dim { + dim_value: 5 # hidden_size + } + } + } + } + } +} +opset_import { + version: 9 +} diff --git a/ngraph/test/models/onnx/dynamic_shapes/rnn_defaults_fwd_const_dynamic.prototxt b/ngraph/test/models/onnx/dynamic_shapes/rnn_defaults_fwd_const_dynamic.prototxt new file mode 100644 index 00000000000000..563ed354ffcb48 --- /dev/null +++ b/ngraph/test/models/onnx/dynamic_shapes/rnn_defaults_fwd_const_dynamic.prototxt @@ -0,0 +1,146 @@ +ir_version: 3 +producer_name: "nGraph ONNX Importer" +graph { + node { + output: "W" + op_type: "Constant" + attribute { + name: "value" + t { + dims: 1 + dims: 5 + dims: 2 + data_type: 1 + float_data: 0.31403765 + float_data: -0.16793324 + float_data: 1.388258 + float_data: -0.6902954 + float_data: -0.3994045 + float_data: -0.7833511 + float_data: -0.30992958 + float_data: 0.3557573 + float_data: -0.4682631 + float_data: 1.1741459 + name: "W_tensor" + } + type: TENSOR + } + } + node { + output: "R" + op_type: "Constant" + attribute { + name: "value" + t { + dims: 1 # num_directions + dims: 5 # gates_count*hidden_size + dims: 5 # input_size + data_type: 1 + float_data: -2.414789 + float_data: -0.42783254 + float_data: -0.82199496 + float_data: -0.03900861 + float_data: -0.43670088 + float_data: -0.53810567 + float_data: -0.10769883 + float_data: 0.75242394 + float_data: -0.2507971 + float_data: 1.0447186 + float_data: -1.4777364 + float_data: 0.19993274 + float_data: 0.925649 + float_data: -2.282516 + float_data: 0.95039636 + float_data: 1.5379831 + float_data: -0.88576007 + float_data: 0.28566247 + float_data: 0.79292643 + float_data: -0.04261953 + float_data: 0.8490583 + float_data: 0.45121244 + float_data: -1.1799014 + float_data: 0.13536449 + float_data: 0.81328654 + name: "R_tensor" + } + type: TENSOR + } + } + node { + input: "X" + input: "W" + input: "R" + output: "Y" + output: "Y_h" + op_type: "RNN" + attribute { + name: "hidden_size" + i: 5 + type: INT + } + } + name: "test_rnn_defaults" + input { + name: "X" + type { + tensor_type { + elem_type: 1 + shape { + dim { + dim_value: -1 # seq_length + } + dim { + dim_value: -1 # batch size + } + dim { + dim_value: 2 # input size + } + } + } + } + } + output { + name: "Y" + type { + tensor_type { + elem_type: 1 + shape { + dim { + dim_value: -1 # seq_length + } + dim { + dim_value: 1 # num_directions + } + dim { + dim_value: -1 # batch_size + } + dim { + dim_value: 5 # hidden_size + } + } + } + } + } + output { + name: "Y_h" + type { + tensor_type { + elem_type: 1 + shape { + dim { + dim_value: 1 # num_directions + } + dim { + dim_value: -1 # batch_size + } + dim { + dim_value: 5 # hidden_size + } + } + } + } + } +} +opset_import { + version: 9 +} diff --git a/ngraph/test/models/onnx/priorbox_clustered.prototxt b/ngraph/test/models/onnx/priorbox_clustered.prototxt new file mode 100644 index 00000000000000..68941b51d9e82d --- /dev/null +++ b/ngraph/test/models/onnx/priorbox_clustered.prototxt @@ -0,0 +1,122 @@ +ir_version: 3 +producer_name: "nGraph ONNX Importer" +graph { + node { + domain: "org.openvinotoolkit" + input: "A" + input: "B" + output: "out" + op_type: "PriorBoxClustered" + attribute { + name: "width" + floats: 0.1 + floats: 0.1 + floats: 0.2 + floats: 0.2 + type: FLOATS + } + attribute { + name: "height" + floats: 0.1 + floats: 0.1 + floats: 0.2 + floats: 0.2 + type: FLOATS + } + attribute { + name: "step_w" + f: 64 + type: FLOAT + } + attribute { + name: "clip" + i: 1 + type: INT + } + attribute { + name: "step_h" + f: 64 + type: FLOAT + } + attribute { + name: "offset" + f: 0.5 + type: FLOAT + } + attribute { + name: "variance" + floats: 0.1 + floats: 0.1 + floats: 0.2 + floats: 0.2 + type: FLOATS + } + } + name: "compute_graph" + input { + name: "A" + type { + tensor_type { + elem_type: 1 + shape { + dim { + dim_value: 1 + } + dim { + dim_value: 1 + } + dim { + dim_value: 1 + } + dim { + dim_value: 1 + } + } + } + } + } + input { + name: "B" + type { + tensor_type { + elem_type: 1 + shape { + dim { + dim_value: 1 + } + dim { + dim_value: 1 + } + dim { + dim_value: 1 + } + dim { + dim_value: 1 + } + } + } + } + } + output { + name: "out" + type { + tensor_type { + elem_type: 1 + shape { + dim { + dim_value: 1 + } + dim { + dim_value: 2 + } + dim { + dim_value: 4 + } + } + } + } + } +} +opset_import { + version: 1 +} diff --git a/ngraph/test/models/onnx/priorbox_clustered_first_input_bad_shape.prototxt b/ngraph/test/models/onnx/priorbox_clustered_first_input_bad_shape.prototxt new file mode 100644 index 00000000000000..48d4076d4e4b7e --- /dev/null +++ b/ngraph/test/models/onnx/priorbox_clustered_first_input_bad_shape.prototxt @@ -0,0 +1,125 @@ +ir_version: 3 +producer_name: "nGraph ONNX Importer" +graph { + node { + domain: "org.openvinotoolkit" + input: "A" + input: "B" + output: "out" + op_type: "PriorBoxClustered" + attribute { + name: "width" + floats: 0.1 + floats: 0.1 + floats: 0.2 + floats: 0.2 + type: FLOATS + } + attribute { + name: "height" + floats: 0.1 + floats: 0.1 + floats: 0.2 + floats: 0.2 + type: FLOATS + } + attribute { + name: "step_w" + f: 64 + type: FLOAT + } + attribute { + name: "clip" + i: 1 + type: INT + } + attribute { + name: "step_h" + f: 64 + type: FLOAT + } + attribute { + name: "offset" + f: 0.5 + type: FLOAT + } + attribute { + name: "variance" + floats: 0.1 + floats: 0.1 + floats: 0.2 + floats: 0.2 + type: FLOATS + } + } + name: "compute_graph" + input { + name: "A" + type { + tensor_type { + elem_type: 1 + shape { + dim { + dim_value: 1 + } + dim { + dim_value: 1 + } + dim { + dim_value: 1 + } + dim { + dim_value: 1 + } + dim { + dim_value: 1 + } + } + } + } + } + input { + name: "B" + type { + tensor_type { + elem_type: 1 + shape { + dim { + dim_value: 1 + } + dim { + dim_value: 1 + } + dim { + dim_value: 1 + } + dim { + dim_value: 1 + } + } + } + } + } + output { + name: "out" + type { + tensor_type { + elem_type: 1 + shape { + dim { + dim_value: 1 + } + dim { + dim_value: 2 + } + dim { + dim_value: 4 + } + } + } + } + } +} +opset_import { + version: 1 +} diff --git a/ngraph/test/models/onnx/priorbox_clustered_most_attrs_default.prototxt b/ngraph/test/models/onnx/priorbox_clustered_most_attrs_default.prototxt new file mode 100644 index 00000000000000..ac7c62bdf3663a --- /dev/null +++ b/ngraph/test/models/onnx/priorbox_clustered_most_attrs_default.prototxt @@ -0,0 +1,96 @@ +ir_version: 3 +producer_name: "nGraph ONNX Importer" +graph { + node { + domain: "org.openvinotoolkit" + input: "A" + input: "B" + output: "out" + op_type: "PriorBoxClustered" + attribute { + name: "variance" + floats: 0.1 + floats: 0.1 + floats: 0.2 + floats: 0.2 + type: FLOATS + } + attribute { + name: "width" + floats: 1.0 + type: FLOATS + } + attribute { + name: "height" + floats: 1.0 + type: FLOATS + } + } + name: "compute_graph" + input { + name: "A" + type { + tensor_type { + elem_type: 1 + shape { + dim { + dim_value: 1 + } + dim { + dim_value: 1 + } + dim { + dim_value: 2 + } + dim { + dim_value: 1 + } + } + } + } + } + input { + name: "B" + type { + tensor_type { + elem_type: 1 + shape { + dim { + dim_value: 1 + } + dim { + dim_value: 1 + } + dim { + dim_value: 3 + } + dim { + dim_value: 3 + } + } + } + } + } + output { + name: "out" + type { + tensor_type { + elem_type: 1 + shape { + dim { + dim_value: 1 + } + dim { + dim_value: 2 + } + dim { + dim_value: 8 + } + } + } + } + } +} +opset_import { + version: 1 +} diff --git a/ngraph/test/models/onnx/priorbox_clustered_second_input_bad_shape.prototxt b/ngraph/test/models/onnx/priorbox_clustered_second_input_bad_shape.prototxt new file mode 100644 index 00000000000000..8d53532b3742b0 --- /dev/null +++ b/ngraph/test/models/onnx/priorbox_clustered_second_input_bad_shape.prototxt @@ -0,0 +1,125 @@ +ir_version: 3 +producer_name: "nGraph ONNX Importer" +graph { + node { + domain: "org.openvinotoolkit" + input: "A" + input: "B" + output: "out" + op_type: "PriorBoxClustered" + attribute { + name: "width" + floats: 0.1 + floats: 0.1 + floats: 0.2 + floats: 0.2 + type: FLOATS + } + attribute { + name: "height" + floats: 0.1 + floats: 0.1 + floats: 0.2 + floats: 0.2 + type: FLOATS + } + attribute { + name: "step_w" + f: 64 + type: FLOAT + } + attribute { + name: "clip" + i: 1 + type: INT + } + attribute { + name: "step_h" + f: 64 + type: FLOAT + } + attribute { + name: "offset" + f: 0.5 + type: FLOAT + } + attribute { + name: "variance" + floats: 0.1 + floats: 0.1 + floats: 0.2 + floats: 0.2 + type: FLOATS + } + } + name: "compute_graph" + input { + name: "A" + type { + tensor_type { + elem_type: 1 + shape { + dim { + dim_value: 1 + } + dim { + dim_value: 1 + } + dim { + dim_value: 1 + } + dim { + dim_value: 1 + } + } + } + } + } + input { + name: "B" + type { + tensor_type { + elem_type: 1 + shape { + dim { + dim_value: 1 + } + dim { + dim_value: 1 + } + dim { + dim_value: 1 + } + dim { + dim_value: 1 + } + dim { + dim_value: 1 + } + } + } + } + } + output { + name: "out" + type { + tensor_type { + elem_type: 1 + shape { + dim { + dim_value: 1 + } + dim { + dim_value: 2 + } + dim { + dim_value: 4 + } + } + } + } + } +} +opset_import { + version: 1 +} diff --git a/ngraph/test/onnx/onnx_import.in.cpp b/ngraph/test/onnx/onnx_import.in.cpp index ae3aa11ccfe2a0..a03e49ffa2aaec 100644 --- a/ngraph/test/onnx/onnx_import.in.cpp +++ b/ngraph/test/onnx/onnx_import.in.cpp @@ -39,7 +39,6 @@ #include "onnx_import/onnx.hpp" #include "onnx_import/onnx_utils.hpp" #include "default_opset.hpp" -#include "exceptions.hpp" #include "ngraph/ngraph.hpp" #include "ngraph/pass/manager.hpp" #include "ngraph/pass/constant_folding.hpp" diff --git a/ngraph/test/onnx/onnx_import_library.cpp b/ngraph/test/onnx/onnx_import_library.cpp index 593b4bf13ae666..643a584ce68c74 100644 --- a/ngraph/test/onnx/onnx_import_library.cpp +++ b/ngraph/test/onnx/onnx_import_library.cpp @@ -15,8 +15,6 @@ //***************************************************************************** #include -#include "onnx/defs/function.h" -#include "onnx/defs/schema.h" #include "gtest/gtest.h" #include "util/test_control.hpp" @@ -25,16 +23,6 @@ using namespace ngraph; static std::string s_manifest = "${MANIFEST}"; -NGRAPH_TEST(onnx, get_function_op_with_version) -{ - const auto* schema = - ONNX_NAMESPACE::OpSchemaRegistry::Schema("MeanVarianceNormalization", 9, ""); - EXPECT_TRUE(schema); - EXPECT_TRUE(schema->HasFunction()); - auto func = schema->GetFunction(); - EXPECT_EQ(func->name(), "MeanVarianceNormalization"); -} - NGRAPH_TEST(onnx, check_ir_version_support) { // It appears you've changed the ONNX library version used by nGraph. Please update the value diff --git a/ngraph/test/onnx/onnx_import_org_openvino.in.cpp b/ngraph/test/onnx/onnx_import_org_openvino.in.cpp index dfd2f025bb98f9..be025c982786c2 100644 --- a/ngraph/test/onnx/onnx_import_org_openvino.in.cpp +++ b/ngraph/test/onnx/onnx_import_org_openvino.in.cpp @@ -39,7 +39,6 @@ #include "onnx_import/onnx.hpp" #include "onnx_import/onnx_utils.hpp" #include "default_opset.hpp" -#include "exceptions.hpp" #include "ngraph/ngraph.hpp" #include "ngraph/pass/manager.hpp" #include "ngraph/pass/constant_folding.hpp" @@ -88,6 +87,96 @@ NGRAPH_TEST(${BACKEND_NAME}, onnx_prior_box) test_case.run(); } +NGRAPH_TEST(${BACKEND_NAME}, onnx_priorbox_clustered) +{ + auto function = onnx_import::import_onnx_model( + file_util::path_join(SERIALIZED_ZOO, "onnx/priorbox_clustered.prototxt")); + + auto test_case = test::TestCase(function); + std::vector A{15.0}; + std::vector B{10.0}; + std::vector output = { + 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, + 0.1, 0.1, 0.2, 0.2, 0.1, 0.1, 0.2, 0.2, 0.1, 0.1, 0.2, 0.2, 0.1, 0.1, 0.2, 0.2, + }; + test_case.add_input(A); + test_case.add_input(B); + test_case.add_expected_output(Shape{1, 2, 16}, output); + test_case.run(); +} + +NGRAPH_TEST(${BACKEND_NAME}, onnx_priorbox_clustered_most_attrs_default) +{ + auto function = onnx_import::import_onnx_model(file_util::path_join( + SERIALIZED_ZOO, "onnx/priorbox_clustered_most_attrs_default.prototxt")); + + auto test_case = test::TestCase(function); + std::vector A(1 * 1 * 2 * 1); + std::iota(std::begin(A), std::end(A), 0.0f); + std::vector B(1 * 1 * 3 * 3); + std::iota(std::begin(B), std::end(B), 0.0f); + std::vector output = {-0.1666666716337203979, + -0.1666666716337203979, + 0.1666666716337203979, + 0.1666666716337203979, + -0.1666666716337203979, + 0.3333333432674407959, + 0.1666666716337203979, + 0.6666666865348815918, + 0.1, + 0.1, + 0.2, + 0.2, + 0.1, + 0.1, + 0.2, + 0.2}; + test_case.add_input(A); + test_case.add_input(B); + test_case.add_expected_output(Shape{1, 2, 8}, output); + test_case.run(); +} + +NGRAPH_TEST(${BACKEND_NAME}, onnx_priorbox_clustered_first_input_bad_shape) +{ + try + { + auto function = onnx_import::import_onnx_model(file_util::path_join( + SERIALIZED_ZOO, "onnx/priorbox_clustered_first_input_bad_shape.prototxt")); + FAIL() << "Expected exception was not thrown"; + } + catch (const ngraph::ngraph_error& e) + { + EXPECT_HAS_SUBSTRING( + e.what(), + std::string("Only 4D inputs are supported. First input rank: 5 (should be 4)")); + } + catch (...) + { + FAIL() << "Expected OnnxNodeValidationFailure exception was not thrown"; + } +} + +NGRAPH_TEST(${BACKEND_NAME}, onnx_priorbox_clustered_second_input_bad_shape) +{ + try + { + auto function = onnx_import::import_onnx_model(file_util::path_join( + SERIALIZED_ZOO, "onnx/priorbox_clustered_second_input_bad_shape.prototxt")); + FAIL() << "Expected exception was not thrown"; + } + catch (const ngraph::ngraph_error& e) + { + EXPECT_HAS_SUBSTRING( + e.what(), + std::string("Only 4D inputs are supported. Second input rank: 5 (should be 4)")); + } + catch (...) + { + FAIL() << "Expected OnnxNodeValidationFailure exception was not thrown"; + } +} + NGRAPH_TEST(${BACKEND_NAME}, onnx_detection_output) { const auto function = onnx_import::import_onnx_model( @@ -490,4 +579,4 @@ NGRAPH_TEST(${BACKEND_NAME}, onnx_model_experimental_detectron_topk_rios) test_case.add_expected_output(Shape{1, 4}, {1, 1, 3, 4}); test_case.run(); -} \ No newline at end of file +} diff --git a/ngraph/test/onnx/onnx_import_rnn.in.cpp b/ngraph/test/onnx/onnx_import_rnn.in.cpp index 768270784c948f..98ffb30578fd29 100644 --- a/ngraph/test/onnx/onnx_import_rnn.in.cpp +++ b/ngraph/test/onnx/onnx_import_rnn.in.cpp @@ -1551,6 +1551,70 @@ NGRAPH_TEST_F(${BACKEND_NAME}, GRUSequenceOp, onnx_model_gru_fwd_linear_before_r test_case.run(DEFAULT_FLOAT_TOLERANCE_BITS + 4); } +NGRAPH_TEST_F(${BACKEND_NAME}, GRUSequenceOp, onnx_model_gru_defaults_fwd_const_dynamic) +{ + auto function = onnx_import::import_onnx_model(file_util::path_join( + SERIALIZED_ZOO, "onnx/dynamic_shapes/gru_defaults_fwd_const_dynamic.prototxt")); + + auto test_case = test::TestCase(function); + test_case.add_input(Shape{4, 3, 2}, in_X); + + // Y + test_case.add_expected_output( + Shape{4, 1, 3, 5}, + std::vector{ + -0.3224981f, -0.44282594f, 0.7499796f, -0.12240417f, 0.12079421f, 0.02534253f, + 0.02504562f, -0.0463777f, 0.01204534f, -0.01497037f, -0.04651929f, -0.6264307f, + 0.7236632f, 0.06250653f, 0.02594197f, -0.06868916f, -0.5412897f, 0.49794048f, + 0.22239858f, -0.11257736f, -0.23071964f, 0.26079988f, -0.07375772f, -0.21816255f, + 0.18764113f, -0.5228772f, 0.00575754f, 0.2514028f, -0.58864325f, 0.49843538f, + -0.6129046f, -0.10794663f, 0.6544055f, -0.70105773f, 0.5397687f, -0.35791716f, + 0.3885092f, -0.15291792f, -0.22324723f, 0.11557932f, -0.42112932f, 0.26772985f, + -0.38304564f, -0.05039781f, -0.5057976f, 0.5775348f, -0.6736855f, -0.20032284f, + 0.03698462f, -0.7693824f, -0.5831348f, 0.25767964f, 0.7121098f, -0.35951245f, + 0.39223647f, -0.6645166f, 0.37950075f, 0.59931314f, -0.4741001f, 0.21156166f, + }); + // Y_h + test_case.add_expected_output(Shape{1, 3, 5}, + std::vector{ + 0.5775348f, + -0.6736855f, + -0.20032284f, + 0.03698462f, + -0.7693824f, + -0.5831348f, + 0.25767964f, + 0.7121098f, + -0.35951245f, + 0.39223647f, + -0.6645166f, + 0.37950075f, + 0.59931314f, + -0.4741001f, + 0.21156166f, + }); + test_case.run(DEFAULT_FLOAT_TOLERANCE_BITS + 7); +} + +NGRAPH_TEST_F(${BACKEND_NAME}, GRUSequenceOp, onnx_model_import_only_gru_defaults_fwd_const_dynamic) +{ + auto function = onnx_import::import_onnx_model(file_util::path_join( + SERIALIZED_ZOO, "onnx/dynamic_shapes/gru_defaults_fwd_const_dynamic.prototxt")); + + auto batch_size = Dimension::dynamic(); + auto seq_length = Dimension::dynamic(); + int64_t hidden_size = 5; + int64_t num_directions = 1; + auto Y_expected_output = PartialShape{batch_size, num_directions, seq_length, hidden_size}; + auto Y_h_expected_output = PartialShape{num_directions, batch_size, hidden_size}; + + EXPECT_EQ(function->get_output_size(), 2); + EXPECT_EQ(function->get_output_partial_shape(0), Y_expected_output); + EXPECT_EQ(function->get_output_partial_shape(1), Y_h_expected_output); + + EXPECT_EQ(count_ops_of_type(function), 1); +} + // RNNLikeSequenceOp test fixture for test setup reuse class RNNSequenceOp : public testing::Test { @@ -2386,3 +2450,67 @@ NGRAPH_TEST_F(${BACKEND_NAME}, RNNSequenceOp, onnx_model_rnn_bidirectional_const }); test_case.run(DEFAULT_FLOAT_TOLERANCE_BITS + 6); } + +NGRAPH_TEST_F(${BACKEND_NAME}, RNNSequenceOp, onnx_model_rnn_defaults_fwd_const_dynamic) +{ + auto function = onnx_import::import_onnx_model(file_util::path_join( + SERIALIZED_ZOO, "onnx/dynamic_shapes/rnn_defaults_fwd_const_dynamic.prototxt")); + + auto test_case = test::TestCase(function); + test_case.add_input(Shape{4, 3, 2}, in_X); + + // Y + test_case.add_expected_output( + Shape{4, 1, 3, 5}, + std::vector{ + 0.02254748f, 0.15776646f, -0.8229023f, 0.19205809f, 0.76984656f, -0.00603169f, + -0.02861464f, 0.04512155f, -0.0011912f, -0.02572936f, -0.13703543f, -0.49651444f, + -0.78868157f, 0.3566854f, 0.8758509f, 0.20788848f, 0.13481987f, -0.756822f, + -0.121436f, 0.97542346f, 0.16959739f, 0.63496053f, 0.1245538f, -0.1970138f, + -0.56581646f, 0.8225869f, 0.9611373f, -0.42990375f, -0.22925597f, 0.2226491f, + 0.08246052f, 0.9798831f, -0.13415998f, -0.5567714f, 0.78594816f, -0.34759718f, + 0.11376679f, -0.07107389f, -0.5420871f, -0.58504283f, -0.96065646f, 0.18588805f, + -0.4870671f, -0.1475982f, 0.82456505f, -0.80264574f, -0.46370947f, 0.9719335f, + -0.7374159f, 0.94937694f, 0.8814341f, 0.67015004f, 0.21958017f, -0.8332769f, + -0.487742f, 0.9918536f, 0.99563396f, 0.94866276f, -0.98504806f, -0.42824882f, + }); + // Y_h + test_case.add_expected_output(Shape{1, 3, 5}, + std::vector{ + -0.80264574f, + -0.46370947f, + 0.9719335f, + -0.7374159f, + 0.94937694f, + 0.8814341f, + 0.67015004f, + 0.21958017f, + -0.8332769f, + -0.487742f, + 0.9918536f, + 0.99563396f, + 0.94866276f, + -0.98504806f, + -0.42824882f, + }); + test_case.run(DEFAULT_FLOAT_TOLERANCE_BITS + 4); +} + +NGRAPH_TEST_F(${BACKEND_NAME}, RNNSequenceOp, onnx_model_import_only_rnn_defaults_fwd_const_dynamic) +{ + auto function = onnx_import::import_onnx_model(file_util::path_join( + SERIALIZED_ZOO, "onnx/dynamic_shapes/rnn_defaults_fwd_const_dynamic.prototxt")); + + auto batch_size = Dimension::dynamic(); + auto seq_length = Dimension::dynamic(); + int64_t hidden_size = 5; + int64_t num_directions = 1; + auto Y_expected_output = PartialShape{batch_size, num_directions, seq_length, hidden_size}; + auto Y_h_expected_output = PartialShape{num_directions, batch_size, hidden_size}; + + EXPECT_EQ(function->get_output_size(), 2); + EXPECT_EQ(function->get_output_partial_shape(0), Y_expected_output); + EXPECT_EQ(function->get_output_partial_shape(1), Y_h_expected_output); + + EXPECT_EQ(count_ops_of_type(function), 1); +} diff --git a/ngraph/test/runtime/ie/unit_test.manifest b/ngraph/test/runtime/ie/unit_test.manifest index dec4695aeb5b39..cdf36d122c7641 100644 --- a/ngraph/test/runtime/ie/unit_test.manifest +++ b/ngraph/test/runtime/ie/unit_test.manifest @@ -249,6 +249,8 @@ IE_CPU.nothing_to_reverse # Unsupported dynamic ops onnx_size_dyn_op +onnx_model_gru_defaults_fwd_const_dynamic +onnx_model_rnn_defaults_fwd_const_dynamic # Constant network # MKLDNNGraph::CreateGraph: No inputs for the topology diff --git a/scripts/install_dependencies/install_NEO_OCL_driver.sh b/scripts/install_dependencies/install_NEO_OCL_driver.sh index edf4540a9df8cf..afce70a9280cc9 100755 --- a/scripts/install_dependencies/install_NEO_OCL_driver.sh +++ b/scripts/install_dependencies/install_NEO_OCL_driver.sh @@ -27,6 +27,7 @@ EXIT_FAILURE=1 EXIT_WRONG_ARG=2 CENTOS_MINOR= +RHEL_VERSION= UBUNTU_VERSION= DISTRO= SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" @@ -85,6 +86,29 @@ do esac done +_install_prerequisites_redhat() +{ + # yum doesn't accept timeout in seconds as parameter + echo + echo "Note: if yum becomes non-responsive, try aborting the script and run:" + echo " sudo -E $0" + echo + + CMDS=("yum -y install https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm && yum install -y ocl-icd") + + for cmd in "${CMDS[@]}"; do + echo "$cmd" + eval "$cmd" + if [[ $? -ne 0 ]]; then + echo "ERROR: failed to run $cmd" >&2 + echo "Problem (or disk space)?" >&2 + echo ". Verify that you have enough disk space, and run the script again." >&2 + exit $EXIT_FAILURE + fi + done + +} + _install_prerequisites_centos() { # yum doesn't accept timeout in seconds as parameter @@ -140,11 +164,12 @@ _install_prerequisites_ubuntu() install_prerequisites() { + echo "Installing prerequisites..." if [[ $DISTRO == "centos" ]]; then - echo "Installing prerequisites..." _install_prerequisites_centos + elif [[ $DISTRO == "redhat" ]]; then + _install_prerequisites_redhat elif [[ $DISTRO == "ubuntu" ]]; then - echo "Installing prerequisites..." _install_prerequisites_ubuntu else echo Unknown OS @@ -195,7 +220,7 @@ install_user_mode() { echo "Installing user mode driver..." - if [[ $DISTRO == "centos" ]]; then + if [[ $DISTRO == "centos" || $DISTRO == "redhat" ]]; then _install_user_mode_centos else _install_user_mode_ubuntu @@ -259,7 +284,7 @@ _uninstall_user_mode_ubuntu() uninstall_user_mode() { - if [[ $DISTRO == "centos" ]]; then + if [[ $DISTRO == "centos" || $DISTRO == "redhat" ]]; then _uninstall_user_mode_centos else _uninstall_user_mode_ubuntu @@ -268,7 +293,7 @@ uninstall_user_mode() _is_package_installed() { - if [[ $DISTRO == "centos" ]]; then + if [[ $DISTRO == "centos" || $DISTRO == "redhat" ]]; then cmd="rpm -qa | grep $1" else cmd="dpkg-query -W -f='${binary:Package}\n' $pkg" @@ -369,7 +394,7 @@ _verify_checksum_centos() verify_checksum() { - if [[ $DISTRO == "centos" ]]; then + if [[ $DISTRO == "centos" || $DISTRO == "redhat" ]]; then _verify_checksum_centos else _verify_checksum_ubuntu @@ -381,7 +406,7 @@ download_packages() mkdir -p "$SCRIPT_DIR/neo" cd "$SCRIPT_DIR/neo" || exit - if [[ $DISTRO == "centos" ]]; then + if [[ $DISTRO == "centos" || $DISTRO == "redhat" ]]; then _download_packages_centos else _download_packages_ubuntu @@ -453,6 +478,13 @@ _check_distro_version() echo "This script is supported only on CentOS 7 and above." >&2 exit $EXIT_FAILURE fi + elif [[ $DISTRO == redhat ]]; then + RHEL_VERSION=$(grep -m1 'VERSION_ID' /etc/os-release | grep -Eo "8.[0-9]{1,2}") + if [[ $? -ne 0 ]]; then + echo "Warning: This runtime can be installed only on RHEL 8" >&2 + echo "Installation of Intel Compute Runtime interrupted" + exit $EXIT_FAILURE + fi elif [[ $DISTRO == ubuntu ]]; then UBUNTU_VERSION=$(grep -m1 'VERSION_ID' /etc/os-release | grep -Eo "[0-9]{2}.[0-9]{2}") if [[ $UBUNTU_VERSION != '18.04' && $UBUNTU_VERSION != '20.04' ]]; then @@ -468,6 +500,8 @@ distro_init() { if [[ -f /etc/centos-release ]]; then DISTRO="centos" + elif [[ -f /etc/redhat-release ]]; then + DISTRO="redhat" elif [[ -f /etc/lsb-release ]]; then DISTRO="ubuntu" fi @@ -514,7 +548,7 @@ check_specific_generation() check_current_driver() { echo "Checking current driver version..." - if [[ $DISTRO == centos ]]; then + if [[ $DISTRO == centos || $DISTRO == redhat ]]; then gfx_version=$(yum info intel-opencl | grep Version) elif [[ $DISTRO == ubuntu ]]; then gfx_version=$(apt show intel-opencl | grep Version) diff --git a/scripts/install_dependencies/install_openvino_dependencies.sh b/scripts/install_dependencies/install_openvino_dependencies.sh index eb715ccb07463e..773fd30c48ce35 100755 --- a/scripts/install_dependencies/install_openvino_dependencies.sh +++ b/scripts/install_dependencies/install_openvino_dependencies.sh @@ -94,7 +94,7 @@ fi if [ "$os" == "auto" ] ; then os=$( . /etc/os-release ; echo "${ID}${VERSION_ID}" ) case $os in - centos7|ubuntu18.04|ubuntu20.04) [ -z "$print" ] && echo "Detected OS: ${os}" ;; + centos7|rhel8.2|ubuntu18.04|ubuntu20.04) [ -z "$print" ] && echo "Detected OS: ${os}" ;; *) echo "Unsupported OS: ${os:-detection failed}" >&2 ; exit 1 ;; esac fi @@ -195,6 +195,22 @@ elif [ "$os" == "ubuntu20.04" ] ; then vainfo ) +elif [ "$os" == "rhel8.2" ] ; then + + pkgs_opencv_req=(gtk3) + pkgs_python=(python3 python3-devel python3-setuptools python3-pip) + pkgs_dev=(gcc gcc-c++ make glibc libstdc++ libgcc cmake curl) + pkgs_myriad=() + pkgs_installer=() + pkgs_pot=() + pkgs_opencv_opt=( + gstreamer1 + gstreamer1-plugins-bad-free + gstreamer1-plugins-good + gstreamer1-plugins-ugly-free + ) + pkgs_dlstreamer=() + elif [ "$os" == "centos7" ] ; then # find -name *.so -exec objdump -p {} \; | grep NEEDED | sort -u | cut -c 23- | xargs -t -n1 yum -q whatprovides @@ -357,7 +373,7 @@ if [ "$os" == "ubuntu18.04" ] || [ "$os" == "ubuntu20.04" ] ; then apt-get update && apt-get install --no-install-recommends $iopt ${pkgs[@]} -elif [ "$os" == "centos7" ] ; then +elif [ "$os" == "centos7" ] || [ "$os" == "rhel8.2" ] ; then [ -z "$interactive" ] && iopt="--assumeyes" [ -n "$dry" ] && iopt="--downloadonly" diff --git a/tests/lib/install_pkg.py b/tests/lib/install_pkg.py index 2d89ccfbeba1df..5729ac5b413147 100644 --- a/tests/lib/install_pkg.py +++ b/tests/lib/install_pkg.py @@ -4,13 +4,32 @@ """ Common utilities for OpenVINO install package. """ -import sys +import errno +import os from pathlib import Path -from proc_utils import get_env_from # pylint: disable=import-error +import subprocess +import sys def get_openvino_environment(install_prefix: Path): """ Get OpenVINO environment variables """ - script = "setupvars.bat" if sys.platform == "win32" else "setupvars.sh" - return get_env_from(install_prefix / "bin" / script) + if sys.platform == "win32": + script = install_prefix / "bin" / "setupvars.bat" + cmd = f"{script} && set" + else: + script = install_prefix / "bin" / "setupvars.sh" + # setupvars.sh is not compatible with /bin/sh. Using bash. + cmd = f'bash -c ". {script} && env"' + + if not os.path.exists(str(script)): + raise FileNotFoundError(errno.ENOENT, os.strerror(errno.ENOENT), str(script)) + + env = {} + dump = subprocess.check_output(cmd, shell=True, universal_newlines=True).strip() + for line in dump.split("\n"): + # split by first '=' + pair = [str(val).strip() for val in line.split("=", 1)] + if len(pair) > 1 and pair[0]: # ignore invalid entries + env[pair[0]] = pair[1] + return env diff --git a/tests/lib/path_utils.py b/tests/lib/path_utils.py index f65182761e20d0..5d9718996a0e36 100644 --- a/tests/lib/path_utils.py +++ b/tests/lib/path_utils.py @@ -2,7 +2,7 @@ # Copyright (C) 2021 Intel Corporation # SPDX-License-Identifier: Apache-2.0 -""" Common utilities for working with processes. +""" Common utilities for working with paths """ import os diff --git a/tests/lib/proc_utils.py b/tests/lib/proc_utils.py index 659c22814aab7a..8057765bfc08a4 100644 --- a/tests/lib/proc_utils.py +++ b/tests/lib/proc_utils.py @@ -5,30 +5,8 @@ """ Common utilities for working with processes. """ -import errno -import os import logging import subprocess -import sys - - -def get_env_from(script): - """ Get environment set by a shell script - """ - if not os.path.exists(str(script)): - raise FileNotFoundError(errno.ENOENT, os.strerror(errno.ENOENT), str(script)) - env = {} - if sys.platform == "win32": - cmd = f'"{script}" && set' - else: - cmd = f'. "{script}" && env' - dump = subprocess.check_output(cmd, shell=True, universal_newlines=True).strip() - for line in dump.split("\n"): - # split by first '=' - pair = [str(val).strip() for val in line.split("=", 1)] - if len(pair) > 1 and pair[0]: # ignore invalid entries - env[pair[0]] = pair[1] - return env def cmd_exec(args, env=None, log=None, verbose=True):